How To Install FTP Server on Ubuntu 26.04 LTS

Install FTP Server on Ubuntu 26.04

If you manage a Linux server and need to move files between machines, setting up a reliable FTP server is one of the first tasks on your list. Whether you are a beginner running your first Ubuntu server or a developer deploying a file-sharing solution for a team, this guide walks you through exactly how to install FTP Server on Ubuntu 26.04 LTS from scratch. You will get a fully working, hardened vsftpd setup with firewall rules and encrypted FTPS support by the time you reach the end.

Ubuntu 26.04 LTS, codenamed Resolute Raccoon, ships with Linux kernel 7.0 and receives five full years of official security updates from Canonical. That makes it an ideal base for long-term server deployments. This tutorial covers every step in sequence: installing vsftpd, creating a dedicated FTP user, applying a chroot jail, configuring passive mode ports, opening the firewall, and enabling TLS encryption. Every command includes a plain-language explanation of what it does and why it matters, not just a block of text to copy and paste blind.

What Is FTP and Why Use vsftpd?

File Transfer Protocol (FTP) is a TCP-based protocol designed specifically for transferring files between a client and a server. It uses two separate channels: port 21 handles authentication and commands, while port 20 (or a negotiated passive port) handles the actual data transfer. That two-channel design dates back to RFC 959 and is why FTP behaves differently from a single-port protocol like SSH.

On Ubuntu, vsftpd (Very Secure FTP Daemon) is the recommended FTP server package. It lives in the official Ubuntu repository, has an extremely small attack surface by design, and gets patched with each Ubuntu security update cycle. Compared to alternatives like ProFTPD or Pure-FTPd, vsftpd is simpler to configure for standard use cases and performs well under high connection loads.

One important concept to understand before you start is passive mode. In active mode, the server tries to initiate the data connection back to the client. Most clients sit behind a NAT router or firewall and cannot accept incoming connections, so the server needs to open a data port instead and wait for the client to connect. That is what passive mode does, and it is why you will configure a specific passive port range later.

Prerequisites

Before you run a single command, confirm your environment matches these requirements:

  • Operating System: Ubuntu 26.04 LTS (Resolute Raccoon), fresh install recommended
  • User privileges: A non-root user with sudo access (running everything as root is a security anti-pattern)
  • SSH access: Terminal access to the server via SSH
  • Firewall: UFW installed and active (default on Ubuntu Server)
  • FTP client: FileZilla or any FTP client on your local machine for testing
  • Network: A static or known IP address for the server

Step 1: Update Your System Before Installing Anything

The first thing any experienced sysadmin does before installing new software is update the package index and apply pending upgrades.

sudo apt update && sudo apt upgrade -y

What this does: apt update refreshes the local package database against Ubuntu’s official mirrors. Without it, apt install may pull an outdated version of vsftpd. apt upgrade -y applies pending patches to existing packages.

Why it matters: Installing vsftpd on a system with an unpatched OpenSSL version is a real security risk, especially for a server that will be reachable on port 21. Spending 60 seconds here saves hours of troubleshooting later.

Expected output: You will see a list of packages being updated, ending with a line similar to:

0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

If a kernel update was applied, reboot before continuing:

sudo reboot

Step 2: Install vsftpd

With the system up to date, install vsftpd from the Ubuntu repository:

sudo apt install vsftpd -y

What this does: Downloads and installs the vsftpd binary, creates the default configuration file at /etc/vsftpd.conf, and registers vsftpd as a systemd service.

Verify the Installation

Confirm vsftpd installed correctly and check its version:

vsftpd -v

Check that the service started automatically:

sudo systemctl status vsftpd

Expected output:

vsftpd.service - vsftpd FTP server
     Loaded: loaded (/lib/systemd/system/vsftpd.service; enabled; vendor preset: enabled)
     Active: active (running) since ...

Enable vsftpd at Boot

sudo systemctl enable vsftpd

Why this matters: Without this command, a server reboot after a kernel update will leave your FTP service silently offline. It is one of the most common oversights in production deployments.

Step 3: Back Up the Default Configuration File

Never edit a config file without keeping a backup first. This rule has saved countless sysadmins from reinstalling packages after a bad edit.

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

What this does: Creates an exact copy of the original vsftpd configuration file with a .bak extension.

Why it matters: The default /etc/vsftpd.conf file is heavily commented and acts as inline documentation. If a misconfiguration breaks FTP access completely, you can restore the backup in seconds instead of hunting for the correct syntax:

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

Step 4: Create a Dedicated FTP User and Directory Structure

Running FTP under your main admin account is a security mistake. Create a separate user specifically for FTP access so that even if the account is compromised, the attacker cannot reach system-level operations.

Create the FTP User

sudo adduser ftpuser

Follow the prompts to set a password. You can skip the optional fields (Full Name, Room Number, etc.) by pressing Enter.

