How to Setup FTP Server with Vsftpd on Raspberry Pi

By 

Updated on

7 min read

Setup FTP Server with Vsftpd on Raspberry Pi

Setting up an FTP server on your Raspberry Pi gives you a simple way to transfer files between the Pi and other devices on your network. This guide uses vsftpd (Very Secure FTP Daemon), a stable and fast FTP server for Linux. We will also show you how to restrict users to their home directories and encrypt the transmission with SSL/TLS.

For this project, you should have Raspberry Pi OS installed on your Raspberry Pi . Running an FTP server does not require a graphical interface, so our recommendation is to use the Raspberry Pi OS Lite image and enable SSH .

Installing vsftpd on Raspberry Pi

The vsftpd package is available in the standard Raspberry Pi OS repositories. To install it, run the following commands:

Terminal
sudo apt update
sudo apt install vsftpd

The ftp service will automatically start after the installation process is complete. To verify it, print the service status:

Terminal
sudo systemctl status vsftpd

The output will look something like below, showing that the vsftpd service is active and running:

output
● vsftpd.service - vsftpd FTP server
   Loaded: loaded (/lib/systemd/system/vsftpd.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2020-10-21 19:00:41 BST; 9s ago
...

Configuring vsftpd

The vsftpd server can be configured by editing the /etc/vsftpd.conf file.

Most of the settings are well documented inside the configuration file. For all available options, visit the official vsftpd page.

Start by opening the vsftpd configuration file:

Terminal
sudo nano /etc/vsftpd.conf

1. FTP Access

To ensure that only local users can access the FTP server, search for the anonymous_enable and local_enable directives and verify that your configuration matches the lines below:

/etc/vsftpd.confcfg
anonymous_enable=NO
local_enable=YES

2. Enabling uploads

Locate and uncomment the write_enable directive to allow changes to the filesystem, such as uploading and removing files.

/etc/vsftpd.confcfg
write_enable=YES

3. Chroot Jail

To prevent the FTP users from accessing files outside of their home directories, uncomment the chroot directive.

/etc/vsftpd.confcfg
chroot_local_user=YES

When the chroot feature is active, vsftpd will refuse to upload files if the directory that the users are locked in is writable.

Use one of the solutions below to make the chroot environment writable:

  • Method 1. - The recommended option to allow upload is to keep chroot enabled and configure FTP directories. In this example, we will create an ftp directory inside the user home, which will serve as the chroot and a writable upload directory for uploading files.

    /etc/vsftpd.confcfg
    user_sub_token=$USER
    local_root=/home/$USER/ftp
  • Method 2. - Another option is to add the following directive in the vsftpd configuration file. Use this option if you must grant writable access to your user to its home directory.

    /etc/vsftpd.confcfg
    allow_writeable_chroot=YES

4. Passive FTP Connections

Passive mode is enabled by default in current vsftpd builds. Set a fixed minimum and maximum port range so the firewall can allow FTP data connections predictably:

/etc/vsftpd.confcfg
pasv_min_port=30000
pasv_max_port=31000

vsftpd can use any port for passive FTP connections. When the passive mode is enabled, the FTP client opens a connection to the server on a random port in the range you have chosen.

5. Limiting User Login

You can configure vsftpd to permit only certain users to log in. To do so, add the following lines at the end of the file:

/etc/vsftpd.confcfg
userlist_enable=YES
userlist_file=/etc/vsftpd.user_list
userlist_deny=NO

When this feature is enabled, you need to explicitly specify which users can log in by adding the user names to the /etc/vsftpd.user_list file (one user per line).

6. Securing Transmissions with SSL/TLS

To encrypt the FTP transmissions with SSL/TLS, you will need to have an SSL certificate and configure the FTP server to use it.

You can use an existing SSL certificate signed by a trusted Certificate Authority or create a self-signed certificate.

If you have a domain or subdomain pointing to the FTP server’s IP address, you can easily generate a free Let’s Encrypt SSL certificate.

In this tutorial, we will generate a self-signed SSL certificate using the openssl command.

Run the following command to create a 2048-bit private key and self-signed certificate valid for 10 years. Both the private key and the certificate will be saved in the same file:

Terminal
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem

Once the files are created, open the configuration file:

Terminal
sudo nano /etc/vsftpd.conf

Find the rsa_cert_file and rsa_private_key_file directives, change their values to the pem file path, and set the ssl_enable directive to YES:

/etc/vsftpd.confcfg
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES

If not specified otherwise, the FTP server will use only TLS to make secure connections.

Restart the vsftpd service

Once you are done configuring the server, the vsftpd configuration file (excluding comments) should look something like this:

/etc/vsftpd.confcfg
listen=NO
listen_ipv6=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
chroot_local_user=YES
user_sub_token=$USER
local_root=/home/$USER/ftp
pasv_min_port=30000
pasv_max_port=31000
userlist_enable=YES
userlist_file=/etc/vsftpd.user_list
userlist_deny=NO
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES

Save the file and restart the vsftpd service for changes to take effect:

Terminal
sudo systemctl restart vsftpd

Opening the Firewall

If you are running a UFW firewall , you will need to allow FTP traffic.

To open port 21 (FTP command port), port 20 (FTP data port), and 30000-31000 (Passive ports range), run the following commands:

Terminal
sudo ufw allow 20:21/tcp
sudo ufw allow 30000:31000/tcp

Reload UFW to apply the new rules:

Terminal
sudo ufw reload

Creating FTP User

To test the FTP server, we will create a new user.

  • If you already have a user that you want to grant FTP access, skip the 1st step.
  • If you set allow_writeable_chroot=YES in your configuration file, skip the 3rd step.
  1. Create a new user named newftpuser:

    Terminal
    sudo adduser newftpuser

    When prompted, set the user password.

  2. Add the user to the allowed FTP users list:

    Terminal
    echo "newftpuser" | sudo tee -a /etc/vsftpd.user_list
  3. Create the FTP directory tree and set the correct permissions :

    Terminal
    sudo mkdir -p /home/newftpuser/ftp/upload
    sudo chmod 550 /home/newftpuser/ftp
    sudo chmod 750 /home/newftpuser/ftp/upload
    sudo chown -R newftpuser: /home/newftpuser/ftp

    As discussed in the previous section, the user will be able to upload files to the ftp/upload directory.

At this point, your FTP server is fully functional, and you should be able to connect to your server using any FTP client such as FileZilla .

Disabling Shell Access

By default, when creating a user, if not explicitly specified the user will have SSH access to the device. To disable shell access, create a new shell that will simply print a message telling the user that their account is limited to FTP access only.

Create the /usr/local/sbin/ftponly shell and make it executable:

Terminal
printf '%s\n' '#!/bin/sh' 'echo "This account is limited to FTP access only."' | sudo tee /usr/local/sbin/ftponly
sudo chmod 755 /usr/local/sbin/ftponly

Append the new shell to the list of valid shells in the /etc/shells file:

Terminal
grep -qxF "/usr/local/sbin/ftponly" /etc/shells || echo "/usr/local/sbin/ftponly" | sudo tee -a /etc/shells

Change the user shell to /usr/local/sbin/ftponly:

Terminal
sudo usermod -s /usr/local/sbin/ftponly newftpuser

Use the same command to change the shell of all users you want to give only FTP access.

Troubleshooting

500 OOPS: vsftpd: refusing to run with writable root inside chroot()
The directory the user is chrooted into is writable. Use the user_sub_token and local_root method from the Chroot Jail section to create a non-writable chroot root with a writable subdirectory beneath it, or add allow_writeable_chroot=YES to your configuration as a quicker workaround.

530 Login incorrect
The user is not listed in /etc/vsftpd.user_list when userlist_enable=YES is set. Add the username to that file and restart vsftpd with sudo systemctl restart vsftpd.

Connected but cannot list files or transfer data
The passive port range is likely blocked. Confirm that UFW allows 30000:31000/tcp and, if you are connecting from outside your network, that your router forwards that port range to the Pi.

FTP client rejects the connection after enabling SSL
Your FTP client must have explicit FTPS (FTP over TLS) enabled. Plain FTP clients will fail to connect once ssl_enable=YES is set in the configuration.

Conclusion

We have shown you how to install and configure a vsftpd FTP server on your Raspberry Pi with chroot jailing and SSL/TLS encryption. If you prefer a simpler alternative that works over your existing SSH connection without a separate server, see how to use SFTP to transfer files.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page