Set up SFTP server with PubKey authentication on Linux machine
A couple of weeks back, I had some trouble setting up an SFTP server for a particular use case of mine. What I require was, to set up an SFTP server with some standard security best practices. But what troubled me was, the documents or guides of SFTP setup and other best practices were scattered. After some reading, I listed out the practices that I want to implement. These are those practices:
- Set up an SFTP server
- Create a chroot jail environment for each SFTP user
- Enable public key authentication for users
- Disable password authentication, etc.
After I set up the server, I thought it would be better to create a single document with all the above-mentioned points accomplished so that the next person with this requirement doesn’t need to spend time collecting separate docs or blogs for this purpose. Instead, they can spend time on additional security implementations on top of this.
Let’s begin. . .
What is SFTP?
SFTP stands for SSH File Transfer Protocol. This method uses the cryptographic network protocol called SSH to transfer files over the network. We know, the normal File Transfer Protocol (FTP) facilitates file transfer without any encryption. But transferring confidential files over an unprotected network is like . . . (I’m not completing this sentence). The SFTP server allows users to upload and download files to and from the server using an encrypted channel which makes the communication secure.
After a very basic introduction, we are going to discuss the steps for SFTP setup. Given below are the main steps:
- Set up SFTP server on Linux machine
- Set up SFTP client with PubKey authentication on the client machine
- Setup authorized_keys list on the server machine
- Test the SFTP connectivity from the client machine to server machine
In order to complete this setup, we have commands to execute on the server as well as in the client machine. Let’s start with the server part:
Set up SFTP server on Linux machine
In this step, we are going to set up an SFTP server on an Ubuntu-based Linux machine. As we have used Ubuntu as the OS, the installation commands will be specific to Ubuntu and Debian but the rest of the steps can be followed in any other Linux distributions. If the server is on a remote location, it should have a hostname or a static IP address that is discoverable over the internet. If you are planning to set up an SFTP server inside your organizational network, the private IP address of the server is enough.
These are the steps that we are going to execute for the SFTP server setup.
- Install OpenSSH server on the machine
- Creating Chroot jail environment
- Configure OpenSSH
Install OpenSSH server on the machine

