Set up a powerful FTP Server in OS X Leopard

Pure-FTPd has always been my ftp server daemon of choice for UNIX systems. It’s free, secure, fast, widely deployed and definitely more powerful than the built-in /usr/libexec/ftpd.

I’d never tried it on Mac, but it was surprisingly easy to set up.

First, download the latest stable release.

mkdir ~/src
cd ~/src
ftp http://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.21.tar.gz
tar -xzvf pure-ftpd-1.021.tar.gz
cd pure-ftpd-1.0.21

Although it’s outdated, read the README file for OS X

more README.MacOS-X

Proceed to install. We enable PAM to use the system users for login, and bonjour. If you want other login options, run

./configure --help

You might want to use puredb (for virtual users) instead of your system users or MySQL.

./configure --with-pam --with-bonjour
make install-strip

Unlike GNU/Linux systems, OS X uses the flexible launchd daemon to manage cron jobs, boot tasks and daemons. Since we want to replace the bundled ftpd daemon, we’ll edit the existing plist. Before editing anything, make sure FTP is disabled in System preferences > Sharing > File Sharing > Options.

nano /System/Library/LaunchDaemons/ftp.plist

With the following content

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
	"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>org.pureftpd.ftpd</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/local/sbin/pure-ftpd</string>
		<string>--chrooteveryone</string>
	</array>
	<key>Sockets</key>
	<dict>
		<key>Listeners</key>
		<dict>
			<key>Bonjour</key>
			<true/>
			<key>SockFamily</key>
			<string>IPV4</string>
			<key>SockServiceName</key>
			<string>ftp</string>
		</dict>
	</dict>
	<key>inetdCompatibility</key>
	<dict>
		<key>Wait</key>
		<false/>
	</dict>
</dict>
</plist>

This file triggers the Pure-FTPd daemon on demand. Enable FTP in File Sharing, and let’s try to connect:

ftp localhost
Trying ::1...
ftp: connect to address ::1: Connection refused
Trying fe80::1%lo0...
ftp: connect to address fe80::1%lo0: Unknown error: 0
Trying 127.0.0.1...
Connected to localhost.
220---------- Welcome to Pure-FTPd ----------
220-Local time is now 13:02. Server port: 21.
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
Name (localhost:willy): willy
331 User willy OK. Password required
Password:
230-User willy has group access to:  admin    _appserv _appserv _lpadmin
230- com.appl com.appl staff
230 OK. Current directory is /Users/willy
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> 

If you want to customize the many options Pure-FTPd has, edit the ProgramArguments section in the plist file. You’ll definitely want to change it if you set it up with MySQL or puredb instead of PAM. You might want to add chrooteveryone to lock the users to their homes by appending this option to that section, for extra security:

<string>--chrooteveryone</string>