Build the Directory Structure

sudo mkdir -p /home/ftpuser/ftp/upload
sudo chown nobody:nogroup /home/ftpuser/ftp
sudo chmod a-w /home/ftpuser/ftp
sudo chown ftpuser:ftpuser /home/ftpuser/ftp/upload

Why each command exists:

  • mkdir -p /home/ftpuser/ftp/upload creates both the chroot root directory and the upload subdirectory in one shot.
  • chown nobody:nogroup /home/ftpuser/ftp assigns ownership of the chroot root to a non-privileged system account. vsftpd strictly requires that the chroot root directory is not writable by the FTP user. Skipping this causes the infamous error: 500 OOPS: vsftpd: refusing to run with writable root inside chroot().
  • chmod a-w /home/ftpuser/ftp removes write permission for everyone on the chroot root, satisfying vsftpd’s security check.
  • chown ftpuser:ftpuser /home/ftpuser/ftp/upload gives the FTP user ownership of only the upload subdirectory, which is where actual file transfers happen.

Add a Test File

Place a test file in the upload directory so you have something to verify during the connection test:

echo "FTP Server on Ubuntu 26.04 LTS is working." | sudo tee /home/ftpuser/ftp/upload/test.txt

Step 5: Configure vsftpd on Ubuntu 26.04 LTS for Secure FTP Server Setup

This is the most important step in the entire guide. The default vsftpd configuration is intentionally minimal, and you need to tune it for both functionality and security.

Open the config file:

sudo nano /etc/vsftpd.conf

Find and update the following directives. If a directive does not exist, add it at the bottom of the file.

Core Access Directives

anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022

What each directive does and why:

  • anonymous_enable=NO: Disables anonymous logins so that random internet users cannot connect without credentials.
  • local_enable=YES: Allows local system users (like ftpuser) to authenticate via FTP. Without this, no one can log in.
  • write_enable=YES: Permits upload operations. Without this, the server is read-only and users cannot transfer files to it.
  • local_umask=022: Sets default permissions for uploaded files to 644 (owner read/write, group and others read-only). This prevents world-writable files from landing on your server.

Chroot Jail Directives

chroot_local_user=YES
allow_writeable_chroot=YES
user_sub_token=$USER
local_root=/home/$USER/ftp

Why chroot matters: chroot_local_user=YES locks each user inside their home directory. Without it, an authenticated user can type cd / and freely browse your entire filesystem including /etc, /var, and /home. This is the single most important security directive in vsftpd.

allow_writeable_chroot=YES is needed here because we are using the home directory as the chroot root. The alternative is the sub-directory method, which is what you set up in Step 4 (the ftp directory with the upload subdirectory).

Passive Mode Directives

pasv_enable=YES
pasv_min_port=40000
pasv_max_port=50000

Why passive mode needs explicit port ranges: If you leave pasv_min_port and pasv_max_port undefined, vsftpd picks random high ports for data connections. Your UFW firewall will block those random ports, and clients will connect successfully on port 21, see a directory listing begin, and then hang indefinitely. Defining the range explicitly lets you open exactly the right ports in UFW.

User Allowlist Directives

userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO

What this does: Activates an allowlist. Only users whose names appear in /etc/vsftpd.userlist can log in. Setting userlist_deny=NO is critical because it inverts the default behavior. If you set it to YES, the list acts as a blocklist and everyone on it gets denied.

Add ftpuser to the allowlist:

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

Logging Directives

xferlog_enable=YES
xferlog_file=/var/log/vsftpd.log

Why logging matters: Every upload and download gets recorded in /var/log/vsftpd.log. This is your primary diagnostic tool when a connection fails silently and your only audit trail if a file transfer goes wrong.

Save and close the file: Ctrl + X, then Y, then Enter.

Step 6: Configure UFW Firewall Rules for FTP Server on Ubuntu 26.04 LTS

Open the ports vsftpd needs to function:

sudo ufw allow 20/tcp
sudo ufw allow 21/tcp
sudo ufw allow 40000:50000/tcp
sudo ufw reload
sudo ufw status

Why each port is opened:

  • Port 21 (command channel): Every FTP session starts here. Blocking it makes the server unreachable.
  • Port 20 (data channel, active mode): Required for active mode transfers. Even when passive mode is the primary method, opening port 20 provides a reliable fallback.
  • Ports 40000:50000 (passive data range): These must match the pasv_min_port and pasv_max_port values you set in vsftpd.conf exactly.

Expected output of sudo ufw status:

Status: active

To                         Action      From
--                         ------      ----
20/tcp                     ALLOW       Anywhere
21/tcp                     ALLOW       Anywhere
40000:50000/tcp            ALLOW       Anywhere

If you want to restrict FTP access to a specific IP range (recommended for production), use:

sudo ufw allow from 192.168.1.0/24 to any port 21

