Install vsftpd FTP Server on VPS
vsftpd (Very Secure FTP Daemon) is a lightweight, secure, and easy-to-configure FTP server for Ubuntu and Debian VPS systems. While SFTP (FTP over SSH) has gained popularity in recent years, FTP/FTPS remains necessary in certain scenarios: legacy applications that require FTP connectivity, shared hosting environments that don't permit SSH access, or non-technical users who prefer graphical FTP clients. This guide walks through setting up vsftpd securely with chroot jails, passive mode, and TLS encryption to safeguard file transfers on your VPS.
Install vsftpd
sudo apt update
sudo apt install vsftpd -y
# Enable vsftpd to start automatically
sudo systemctl enable vsftpd
sudo systemctl start vsftpd
Configure vsftpd
The main configuration file is /etc/vsftpd.conf. Back up the original first:
sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.bak
sudo nano /etc/vsftpd.conf
Find and edit (or add) these directives:
# Allow local users to login
local_enable=YES
write_enable=YES
# Chroot jail - confine users to their home directory
chroot_local_user=YES
chroot_list_enable=NO
# Disable anonymous login for security
anonymous_enable=NO
# Passive mode
pasv_enable=YES
pasv_address=YOUR.VPS.IP.ADDRESS
pasv_min_port=40000
pasv_max_port=40100
# FTPS (FTP over TLS/SSL)
ssl_enable=YES
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_tlsv1_2=YES
ssl_tlsv1_3=YES
require_ssl_reuse=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
# Logging
xferlog_enable=YES
xferlog_file=/var/log/vsftpd.log
log_ftp_protocol=YES
# Performance
max_clients=200
max_per_ip=4
Replace YOUR.VPS.IP.ADDRESS with your VPS's public IP address (e.g., 192.0.2.10) or a domain name that resolves to it.
Generate Self-Signed SSL Certificate for FTPS
For testing or internal use, you can generate a self-signed certificate:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/vsftpd.pem \
-out /etc/ssl/private/vsftpd.pem
# Set correct permissions
sudo chmod 600 /etc/ssl/private/vsftpd.pem
For production, obtain a signed certificate from a trusted CA (such as Let's Encrypt or a commercial provider), then edit the config to point to the certificate and private key files separately.
Create FTP User Account
Create a system user with a home directory for FTP access:
# Create user named ftpuser
sudo useradd -m -d /home/ftpuser -s /usr/sbin/nologin ftpuser
# Set a password
sudo passwd ftpuser
# Configure home directory as chroot jail
sudo chmod 555 /home/ftpuser
sudo mkdir -p /home/ftpuser/upload
sudo chmod 755 /home/ftpuser/upload
sudo chown ftpuser:ftpuser /home/ftpuser/upload
This user can access files only within /home/ftpuser and its writable subdirectories like upload/.
Open Firewall Ports
FTP uses port 21 for control connections and the port range 40000–40100 for passive data transfers:
# Using ufw
sudo ufw allow 21/tcp
sudo ufw allow 40000:40100/tcp
# Or with iptables
sudo iptables -A INPUT -p tcp --dport 21 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 40000:40100 -j ACCEPT
sudo systemctl restart vsftpd. Verify syntax with sudo vsftpd -olisten=NO /etc/vsftpd.conf (no output means OK).
Verify That vsftpd Is Working Correctly
# Check service status
sudo systemctl status vsftpd
# Verify port 21 is listening
sudo ss -tlnp | grep :21
# Test connection from another machine using ftp client
ftp YOUR.VPS.IP.ADDRESS
# Enter username and password
# Or use lftp in one command
lftp -u ftpuser,PASSWORD YOUR.VPS.IP.ADDRESS
# View connection logs
sudo tail -20 /var/log/vsftpd.log
Common Issues & Troubleshooting
Error: "500 OOPS: vsftpd: refusing to run with writable root inside chroot()"
vsftpd does not allow write permissions on the home directory when using chroot. Set directory permission to 555 or 755 (no write bit):
sudo chmod 555 /home/ftpuser
Error: "530 Login incorrect" even with correct credentials
Verify the user's login shell is set to nologin or false:
grep ftpuser /etc/passwd
# Should end with /usr/sbin/nologin or /bin/false
# If not, fix it:
sudo usermod -s /usr/sbin/nologin ftpuser
Error: "Passive mode connection timeout" or wrong IP in PASV response
Check that pasv_address in vsftpd.conf points to the correct public IP or domain that clients can reach. If behind a load balancer or NAT:
sudo nano /etc/vsftpd.conf
# Find pasv_address= and set it to the public IP or domain
# pasv_address=1.2.3.4
sudo systemctl restart vsftpd
FTPS client rejects self-signed certificate
When using self-signed certificates, FTP clients warn about certificate validation. In the ftp CLI, use set ssl:verify-certificate no. In graphical clients (e.g., FileZilla), click "Always trust this host".
Permission denied when uploading files
Ensure writable directories (like upload/) have correct ownership and permissions:
sudo chown ftpuser:ftpuser /home/ftpuser/upload
sudo chmod 755 /home/ftpuser/upload
Frequently Asked Questions
Why use FTP when SFTP is available?
SFTP is more secure and widely preferred today, but FTP remains necessary in several cases: legacy applications hardcoded for FTP, shared hosting restrictions that prohibit SSH, or non-technical users who need simple graphical FTP client support.
What is the purpose of chroot jail?
Chroot jail restricts an FTP user to see and access files only within their home directory. If the FTP server is compromised, an attacker cannot access /etc, /root, or other users' /home directories—a critical containment strategy.
Should I use FTP or FTPS?
Always use FTPS on a production VPS. Plain FTP transmits credentials in cleartext over the network. SFTP is equally secure and often preferred, but if the application requires FTP, FTPS is the next-best option.