Server Management
How to Set Up Secure File Transfers (SFTP and FTPS)
Plain FTP sends your username, password, and files in cleartext, so anyone on the network can read them; it must not be used. The right answer is SFTP, which rides on the OpenSSH you already have, is fully encrypted, and needs nothing installed. This guide sets up a dedicated chrooted SFTP user, and covers FTPS with forced TLS only as an alternative when a legacy client cannot speak SFTP.
Prefer SFTP: Nothing to Install
If OpenSSH is running, SFTP already works over the same encrypted channel as SSH on port 22. Confirm the server is up.
sudo systemctl status ssh --no-pager # OpenSSH provides SFTP automatically, no extra package needed
Create a Dedicated, Restricted SFTP User
Make a user that can transfer files but cannot get a shell, and add it to an sftp-only group.
sudo groupadd sftponly # --shell /usr/sbin/nologin denies an interactive shell; this account is for file transfer only sudo useradd -m -g sftponly -s /usr/sbin/nologin sftpuser sudo passwd sftpuser # or, better, install an SSH key for this user
Set Up the Chroot Directory Ownership
For chroot to work, the chroot root must be owned by root and not writable by the user. Put writable content in a subdirectory the user owns.
# The chroot root itself MUST be root-owned and not group/other writable sudo chown root:root /home/sftpuser sudo chmod 755 /home/sftpuser # Give the user a writable upload area inside the jail sudo mkdir -p /home/sftpuser/upload sudo chown sftpuser:sftponly /home/sftpuser/upload
Lock the User Into an SFTP Chroot
Add a Match block so this user (and the sftponly group) is forced into internal-sftp, chrooted to their home, with no shell, TCP forwarding, or tunneling.
sudo tee /etc/ssh/sshd_config.d/10-sftp.conf > /dev/null <<EOF
Match Group sftponly
ChrootDirectory %h # jail the user to their home directory
ForceCommand internal-sftp # allow only SFTP, never a shell
AllowTcpForwarding no
X11Forwarding no
EOF
sudo sshd -t && sudo systemctl reload ssh # validate config, then reloadVerify the SFTP Connection
Connect with the sftp client. You should land inside the jail and only be able to write under upload.
sftp sftpuser@your_server_ip # At the sftp> prompt: # pwd -> shows / (the chroot, which is really their home) # cd upload -> the only writable place # put localfile.txt # bye
Alternative: FTPS with Forced TLS (vsftpd)
Only if a legacy client truly cannot use SFTP, set up vsftpd with TLS REQUIRED, anonymous access off, and users chrooted. Never enable plain FTP without ssl_enable.
sudo apt update && sudo apt install -y vsftpd sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.backup # Generate a self-signed (or use your real) certificate for the TLS layer sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem sudo tee -a /etc/vsftpd.conf > /dev/null <<EOF anonymous_enable=NO # no anonymous logins, ever local_enable=YES write_enable=YES chroot_local_user=YES # jail each user to their home ssl_enable=YES # turn on TLS force_local_data_ssl=YES # REQUIRE TLS for data transfers (no cleartext fallback) force_local_logins_ssl=YES # REQUIRE TLS for the login/credentials rsa_cert_file=/etc/ssl/private/vsftpd.pem rsa_private_key_file=/etc/ssl/private/vsftpd.pem EOF sudo systemctl restart vsftpd # Firewall: control + passive data ports sudo ufw allow 21/tcp sudo ufw allow 990/tcp sudo ufw allow 40000:50000/tcp
Use SFTP: it is encrypted, already included with OpenSSH, and here it is locked to a chrooted, shell-less user. Plain FTP transmits credentials in cleartext and must never be used; if a legacy client forces your hand, only FTPS with TLS required is acceptable.