AlmaLinux

Configure vsftpd FTP Server on Rocky Linux 10 / AlmaLinux 10

vsftpd (Very Secure FTP Daemon) is the default FTP server on most RHEL-based distributions. It handles file transfers with solid security defaults, chroot jailing, virtual users, and SSL/TLS support. While SFTP over SSH has replaced FTP in many environments, vsftpd remains the go-to choice when you need a dedicated FTP server for legacy applications, automated file drops, or environments where FTP is a hard requirement.

Original content from computingforgeeks.com - post 114170

This guide covers installing and configuring vsftpd on Rocky Linux 10 and AlmaLinux 10 with local user authentication, chroot jailing, passive mode, SELinux configuration, and firewall rules.

Prerequisites

  • Rocky Linux 10 or AlmaLinux 10 with root or sudo access
  • Ports 20-21/TCP (FTP) and a passive port range (30000-31000) open in the firewall

Install vsftpd

vsftpd is available in the default Rocky Linux 10 AppStream repository:

sudo dnf install -y vsftpd ftp

The ftp package is the command-line client, useful for testing. Verify the installed version:

vsftpd -v

Rocky Linux 10 ships vsftpd 3.0.5:

vsftpd: version 3.0.5

Configure vsftpd for Local Users

The main configuration file is at /etc/vsftpd/vsftpd.conf. Back up the default config, then replace it with a production-ready configuration:

sudo cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.bak

Edit the configuration file:

sudo vi /etc/vsftpd/vsftpd.conf

Set the following configuration. This disables anonymous access, enables local user login with write permissions, chroot-jails users to their home directories, and defines a passive port range:

anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
chroot_local_user=YES
allow_writeable_chroot=YES
listen=YES
listen_ipv6=NO
pam_service_name=vsftpd
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd/user_list
pasv_min_port=30000
pasv_max_port=31000

Key settings explained:

  • chroot_local_user=YES – locks users into their home directory so they cannot browse the filesystem
  • userlist_enable=YES with userlist_deny=NO – only users listed in /etc/vsftpd/user_list can log in (whitelist mode)
  • pasv_min_port/pasv_max_port – defines the passive mode port range, needed for clients behind NAT/firewalls
  • allow_writeable_chroot=YES – required since vsftpd 3.0 when the chroot directory is writable

Create FTP Users

Create a system user for FTP access. This user gets a home directory for file uploads:

sudo useradd -m ftpuser
sudo passwd ftpuser

Add the user to the vsftpd whitelist:

echo "ftpuser" | sudo tee -a /etc/vsftpd/user_list

If you want the FTP user to be shell-restricted (cannot SSH into the server), set their shell to /sbin/nologin:

sudo usermod -s /sbin/nologin ftpuser

For /sbin/nologin to work with vsftpd’s PAM authentication, add it to the allowed shells list:

echo "/sbin/nologin" | sudo tee -a /etc/shells

Configure SELinux

Rocky Linux 10 runs SELinux in enforcing mode. vsftpd needs specific SELinux booleans to allow read/write access to user home directories:

sudo setsebool -P ftpd_full_access on

Verify the boolean is set:

getsebool ftpd_full_access

The output should confirm ftpd_full_access --> on. Without this, users will get “permission denied” errors when uploading files even though filesystem permissions look correct.

If you only want FTP users to read files (no uploads), use the more restrictive boolean instead:

sudo setsebool -P ftpd_anon_write off
sudo setsebool -P allow_ftpd_full_access on

Configure Firewall

Open the FTP service port and the passive mode port range in firewalld:

sudo firewall-cmd --permanent --add-service=ftp
sudo firewall-cmd --permanent --add-port=30000-31000/tcp
sudo firewall-cmd --reload

Verify the rules are active:

sudo firewall-cmd --list-all

You should see ftp in the services list and 30000-31000/tcp in the ports list.

Start and Enable vsftpd

Start the vsftpd service and enable it to start on boot:

sudo systemctl enable --now vsftpd

Verify the service is running:

sudo systemctl status vsftpd

Check that vsftpd is listening on port 21:

ss -tlnp | grep vsftpd

Test the FTP Connection

Test from the server itself or from a remote client. Using the command-line FTP client:

ftp 127.0.0.1

Enter the username and password when prompted. After logging in, run pwd to confirm you are chrooted to the home directory, then quit to disconnect.

From a remote machine, replace 127.0.0.1 with the server’s IP address. If the connection times out, check the firewall and verify passive mode port range is open.

Enable SSL/TLS for Secure FTP (FTPS)

Plain FTP sends credentials and data in clear text. For any production use, enable TLS encryption. Generate a self-signed certificate or use an existing one:

sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/pki/tls/private/vsftpd.key -out /etc/pki/tls/certs/vsftpd.pem -subj "/CN=$(hostname)"

Add these TLS directives to the end of /etc/vsftpd/vsftpd.conf:

ssl_enable=YES
ssl_tlsv1_2=YES
ssl_sslv2=NO
ssl_sslv3=NO
rsa_cert_file=/etc/pki/tls/certs/vsftpd.pem
rsa_private_key_file=/etc/pki/tls/private/vsftpd.key
force_local_data_ssl=YES
force_local_logins_ssl=YES
require_ssl_reuse=NO
ssl_ciphers=HIGH

Restart vsftpd to apply TLS:

sudo systemctl restart vsftpd

After enabling TLS, plain FTP clients will be rejected. Use an FTPS-capable client like FileZilla, lftp, or curl with the --ftp-ssl flag.

Troubleshooting

500 OOPS: vsftpd refusing to run with writable root

This happens when chroot_local_user=YES is set but allow_writeable_chroot=YES is missing. Add allow_writeable_chroot=YES to the config and restart.

530 Login incorrect (valid credentials)

Check that the user is listed in /etc/vsftpd/user_list (when using whitelist mode). Also verify the user’s shell is in /etc/shells if using /sbin/nologin.

Permission denied on upload (SELinux)

Check for SELinux denials:

sudo ausearch -m avc -ts recent | grep vsftpd

The fix is usually setsebool -P ftpd_full_access on. For non-default upload directories, set the correct SELinux context:

sudo semanage fcontext -a -t public_content_rw_t "/ftp/uploads(/.*)?"
sudo restorecon -Rv /ftp/uploads

Conclusion

vsftpd is running on your Rocky Linux 10 / AlmaLinux 10 server with local user authentication, chroot jailing, and passive mode configured. For production deployments, always enable TLS to encrypt credentials and file transfers. Consider using SFTP (over SSH) as a simpler alternative if your clients support it – it requires no additional server software and inherits SSH’s encryption and authentication. Refer to the official vsftpd documentation for advanced features like virtual users, bandwidth throttling, and per-user configuration.

Related Articles

CentOS Manage SELinux Status, Context, Ports and Booleans Using Ansible AlmaLinux How To Install WildFly on Rocky Linux 8|AlmaLinux 8 CentOS How To Install NetBox IPAM on Rocky Linux 8 / CentOS 8 AlmaLinux Install VMWare Workstation on Rocky 8 / Alma 8

Leave a Comment

Press ESC to close