vsftpd is a surprisingly resilient and high-performance FTP server, but its configuration can feel like navigating a minefield of security implications.
Let’s get vsftpd running. First, install it:
sudo apt update
sudo apt install vsftpd
Now, the core configuration file: /etc/vsftpd.conf.
sudo nano /etc/vsftpd.conf
The most immediate hurdle is enabling local user logins. By default, vsftpd is often configured for anonymous access or restricted user access. To allow your system users to log in with their existing credentials, you need to set:
local_enable=YES
This tells vsftpd to consult the system’s user authentication database (like /etc/passwd) for login attempts.
Next, enabling write operations is crucial for any practical FTP server. If users can’t upload files, it’s not much of an FTP server. Add or uncomment:
write_enable=YES
This grants users permission to upload, delete, and rename files within their allowed directories, provided their file system permissions permit it.
For security, especially if you’re not explicitly allowing anonymous access, it’s good practice to disable it. If you see anonymous_enable=YES and you don’t want it, change it to:
anonymous_enable=NO
This prevents anyone from logging in with the username "anonymous" or "ftp".
Now, let’s consider where users land after they log in. By default, they’ll be placed in their home directory. If you want to restrict users to a specific directory, even if their home directory is elsewhere, you can use chroot. This "jails" the user to a specific directory.
To enable this for all local users:
chroot_local_user=YES
However, this often breaks logins because the user’s home directory becomes their root. The jail directory itself must be owned by root and not writable by any other user. To make this work reliably, you often need a writable directory inside the jail.
First, create a directory for your user, say /home/youruser, and then create a subdirectory that will be writable:
sudo mkdir -p /home/youruser/ftp
sudo chown root:root /home/youruser
sudo chmod 755 /home/youruser
sudo chown youruser:youruser /home/youruser/ftp
Then, in your vsftpd.conf, you’ll need to tell vsftpd to allow writeable root directories if you’re using chroot_local_user=YES. This is a bit of a security trade-off, but necessary for this setup.
allow_writeable_chroot=YES
If you’re using chroot_local_user=YES and users can’t log in, and you’ve followed the directory permissions above, this is almost certainly the setting you need. Without it, vsftpd will refuse to start or allow logins for chrooted users if their jail directory is writable.
To make the changes active, restart the vsftpd service:
sudo systemctl restart vsftpd
You can check its status to ensure it’s running without errors:
sudo systemctl status vsftpd
A common issue after enabling chroot_local_user is that users can log in but immediately get disconnected or can’t see any files. This is because the chroot directory itself must be owned by root and not writable by the user. The allow_writeable_chroot=YES setting is a workaround for this, but a more secure way is to have a root-owned directory as the jail, and then a writable subdirectory within it for the user’s uploads.
Another area that trips people up is passive mode. FTP connections can be active or passive. In active mode, the server initiates the data connection back to the client, which often fails due to firewalls. Passive mode is generally preferred. To enable it, and to tell vsftpd which ports to use for passive connections:
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=50000
You’ll then need to open these ports in your firewall (e.g., UFW):
sudo ufw allow 20/tcp # For active mode data connections (less common for clients)
sudo ufw allow 21/tcp # FTP control port
sudo ufw allow 40000:50000/tcp # Passive mode data ports
sudo ufw enable
If you’re dealing with SELinux on Red Hat-based systems, you might find that FTP operations fail even with correct file permissions and vsftpd configurations. You’ll need to allow FTP access for SELinux:
sudo setsebool -P ftpd_full_access on
This command allows FTP daemons to perform all operations, including writing to directories.
Finally, if you’re seeing connection refused errors and vsftpd is running, check if inetd or xinetd is managing vsftpd. It shouldn’t be. vsftpd should be running as a standalone daemon. Ensure these lines are commented out in /etc/inetd.conf or /etc/xinetd.d/vsftpd:
#ftp stream tcp nowait root /usr/sbin/tcpd vsftpd
or
disable = no
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/sbin/vsftpd
log_on_failure += USERID
The next error you’ll likely encounter is related to TLS/SSL certificate configuration if you decide to enable secure FTP.