For our Blog Visitor only Get Additional 3 Month Free + 10% OFF on TriAnnual Plan YSBLOG10
Grab the Deal

How to Create FTP on Linux Server in 2026? – (Step by Step Guide)

To create FTP on a Linux server, install the vsftpd package, add an FTP user, harden vsftpd.conf (disable anonymous, chroot users, enable passive mode), open firewall and passive ports, enable TLS for FTPS, then start and test the service with a client like FileZilla. Use SFTP when security or compliance is a priority.

In this guide, you’ll learn how to create FTP on a Linux server securely using vsftpd. We’ll cover Ubuntu/Debian and RHEL/CentOS/Rocky, add users, configure passive mode, enable FTPS, handle firewalls and SELinux, and troubleshoot common errors. As a hosting team at YouStable, we deploy this setup daily on production servers.

What You’ll Need

  • A Linux server (Ubuntu/Debian or RHEL/CentOS/Rocky/AlmaLinux)
  • Root or sudo access
  • Open ports: 21/TCP and a passive range (e.g., 30000–31000/TCP)
  • A domain or server IP
  • Optional: A TLS certificate (self-signed or from Let’s Encrypt) for FTPS

FTP vs SFTP vs FTPS: What to Choose

  • FTP (port 21): Unencrypted; fine for trusted internal networks, not recommended over the internet.
  • FTPS (FTP over TLS): Adds encryption to FTP; works with most GUI clients and legacy workflows.
  • SFTP (SSH File Transfer): Different protocol via SSH (port 22), simpler through firewalls and typically more secure by design. Preferred for modern setups.

We’ll configure vsftpd with TLS (FTPS). If you only need secure file transfer and you already have SSH, consider SFTP as a simpler, safer alternative.

Step-by-Step: Install and Configure vsftpd

Step 1 — Install vsftpd

Ubuntu/Debian:

sudo apt update
sudo apt install -y vsftpd

RHEL/CentOS/Rocky/AlmaLinux:

sudo dnf install -y vsftpd
# or on older systems:
# sudo yum install -y vsftpd

Step 2 — Create an FTP User and Directory

Create a dedicated system user for FTP uploads. Avoid using root.

# Create user and set password
sudo adduser ftpuser
# or on RHEL-based:
# sudo useradd -m ftpuser && sudo passwd ftpuser

# Create an uploads directory and set ownership
sudo mkdir -p /home/ftpuser/uploads
sudo chown ftpuser:ftpuser /home/ftpuser/uploads
sudo chmod 755 /home/ftpuser
sudo chmod 755 /home/ftpuser/uploads

Tip: vsftpd’s chroot mode requires the user’s home directory not be writable. We keep the home non-writable and create a writable subdirectory like uploads.

Step 3 — Secure vsftpd Configuration

Back up the default configuration, then apply a hardened baseline.

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

Add or update these lines:

listen=YES
listen_ipv6=NO

anonymous_enable=NO
local_enable=YES
write_enable=YES

# Chroot users to home; ensure home is not writable (use subdirs for writes)
chroot_local_user=YES
allow_writeable_chroot=NO

# Passive mode for NAT/cloud environments
pasv_enable=YES
pasv_min_port=30000
pasv_max_port=31000

# Security hardening
user_sub_token=$USER
local_root=/home/$USER
hide_ids=YES
use_localtime=YES
utf8_filesystem=YES

# Logging
xferlog_enable=YES
xferlog_std_format=NO
log_ftp_protocol=YES
vsftpd_log_file=/var/log/vsftpd.log

# Restrict which users can log in (create userlist file)
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd.userlist

Register the allowed user:

echo "ftpuser" | sudo tee -a /etc/vsftpd.userlist

Key notes:

  • chroot_local_user=YES locks users into their home directory.
  • allow_writeable_chroot=NO avoids security warnings; keep home non-writable but use writable subfolders.
  • Passive mode is mandatory behind NAT and most cloud networks.
  • userlist_deny=NO means only users listed can log in.

Step 4 — Firewall and Passive Ports

Open port 21 and the passive range you set (30000–31000 in this example). Also allow these in your cloud security group (AWS, Azure, GCP).

