How can we help?
Categories
< All Topics
Print

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, port 21, 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), port 22.

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 by root: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, enable log_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.

Table of Contents