SSH & ACCESS
August 21, 2026

How to Set Up SFTP Access on Your Server

7 min read
Author
CloudStick Team
DevOps Engineer
Share this article
How to Set Up SFTP Access on Your Server
CloudStick
SFTP
Access

SFTP Runs Over SSH, Not FTP

SFTP (SSH File Transfer Protocol) is not a secure variant of FTP — it's a completely different protocol that tunnels file transfers through an existing SSH connection. That distinction matters practically: because SFTP rides on SSH, it uses the single TCP port your server already has open for SSH, typically port 22. There's no separate data port range to open, no passive-mode negotiation, and no extra firewall rule to write. Every byte, including the login credentials, is encrypted the same way an SSH terminal session is encrypted. Plain FTP, by contrast, sends credentials and file contents in the clear and needs its own set of ports. If your firewall already allows SSH, it already allows SFTP.

OpenSSH Already Supports SFTP by Default

On a standard Ubuntu or Debian server, the SFTP subsystem is enabled the moment OpenSSH is installed — there's nothing to install separately. You can confirm it by checking the sshd configuration file:

grep -i subsystem /etc/ssh/sshd_config
Subsystem sftp /usr/lib/openssh/sftp-server

That single line is the entire "server" side of SFTP. Any user with a normal SSH login can already open an SFTP session against your server today — the work in this guide is about creating a user who can transfer files without also getting a full interactive shell or visibility into the rest of the filesystem.

Create a Dedicated SFTP User

Start with a normal system account rather than handing out your own login. Create the user, then override its shell behavior specifically for SFTP rather than blocking shell access outright — a plain /usr/sbin/nologin shell can interfere with the SFTP subsystem in some sshd configurations, so the more reliable approach is ForceCommand internal-sftp, which replaces whatever shell the account has with the SFTP handler for every SSH session that user opens.

sudo adduser sftpuser
# add to the bottom of /etc/ssh/sshd_config
Match User sftpuser
ChrootDirectory /home/sftpuser
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
sudo systemctl reload ssh

The Match User block only applies these restrictions to that one account, so every other SSH login on the server is unaffected. Reloading rather than restarting the ssh service applies the change without dropping any existing connections.

Lock the User to One Directory

ChrootDirectory only takes effect if the ownership on that directory is strict. sshd requires the chroot directory itself, and every directory above it in the path, to be owned by root:root and writable by nobody except the owner — otherwise it will refuse the connection outright rather than silently ignore the setting. Because the chroot root can't be writable by the SFTP user, actual uploads need to happen inside a subdirectory that the user does own.

sudo chown root:root /home/sftpuser
sudo chmod 755 /home/sftpuser
sudo mkdir /home/sftpuser/uploads
sudo chown sftpuser:sftpuser /home/sftpuser/uploads
PREREQUISITE

Get the ownership on /home/sftpuser right before testing anything else. If sshd rejects the chroot because permissions are too loose, the connection just drops with a generic "Connection closed" message and no further detail in the client — the real cause is almost always ownership or write permissions on the chroot path itself, so check that first.

Use Key-Based Authentication

Password-only SFTP accounts are worth avoiding for the same reason password-only SSH accounts are: they're a standing target for brute-force attempts. Give the SFTP user an SSH key pair the same way you would any other account. The detail worth understanding is where authorized_keys has to live relative to the chroot. Chrooting only restricts the filesystem view inside the SFTP session itself — sshd authenticates the connection and reads authorized_keys from the account's real home directory before the chroot is ever applied. That means the key file stays at the normal path, /home/sftpuser/.ssh/authorized_keys, and does not need to sit inside the writable uploads subdirectory or anywhere the chrooted session can see.

WARNING

Don't loosen the ownership on /home/sftpuser or its .ssh directory to make key setup easier. sshd checks strict permissions on .ssh and authorized_keys too — group- or world-writable permissions on either will cause it to silently ignore the key and fall back to password auth, or reject the login entirely depending on your StrictModes setting.

Test It and What to Do Next

Confirm the whole setup from a client machine before handing the account to anyone else:

sftp sftpuser@yourserver

A successful session should drop you at / inside the chroot with only the uploads directory visible and writable — anything else visible means the chroot ownership needs another look. Repeat this for every site or client that needs file access, and the manual steps above — creating the user, writing the Match User block, fixing ownership, distributing keys — all repeat identically each time.

CloudStick skips that repetition entirely. When you create a website on a CloudStick-managed server, a scoped SFTP account is provisioned automatically and chrooted to that site's own document root — there's no sshd_config to edit and no ownership chain to double-check by hand. SFTP access is included on every plan, including the free one; plain FTP is available as an add-on on paid plans for cases that specifically call for it, and both are always scoped to a single site's directory rather than the whole server, so one client's file access can never reach another site hosted on the same box.

Leave a comment
Full Name
Email Address
Message
Contents