This guide explains how to set up vsftpd (Very Secure File Transfer Protocol Daemon), which allows users to upload files via FTPS (also known as FTP-SSL and FTP Secure). This guide is written for the Vultr One-Click LAMP server on Ubuntu 18.04 using a free Let's Encrypt SSL/TLS certificate. With minor modifications, you can adapt this guide to any server distribution with vsftpd in their repository, and use Apache or Nginx.
A One-Click LAMP server configured with a Fully Qualified Domain Name (FQDN).
A free Let's Encrypt certificate pointing to your domain name.
Update the local package index.
$ sudo apt update
Install the vsftpd daemon.
$ sudo apt install vsftpd
UFW, or Uncomplicated Firewall, is installed by default on Ubuntu systems. If it is enabled, open the necessary ports: 20 and 21 for FTP, 40000-50000 for passive FTP, and 990 for TLS.
$ sudo ufw allow 20/tcp
$ sudo ufw allow 21/tcp
$ sudo ufw allow 40000:50000/tcp
$ sudo ufw allow 990/tcp
$ sudo ufw status
If the firewall is enabled, the rules should look like this:
Output
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Apache Full ALLOW Anywhere
20/tcp ALLOW Anywhere
21/tcp ALLOW Anywhere
40000:50000/tcp ALLOW Anywhere
990/tcp ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Apache Full (v6) ALLOW Anywhere (v6)
20/tcp (v6) ALLOW Anywhere (v6)
21/tcp (v6) ALLOW Anywhere (v6)
40000:50000/tcp (v6) ALLOW Anywhere (v6)
990/tcp (v6) ALLOW Anywhere (v6)
Create a dedicated user to log in to FTP, and use a strong password.
$ sudo adduser ftpaccess
For increased security, block this user from logging in via SSH.
$ sudo nano /etc/ssh/sshd_config
Add the following line to the bottom of the file.
DenyUsers ftpaccess
Save and exit the file.
Restart SSH to enforce the changes.
$ sudo service sshd restart
Set the home directory to the folder above the default webroot. vsftpd restricts the user's access to their specific home directory using chroot jails and requires that the directory be not writable by the user. For Apache, the default webroot is /var/www/html.
$ sudo usermod -d /var/www ftpaccess
Set the ownership of the webroot to the FTP user.
$ sudo chown ftpaccess:ftpaccess /var/www/html
Verify the permissions of the directory.
$ sudo ls -la /var/www/html
Open the configuration file for vsftpd
.
$ sudo nano /etc/vsftpd.conf
Ensure anonymous FTP access is disabled and local users can log in.
#
# Allow anonymous FTP? (Disabled by default).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
local_enable=YES
#
Uncomment these lines to allow the FTP user to upload files, and prevent them from accessing any files outside of their home directory.
write_enable=YES
local_umask=022
chroot_local_user=YES
Add force_dot_files=YES
in the file to show hidden files such as .htaccess
.
force_dot_files=YES
Set the range of ports available for passive FTP. Make sure these values match the firewall settings added in Step 2.
pasv_min_port=40000
pasv_max_port=50000
Restrict FTP access to users specified in /etc/vsftpd.userlist
.
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO
Save and exit the file.
Edit /etc/vsftpd.userlist
.
$ sudo nano /etc/vsftpd.userlist
Add the ftpaccess user to the file.
ftpaccess
Save and exit the file.
Restart vsftpd
to load the changes.
$ sudo systemctl restart vsftpd
You should be able to log in with any FTP client as the ftpaccess user, but the server is un-encrypted. Continue with Step 5 to set up encryption.
By default, FTP does not encrypt credentials or data in transit. Follow these steps to use the server's Let's Encrypt certificate to secure the connection. You can follow our guide to obtain a Let's Encrypt certificate for a LAMP server if you need to install one first.
Edit the vsftpd
configuration file.
$ sudo nano /etc/vsftpd.conf
Find the two lines beginning with rsa_
and comment them out by adding #
at the beginning.
#rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
Add the following lines. Adjust the pathname to match the location of the server's certificate files.
rsa_cert_file=/etc/letsencrypt/live/example.com/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/example.com/privkey.pem
Add this line to allow clients that can't connect over TLS to use SSL.
ssl_enable=YES
Deny anonymous connections and force a secure connection by adding the following lines.
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
Specify which protocols to use. For security, allow TLS and block older versions of SSL.
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
Add the following to use strong encryption methods.
ssl_ciphers=HIGH
Do not require the reuse of SSL sessions. Setting this to yes may interfere with many FTP clients.
require_ssl_reuse=NO
Add the ports used for passive FTP.
pasv_min_port=40000
pasv_max_port=50000
Save and exit the file.
Restart the server.
$ sudo systemctl restart vsftpd
A good verification test is to attempt a connection with the default command-line ftp client, which will fail because it doesn't support encryption.
Connect using command-line ftp
from a different machine.
$ ftp example.com
Enter the username when prompted and ensure access is denied.
530 Non-anonymous sessions must use encryption.
ftp: Login failed.
With a client that supports FTPS, such as FileZilla or Cyberduck, connect to the server and check the connection log. You should find entries similar to this:
Status: Connection established, waiting for welcome message...
Status: Initializing TLS...
Status: Verifying certificate...
Status: TLS connection established.
You can now securely connect to your server via FTPS and upload files to your website directory.