This blocks the entire public internet from port 21 and limits access to your internal network subnet.

Step 7: Restart vsftpd and Test the Connection

Apply all configuration changes by restarting the service:

sudo systemctl restart vsftpd
sudo systemctl status vsftpd

Confirm the service shows Active: active (running) before testing.

Test With FileZilla

Open FileZilla and enter the following connection details:

  • Host: ftp://YOUR_SERVER_IP
  • Username: ftpuser
  • Password: (the password you set in Step 4)
  • Port: 21

Click Quickconnect. You should see the /home/ftpuser/ftp directory structure and the test.txt file you created earlier. Try uploading a small file to the upload folder to confirm write access works correctly.

Step 8: Enable FTPS for Encrypted FTP Server Transfers

Plain FTP sends your username, password, and file data in cleartext. Anyone on the same network segment can intercept those credentials with a basic packet sniffer. FTPS (FTP Secure) wraps the FTP session in TLS to fix that.

Generate a Self-Signed SSL Certificate

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/vsftpd.key \
  -out /etc/ssl/certs/vsftpd.crt

Fill in the prompts (country code, organization name, etc.). The values do not affect functionality for a self-signed certificate.

Why RSA 2048-bit: NIST currently considers 2048-bit RSA the minimum acceptable key length. Keys below this are cryptographically weak and should not be used for any server handling real data.

Add SSL Directives to vsftpd.conf

sudo nano /etc/vsftpd.conf

Add these lines at the bottom:

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

Why ssl_sslv2=NO and ssl_sslv3=NO: SSLv2 and SSLv3 are both cryptographically broken. SSLv3 is vulnerable to the POODLE attack, and SSLv2 is vulnerable to DROWN. Explicitly disabling both prevents any client from negotiating a downgrade to these protocols.

Why force_local_data_ssl=YES and force_local_logins_ssl=YES: These two directives reject unencrypted connections. Without them, a misconfigured client could still connect over plaintext FTP even with SSL enabled.

Open the FTPS Port and Restart

sudo ufw allow 990/tcp
sudo systemctl restart vsftpd

Port 990 is the standard FTPS (implicit TLS) port. In FileZilla, change the protocol to FTP over TLS (FTPS) and connect on port 990 to test.

Troubleshooting Common FTP Server Issues on Ubuntu 26.04 LTS

Even a careful setup can run into issues. Here are the five most common problems and their exact fixes.

Error 1: 500 OOPS: vsftpd: refusing to run with writable root inside chroot()

This means the chroot root directory is writable by the FTP user. vsftpd refuses to start in this state by design.

Fix:

sudo chmod a-w /home/ftpuser/ftp

Or add allow_writeable_chroot=YES to /etc/vsftpd.conf if you intentionally need the chroot root to be writable.

Error 2: Connection hangs after directory listing starts

This is almost always a passive mode port mismatch. The client connects on port 21, authenticates, and then vsftpd tries to open a data port that UFW is blocking.

Fix: Confirm that pasv_min_port and pasv_max_port in /etc/vsftpd.conf match the UFW range exactly, and that the UFW rule is active:

sudo ufw status | grep 40000

Error 3: 530 Login incorrect for a valid system user

The user exists on the system but vsftpd is rejecting the login. This is usually an allowlist misconfiguration.

Fix: Check /etc/vsftpd.userlist for the username and confirm userlist_deny=NO is set in vsftpd.conf:

cat /etc/vsftpd.userlist
grep userlist_deny /etc/vsftpd.conf

Error 4: vsftpd fails to start after editing vsftpd.conf

vsftpd does not print friendly syntax errors. It just fails silently in systemctl status.

Fix: Run vsftpd directly in the terminal to expose the problem line:

sudo vsftpd /etc/vsftpd.conf

If you cannot identify the issue, restore the backup and re-apply changes one directive at a time:

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

Error 5: SSL connection failed in FileZilla with FTPS

This usually means require_ssl_reuse=NO is missing from vsftpd.conf, or the certificate path is wrong.

Fix: Confirm both certificate paths are correct and that require_ssl_reuse=NO is present, then restart vsftpd:

ls -la /etc/ssl/private/vsftpd.key /etc/ssl/certs/vsftpd.crt
sudo systemctl restart vsftpd

[su_box title=”VPS Manage Service Offer” style=”bubbles” box_color=”#000000″ radius=”10″]If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal![/su_box]

r00t is a Linux Systems Administrator and open-source advocate with over ten years of hands-on experience in server infrastructure, system hardening, and performance tuning. Having worked across distributions such as Debian, Arch, RHEL, and Ubuntu, he brings real-world depth to every article published on this blog. r00t writes to bridge the gap between complex sysadmin concepts and practical, everyday application — whether you are configuring your first server or optimizing a production environment. Based in New York, US, he is a firm believer that knowledge, like open-source software, is best when shared freely.

Related Posts