On this page 27 sections
- What vsftpd is
- Install and start the service
- Main configuration file
- Listen configuration
- Enable local users
- Important: allow local users to upload with put
- Prepare a writable upload directory
- Test put as a local user
- Local umask
- Chroot local users
- Writable chroot compatibility option
- Set a common local root
- Per-user configuration
- Restrict which local users may connect
- Passive FTP
- Firewall rules
- Anonymous read-only access
- Anonymous uploads
- Logging
- Connection limits and timeouts
- Enable TLS for FTPS
- Complete local-user configuration
- Apply and verify changes
- Troubleshoot failed uploads
- Troubleshoot hanging listings or transfers
- FTP client quick reference
- FTP, FTPS and SFTP
What vsftpd is
vsftpd, or Very Secure FTP Daemon, is an FTP server for Unix-like systems. FTP normally uses TCP port 21 for its control connection and a separate data connection for directory listings and file transfers.
Traditional FTP does not encrypt credentials or transferred data. Use FTPS when FTP compatibility is required over an untrusted network, or consider SFTP when SSH-based file transfer is suitable.
Install and start the service
On Debian and Ubuntu, install vsftpd with APT and enable the service at boot.
sudo apt update
sudo apt install vsftpdsudo systemctl enable --now vsftpdsudo systemctl --no-pager --full status vsftpdMain configuration file
The main configuration file is normally /etc/vsftpd.conf. Back it up before making changes.
sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.bak
sudo nano /etc/vsftpd.confgrep -Ev '^[[:space:]]*(#|$)' /etc/vsftpd.confListen configuration
Changing the port does not encrypt or secure FTP. It only changes where the service listens.
listen=YES
listen_ipv6=NO
listen_port=21Enable local users
local_enable=YES allows local Linux accounts to authenticate. Anonymous access can remain disabled when the server is intended only for known users.
anonymous_enable=NO
local_enable=YESsudo adduser ftpuserImportant: allow local users to upload with put
anon_upload_enable is only for anonymous users. It is not required for a local authenticated user to run put.
local_enable=YES
write_enable=YES
local_umask=022Prepare a writable upload directory
The user needs execute permission on every parent directory and write plus execute permission on the destination directory.
sudo install -d -o ftpuser -g ftpuser -m 0750 /home/ftpuser/uploadsnamei -l /home/ftpuser/uploadsTest put as a local user
Avoid placing real passwords directly in a command when shell history or process visibility is a concern. curl -u ftpuser prompts for the password.
echo 'vsftpd upload test' > test.txtftp SERVER_IPcd uploads
put test.txt
lscurl -u ftpuser -T test.txt ftp://SERVER_IP/uploads/Local umask
Use 002 instead when files should remain group-writable in a controlled shared group.
local_umask=022local_umask=002Chroot local users
The safer layout is a non-writable chroot root containing a writable subdirectory. This avoids making the root of the jail writable.
chroot_local_user=YESsudo chown root:root /home/ftpuser
sudo chmod 0755 /home/ftpuser
sudo install -d -o ftpuser -g ftpuser -m 0750 /home/ftpuser/uploadsWritable chroot compatibility option
This option does not enable uploads by itself. write_enable=YES and suitable filesystem permissions are still required.
chroot_local_user=YES
allow_writeable_chroot=YESSet a common local root
If several users share this path, manage ownership and group permissions carefully instead of granting broad world-write permissions.
local_root=/srv/ftp/usersPer-user configuration
user_config_dir allows individual users to override supported directives. Each file inside the directory must have the same name as the Linux account.
user_config_dir=/etc/vsftpd/user_configsudo mkdir -p /etc/vsftpd/user_config
echo 'local_root=/srv/ftp/ftpuser' | sudo tee /etc/vsftpd/user_config/ftpuserRestrict which local users may connect
With userlist_deny=NO, the meaning changes: only users in the file may log in.
userlist_enable=YES
userlist_deny=YES
userlist_file=/etc/vsftpd.user_listecho 'blockeduser' | sudo tee -a /etc/vsftpd.user_listuserlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd.allowed_usersPassive FTP
When the server is behind NAT, advertise the public address or DNS name that clients can reach.
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100pasv_address=ftp.example.com
pasv_addr_resolve=YESFirewall rules
The router or cloud firewall must also forward or permit the same ports when applicable.
sudo ufw allow 21/tcp
sudo ufw allow 40000:40100/tcp
sudo ufw statusAnonymous read-only access
Anonymous FTP can provide public downloads. Keep write access disabled unless there is a clear operational requirement.
anonymous_enable=YES
local_enable=NO
anon_root=/srv/ftp/public
write_enable=NO
no_anon_password=YESsudo install -d -o root -g root -m 0755 /srv/ftp/publicAnonymous uploads
Exact service account and group names vary by distribution. Verify them before applying ownership changes.
anonymous_enable=YES
anon_root=/srv/ftp/anonymous
write_enable=YES
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_umask=022sudo install -d -o root -g root -m 0755 /srv/ftp/anonymous
sudo install -d -o ftp -g nogroup -m 0730 /srv/ftp/anonymous/uploadsLogging
Enable transfer logging for operational troubleshooting and security review. Protocol logging is more verbose and may record sensitive session details, so use it deliberately.
xferlog_enable=YES
log_ftp_protocol=YES
vsftpd_log_file=/var/log/vsftpd.logsudo journalctl -u vsftpd -n 50 --no-pager
sudo tail -n 50 /var/log/vsftpd.logConnection limits and timeouts
Limits can reduce resource exhaustion and abandoned sessions. Choose values that fit the expected number of legitimate users.
max_clients=50
max_per_ip=5
idle_session_timeout=600
data_connection_timeout=120
delay_failed_login=3Enable TLS for FTPS
Use a certificate trusted by clients in production. Available TLS directives can vary by distribution and vsftpd build, so confirm them with the installed manual.
sudo openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-keyout /etc/ssl/private/vsftpd.key \
-out /etc/ssl/certs/vsftpd.crt
sudo chmod 0600 /etc/ssl/private/vsftpd.keyssl_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
ssl_sslv2=NO
ssl_sslv3=NOComplete local-user configuration
Create a writable subdirectory such as /home/ftpuser/uploads; do not assume this configuration alone grants filesystem access.
listen=YES
listen_ipv6=NO
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
chroot_local_user=YES
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
xferlog_enable=YES
log_ftp_protocol=YES
idle_session_timeout=600
data_connection_timeout=120Apply and verify changes
Restart vsftpd, check that it started successfully and confirm that the expected socket is listening.
sudo systemctl restart vsftpd
sudo systemctl --no-pager --full status vsftpd
sudo ss -lntp | grep ':21'sudo journalctl -u vsftpd -n 50 --no-pagerTroubleshoot failed uploads
Common causes include:
write_enable=NOor a missingwrite_enabledirective.- The destination directory is not writable by the authenticated Linux account.
- A parent directory lacks execute permission.
- The FTP user is chrooted somewhere different from the expected path.
- Mandatory access controls such as AppArmor or SELinux deny the operation.
- The filesystem is mounted read-only or has no free space.
grep -E '^(local_enable|write_enable|local_root|local_umask|chroot_local_user|allow_writeable_chroot)=' /etc/vsftpd.confnamei -l /home/ftpuser/uploads
sudo -u ftpuser test -w /home/ftpuser/uploads && echo writable || echo not-writableTroubleshoot hanging listings or transfers
The passive port range must match across vsftpd, the host firewall, any cloud firewall and NAT port forwarding.
grep -E '^pasv_' /etc/vsftpd.conf
sudo ufw status
sudo ss -lntp | grep ':21'FTP client quick reference
These commands run inside an interactive FTP client.
ls
pwd
cd remote-directory
lcd local-directory
get file.txt
put file.txt
mget *.txt
mput *.txt
binary
passive
delete file.txt
mkdir directory
rmdir directory
byeFTP, FTPS and SFTP
- FTP is the traditional protocol, normally using TCP 21, without encryption by default.
- FTPS is FTP protected by TLS and can be served by vsftpd.
- SFTP is the SSH File Transfer Protocol, normally using TCP 22.
SFTP is not FTP over TLS and is not provided by vsftpd.