To set up FTP on a Linux server, install and configure vsftpd, create a restricted FTP user, open firewall ports (21 and a passive range), enable optional TLS for encryption, and test with an FTP client. This guide shows step-by-step instructions for Ubuntu/Debian and RHEL/CentOS/AlmaLinux with secure, production-ready settings.
If you’re wondering how to set up FTP on a Linux server, you’re in the right place. In this tutorial, I’ll walk you through installing and hardening an FTP server with vsftpd, opening firewall and SELinux rules, enabling FTPS encryption, and testing with FileZilla or lftp. The process is beginner-friendly but follows enterprise-grade best practices I use for production environments.
Before You Begin: FTP vs SFTP and What You Should Choose
FTP is a legacy file transfer protocol that sends data in plain text. SFTP (part of OpenSSH) encrypts traffic end-to-end and is generally preferred for security. If you must use classic FTP for compatibility, always enable TLS (FTPS) to encrypt credentials and data. This guide focuses on vsftpd (very secure FTP daemon) with optional TLS.
What We’ll Use
We’ll deploy vsftpd because it’s fast, stable, and widely available. Steps cover Ubuntu/Debian and RHEL/CentOS/AlmaLinux. We’ll configure passive mode, chroot jails, user allowlists, and (optionally) FTPS so you can pass security scans and work smoothly with GUI clients like FileZilla.
Prerequisites
- A Linux server (Ubuntu 22.04+/20.04+, Debian 11/12, AlmaLinux/RHEL/CentOS 8+)
- Root or sudo privileges
- Firewall access (UFW or firewalld) and, on RHEL-based systems, SELinux tools
- A domain or IP address for clients to connect
Step 1: Install vsftpd
Ubuntu/Debian
sudo apt update
sudo apt install -y vsftpd
sudo systemctl enable --now vsftpd
sudo systemctl status vsftpd
RHEL/CentOS/AlmaLinux
sudo dnf install -y vsftpd policycoreutils-python-utils
sudo systemctl enable --now vsftpd
sudo systemctl status vsftpd
If the service is active, you can proceed to configuration.
Step 2: Back Up and Harden the vsftpd Configuration
Back up the default config and open it for editing:
sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.bak
sudo nano /etc/vsftpd.conf
Use these secure, production-ready settings. Add or update the following lines:
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
# Chroot users into their home
chroot_local_user=YES
allow_writeable_chroot=YES
# Passive mode for firewalls/NAT
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
# Allowlist specific users only
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO
# Improve security hygiene
pam_service_name=vsftpd
seccomp_sandbox=YES
Save and restart:
sudo systemctl restart vsftpd
Step 3: Create a Restricted FTP User
Create a dedicated user and prevent shell access. We’ll also add nologin to /etc/shells so PAM allows FTP logins with that shell.
# Create user and set password
sudo adduser ftpuser
sudo passwd ftpuser
# Restrict shell access
sudo usermod -s /usr/sbin/nologin ftpuser
echo /usr/sbin/nologin | sudo tee -a /etc/shells
# Optional: create a dedicated FTP directory
sudo mkdir -p /home/ftpuser/ftp
sudo chown -R ftpuser:ftpuser /home/ftpuser/ftp
Now allow the user to log in via the allowlist:
echo "ftpuser" | sudo tee -a /etc/vsftpd.userlist
sudo systemctl restart vsftpd
Step 4: Open Firewall Ports (FTP + Passive Range)
UFW (Ubuntu/Debian)
sudo ufw allow 21/tcp
sudo ufw allow 40000:40100/tcp
sudo ufw reload
sudo ufw status
firewalld (RHEL/CentOS/AlmaLinux)
sudo firewall-cmd --permanent --add-service=ftp
sudo firewall-cmd --permanent --add-port=40000-40100/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Using passive mode avoids complex NAT traversal and is recommended for cloud servers behind security groups or load balancers.
Step 5: Configure SELinux for FTP (RHEL-Based Only)
Enable home directory access and passive mode; then inform SELinux about your passive port range:
sudo setsebool -P ftp_home_dir 1
sudo setsebool -P ftpd_use_passive_mode 1
sudo semanage port -a -t ftp_port_t -p tcp 40000-40100 || \
sudo semanage port -m -t ftp_port_t -p tcp 40000-40100
If semanage isn’t found, install the policycoreutils-python-utils package (already covered above).
Step 6: Enable TLS/FTPS Encryption (Recommended)
Encrypting FTP (FTPS) protects credentials and data in transit. Generate a self-signed certificate or use a valid one from your CA.
# Generate a self-signed cert (valid 3 years)
sudo openssl req -x509 -nodes -days 1095 -newkey rsa:2048 \
-keyout /etc/ssl/private/vsftpd.key \
-out /etc/ssl/certs/vsftpd.crt \
-subj "/CN=$(hostname -f)"
# Set permissions
sudo chmod 600 /etc/ssl/private/vsftpd.key
Edit vsftpd.conf and add:
ssl_enable=YES
allow_anon_ssl=NO
force_local_logins_ssl=YES
force_local_data_ssl=YES
rsa_cert_file=/etc/ssl/certs/vsftpd.crt
rsa_private_key_file=/etc/ssl/private/vsftpd.key
# Harden TLS
ssl_sslv2=NO
ssl_sslv3=NO
ssl_tlsv1=YES
require_ssl_reuse=NO
ssl_ciphers=HIGH
Restart the service:
sudo systemctl restart vsftpd
In clients like FileZilla, choose “FTP over TLS (explicit)” to avoid plaintext logins.
Step 7: Test Your FTP Server
Command-Line Test
# Install lftp (recommended)
sudo apt install -y lftp # Ubuntu/Debian
sudo dnf install -y lftp # RHEL/CentOS/AlmaLinux
# Connect (replace server_ip or domain)
lftp -u ftpuser ftp://server_ip
# With FTPS:
lftp -u ftpuser ftps://server_ip
# If certificate is self-signed:
set ssl:verify-certificate no
GUI Test (FileZilla)
- Host: your_server_ip or domain
- Protocol: FTP — if FTPS enabled, select “FTP — TLS (explicit)”
- Port: 21
- Encryption: Require explicit FTP over TLS (recommended)
- Logon Type: Normal, User: ftpuser, Password: your password
Troubleshooting Common FTP Errors
- 530 Login incorrect: Ensure the user is in
/etc/vsftpd.userlist, the password is correct, and/usr/sbin/nologinis listed in/etc/shells. - 500 OOPS: refusing to run with writable root: Keep
allow_writeable_chroot=YESor make the user’s chroot directory non-writable (and use a writable subfolder). - Connection timed out: Open port 21 and passive ports (40000–40100). Check cloud security groups and local firewall.
- TLS handshake/GnuTLS -15: Add
require_ssl_reuse=NOinvsftpd.confand restart. - RHEL-based SELinux denials: Enable
ftp_home_dir,ftpd_use_passive_mode, and assign passive ports withsemanage.
Best Practices to Keep Your FTP Server Secure
- Prefer SFTP or FTPS: Avoid plain FTP logins whenever possible.
- Restrict users: Use
userlist_enable=YESand allow only specific accounts. - Chroot users: Prevent lateral movement by confining users to their home directories.
- Harden passwords: Enforce strong password policies and consider MFA at the app layer.
- Limit exposure: Only open required passive port ranges; avoid wide ranges.
- Monitor logs: Check
/var/log/vsftpd.logand system logs for suspicious activity. - Use Fail2ban: Add a vsftpd jail to block brute-force attempts.
- Automate backups: Regularly back up FTP content to offsite storage.
Quick Alternative: Use SFTP (Built into OpenSSH)
In many cases, SFTP is simpler and more secure. It’s usually enabled by default with SSH. Create a user and connect with an SFTP client on port 22. You can chroot SFTP-only users by editing /etc/ssh/sshd_config with a Match block and restarting sshd. If strict compliance or legacy software mandates FTP, stick with FTPS.
FAQs: How to Set Up FTP on Linux Server
Is FTP or SFTP better for Linux servers?
SFTP is better for security because it encrypts everything via SSH. If you must use FTP for compatibility, use FTPS (FTP over TLS) so credentials and files aren’t exposed in plaintext. Most modern clients support SFTP and FTPS.
Which FTP server should I use on Ubuntu or CentOS?
vsftpd is the most common choice due to its security focus and stability. Alternative servers include ProFTPD and Pure-FTPd, but vsftpd is widely available, easy to harden, and supported by most distributions.
How do I fix “500 OOPS: vsftpd: refusing to run with writable root”?
Either set allow_writeable_chroot=YES in /etc/vsftpd.conf or keep the chroot directory non-writable and create a writable subdirectory (for example, /home/ftpuser/ftp/upload). Then restart vsftpd.
What firewall ports are required for FTP?
Open TCP 21 for control and a passive range (commonly 40000–40100). On RHEL-based systems with SELinux, also map the passive range to the ftp_port_t type with semanage and enable ftpd_use_passive_mode.
How do I enable FTP over TLS (FTPS) on vsftpd?
Generate a certificate, then add ssl_enable=YES, set rsa_cert_file and rsa_private_key_file, disable SSLv2/3, and restart vsftpd. In your client, select “Require explicit FTP over TLS.” This secures credentials and data in transit.
Final Thoughts
You now know how to set up FTP on a Linux server the right way: install vsftpd, lock it down, open the correct firewall/SELinux rules, and enable FTPS for encryption. If you want a faster route with expert hardening and 24/7 help, host on YouStable and let our engineers configure it for you.