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
Software requirements and conventions used
|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
$ - 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.
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
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
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
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. write_enable=YES
Once this directive is enabled, all we have to do is to work on another two options:
anon_mkdir_write_enable. When the former is set to
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. anon_upload_enable=YES
anon_mkdir_write_enable directive, instead, when set to
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
# Uncomment this if you want the anonymous FTP user to be able to create # new directories. anon_mkdir_write_enable=YES
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
YES if the one above is our desired behavior:
To allow the local system users to access the ftp server with their system
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
# Uncomment this to allow local users to log in. local_enable=YES
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
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) #local_umask=022
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
$ openssl passwd -1 Password: Verifying - Password: $pfwh3Jou$DQBiNjw8bBtDqys7ezTpr.
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
/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
/etc/pam.d directory. Its content will be the following:
#%PAM-1.0 auth required pam_pwdfile.so pwdfile /etc/vsftpd/virtual_users.pwd account required pam_permit.so
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
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
151 of the configuration file:
# This option specifies the location of the RSA certificate to use for SSL # encrypted connections. rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key ssl_enable=YES
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,
instead, is used to specify the location of the RSA private key. Finally,
ssl_enable directive is used to enable the use of SSL encryption.
The example uses the
/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 pasv_enable=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
# The minimum port to allocate for PASV style data connections. Can be used to # specify a narrow port range to assist firewalling. pasv_min_port=10090 # 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) pasv_max_port=10100
With the following configuration the server will use a range of ports that goes
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.