Configure FTP Server on Linux: vsftpd Complete Guide

FTP (File Transfer Protocol) is used to transfer files between systems over a network. vsftpd (Very Secure FTP Daemon) is the standard FTP server on RHEL/CentOS systems. Port: 21 (control), 20 (data).

FTP Server Profile

Package:       vsftpd
Daemon:        vsftpd
Config file:   /etc/vsftpd/vsftpd.conf
Anonymous dir: /var/ftp/pub
Port:          21 (control), 20 (data in active mode)
Log file:      /var/log/vsftpd.log

Install and Start vsftpd

# yum install vsftpd* -y
# systemctl start vsftpd
# systemctl enable vsftpd
# systemctl status vsftpd

Configure Anonymous FTP Access

# vim /etc/vsftpd/vsftpd.conf

anonymous_enable=YES                  # allow anonymous login
anon_upload_enable=YES                # allow anonymous uploads
anon_mkdir_write_enable=YES           # allow anonymous mkdir
anon_root=/var/ftp/pub                # anonymous root directory

# Set directory permissions:
# chmod 777 /var/ftp/pub

# SELinux boolean for anonymous write:
# setsebool -P allow_ftpd_anon_write 1

# systemctl restart vsftpd

Configure Authenticated User FTP

# vim /etc/vsftpd/vsftpd.conf
local_enable=YES                      # allow local users to log in
write_enable=YES                      # allow write operations
local_umask=022                       # default umask for uploaded files

# Chroot users to their home directory (security):
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list  # users exempt from chroot

# systemctl restart vsftpd

Passive Mode Configuration

Passive mode is required when clients are behind NAT/firewalls. The server opens a high-numbered port for data.

# vim /etc/vsftpd/vsftpd.conf
pasv_enable=YES
pasv_min_port=10000
pasv_max_port=10100
pasv_address=192.168.1.100            # server's public IP

# Open passive port range in firewall:
# firewall-cmd --permanent --add-port=10000-10100/tcp
# firewall-cmd --reload

Secure FTP with TLS (FTPS)

# Generate SSL certificate:
# openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/vsftpd/vsftpd.key \
    -out /etc/vsftpd/vsftpd.crt

# vim /etc/vsftpd/vsftpd.conf
ssl_enable=YES
rsa_cert_file=/etc/vsftpd/vsftpd.crt
rsa_private_key_file=/etc/vsftpd/vsftpd.key
force_local_data_ssl=YES
force_local_logins_ssl=YES

# systemctl restart vsftpd

Allow/Deny Users

# Block specific users (/etc/vsftpd/ftpusers — always denied):
# vim /etc/vsftpd/ftpusers
baduser1
baduser2

# User list control (/etc/vsftpd/user_list):
userlist_enable=YES
userlist_deny=YES   # users IN list are DENIED
# userlist_deny=NO → users IN list are ALLOWED only

Firewall and SELinux for FTP

# RHEL 7 firewall:
# firewall-cmd --permanent --add-service=ftp
# firewall-cmd --reload

# RHEL 6 iptables:
# iptables -A INPUT -p tcp --dport 21 -j ACCEPT
# service iptables save

# SELinux booleans for FTP:
# getsebool -a | grep ftp
# setsebool -P ftp_home_dir 1          # allow access to home dirs
# setsebool -P allow_ftpd_anon_write 1 # allow anonymous write
# setsebool -P ftpd_full_access 1      # full access for authenticated users

FTP Troubleshooting

# Can't connect:
# 1. Check service: systemctl status vsftpd
# 2. Check port 21: ss -tulnp | grep 21
# 3. Check firewall: firewall-cmd --list-all
# 4. Check SELinux: sealert -a /var/log/audit/audit.log
# 5. Check logs: tail -f /var/log/vsftpd.log

# "500 OOPS: vsftpd: refusing to run with writable root inside chroot":
# Add to vsftpd.conf: allow_writeable_chroot=YES

# Test FTP from command line:
# ftp 192.168.1.100
ftp> user anonymous
ftp> ls
ftp> get filename
ftp> bye