How to setup an SFTP server on CentOS

This tutorial explains how to setup and use an SFTP server on CentOS. Before I start, let me explain what actually SFTP represents and what it is used for. Currently, most people know that we can use normal FTP for transferring, downloading or uploading data from a server to client or client to server. But this protocol is getting hacked easily (if TLS is not used) by anonymous intruders as it the ports are widely open to anyone. Therefore, SFTP has been introduced to as another alternative to meet the main purpose to strengthen the security level.

SFTP stands for SSH File Transfer Protocol or Secure File Transfer Protocol. It uses a separate protocol packaged with SSH to provide a secure connection.

1. Preliminary Note

For this tutorial, I am using CentOS 6.4 in the 32bit version. The same steps will work on CentOS 7 as well. The tutorial result will show how a client can be provided with access to the SFTP server but unable to login to the server itself by SSH.

2. Installation Phase

Unlike normal FTP, there’s no need to install additional packages in order to use SFTP. We just require the prebuild SSHd package that got already installed during installation on the server. Therefore, just check to confirm if you already have the required SSH package. Below are the steps:


rpm -qa|grep ssh

The output should be similar to this:

[root@SFTP01 ~]# rpm -qa|grep ssh

That’s all, now we’ll go on how to make the SFTP configuration.

3. Configuration Phase

Once all prerequisites of installation are done, we’ll step over to configuration phase. For best practice, we need to create a group and user so that we can manage all user that shall get SFTP access. But first, let’s create an additional folder called data. Below are the steps:

mkdir -p /data/shahrilk

Basically what I’m trying to do with the above step is to get a separate folder as main directory for the SFTP access. All user directories for the SFTP users will be subdirectories of this data folder.

Let’s create a group for the SFTP user, below are the steps:

groupadd sftpusers

Then create a user and assign it to the SFTPUSERS group. Below are the steps:

useradd -g sftpusers -d /upload -s /sbin/nologin shahrilk
passwd shahrilk

Changing password for user shahrilk.
New password:
BAD PASSWORD: it is based on a dictionary word
Retype new password:
passwd: all authentication tokens updated successfully.

Below is the explanation of the above commands:

  1. I create a user and include the user into sftpusers group using -g command.
  2. I assign the main directory for the user to be in the /upload directory by setting the -d /upload command. This means that later the /upload folder will be under /data/shahrilk/upload.
  3. I limit the access to the /sbin/nologin shell to ensure the user is only able to use the SFTP protocol, not SSH.
  4. I name the user “shahrilk”.
  5. Set password for user “shahrilk”.

Now let’s create the /upload folder under /data/shahrilk, then assign appropriate ownership to the folder.

chown -R shahrilk:sftpusers /data/shahrilk
mkdir -p /data/shahrilk/upload
chown -R shahrilk:sftpusers /data/shahrilk/upload

Once done, verify that the new folder under the directory /data exists and that we made the configuration correct.

[root@SFTP01 ~]# ls -ld /data/
drwx—–x 14 root root 4096 Aug 19 11:13 /data/

[root@SFTP01 ~]# ls -ld /data/shahrilk
drwxr-xr-x 4 shahrilk sftpusers 4096 Jan 19 2016 /data/shahrilk

[root@SFTP01 ~]# ls -ld /data/shahrilk/upload
drwxr-xr-x 2 shahrilk sftpusers 4096 Aug 30 08:42 /data/shahrilk/upload

[root@SFTP01 ~]# cat /etc/passwd|grep shahrilk

Now configure the SSH protocol to create an SFTP process. This can be done by editing the configuration file under /etc/ssh/sshd_config . Below are the steps:

vi /etc/ssh/sshd_config

Subsystem sftp internal-sftp

Match Group sftpusers
ChrootDirectory /data/%u
ForceCommand internal-sftp

Once done restart the SSH services, below are the steps :-

service sshd status

openssh-daemon (pid 1468) is running…

service sshd restart

Stopping sshd: [ OK ]
Starting sshd: [ OK ]

4. Testing Phase

Now everything has been configured, so let’s make a test to ensure the setup meets our purpose.
I’ll access SFTP by using another server called TEST01. First, I’ll verify the Port of the SFTP server . To do that I’ll use the nmap function. If your client server didn’t have it you may download and install it with yum as shown below:

yum list nmap

