A comprehensive guide to setting up and troubleshooting a secure SFTP server on your Virtual Private Server (VPS). Learn how to securely transfer and manage files from your home computer.
Before diving into the setup, it's essential to understand what SFTP is and why it's the preferred method for secure file transfers to your VPS.
22
, the same port used by SSH.To begin, you'll need to connect to your VPS via SSH. This is usually done using a terminal on Linux/macOS or a client like PuTTY on Windows.
ssh your_username@your_vps_ip_address
Replace your_username
with your VPS login (e.g., root
or your primary user) and your_vps_ip_address
with the actual IP address of your VPS.
Most Linux VPS instances come with OpenSSH server pre-installed, which provides SFTP functionality. Let's verify its presence and status.
sudo apt update
sudo apt install openssh-server -y
sudo systemctl status ssh
sudo yum update
sudo yum install openssh-server -y
sudo systemctl status sshd
If the service is not running, start and enable it to run on boot:
sudo systemctl start ssh # or sshd for CentOS/RHEL
sudo systemctl enable ssh # or sshd for CentOS/RHEL
For enhanced security, it's highly recommended to create dedicated SFTP users with restricted access. This involves "chrooting" them, effectively locking them into a specific directory and preventing access to other parts of your server.
sudo groupadd sftpusers
sudo useradd -m -g sftpusers -s /usr/sbin/nologin sftpuser_name
sudo passwd sftpuser_name
-m
: Creates a home directory for the user.-g sftpusers
: Assigns the user to the sftpusers
group.-s /usr/sbin/nologin
: Prevents the user from logging in via SSH (they can only use SFTP).sftpuser_name
with your desired username.This directory will serve as the SFTP user's "jail." It must be owned by root
and not writable by the SFTP group or any other user. This is crucial for security.
sudo mkdir -p /home/sftpuser_name/sftp_root
sudo chown root:root /home/sftpuser_name
sudo chmod 755 /home/sftpuser_name
This is where your home computer will upload/download files. This directory should be owned by the SFTP user.
sudo mkdir /home/sftpuser_name/sftp_root/uploads
sudo chown sftpuser_name:sftpusers /home/sftpuser_name/sftp_root/uploads
sudo chmod 775 /home/sftpuser_name/sftp_root/uploads
sshd_config
):
Open the SSH configuration file:
sudo nano /etc/ssh/sshd_config
Find the Subsystem sftp
line and change it to:
Subsystem sftp internal-sftp
Then, **add the following block to the very end of the file:**
Match Group sftpusers
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
AllowAgentForwarding no
Match Group sftpusers
: Applies these rules to users in the sftpusers
group.ChrootDirectory %h
: Restricts the user to their home directory (%h
expands to the user's home directory, e.g., /home/sftpuser_name
).ForceCommand internal-sftp
: Forces the use of the SFTP subsystem, preventing shell access.AllowTcpForwarding no
, X11Forwarding no
, AllowAgentForwarding no
: Disable these for enhanced security.Save and close the file (Ctrl+X, Y, Enter in nano).
sudo systemctl restart ssh # or sshd for CentOS/RHEL
If you're using a firewall like UFW (Uncomplicated Firewall) on Ubuntu, ensure port 22 is open to allow SFTP connections.
sudo ufw allow 22/tcp
sudo ufw enable
Important: If you changed your SSH port from the default 22, make sure to open that specific port in your firewall instead.
Now that your SFTP server is configured, you can connect from your home computer using an SFTP client.
sftp
command (Linux/macOS): For command-line users.22
(or your custom SSH port).sftpuser_name
).You should now be connected and only see the contents of the uploads
directory (or any other writable directories you created within the chrooted area).
sftp sftpuser_name@your_vps_ip_address
You'll be prompted for the password. Once connected, you can use commands like ls
, cd
, put local_file
(to upload), and get remote_file
(to download).
If your SSH service fails to start after making configuration changes, you'll see messages like:
May 29 01:31:50 7io systemd[1]: Failed to start ssh.service - OpenBSD Secure Sh>
May 29 01:31:52 7io systemd[1]: ssh.service: Start request repeated too quickly.
May 29 01:31:52 7io systemd[1]: ssh.service: Failed with result 'exit-code'.
This indicates an underlying error preventing the service from launching. Here's how to diagnose and fix it:
The most important step is to find the specific error message:
sudo systemctl status ssh.service
sudo journalctl -xeu ssh.service
Look for lines indicating "Error," "failed to," "permission denied," or "Bad configuration option."
sshd_config
syntax:
sudo sshd -t
This command tests your SSH configuration file for syntax errors. If it outputs errors, fix them in /etc/ssh/sshd_config
.
ChrootDirectory
permissions:
The directory specified as ChrootDirectory
(e.g., /home/sftpuser_name
) and its parent directories must be owned by root:root
and not writable by any other user or group.
ls -ld /home/sftpuser_name
ls -ld /home/sftpuser_name/sftp_root # If this is your actual chroot
Correct permissions if needed (e.g., sudo chown root:root /home/sftpuser_name && sudo chmod 755 /home/sftpuser_name
).
sshd_config
changes: Ensure the Match Group
block is at the very end of the file and free of typos.This specific error means the SSH daemon cannot find or create its temporary directory for privilege separation. This directory is crucial for security.
Context: The /run
directory is a tmpfs
(temporary file system) that is created in RAM at boot, meaning its contents are cleared on every reboot. Normally, systemd
or the OpenSSH package handles its creation.
You can create the directory manually to get SSH running immediately. This is temporary and will be lost on reboot.
sudo mkdir -p /run/sshd
sudo chmod 0755 /run/sshd
sudo chown root:root /run/sshd
sudo systemctl restart ssh
tmpfiles.d
Configuration)If your system doesn't have a default sshd.conf
in /usr/lib/tmpfiles.d/
, you can create one in /etc/tmpfiles.d/
. Files in /etc/tmpfiles.d/
take precedence and are safe from package updates.
sudo nano /etc/tmpfiles.d/sshd.conf
d /run/sshd 0755 root root -
d
: Specifies a directory./run/sshd
: The path.0755
: Permissions.root root
: Owner and group.-
: No age limit for deletion.systemd-tmpfiles
to process the new configuration:
sudo systemd-tmpfiles --create
sudo systemctl restart ssh
sudo systemctl status ssh
It should now show as active (running)
.
RuntimeDirectory
in Service Override)If the `tmpfiles.d` approach doesn't work, or if your SSH service unit already has `RuntimeDirectory=sshd` but still fails due to a race condition, you can force `systemd` to create it earlier in the service startup process.
sudo systemctl edit ssh.service
[Service]
RuntimeDirectory=sshd
sudo systemctl daemon-reload
sudo systemctl restart ssh
Once your SFTP server is operational, follow these best practices to maintain a high level of security:
~/.ssh/authorized_keys
file on the VPS./var/log/auth.log
on Debian/Ubuntu, /var/log/secure
on CentOS/RHEL) for suspicious login attempts or activity.