UFW (Ubuntu/Debian):

sudo ufw allow 21/tcp
sudo ufw allow 30000:31000/tcp
sudo ufw reload
sudo ufw status

firewalld (RHEL-based):

sudo firewall-cmd --permanent --add-port=21/tcp
sudo firewall-cmd --permanent --add-port=30000-31000/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Step 5 — Enable TLS (FTPS)

Generate a certificate (use Let’s Encrypt for production if you have a domain).

Here we create a self-signed cert:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/vsftpd.key \
  -out /etc/ssl/certs/vsftpd.crt \
  -subj "/C=US/ST=State/L=City/O=Company/OU=IT/CN=$(hostname -f)"

Add TLS settings to /etc/vsftpd.conf:

ssl_enable=YES
rsa_cert_file=/etc/ssl/certs/vsftpd.crt
rsa_private_key_file=/etc/ssl/private/vsftpd.key
allow_anon_ssl=NO
force_local_logins_ssl=YES
force_local_data_ssl=YES
ssl_tlsv1=YES
ssl_tlsv1_1=NO
ssl_tlsv1_2=YES
require_ssl_reuse=NO
ssl_ciphers=HIGH

Note: require_ssl_reuse=NO improves compatibility with many clients.

Step 6 — Start and Enable vsftpd

sudo systemctl enable --now vsftpd
sudo systemctl status vsftpd

Step 7 — SELinux Considerations (RHEL-based)

If SELinux is enforcing, allow user home directories for FTP and mark ports if needed.

# Allow FTP to read/write user home directories
sudo setsebool -P ftp_home_dir on

# If you need full access (less strict):
# sudo setsebool -P ftpd_full_access on

# Label user home directories correctly (usually default is fine)
sudo restorecon -R /home/ftpuser

# If passive ports are custom, label them (if not recognized)
# Install tools:
sudo dnf install -y policycoreutils-python-utils
# Then add passive ports:
sudo semanage port -a -t ftp_port_t -p tcp 30000-31000 || \
sudo semanage port -m -t ftp_port_t -p tcp 30000-31000

Step 8 — Test with CLI and FileZilla

Command line (lftp recommended for FTPS):

lftp -e "set ftp:ssl-force true; set ftp:passive-mode true; ls; bye" \
  -u ftpuser ftp://YOUR_SERVER_IP

FileZilla:

  • Host: your domain or IP
  • Port: 21
  • Protocol: FTP – File Transfer Protocol
  • Encryption: Require explicit FTP over TLS
  • Logon Type: Normal (username/password)
  • Transfer Settings: Passive mode

Optional: Per-User Rules, Bandwidth Limits, and Anonymous Read-Only

Allow Only Specific Users

Already enabled via userlist. Add users as needed:

echo "anotheruser" | sudo tee -a /etc/vsftpd.userlist

Per-User Configuration

Create files under /etc/vsftpd/user_conf/USERNAME to override settings for a specific user.

sudo mkdir -p /etc/vsftpd/user_conf
echo "local_root=/var/www/project1" | sudo tee /etc/vsftpd/user_conf/ftpuser

If you must serve public files, enable anonymous read-only carefully:

anonymous_enable=YES
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_root=/var/ftp/pub

Set permissions:

sudo mkdir -p /var/ftp/pub
sudo chown -R ftp:ftp /var/ftp/pub
sudo chmod -R 755 /var/ftp/pub

Security Hardening Best Practices

  • Prefer SFTP when possible; it’s simpler and secure over SSH.
  • Use FTPS only with TLS enforced (force_local_logins_ssl=YES and force_local_data_ssl=YES).
  • Disable anonymous access on public servers.
  • Use strong, unique passwords or SSH keys (for SFTP).
  • Restrict logins to an allowlist with userlist_enable and userlist_deny=NO.
  • Keep home dirs non-writable; use subfolders for uploads.
  • Enable and monitor logs: /var/log/vsftpd.log.
  • Install Fail2Ban to block brute-force attempts.
  • Patch regularly: keep OS and vsftpd up to date.
  • Back up configuration and test restores.

