How to setup vsftpd on Debian

Vsftpd is the acronym of Very Secure FTP Daemon: it is one of the most used ftp servers on Linux and other Unix-like operating systems. It is open source and released under the GPL license, and supports virtual users and SSL for data
encryption. In this tutorial we will see how to install it and configure it on Linux.

In this tutorial you will learn:

  • How to install vsftpd on Debian 10
  • How to configure vsftpd
  • How to setup anonymous usage
  • How to setup login with local users
  • How to setup virtual users
  • How to setup ufw to allow incoming traffic

How to setup vsftpd on Debian

How to setup vsftpd on Debian

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Debian 10 (Buster)
Software vsftpd, openssl, libpam-pwdfile
Other Root permissions to install and configure vsftpd
Conventions # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux-commands to be executed as a regular non-privileged user


Vsftpd is available in the official Debian repositories, therefore to install it we can use our favorite package manager; it’s just a matter of synchronizing the repositories and install the package. Both things can be accomplished by
running the following commands:

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

Few seconds and the package will be installed on our Debian system. The installation scripts included in the package will also take care to start the vsftpd service automatically but we must remember to restart or reload the service each time we change the configuration file. To be able to use the virtual users feature provided by the vsftpd we also need to install another package:

$ sudo apt-get install libpam-pwdfile

We will see its usage in the dedicated section of this tutorial.

Once the needed packages are installed, we can proceed further and configure vsftpd: we will see how to do it in the next section of this tutorial.

Vsftpd setup

The vsftpd configuration file is /etc/vsftpd.conf. If we open it we can see the various directives already contained in it. Let’s see what are the most relevant for the most common cases.

Enable anonymous login

Unauthenticated access to the server, as anonymous users, is disabled by default. To enable it, we must use the anonymous_enable directive, which on the configuration file is placed at line 25. All we have to do is to set it on YES:
must change the instruction to:


Another directive we may want to change is the one which let us set a directory in what vsftpd will try to navigate after an anonymous access. The directive which let us control this setting is anon_root. Let’s say we want an anonymous user to access the /srv/ftp directory by default, we would write:


All the anonymous login are mapped internally to a designed user, which, by default is ftp. To change this mapping we have to use the ftp_username option and set it to the name of the user we want to map anonymous users to.

By default an anonymous user will not be allowed to write anything on the server, for obvious security reasons. If you want to change this behavior (not recommended) there are few options that need to be changed. First of all the general write_enable directive must be set to YES. This directive is commented on line 31 of the configuration file, so all you have to do is to remove the comment.

# Uncomment this to enable any form of FTP write command.

Once this directive is enabled, all we have to do is to work on another two options: anon_upload_enable and anon_mkdir_write_enable. When the former is set to YES an anonymous user will be able to upload files, but only if the user on which it is mapped to (as we said, ftp, by default) has write permissions on the destination directory. To activate this option, all we have to do is to remove the comment from the line 40 of the configuration file:

# Uncomment this to allow the anonymous FTP user to upload files. This only
# has an effect if the above global write enable is activated. Also, you will
# obviously need to create a directory writable by the FTP user.

The anon_mkdir_write_enable directive, instead, when set to YES allows anonymous users to create new directories on the server, at the same conditions we saw above (the underlying user on the server must have write permissions on the parent directory). The directive is located at line 44 of the configuration file:

# Uncomment this if you want the anonymous FTP user to be able to create
# new directories.

Once again, since the variable is already set to YES, for it to be relevant, all we have to do is to remove the comment from it.

To allow anonymous users to perform also other kind of write operations, as for example renaming or deleting a directory, we must use another directive which is not present in the configuration file, anon_other_write_enable and set it to YES if the one above is our desired behavior:


Authenticated logins

To allow the local system users to access the ftp server with their system password, the local_enable directive must be set to YES: this is the default on the Debian system. The directive can be found on line 28 of the daemon
configuration file:

# Uncomment this to allow local users to log in.

By default, when a local user successfully authenticates, he/she will have its own home directory as root. It is possible, however, to specify an alternative starting point by using the local_root directive. This directive is not present in the configuration file, so we must add it if we want to use. To set the /srv/ftp directory as local root, for example, we would write:


Chroot local users

As a security measure it is possible to chroot each authenticated user in its own home directory. To accomplish this task we must use the chroot_local_user directive:


When this feature is enabled, it is possible to specify a list of exclusions, (a list of users which should not be chrooted) using the following directives:


The first directive is needed to activate the feature, the other one to specify the location of the file containing the exclusion list. The file must be created if doesn’t already exist, otherwise login will fail.

As a security measure, when an user is chrooted, it should not be able to write to the top level directory of the chroot. If it is the case, in the most recent versions of vsftpd, an user will not be able to login, and the server will respond with the following message:

