SFTP Help; One master account with total control and multiple sub accounts with limited control.

January 7, 2015 1.5k views

So I'm looking some advice on a proper sftp setup. I have already read several tutorials on D.O and surfed various forums looking for the ideal solution.

I working on creating a better environment then I currently have (apache2, mysql, php, sftp) and wanted to try out nginx, MariaDB, php, sftp, fail2ban, iptables, etc... Everything is working well but sftp, it seems to be permissions, let me breadk down.

Current environment:

  • 512MB plan
  • Debian 7.0x64
  • Nginx
  • MariaDB
  • PHP
  • OpenSSH

For reference I moved the the default Nginx root from /usr/share/nginx/www to /var/www. I have already changed all the server {} blocks and that's fine. I can access the root and all from my ip. The trouble comes from multiple sftp accounts and vhost (sorta, not really).

I wanted to have a master account (let's say john) that has SSH and can access the entire server via SFTP. John is in the sudo group and basically has all privileges besides root, I'm connecting via FileZilla not terminal. I'm thinking this is not 100% best idea and might want to create a master ftp account with the access to /var/www but with /usr/sbin/nologin.

The john account can navigate all the files and create, delete, modify, etc...:

- and so on....

/var/www is currently www-data:www-data and everything works, however, I want specific user accounts for each site. would get "jim" would get "jack"

and so on... They are jailed to their respected directory but have read, write.

I created a group called sftp-only, added nologin to /etc/shells and jailed the users.

$ sudo groupadd sftp-only
$ echo "/sbin/nologin" >> /etc/shells
$ sudo usermod -g sftp-only -s /usr/sbin/nologin -d /var/www/ <username>
$ sudo usermod -g sftp-only -s /usr/sbin/nologin -d /var/www/ <username>

Then in sshd_config added the Match group

$ sudo nano /etc/ssh/sshd_config

In file:

Subsystem       sftp    internal-sftp
Match Group sftp-only
    ChrootDirectory %h
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no

However, in order for this to work I need to chown each jail directory with username:sftp-only AND need the parent directory to be root:root which kills my permissions:

$ sudo chown root:root /var/www
$ sudo chown <username>:sftp-only /var/www/

Major issues:

  1. /var/www should not be owned by root but instead www-data (best practice & security)
  2. Master ftp account can no longer act as a master account
  3. Child sftp-only accounts are finicky

It all comes down to permissions and I have really no idea where to go... anyone dealt with this before? I have a feeling it is simply not possible, I'm trying to keep the server as third-party free as possible but I think I might need one.

Again really looking to keep it third-party free but willing to accept any advice at this point.

1 comment
1 Answer

Alright since I did not get an answer I kept search and search and search and finally found something! I'm writing this up for another tutorial I'm creating so excuse any spelling mistakes and such, only the first draft (but it works!).

Before this section starts I want to give a massive shout-out to the user Time Sheep over at for this answer. He came up with a fantastic solution for jailing users while still keeping www-data permissions for /var/www.

Basically we are going to jail the user to their home directory (ex. /home/john/www) and then mount (link) that www folder to the site the user has access to edit. We also supply the g+s & use setfacl to keep the new written data under the www-data permissions. When that is all done we save the mount in the fstab file for when the server reboots.

First we need to add a group for our users, we could call this any but keep it lower-case and without spaces or numbers. For example developer, sitename, content-advisor, etc.. We are going to use sftp-only for these examples.

sudo groupadd sftp-only

Second check to see if /usr/sbin/nologin or /sbin/nologin is a valid shell.

$ less /etc/shells

If in the return list it does not exists CTRL+Z to exit out and add it with:

# Most systems:
echo "/sbin/nologin" >> /etc/shells
# Debian/Ubuntu:
echo "/usr/sbin/nologin" >> /etc/shells

Re-run a less on shell to see if it was added

$ less /etc/shells

SFTP will only work if the shell used on the user (in this case /usr/sbin/shell) is in the /etc/shells.

Third we need to setup the sftp-server Subsystem in sshd_config, open up the file:

$ sudo nano /etc/ssh/sshd_config

Locate the following line in the file and comment it out (if it is not already):

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

and under it add

Subsystem       sftp    internal-sftp

after that add the following at the VERY END of the file with modified settings

Match Group sftp-only
    ChrootDirectory /home/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no

It must go at the very end or an error will be produced!

Save the file and restart ssh.

$ sudo service ssh restart

Finally we need to setup a chroot environment, this will lock the user to the /home/<username>/www folder which is mounted to /var/www/ To add a new user run:

$ sudo useradd <username>
$ sudo usermod -g sftp-only -s /usr/sbin/nologin <username>
$ sudo chown root:root /home/<username>
$ sudo mkdir -p /home/<username>/www
$ sudo mount --bind /var/www/ /home/<username>/www
$ sudo chmod g+s /home/<username>/www
$ sudo chown -R <username>:www-data /home/<username>/www
$ sudo setfacl -d -m g::rwx /home/<username>/www
$ sudo nano /etc/fstab
# Add:
/var/www/        /home/<username>/www        none        bind        0        0

Make sure to replace <username> with your user you are creating and replace the /var/www/ with the site you want the user to have access to. The user could also have access to multiple sites by linking multiple directories.

$ sudo mount --bind /var/www/ /home/<username>/site1
$ sudo mount --bind /var/www/ /home/<username>/site2
$ sudo mount --bind /var/www/ /home/<username>/site3

Make sure to set the proper permissions & add the lines in etc/fstab. As well the chroot directory must be own by root for sftp to work so the line $ sudo chown root:root /home/<username> is very much required!

You can repeat the above for an existing user, just ignore the useradd and proceed to usermod.

I also recommend using /usr/sbin/nologin over /bin/false as the user will get a polite message if they try to SSH saying "This account is currently not available" while /bin/false immediately exists the user out of shell. As well we added /usr/sbin/nologin above to the /etc/shell so might as well stay consistent.

Hope that helps others!

Have another answer? Share your knowledge.