What is OpenSSH? Given below is the definition of OpenSSH by Wikipedia:
OpenSSH (also known as OpenBSD Secure Shell) is a suite of secure networking utilities based on the Secure Shell (SSH) protocol, which provides a secure channel over an unsecured network in a client–server architecture.
We are installing the OpenSSH server on our server machine. Use the below command to install the OpenSSH server.
$ sudo apt update
$ sudo apt install openssh-server
It says that to use SFTP safely, it is best to create groups and users to use the service and only that service. This rule applies to any other services in general too.
Use the command below to create a group in Linux:
(Note: Replace <group-name>
with the name of your choice)
#Syntax:
$ sudo groupadd <group-name>#Example:
$ sudo groupadd sftp-group
Next, we can create a user for SFTP without any interactive shell or login and add it to the group that we just created. (Because the sole purpose of this user is for the SFTP connection.)
#Syntax
$ sudo useradd -G <group-name> -s /sbin/nologin <username>#Example
$ sudo useradd -G sftp-group -s /sbin/nologin sftp-user
The ‘-G’ option adds the mentioned group ‘sftp-group’ as a supplementary group to the user ‘sftp-user’. With the “-s” option, the user gets “/sbin/nologin” as the shell which denies interactive shell access for the user. Next, check whether the home directory is created under path ‘/home’ with the same username. If not, create the home directory for the newly created user by using this command:
#Syntax
$ mkdir /home/<username>#Example
$ mkdir /home/sftp-user
Creating Chroot jail environment
What is chroot jail environment? Given below is the definition of Chroot by ArchLinux wiki:
A chroot is an operation that changes the apparent root directory for the current running process and their children. A program that is run in such a modified environment cannot access files and commands outside that environmental directory tree. This modified environment is called a chroot jail.
We need to provide the ownership of the user’s home directory to the ‘root’ user in order for the chroot jail to work. Use the given commands for that purpose:
#Syntax
$ sudo chown root /home/<username>#Example
$ sudo chown root /home/sftp-user
Here, the group should remain as the primary group of the user as the user needs to access the directory. Also, use the below-mentioned commands to make sure that the created user can also access the home directory.
#Syntax
$ sudo chmod g+rx /home/<username>#Example
$ sudo chmod g+rx /home/sftp-user
As we are setting up the chroot jail environment in this manner, there is a limitation with this setup. Here, the owner of the user’s home directory is the ‘root’ user, so the user doesn't have write permission to the home directory. The user cannot create directories or files inside the home directory directly.
In order to overcome this limitation, we are creating a subdirectory for the user inside this home directory and make the user the owner of it. In this way, the user can manage files and directories within the subdirectory freely. As our main purpose of SFTP is to share files securely, this limitation won’t affect us much. Use the below commands for this purpose.
#Syntax
$ mkdir /home/<username>/<directory-name>
$ chown <username>:<groupname> /home/<username>/<directory-name>#Example
$ mkdir /home/sftp-user/data
$ chown sftp-user:sftp-user /home/sftp-user/data
The above commands create a directory called ‘data’ inside the user’s (sftp-user) home directory. Also, make this user the owner of that directory which enables the user to create files and directories inside that directory.
Configure OpenSSH
Here, we are going to configure OpenSSH with certain requirements. We are going to create a group and configure it for a set of users. We know, we have already created a group called ‘sftp-group’ in the server. Next, we are going to configure OpenSSH by editing the config file. This is the path for OpenSSH config file: ‘/etc/ssh/sshd_config’. Edit the file ‘/etc/ssh/sshd_config’ and include the following line at the end of the file.
Match Group <group-name>
ChrootDirectory /home/%u
ForceCommand internal-sftp
AllowTcpForwarding no
PasswordAuthentication no
X11Forwarding no
Here, the Match block must be the last configuration item in the config file. Any configuration following a Match block overrides the general settings when the Match conditions are met. In the above command, you need to replace the <group-name>
with sftp-group
. The ‘ChrootDirectory’ locks the user into the directory specified as arguments. The “ForceCommand” ensures that the user cannot trigger any other command, but only enter the “internal-sftp” subsystem.
We also need to configure the SFTP subsystem to use ‘internal-sftp’ otherwise ‘external-sftp’ will be used which cannot be found in chroot jail of the user. So, edit the ‘Subsystem’ value with this given value.
Subsystem sftp internal-sftp
If we need to use another port number rather than the default port 22, we can use the ‘Port’ command for that.
#Format
Port <port-number>#Example
Port 3456
Also, given below are some additional config values that I have added to my config file.
PermitRootLogin no
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
As we are going to use Pubkey authentication and also going to remove the password authentication method for this SFTP server, the above-mentioned config values are required. More details about each of those values can be found on its man (manual) page.
After all the config updates are made, it is required to restart the SSH service in order for the edits to take effect. Use the below command for this:
$ sudo systemctl restart sshd
Set up SFTP client with PubKey authentication on the client machine
In this demo, we are using a Linux machine for clients too. The following steps need to be accomplished on the client machine for SFTP connectivity.
- Install OpenSSH client
- Generate Pubkey pair
Install OpenSSH client
Install OpenSSH client on the client machine for SFTP connectivity. Use the below-mentioned command
$ sudo apt install openssh-client
Generate Pubkey pair
Next, we are going to generate Pubkey pair on the client machine for the SFTP connectivity. We are going to create an RSA key-pair with the below command.
#Format
$ ssh-keygen -t <key-type> -f <filename and location>#Example
$ ssh-keygen -t rsa -f sftp-key
The above example generates a key pair named ‘sftp-key’ (private key) and ‘sftp-key.pub’ (public key). The ‘-f’ option helps us to create custom key names and its location. Default keygen creates the file in ‘~/.ssh/’ location with the key name ‘id_rsa’.
Add authorized keys on server machine from the client machine
As we have completed generating client key pairs, our next step is to add the client’s public key into the server’s authorized key list. As the first step, we need to create the ‘authorized_keys’ file on the server machine. Use the commands below for this purpose
#Format
$ mkdir /home/<username>/.ssh
$ sudo chown <username>:<groupname> /home/<username>/.ssh
$ sudo chmod 0700 /home/<username>/.ssh#Example
$ mkdir /home/sftp-user/.ssh
$ sudo chown sftp-user:sftp-user /home/<username>/.ssh
$ sudo chmod 0700 /home/sftp-user/.ssh
The above commands create a directory called ‘.ssh’ inside the user’s home directory. The next command makes the user the owner of that directory and then provides full permission to that user.
(Note: Here, the <groupname> is ‘sftp-user’ itself. Not the group ‘sftp-group’ that we created initially.)
Then, we need to move the public key of the client to the server machine. This can be done either by moving the file from the client machine to the server machine or by creating a file (with any filename) in the server machine and copy the contents in that file from the client.
If the ‘.ssh’ directory doesn’t contain a file named ‘authorized_keys’, create one.
#Move to .ssh directory
$ cd /home/<username>/.ssh#List the directory to check whether 'authorized_keys' file is already present
$ ls#If there is not such file, create it
$ touch authorized_keys
As we have already moved the client machine’s public key to the server, we are going to add the public key to this authorized file. Initially, the ‘authorized_keys’ file will be empty but as a safe method, instead of editing the file, append the public key details into the ‘authorized_keys’ file. Use the commands below:
#Format
$ cat <public-key> >> /home/<username>/.ssh/authorized_keysExample
$ cat sftp-key.pub >> /home/sftp-user/.ssh/authorized_keys
After you added the public key to the authorized keys list, you can remove the public key that you have created or moved.
Test the SFTP connectivity from the client machine to server machine
Here, we are going to test the SFTP connectivity from the client’s machine to the server machine. We are going to access the SFTP server from the client machine where its public key is already been authorized in the server. For the ssh/sftp connection from a Linux machine, the private key needs to be in ‘.pem’ format. As we have created the RSA key via ssh-keygen, we just need to rename the key with ‘.pem’ added. Also, provide necessary permission for this key to ensure your key is not publicly viewable. Use the commands below
#Format
$ mv <private-key> <private-key>.pem
$ chmod 400 <private-key>.pem#Example
$ mv sftp-key sftp-key.pem
$ chmod 400 sftp-key.pem
For connecting to the SFTP server, we require these parameters:
- SFTP port number (if custom port is set up in the config file)
- The private key for authentication
- Username of the SFTP user
- Hostname or IP address of the SFTP server
If we have all these values, we can connect to the server by using the command below:
(Run this command from where the private key resides or give the absolute or relative location of the key file)
#Format
$ sftp -P <port-number> -i <private-key> <username>@<hostname or IP-Address>#Example
$ sftp -P 3456 -i sftp-key.pem sftp-user@<server hostname or IP>
If every parameter that you have passed is correct, you will get connected to the SFTP server.
Voila ! ! !
Next steps
If we need to add more users to the same SFTP server, we can do that by using the same above-mentioned commands themselves. I’m pointing out the steps in a nutshell:
In Client machine:
- Install OpenSSH client on the machine
Follow the steps under the section ‘Install OpenSSH client’ - Generate a key pair for the SFTP connection
(Use the methods under this section ‘Generate Pubkey pair’ for that)
In server machine:
- Create a new user and add the user to the existing SFTP group.
- Create its home directory with the same username under ‘/home’ directory (if not created by default)
- Follow the steps under ‘Creating Chroot jail environment’ for this user
- Follow the steps under ‘Add authorized keys on server machine from the client machine’ for adding the client’s public key to server’s authorized list.