Jailed chroot SFTP accounts CentOS 5 (dirty interactive script at end)

Say you’re running a webserver with API’s that offer specific services to customers, which as a result generates some form of valuable output file like reports etc. Or possibly the opposite situation, where frequent uploads of files such as a databases are necessary for the use of the webapp services. 

Despite these reports being generated and easily accessible for download via the webportal, as well as the ability for uploading necessary files to the webapps, there is always going to be a user that wants to be able to do this in a different manner.

And who can blame them when user is dealing with the personal information of their client base, and also wants to be able to achieve a form of file management that can be scripted and automated?

So how can we give them this access in a manner that restricts their ability to interact with the rest of the server? The answer is a jailed SFTP account.


OpenSSH 5 (I had to upgrade OpenSSH manually because CentOS 5 natively supports a previous version that wouldn’t suffice for this purpose). 

…if by chance you need to do the same on CentOS or another RPM distro that has the same limitation, follow the installation instructions in this guide:

Installing OpenSSH 5 in CentOS 5


Locate your sshd_config file and open with your desired text editor.

Locate out the following line and comment out with a # if not already done so:

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

Scroll down and append the following to the end:

Subsystem sftp internal-sftp         

Match Group sftponly         

ChrootDirectory  /home/%u         

ForceCommand internal-sftp         

AllowTcpForwarding no

Restart the SSH service:

# /etc/init.d/sshd restart

…..(or # service ssh restart depending on distro)

Now we need to make an account and folder that a user can read and write to, yet with restricted permissions to the user home folder itself, no access to any other folders on the server and most of all NO SHELL ACCESS.

The best way to achieve this is to set up a jailed chroot, so when they connect via SFTP to /home/<user>/ it will appear to them as the root directory where they are not the owner and they cannot write to. This is particularly important because otherwise they could potentially alter SSH configuration files, such as the pubkeys – an obvious security risk.

Instead the folder /home/<user>/sftp/ (or to them /sftp) is created where they have ownership along with read and write permissions.

Firstly we need to create a group for the user called ‘sftponly’, just like we specified in the sshd config file:

# groupadd sftponly

Now if you’re lazy, feel free to run this interactive script I created that will do the rest. Simply copy the output below into a file, name it what you want, and run it as so.

# bash /path/to/script

***Remember to chmod +x the file first.

Then, simply follow the prompts. 

Otherwise you can just follow the command order in the script or alter to suit your fancy.


Be sure to generate and copy the pubkey onto the server if you want the script to add it automatically, otherwise you can do it manually later by copying it into ~/.ssh/authorized_keys file.

#!/usr/bin/env bash
# This script serves to create and configure new user accounts for SFTP
# Just enter in the details correctly when prompted and it'll do it all for you.
# You can thank me later ;) -- Your friendly admin.
# Note: Script must be run as root. Run as "bash SFTPcreator.sh"
# Note: Tested only on CentOS 5.9
# Note: Requires OpenSSH 5
# Pre-Config: Make sure the following is matched in sshd_config:
# " #Subsystem sftp /usr/libexec/openssh/sftp-server"
# ...as well as:
# " Subsystem sftp internal-sftp
# Match Group sftponly
# ChrootDirectory /home/%u
# ForceCommand internal-sftp
# AllowTcpForwarding no "

isRoot() {
# Check if the current user is root or not !
if [ $EUID = 0 ]; then
return 0
return 1
makeSftpUser() {
read -p “Type in desired SFTP username \ home folder name: ” User
/usr/sbin/useradd -m $User
/usr/sbin/usermod -G sftponly $User
#restricts SSH shell access so they can SFTP but not SSH
/usr/sbin/usermod -s /bin/false $User
#Creates Password for account
read -p “Type in password for the account: ” Pass echo -n $Pass | passwd $User –stdin

## Creates ~/$USER/sftp directory and sets correct privileges and
## permissions to allow SSH public key authentication. Also restricts
## users ability to modify their home directory, and grants full
## read\write access to their ~/$USER/sftp directory
chown root:root /home/$User
chmod 755 /home/$User/
chmod 755 /home/$User
mkdir /home/$User/sftp
chown $User:sftponly /home/$User/sftp
mkdir /home/$User/.ssh/
touch /home/$User/.ssh/authorized_keys
chown $User:$User /home/$User/.ssh
chmod 700 /home/$User/.ssh/
chmod 700 /home/$User/.ssh
chown $User:$User /home/$User/.ssh/authorized_keys
chmod 600 /home/$User/.ssh/authorized_keys
addPubKeyYN() {
echo “Note: You need to have a valid pubkey file installed”
echo “..and be able to specify the file path to continue”
echo ” ”
echo ” ”
read -p “Would you like to import a public key (y/n)? ” ANS
if [ “$ANS” = y ] ; then
read -p “Can you please humour me and re-enter your new username?: ” User2
read -p “Please specify the path to pubkey file (or files using wildcards):” Path
cat $Path >> /home/$User2/.ssh/authorized_keys
clear && restartAndExit
echo “If you selected no then you will need to add pubkeys manually” && sleep 5 && clear && restartAndExit
restartAndExit() {
##Restart sshd
echo “Restarting sshd service and exiting.”
/etc/init.d/sshd restart
echo ” ”
echo “If all went well you can connect using the command: ”
echo ” ”
echo “sftp -oPort= [USERNAME]@:sftp/” && sleep 5
##proceeds if root, exits if not
if [ isRoot = 0 ]; then
else makeSftpUser