Loaded plugins: refresh-packagekit, security
Repository ‘OEL64’ is missing name in configuration, using id
Available Packages
nmap.i686 2:5.51-2.0.1.el6 OEL64

yum install nmap -y

Loaded plugins: refresh-packagekit, security
Repository ‘OEL64’ is missing name in configuration, using id
Setting up Install Process
Resolving Dependencies
–> Running transaction check
—> Package nmap.i686 2:5.51-2.0.1.el6 will be installed
–> Finished Dependency Resolution

Package Arch Version Repository Size
nmap i686 2:5.51-2.0.1.el6 OEL64 2.7 M

Transaction Summary
Install 1 Package(s)

Total download size: 2.7 M
Installed size: 9.7 M
Downloading Packages:
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Warning: RPMDB altered outside of yum.
Installing : 2:nmap-5.51-2.0.1.el6.i686 1/1
Verifying : 2:nmap-5.51-2.0.1.el6.i686 1/1

nmap.i686 2:5.51-2.0.1.el6

[root@TEST01 /]# nmap -n SFTP01

Starting Nmap 5.51 ( ) at 2016-08-30 02:27 MYT
Nmap scan report for SFTP01 (
Host is up (0.000085s latency).
Not shown: 998 closed ports
22/tcp open ssh
111/tcp open rpcbind

Nmap done: 1 IP address (1 host up) scanned in 0.23 seconds

You’ll notice that currently on our SFTP server, the only open port is SSH 22. Now, let’s try to access the SFTP from TEST01 client. Below are the steps:

[root@TEST01 /]# which sftp
[root@TEST01 /]# sftp shahrilk@SFTP01
Connecting to SFTP01…
shahrilk@sftp01’s password:
sftp> pwd
Remote working directory: /upload

Great! Now our SFTP server is acessible from outside. Notice that the default directory is /upload . This means that SFTP will only show the default path as /upload even though our previous configuration made in the SFTP server directory is /data/shahrilk/upload.
Now let’s try to get a file from the SFTP server directory into our testing client. First, let’s create a test file under /data/shahrilk/upload . Below are the steps:

cd /data/shahrilk/upload
touch testing_file.txt

Then go back to our testing site TEST01 and see if we able to get and download the created file.

[root@TEST01 /]# sftp shahrilk@SFTP01
Connecting to SFTP01…
shahrilk@sftp01’s password:
sftp> pwd
Remote working directory: /upload
sftp> ls
sftp> get testing_file.txt
Fetching /upload/testing_file.txt to testing_file.txt
sftp> quit

Excellent! Our SFTP test has been successful, let’s try to access SSH using the user shahrilk . As previously we’ve set configuration as /sbin/nologin, therefore the user won’t be able to use SSH services:

[root@TEST01 ~]# ssh shahrilk@SFTP01
shahrilk@sftp01’s password:
^CConnection to sftp01 closed.

Nice! Now we have a secured SFTP server up and running.

How to Setup Chroot SFTP in Linux (Allow Only SFTP, not SSH)

If you want to setup an account on your system that will be used only to transfer files (and not to ssh to the system), you should setup SFTP Chroot Jail as explained in this article.

In a typical sftp scenario (when chroot sftp is not setup), if you use sftp, you can see root’s file as shown below.

If you want to give sftp access on your system to outside vendors to transfer files, you should not use standard sftp. Instead, you should setup Chroot SFTP Jail as explained below.

Non-Chroot SFTP Environment

In the following example (a typical sftp environment), john can sftp to the system, and view /etc folder and download the files from there.

# sftp
john@thegeekstuff's password:
sftp> pwd
Remote working directory: /home/john

sftp> ls
projects  john.txt documents 

sftp> cd /etc
sftp> ls -l passwd
-rw-r--r--    0 0        0            3750 Dec 29 23:09 passwd

sftp> get passwd
Fetching /etc/passwd to passwd
/etc/passwd     100% 3750     3.7KB/s   00:00

Chroot SFTP Environment

In the following example, john can sftp to the system, and view only the directory that you’ve designated for john to perform sftp (i.e /incoming).

When john tries to perform ‘cd /etc’, it will give an error message. Since SFTP is setup in an chroot environment, john cannot view any other files in the system.

# sftp
john@thegeekstuff's password:
sftp> pwd
Remote working directory: /home/john

sftp> ls
sftp> cd /etc
Couldn't canonicalise: No such file or directory

Now that you know what Chroot SFTP environment is, let us see how to set this up.

1. Create a New Group

Create a group called sftpusers. Only users who belong to this group will be automatically restricted to the SFTP chroot environment on this system.

# groupadd sftpusers

2. Create Users (or Modify Existing User)

Let us say you want to create an user guestuser who should be allowed only to perform SFTP in a chroot environment, and should not be allowed to perform SSH.

The following command creates guestuser, assigns this user to sftpusers group, make /incoming as the home directory, set /sbin/nologin as shell (which will not allow the user to ssh and get shell access).

# useradd -g sftpusers -d /incoming -s /sbin/nologin guestuser
# passwd guestuser

Verify that the user got created properly.

# grep guestuser /etc/passwd

If you want to modify an existing user and make him an sftp user only and put him in the chroot sftp jail, do the following:

# usermod -g sftpusers -d /incoming -s /sbin/nologin john

On a related note, if you have to transfer files from windows to Linux, use any one of the sftp client mentioned in this top 7 sftp client list.

3. Setup sftp-server Subsystem in sshd_config

You should instruct sshd to use the internal-sftp for sftp (instead of the default sftp-server).

Modify the the /etc/ssh/sshd_config file and comment out the following line:

#Subsystem       sftp    /usr/libexec/openssh/sftp-server

Next, add the following line to the /etc/ssh/sshd_config file

Subsystem       sftp    internal-sftp
# grep sftp /etc/ssh/sshd_config
#Subsystem      sftp    /usr/libexec/openssh/sftp-server
Subsystem       sftp    internal-sftp

4. Specify Chroot Directory for a Group

You want to put only certain users (i.e users who belongs to sftpusers group) in the chroot jail environment. Add the following lines at the end of /etc/ssh/sshd_config

# tail /etc/ssh/sshd_config
Match Group sftpusers
        ChrootDirectory /sftp/%u
        ForceCommand internal-sftp

In the above:

  • Match Group sftpusers – This indicates that the following lines will be matched only for users who belong to group sftpusers
  • ChrootDirectory /sftp/%u – This is the path that will be used for chroot after the user is authenticated. %u indicates the user. So, for john, this will be /sftp/john.
  • ForceCommand internal-sftp – This forces the execution of the internal-sftp and ignores any command that are mentioned in the ~/.ssh/rc file.

5. Create sftp Home Directory

Since we’ve specified /sftp as ChrootDirectory above, create this directory (which iw equivalent of your typical /home directory).

# mkdir /sftp

Now, under /sftp, create the individual directories for the users who are part of the sftpusers group. i.e the users who will be allowed only to perform sftp and will be in chroot environment.

# mkdir /sftp/guestuser

So, /sftp/guestuser is equivalent to / for the guestuser. When guestuser sftp to the system, and performs “cd /”, they’ll be seeing only the content of the directories under “/sftp/guestuser” (and not the real / of the system). This is the power of the chroot.

So, under this directory /sftp/guestuser, create any subdirectory that you like user to see. For example, create a incoming directory where users can sftp their files.

# mkdir /sftp/guestuser/incoming

6. Setup Appropriate Permission

For chroot to work properly, you need to make sure appropriate permissions are setup properly on the directory you just created above.

Set the owenership to the user, and group to the sftpusers group as shown below.

# chown guestuser:sftpusers /sftp/guestuser/incoming

The permission will look like the following for the incoming directory.

# ls -ld /sftp/guestuser/incoming
drwxr-xr-x 2 guestuser sftpusers 4096 Dec 28 23:49 /sftp/guestuser/incoming

The permission will look like the following for the /sftp/guestuser directory

# ls -ld /sftp/guestuser
drwxr-xr-x 3 root root 4096 Dec 28 23:49 /sftp/guestuser

# ls -ld /sftp
drwxr-xr-x 3 root root 4096 Dec 28 23:49 /sftp

7. Restart sshd and Test Chroot SFTP

Restart sshd:

# service sshd restart

Test chroot sftp environment. As you see below, when gusetuser does sftp, and does “cd /”, they’ll only see incoming directory.

# sftp
guestuser@thegeekstuff's password:

sftp> pwd
Remote working directory: /incoming

sftp> cd /
sftp> ls

When guestuser transfers any files to the /incoming directory from the sftp, they’ll be really located under /sftp/guestuser/incoming directory on the system.