After a couple hours googling and finding only the pieces of the possible solution, I’ve decided to put together a simple guide to setup a FTP server on Ubuntu.

Create the FTP user

We begin by creating a system user with no shell privileges. This user wouldn’t be able to ssh to the server.

$ sudo useradd --home /home/simpleftp --gid nogroup -m --shell /bin/false simpleftp

The home parameter is the directory where the user will be jailed when connecting to the FTP.

Set user’s password:

$ sudo passwd simpleftp

Set directory permissions

$ sudo chown -R simpleftp:root /home/simpleftp
$ sudo chmod +rw /home/simpleftp

Installing VSFTP

Installing VSFTP should be straight forward. There’s no need to add 3rd party APT repositories.

$ sudo apt-get update
$ sudo apt-get install vsftpd

Check everything installed correctly:

$ vsftpd -v
vsftpd: version 3.0.2

Configuring VSFTP

Open the VSFTP configuration file:

$ nano /etc/vsftpd.conf

Now, this arethe minimum settings you need to run VSFTP without any hassle:

anonymous_enable=NO
local_enable=YES
write_enable=YES
chroot_local_user=YES
chroot_list_enable=YES
ls_recurse_enable=YES
pam_service_name=ftp
seccomp_sandbox=NO
check_shell=NO
allow_writeable_chroot=YES


I believe the most important setting here is allow_writeable_chroot. I spent a while looking why I wasn’t able to connect successfully to the FTP if the root directory (/home/simpleftp) had write permissions. I was usingTransmit (which didn't show me what was the error).

In case you’re curious about what error was I getting:
500 OOPS: vsftpd: refusing to run with writable root inside chroot()

Finally

Fireup another terminal and run:

$ ftp yourserver.com
Connected to yourserver.com.
220 Welcome to YourServer FTP service.
Name (yourserver.com:someuser): [enter the ftp username]
331 Please specify the password.
Password: [enter your password]
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

Reminder

Be sure to check your IPTABLES rules to allow FTP connections to the server.

$ sudo iptables -A INPUT -p tcp --dport 21 -j ACCEPT
$ sudo iptables -A OUTPUT -p tcp --sport 20 -j ACCEPT


VSFTP & Symbolic links

VSFTP doesn’t follow symlinks. Period. If you ever need to create a symlink in the FTP directory, the easiest way to do it is by mounting the target directory. Let me show you an example:

First, create the directory inside user’s chroot

mkdir -p /home/simpleftp/my-dir

Then, mount the directory you want to be available in VSFTP for that user

mount --bind /path/to/target/directory /home/simpleftp/my-dir