How to Set Up a Secure FTP Server on Debian 10 with Pure-FTPd
Pure-FTPd is a free open-source FTP server designed with security in mind. In this tutorial, we are going to learn how to set up an FTP server on Debian 10 with Pure-FTPd and how to enforce TLS encryption.
Pure-FTPd Features:
- It supports SSL/TLS encryption and thus passwords and commands can be protected.
- It can run on most Unix-like systems: Linux, BSDs, Solaris, Darwin, HPUX, AIX, and even iPhone.
- Available in 21 languages.
- Allows you to monitor active sessions.
- Supports a virtual quota system.
- And much more
For a complete list of features, please go to Pure-FTPd official website.
Step 1: Install Pure-FTPd on Debian 10 Server
It’s in the software repository, so issue the following command to install the FTP server.
sudo apt install pure-ftpd
Once installed, Pure-FTPd will be automatically started, as can be seen with this command:
systemctl status pure-ftpd
Output:
● pure-ftpd.service Loaded: loaded (/etc/init.d/pure-ftpd; generated) Active: active (running) since Wed 2021-06-16 13:15:52 UTC; 23s ago Docs: man:systemd-sysv-generator(8) Tasks: 1 (limit: 558) Memory: 972.0K CGroup: /system.slice/pure-ftpd.service └─9223 pure-ftpd (SERVER)
If it’s not running, star it with:
sudo systemctl start pure-ftpd
And it’s listening on TCP port 21, which is the control port, as can be seen with
sudo ss -lnpt | grep pure-ftpd
The other port is the data port (TCP port 20), which will be used when a user transfer files over FTP.
Anonymous access is disabled by default. From now on you can use your system account to log in, but plain text FTP is insecure and strongly discouraged. To have a secure FTP server, we need to encrypt communication with TLS.
Step 2: Enforce TLS Encryption
To enable both plain-text and TLS encryption, run the following command, which create the /etc/pure-ftpd/conf/TLS
file and put number 1 into the file.
echo 1 | sudo tee /etc/pure-ftpd/conf/TLS
But it’s recommended to disable plain-text and use TLS encryption only, so put the number 2 to the file instead.
echo 2 | sudo tee /etc/pure-ftpd/conf/TLS
Now we enforced TLS, we need to obtain a valid TLS certificate. A self-signed certificate is not recommended because users will see warning message like the screenshot below.
Step 3: Obtain a Trusted TLS Certificate from Let’s Encrypt
Run the following command to install Let’s Encrypt client (certbot) from the default Debian 10 repository.
sudo apt install certbot
I recommend using the standalone
or webroot
plugin to obtain TLS certificate for Pure-FTPd.
Standalone Plugin
If there’s no web server running on your Debian 10 server, you can use the standalone plugin. Run the following command. Don’t forget to set DNS A record for your sub-domain.
sudo certbot certonly --standalone --preferred-challenges http --agree-tos --email [email protected] -d ftp.example.com
Where:
certonly
: Obtain a certificate but don’t install it.--standalone
: Use the standalone plugin to obtain a certificate--preferred-challenges http
: Perform http-01 challenge to validate our domain, which will use port 80.--agree-tos
: Agree to Let’s Encrypt terms of service.--email
: Email address is used for account registration and recovery.-d
: Specify your domain name.
As you can see from the following screenshot, I successfully obtained the certificate.
Using webroot Plugin
If your Debian 10 server has a web server, then it’s a good idea to use the webroot plugin to obtain a certificate because the webroot plugin works with pretty much every web server and we don’t need to install the certificate in the web server.
First, you need to create a virtual host for ftp.example.com
.
Apache
If you are using Apache, then
sudo nano /etc/apache2/sites-available/ftp.example.com.conf
And paste the following lines into the file.
<VirtualHost *:80>
ServerName ftp.example.com
DocumentRoot /var/www/Pure-FTPd
</VirtualHost>
Save and close the file. Then create the web root directory.
sudo mkdir /var/www/Pure-FTPd
Set www-data (Apache user) as the owner of the web root.
sudo chown www-data:www-data /var/www/Pure-FTPd -R
Enable this virtual host.
sudo a2ensite ftp.example.com
Reload Apache for the changes to take effect.
sudo systemctl reload apache2
Once virtual host is created and enabled, run the following command to obtain Let’s Encrypt certificate using webroot plugin.
sudo certbot certonly --webroot --agree-tos --email [email protected] -d ftp.example.com -w /var/www/Pure-FTPd
Nginx
If you are using Nginx, then
sudo nano /etc/nginx/conf.d/ftp.example.com.conf
Paste the following lines into the file.
server {
listen 80;
listen [::]:80;
server_name ftp.example.com;
root /var/www/Pure-FTPd/;
location ~ /.well-known/acme-challenge {
allow all;
}
}
Save and close the file. Then create the web root directory.
sudo mkdir -p /var/www/Pure-FTPd
Set www-data (Nginx user) as the owner of the web root.
sudo chown www-data:www-data /var/www/Pure-FTPd -R
Reload Nginx for the changes to take effect.
sudo systemctl reload nginx
Once virtual host is created and enabled, run the following command to obtain Let’s Encrypt certificate using webroot plugin.
sudo certbot certonly --webroot --agree-tos --email [email protected] -d ftp.example.com -w /var/www/Pure-FTPd
Step 4: Install the Certificate
Pure-FTPd requires that the certificate and private key are combined into one file named pure-ftpd.pem
and stored under /etc/ssl/private/
directory.
Change to the /etc/letsencrypt/live/ftp.example.com/
directory.
sudo su -
cd /etc/letsencrypt/live/ftp.example.com/
You can use cat
command to combine two files into one like below.
cat fullchain.pem privkey.pem | sudo tee /etc/ssl/private/pure-ftpd.pem
Make sure only the root user can read the file.
sudo chmod 600 /etc/ssl/private/pure-ftpd.pem
We need to generate the Diffie-Hellman parameter with:
sudo openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 4096
If your server has a single CPU core, then this is going to take a long time (about 10 minutes).
Once that’s done, restart Pure-FTPd.
sudo systemctl restart pure-ftpd
Check the status to see if it’s running.
systemctl status pure-ftpd
Now you can connect to your FTP server over TLS.
Step 5: Open FTP Ports In Firewall
If you use the UFW firewall, then run the following command to open TCP port 20 and 21.
sudo ufw allow 20,21/tcp
Step 6: Connect to FTP Server
If you use Nautilus file manager to connect to FTP server via plain text ftp://
protocol
The connection will be refused.
Instead of ftp://
, you must use ftps://
.
By default, FTP users will be brought to the /
root directory on the server.
Please note that Filezilla doesn’t trust any certificate (self-signed or CA-signed) by default. Users must choose to trust certificate for themselves.
And you need to use the FTP explicit TLS protocol (ftpes://ftp.example.com
) in Filezilla.
Auto-Renew TLS Certificate
You can create Cron job to automatically renew TLS certificate. Simply open the root user’s crontab file.
sudo crontab -e
Add the following line at the bottom of the file.
@daily certbot renew --quiet && cd /etc/letsencrypt/live/ftp.example.com/ && cat fullchain.pem privkey.pem | tee /etc/ssl/private/pure-ftpd.pem && systemctl reload pure-ftpd
It’s necessary to reload pure-ftpd
to make it pick up the new certificate and private key.
Wrapping Up
I hope this tutorial helped you set up a secure FTP server with Pure-FTPd on Debian 10. As always, if you found this post useful, then subscribe to our free newsletter. You can also follow us on Twitter or like our Facebook page.
I find your work always very educative and informative
Thanx for the useful article.
I have a small question. Isn’t using ‘tee’ in a cron sequence unnecessary. Parallel output to the terminal is not needed, just ‘cat fullchain.pem privkey.pem > /etc/ssl/private/pure-ftpd.pem’ is sufficient.