Introduction: Why File Transfer Protocol Choice Matters
Every website, application, and server deployment involves moving files between machines. Whether you are uploading your latest WordPress theme, deploying application code, or backing up critical data, you need a reliable file transfer protocol. For decades, FTP (File Transfer Protocol) has been the default choice. But in today's security-conscious environment, SFTP (SSH File Transfer Protocol) has emerged as the superior alternative.
The difference between these two protocols is not just academic — it directly impacts whether your credentials travel across the internet in plain text or inside an encrypted tunnel. In this comprehensive guide, we will explore how each protocol works at a technical level, compare their security models, walk through complete setup guides for both ProFTPD and OpenSSH SFTP, and help you make the right choice for your infrastructure.
Understanding FTP: The Legacy Protocol
How FTP Works Under the Hood
FTP was designed in 1971 (RFC 114) and formalized in RFC 959 in 1985 — long before encryption was a standard concern. It operates on a client-server model using two separate TCP connections:
Control Channel (Port 21)
Carries all commands and responses between client and server. Authentication (USER/PASS commands), directory listing requests, and transfer initiation happen here. This channel stays open throughout the entire session.
Data Channel (Port 20 or dynamic)
Carries the actual file data and directory listings. A new data connection is established for each file transfer or directory listing operation. This channel opens and closes repeatedly during a session.
Active Mode vs Passive Mode
FTP has two connection modes that determine how the data channel is established. Understanding this distinction is critical for firewall configuration and troubleshooting:
| Mode | How It Works | Firewall Impact | Common Usage |
|---|---|---|---|
| Active Mode | Client sends PORT command with its IP and port number. Server connects FROM port 20 TO the client on that port. | Requires client to accept incoming connections — blocked by most NAT routers and firewalls | Rare in modern setups |
| Passive Mode | Client sends PASV command. Server responds with an IP and port. Client connects TO the server on that port. | All connections are initiated by the client — works through NAT/firewalls naturally | Standard for all modern FTP clients |
The FTP Authentication Flow (Unencrypted)
Here is what happens when a client connects to an FTP server — pay close attention to what travels in plain text over the network:
to port 21
Ready
plain text
plain text
successful
Every command, including the password, travels as readable ASCII text. A network sniffer running tcpdump -A -i eth0 port 21 would capture the complete credentials in seconds. This fundamental design flaw is why FTP is considered insecure for any environment where network traffic might be intercepted — which is essentially every production environment.
FTP Command Reference
FTP uses a simple text-based command protocol. Here are the most common commands you will see in server logs and packet captures:
| Command | Purpose | Example |
|---|---|---|
| USER | Send username | USER webadmin |
| PASS | Send password | PASS mypassword123 |
| LIST | List directory contents | LIST /public_html |
| RETR | Download a file | RETR index.html |
| STOR | Upload a file | STOR style.css |
| DELE | Delete a file | DELE old-backup.zip |
| MKD | Create directory | MKD uploads |
| PASV | Enter passive mode | PASV |
| QUIT | Close connection | QUIT |
Understanding SFTP: The Encrypted Alternative
How SFTP Works
SFTP is not FTP over SSH — it is a completely different binary protocol that runs as a subsystem of the SSH protocol. It was designed from the ground up as part of the SSH-2 protocol specification. SFTP uses a single encrypted connection on port 22 (the standard SSH port), which makes it dramatically simpler to firewall and manage compared to FTP's multi-port architecture.
The SFTP Authentication Flow (Fully Encrypted)
to port 22
encrypted
encrypted
encrypted
encrypted
The entire session — from the initial handshake through authentication and all file transfers — is encrypted using modern algorithms like AES-256-GCM or ChaCha20-Poly1305. Even if an attacker captures every packet, they see only encrypted bytes with no practical way to recover the original content.
SFTP Authentication Methods
SFTP inherits all SSH authentication methods, giving you far more secure options than FTP can offer:
- Password authentication — encrypted in transit (unlike plain FTP where passwords are visible on the wire)
- SSH key pairs — public/private key authentication where no password is transmitted at all
- Certificate-based authentication — SSH certificates signed by a trusted Certificate Authority for enterprise environments
- Multi-factor authentication — combine keys with passwords or TOTP tokens for maximum security
Why Single-Port Matters
SFTP's single-port design is a significant operational advantage over FTP:
With SFTP, you open port 22 in your firewall and you are done. With FTP in passive mode, you need port 21 plus a range of thousands of high ports (typically 49152-65534). This massive port range creates a larger attack surface and more complex firewall rules. In containerized and cloud environments where port management is automated, SFTP's simplicity becomes even more valuable.
Complete Security Comparison
| Security Feature | FTP | FTPS | SFTP |
|---|---|---|---|
| Credential encryption | None | TLS | SSH |
| Data encryption | None | TLS | SSH |
| Key-based auth | Not supported | Client certificates | SSH keys (simple) |
| Ports required | 21 + passive range | 990 + passive range | 22 only |
| Firewall complexity | Complex | Complex | Simple |
| Chroot / jail support | Yes | Yes | Yes |
| Data integrity | None | TLS MAC | SSH HMAC |
| MITM protection | None | If cert verified | Host key pinning |
| Compliance (PCI-DSS) | Fails | Passes | Passes |
Setting Up ProFTPD: Complete FTP Server Guide
If you need to support legacy FTP clients or applications that require FTP specifically, ProFTPD is one of the most configurable FTP servers available for Linux. Below is a complete setup guide from installation through production hardening.
Reading package lists... Done
Setting up proftpd-basic (1.3.8+dfsg-4) ...
Edit /etc/proftpd/proftpd.conf with these essential settings:
ServerName "My FTP Server"
ServerType standalone
DefaultServer on
Port 21
UseReverseDNS off
IdentLookups off
# Passive mode port range
PassivePorts 49152 65534
MasqueradeAddress YOUR_SERVER_IP
# Security settings
DefaultRoot ~
RequireValidShell off
MaxInstances 30
MaxLoginAttempts 3
TimeoutIdle 600
TimeoutNoTransfer 300
# Logging
TransferLog /var/log/proftpd/xferlog
SystemLog /var/log/proftpd/proftpd.log
For hosting environments, create virtual FTP users independent of system accounts:
$ /usr/bin/ftpasswd --passwd --name=webuser1 --uid=1001 \
--gid=1001 --home=/var/www/site1 --shell=/usr/sbin/nologin \
--file=/etc/proftpd/ftpd.passwd
# Create virtual group
$ /usr/bin/ftpasswd --group --name=ftpusers --gid=1001 \
--member=webuser1 --file=/etc/proftpd/ftpd.group
Add authentication directives to proftpd.conf:
AuthGroupFile /etc/proftpd/ftpd.group
AuthOrder mod_auth_file.c
At minimum, enable TLS encryption to protect credentials in transit:
$ sudo openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /etc/ssl/private/proftpd.key \
-out /etc/ssl/certs/proftpd.crt
TLS module configuration:
<IfModule mod_tls.c>
TLSEngine on
TLSProtocol TLSv1.2 TLSv1.3
TLSCipherSuite HIGH:!aNULL:!MD5
TLSRSACertificateFile /etc/ssl/certs/proftpd.crt
TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key
TLSRequired on
</IfModule>
$ sudo ufw allow 49152:65534/tcp
$ sudo ufw reload
Firewall reloaded
Setting Up OpenSSH SFTP with Chroot Jails
SFTP is built into OpenSSH, which is already installed on virtually every Linux server. Setting up isolated SFTP access with chroot jails is straightforward and provides far better security than any FTP configuration.
$ sudo groupadd sftpusers
# Create a user with no shell access
$ sudo useradd -m -g sftpusers -s /usr/sbin/nologin sftpuser1
$ sudo passwd sftpuser1
# Critical: chroot directory MUST be owned by root
$ sudo chown root:root /home/sftpuser1
$ sudo chmod 755 /home/sftpuser1
# Create writable subdirectory for the user
$ sudo mkdir -p /home/sftpuser1/files
$ sudo chown sftpuser1:sftpusers /home/sftpuser1/files
/ must be owned by root and not writable by any other user or group. If this requirement is not met, SSH will refuse the connection with "fatal: bad ownership or modes for chroot directory." The user's writable area must be a subdirectory inside the chroot.
Subsystem sftp internal-sftp
Match Group sftpusers
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
AllowAgentForwarding no
Key directives explained:
- ChrootDirectory %h — locks the user into their home directory, preventing access to system files
- ForceCommand internal-sftp — prevents shell access entirely; only SFTP operations are allowed
- AllowTcpForwarding no — prevents SSH tunnel abuse through the SFTP account
- internal-sftp — uses the built-in SFTP server (faster and more secure than external sftp-server binary)
$ sudo sshd -t
(no output means configuration is valid)
# Test the SFTP connection
$ sftp sftpuser1@localhost
Connected to localhost.
sftp> pwd
Remote working directory: /
sftp> ls
files
sftp> cd /etc
Couldn't canonicalise: No such file or directory
The last command confirms the chroot is working — the user cannot access directories outside their jail.
$ ssh-keygen -t ed25519 -f ~/.ssh/sftp_key -C "sftp access"
# Copy public key to server
$ sudo mkdir -p /home/sftpuser1/.ssh
$ sudo cp ~/.ssh/sftp_key.pub /home/sftpuser1/.ssh/authorized_keys
$ sudo chown -R sftpuser1:sftpusers /home/sftpuser1/.ssh
$ sudo chmod 700 /home/sftpuser1/.ssh
$ sudo chmod 600 /home/sftpuser1/.ssh/authorized_keys
# Connect with key — no password needed
$ sftp -i ~/.ssh/sftp_key sftpuser1@server
File Permissions Reference
| Path | Owner | Permission | Reason |
|---|---|---|---|
| /home/user (chroot root) | root:root | 755 | SSH chroot requires root ownership |
| /home/user/files | user:group | 755 | User's actual working directory |
| /home/user/.ssh | user:group | 700 | SSH refuses if group/world readable |
| /home/user/.ssh/authorized_keys | user:group | 600 | SSH refuses if group/world readable |
| Uploaded files | user:group | 644 | Web server can read, owner can write |
| Uploaded directories | user:group | 755 | Web server can traverse |
ForceCommand internal-sftp -u 0022. This ensures new files automatically receive 644 permissions and directories receive 755 permissions.
Automation and Scripting
FTP Automation with lftp
lftp -u "$FTP_USER,$FTP_PASS" "$FTP_HOST" <<CMD
set ssl:verify-certificate false
mirror --reverse --delete --verbose \
./public_html/ /var/www/site/
bye
CMD
SFTP/SSH Automation with rsync (Recommended)
rsync -avz --delete \
-e "ssh -i ~/.ssh/deploy_key" \
./public_html/ user@server:/home/user/files/public_html/
# Single file with scp
scp -i ~/.ssh/deploy_key ./config.php user@server:/home/user/files/
CI/CD Pipeline Integration
- name: Deploy via SFTP
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SFTP_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "dist/*"
target: "/home/user/files/public_html"
FTPS: The Middle Ground
Explicit FTPS (FTPES)
Client connects to port 21, then issues AUTH TLS to upgrade the connection. If the server does not support TLS, the client can optionally fall back to plain FTP. This is the preferred and more widely supported method.
Implicit FTPS
Client connects to port 990, and TLS is required from the very start. There is no negotiation or downgrade possibility. Less common but prevents downgrade attacks entirely.
Performance Comparison
| Metric | FTP | FTPS | SFTP |
|---|---|---|---|
| Connection setup | Fast | TLS adds latency | SSH adds latency |
| Bulk transfer | Fastest | Near FTP | ~5-15% slower |
| Many small files | New conn per file | TLS + new conn | Single channel |
| CPU overhead | Minimal | TLS encryption | SSH encryption |
| Resume support | Yes | Yes | Yes |
Making Your Decision
Troubleshooting Common Issues
SFTP: "bad ownership or modes"
Chroot directory must be owned by root with permissions 755. Verify with: namei -l /home/sftpuser1
FTP: Passive mode timeout
Passive port range not open in firewall, or MasqueradeAddress not set to the server public IP.
SFTP: "Permission denied (publickey)"
Check .ssh (700) and authorized_keys (600) permissions. Verify key format and ownership.
FTP: "530 Login incorrect"
Virtual user AuthUserFile path may be wrong. Check /var/log/proftpd/proftpd.log.
How Panelica Handles File Transfer
Each Panelica user automatically receives:
- Isolated SFTP access with chroot jails preventing visibility of other accounts
- ProFTPD virtual user for legacy clients requiring FTP protocol compatibility
- Automatic file permissions with correct ownership and modes during user creation
- Per-user resource limits where FTP/SFTP connections count toward cgroup allocation
- Zero manual SSH configuration — the panel manages Match blocks, chroot directories, and keys
Conclusion
The choice between FTP and SFTP in 2026 is unambiguous: SFTP should be your default for everything. It provides strong encryption, uses a single port, supports superior authentication methods, and is already available on every Linux server through OpenSSH. FTP remains available for legacy compatibility, but it should always be wrapped in TLS if it must be used at all. Your credentials, your files, and your users deserve the protection that encryption provides. Plain-text FTP belongs in the history books.