500 OOPS: vsftpd: refusing to run with writable root inside chroot()

This issue can be solved in basically two ways. This first one is obviously consists into fixing the permissions, denying the user write access to the top level directory of the chroot and letting them write only on sub-directories.
The second way to solve the problem, if you don’t care about the possible security implications, is to bypass this restriction, using the following directive:


Speaking about permissions, it’s important to keep in mind that the default umask for local user is set to 077. If this setting is considered too restrictive, it is possible to change it using the local_umask directive. This directive is commented at line 35 of the configuration file:

# Default umask for local users is 077. You may wish to change this to 022,
# if your users expect that (022 is used by most other ftpd's)

Login with virtual users

One nice feature offered by vsftpd is the possibility to login using virtual users. A virtual user is an user who doesn’t really exist on the system, but only in the context of the sftpd application. To enable this feature we have to use the following directive:


When the feature is active, all non-anonymous logins (so even real/local users) are mapped to the user specified with the guest_username directive, which by default, as we already saw is ftp.

The next step is to create a file containing the usernames and passwords of virtual users. To generate an hashed password, we can use openssl and issue the following command:

$ openssl passwd -1
Verifying - Password:

The passwd command of openssl is used to generated hashed passwords (md5). In the example above, we were asked for the password to be hashed and its confirmation. Finally the hashed password is generated and displayed onscreen.

The username, together with the password, must be put into a file, let’s say it is /etc/virtual_users.pwd, in the following format:


So supposing our virtual user is called “linuxconfig” we would write:


The operation must be repeated for each virtual user we want to configure.

Now we have to create the pam service that will be used by vsftpd to authenticate virtual users. We will name the file vsftpd_virtual and place it in the /etc/pam.d directory. Its content will be the following:

auth    required pwdfile /etc/vsftpd/virtual_users.pwd
account required

As you can see, we specified the path of the file containing the username and passwords of the virtual users in the first line. All we need to do, now, is to instruct vsftpd to use this pam “service”. We can do it with the pam_service_name directive:


At this point we can save the configuration file, restart the daemon and verify that we are able to login with the virtual user we just created.

Enabling SSL support for data encryption

By default SSL support is disabled on vsftpd, so transferred data will be not encrypted. To enable SSL support we must use the following directives, located at lines 149 to 151 of the configuration file:

# This option specifies the location of the RSA certificate to use for SSL
# encrypted connections.

The first directive, rsa_cert_file is used to indicate the path of the RSA certificate to use for SSL encrypted connections. The second one, rsa_private_key, instead, is used to specify the location of the RSA private key. Finally, the ssl_enable directive is used to enable the use of SSL encryption.

The example uses the /etc/ssl/certs/ssl-cert-snakeoil.pem and /etc/ssl/private/ssl-cert-snakeoil.key files, but you almost certainly want to use a dedicated one.

Specifying port range for passive mode

FTP passive mode is the default on a new installation of vsftpd, but if we want to be enable it explicitly we can use the following directive:

# Set to NO if you want to disallow the PASV method of obtaining a data connection
# (passive mode). Default: YES

When the server operates in passive mode, it sends to the client an IP address and port that it should listens to for connection. This ports are by default selected randomly, however, since we must use a firewall on our server, we must know what ports we should allow traffic thorough. The range of ports to use can be specified with the pasv_min_port and pasv_max_port directives, for example:

# The minimum port to allocate for PASV style data connections. Can be used to
# specify a narrow port range to assist firewalling.

# The maximum port to allocate for PASV style data connections. Can be used to
# specify a narrow port range to assist firewalling. Default: 0 (use any port)

With the following configuration the server will use a range of ports that goes from 10090 to 10100.

Firewall setup

For our vsftpd server to work correctly we must allow traffic through the needed ports, some we must setup the appropriate rules for our firewall. In this tutorial I will assume the use of the ufw firewall manager (Uncomplicated Firewall).

The first port we want to allow traffic through is port 21, which is the standard port used by the FTP protocol:

$ sudo ufw allow in 21/tcp

As a second thing we must allow incoming traffic via the specified port range we setup in the previous section. To specify a range of ports we can run:

$ sudo ufw allow in 10090:10100/tcp


In this article we saw how to install and configure vsftpd on Debian 10 Buster. We saw how to setup anonymous usage and local users usage, and how we can take advantage of the virtual users feature provided by the service. Since FTP doesn’t provide data encryption, we saw how to enable SSL support, and finally how to setup the firewall to allow incoming traffic through the needed ports. For a complete list of the possible directives that can be used in the vsftpd configuration file, please take a look at the vsftpd.conf manpage (VSFTPD.CONF(5)). Want to know how to programmatically work with an FTP server? Take a look at our article on How to connect to an FTP server using python.