Basic Fail2Ban jail (example; adjust to your distro):

# Install Fail2Ban
sudo apt install -y fail2ban  # Debian/Ubuntu
# sudo dnf install -y fail2ban  # RHEL-based

# Create a simple jail for vsftpd
sudo tee /etc/fail2ban/jail.d/vsftpd.local >/dev/null <<'EOF'
[vsftpd]
enabled = true
port    = ftp,ftp-data,ftps,30000:31000
filter  = vsftpd
logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 3600
EOF

sudo systemctl enable --now fail2ban

Common Errors and Fixes

  • Connection timed out: Open port 21 and passive range in OS firewall and cloud security groups. Ensure pasv_min_port/pasv_max_port are configured.
  • 530 Login incorrect: Verify user exists, password is correct, and user is in /etc/vsftpd.userlist when userlist_deny=NO. Check PAM config at /etc/pam.d/vsftpd.
  • 500 OOPS: vsftpd: refusing to run with writable root inside chroot: Keep /home/USER non-writable. Set allow_writeable_chroot=NO and use a writable subdirectory.
  • FTPS handshake fails: Ensure require_ssl_reuse=NO and TLS ports are open; client should use “Require explicit FTP over TLS.”
  • Stuck listing directories: Force passive mode in the client and ensure passive ports are allowed.

If you don’t need traditional FTP compatibility, SFTP is easier to secure and firewall. It uses SSH, supports key-based auth, and avoids separate passive ports. You can chroot SFTP users via OpenSSH’s internal-sftp subsystem.

# Example SFTP-only group with chroot
sudo groupadd sftpusers
sudo usermod -aG sftpusers ftpuser
sudo nano /etc/ssh/sshd_config

# Add at the bottom:
Match Group sftpusers
    ChrootDirectory /home/%u
    ForceCommand internal-sftp
    PasswordAuthentication yes
    X11Forwarding no
    AllowTcpForwarding no

sudo chmod 755 /home/ftpuser
sudo systemctl restart ssh

When Managed Hosting Helps

Running FTP/FTPS reliably involves OS updates, TLS, firewalls, SELinux, and ongoing log monitoring. If you’d rather focus on your website or apps, YouStable’s managed Linux VPS and cloud servers come pre-hardened with SFTP/FTPS options, automated backups, and 24×7 support from engineers who do this daily.

FAQ’s

Is FTP or SFTP better for a Linux server?

SFTP is generally better: it’s encrypted by default, simpler to firewall (port 22 only), and integrates with SSH keys. Use FTPS (vsftpd with TLS) if you need legacy FTP compatibility with encryption. Avoid plain FTP over the internet.

Which ports must be open for FTP passive mode?

Open TCP 21 plus a passive port range you define (e.g., 30000–31000). Allow these in both the OS firewall (UFW/firewalld) and any cloud/network security groups. Configure pasv_min_port and pasv_max_port in vsftpd.conf to match.

How do I allow only certain users to log in via FTP?

Enable userlist in vsftpd.conf: userlist_enable=YES, userlist_deny=NO, userlist_file=/etc/vsftpd.userlist. Then add allowed usernames (one per line) to /etc/vsftpd.userlist. Restart vsftpd to apply changes.

How do I fix “refusing to run with writable root inside chroot”?

Ensure the user’s home directory is not writable (chmod 755 /home/USER). Keep uploads in a writable subdirectory like /home/USER/uploads with proper ownership. Set allow_writeable_chroot=NO to maintain security.

Can I use Let’s Encrypt for FTPS with vsftpd?

Yes. Point rsa_cert_file to /etc/letsencrypt/live/yourdomain/fullchain.pem and rsa_private_key_file to /etc/letsencrypt/live/yourdomain/privkey.pem. Ensure file permissions allow vsftpd to read them, then restart vsftpd. Renewals are automatic with certbot.

With the above steps, you can create FTP on a Linux server that’s fast, secure, and production-ready. If you prefer a turnkey setup with expert monitoring, YouStable’s managed hosting team can implement and maintain FTPS/SFTP for you.

Sanjeet Chauhan

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top