Set Up a Basic FTP/Secure FTP Server with vsftpd
Introduction
This guide will walk you through installing and configuring vsftpd for FTP and FTPS (TLS) on a ServerStadium VM or a dedicated server running Ubuntu 24.04. You’ll also set up SFTP access using OpenSSH, create user accounts locked to their own folders, and open only the ports you need.
Note on terminology: “Secure FTP” can mean FTPS (FTP over TLS, handled by vsftpd) or SFTP (SSH File Transfer Protocol, handled by the SSH server). This tutorial covers both.
Prerequisites
- A ServerStadium VM or dedicated server running Ubuntu 24.04 (or similar).
- SSH access with a sudo-capable user.
- A domain (e.g.,
ftp.example.com
) if you plan to enable FTPS with Let’s Encrypt.
Part A — Install vsftpd and Configure FTPS (Explicit TLS)
1) Install packages and create a base directory for FTP users
sudo apt update && sudo apt -y upgrade
sudo apt -y install vsftpd openssl ufw certbot
sudo mkdir -p /srv/ftp/users
sudo chown root:root /srv/ftp
sudo chmod 755 /srv/ftp
2) Prepare vsftpd user allowlist and passive ports
# Only users listed here will be allowed to log in via FTP/FTPS
echo "ftpuser1" | sudo tee -a /etc/vsftpd.userlist
# Open a small passive port range (adjust as needed)
echo "40000 40100" | sudo tee /etc/vsftpd.passive.ports >/dev/null
3) Generate or obtain a TLS certificate
- Recommended (public domain): Use Let’s Encrypt standalone challenge (port 80 must be reachable):
sudo systemctl stop vsftpd
sudo certbot certonly --standalone -d ftp.example.com -m you@example.com --agree-tos -n
Certificates will be under/etc/letsencrypt/live/ftp.example.com/
. - Or self-signed (lab use):
sudo openssl req -x509 -nodes -newkey rsa:4096 -keyout /etc/ssl/private/vsftpd.key -out /etc/ssl/certs/vsftpd.crt -days 825
4) Configure vsftpd
sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.bak
sudo tee /etc/vsftpd.conf >/dev/null <<'EOF'
listen=YES
listen_ipv6=NO
# Local user access
local_enable=YES
write_enable=YES
chroot_local_user=YES
allow_writeable_chroot=YES
# Limit logins to an allowlist
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO
# User home mapping under /srv/ftp/users/$USER
user_sub_token=$USER
local_root=/srv/ftp/users/$USER
# Passive mode (open these in firewall)
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
# If behind NAT, set your public IP:
# pasv_address=203.0.113.10
# TLS (Explicit FTPS via AUTH TLS)
ssl_enable=YES
allow_anon_ssl=NO
force_local_logins_ssl=YES
force_local_data_ssl=YES
# Use Let’s Encrypt paths if obtained; otherwise use self-signed
rsa_cert_file=/etc/letsencrypt/live/ftp.example.com/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/ftp.example.com/privkey.pem
# rsa_cert_file=/etc/ssl/certs/vsftpd.crt
# rsa_private_key_file=/etc/ssl/private/vsftpd.key
# TLS hardening
ssl_tlsv1=NO
ssl_tlsv1_1=NO
ssl_tlsv1_2=YES
require_ssl_reuse=NO
ssl_ciphers=HIGH
# Logging
xferlog_std_format=NO
log_ftp_protocol=YES
EOF
sudo systemctl restart vsftpd
sudo systemctl enable vsftpd
5) Create an FTP/FTPS user (chrooted to their own folder)
sudo adduser --home /srv/ftp/users/ftpuser1 --shell /usr/sbin/nologin ftpuser1
sudo mkdir -p /srv/ftp/users/ftpuser1
sudo chown -R ftpuser1:ftpuser1 /srv/ftp/users/ftpuser1
# Ensure the user is in the allowlist
echo "ftpuser1" | sudo tee -a /etc/vsftpd.userlist
# (Optional) Repeat for additional users
6) Open only required firewall ports
# Control channel (21) + passive range + SSH (for SFTP, Part B)
sudo ufw allow 21/tcp
sudo ufw allow 40000:40100/tcp
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
Part B — Enable SFTP (SSH File Transfer) with Chroot
SFTP uses the SSH server (not vsftpd). We’ll create a restricted SFTP group whose members are locked to their own directories.
# Create an SFTP-only group
sudo groupadd sftpusers
# Create base directories; chroot requires the chroot path to be root-owned and not writable by the user
sudo mkdir -p /srv/sftp
sudo chown root:root /srv/sftp
sudo chmod 755 /srv/sftp
# Example SFTP user
sudo useradd -m -d /srv/sftp/sftpuser1 -s /usr/sbin/nologin -G sftpusers sftpuser1
sudo passwd sftpuser1
# Create a writable subfolder inside the chroot
sudo mkdir -p /srv/sftp/sftpuser1/upload
sudo chown sftpuser1:sftpuser1 /srv/sftp/sftpuser1/upload
sudo chmod 750 /srv/sftp/sftpuser1/upload
Edit the SSH daemon configuration to force SFTP and chroot users in the sftpusers
group:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo tee -a /etc/ssh/sshd_config >/dev/null <<'EOF'
# SFTP-only jail for sftpusers
Subsystem sftp internal-sftp
Match Group sftpusers
ChrootDirectory /srv/sftp/%u
ForceCommand internal-sftp
X11Forwarding no
AllowTcpForwarding no
EOF
sudo systemctl restart ssh
Users in sftpusers
now connect with any SFTP client (port 22) and are jailed to /srv/sftp/<username>
with write access limited to the upload
subfolder.
Connectivity & Client Settings
- FTPS (Explicit): Use your FTP client’s “FTP over TLS (explicit)” mode, host
ftp.example.com
, port21
, enable passive mode, and trust the certificate (Let’s Encrypt recommended). - SFTP: Use the SFTP protocol (not FTP) on host
ftp.example.com
(or your server IP), port22
.
Troubleshooting
- FTPS handshake fails: Verify certificate paths in
/etc/vsftpd.conf
, confirm DNS points to your server, and ensure ports 21 and 40000–40100/tcp are open. - Login denied (FTP): Make sure the username is listed in
/etc/vsftpd.userlist
. - SFTP chroot error: Ensure
/srv/sftp/<user>
is owned byroot:root
and not writable; use a writable subfolder for uploads. - Behind NAT: Set
pasv_address=<public_ip>
in/etc/vsftpd.conf
and forward the passive range on your firewall. - Logs: Check
/var/log/syslog
and/var/log/auth.log
for SSH/SFTP; for vsftpd, enablelog_ftp_protocol=YES
(already set).
Need a quick start? Spin up an instant, low-cost ServerStadium dedicated server and deploy secure file transfer in minutes.
Conclusion
You’ve set up FTP/FTPS with vsftpd and SFTP with OpenSSH, created locked-down user areas, and opened only the necessary ports—perfect for client uploads and internal file exchange. For more help or information about ServerStadium services, visit our knowledge base or the ServerStadium website.