Restricted shell file server with scponly

Today it’s fairly typical to have an always on, high speed internet connection. Many geeks like myself will run a Linux box 24/7 at home that acts as a file server, media server, and possibly a few other roles like email and web. Enabling ssh access it extremely handy for when you’re away from home, not only does it give you secured shell access but it enables tunneling over ssh. A secondary but also valuable ability of this type of setup is online file storage that is on hardware you own (or more specifically, not owned by someone random).

You might want to enable friends of yours to also enjoy the benefits of having online file storage, but you might not want them tinkering around inside your system with full shell access. Whatever the reason for your paranoia, scponly is a great solution.

scponly is an alternative ‘shell’ (of sorts) for system administrators who would like to provide access to remote users to both read and write local files without providing any remote execution priviledges. Functionally, it is best described as a wrapper to the tried and true ssh suite of applications.

It is quite easy to install and configure scponly on Ubuntu:

$ sudo apt-get install scponly

During the package configuration step that is triggered automatically on the install, you’ll be asked if you want chroot or not.

While the warning appears to be quite dire, choosing yes has some advantages. In a chroot jail the apparent root directory is modified, this limits the users visibility to the filesystem – often to their home directory. The security warning is due to the implementation of scponly needing suid-root  privileges in order to create the chroot jail. You need to assume that the scponly code doesn’t contain any potential exploits, a trade off for the reduced filesystem visibility that in turn increases system security. In the end, as scponly is wrapping the well known and validated ssh suite we’re in a fairly good place.

Next we need to uncompress and modify the setup helper script to be executable:

$ cd /usr/share/doc/scponly/setup_chroot
$ sudo gunzip
$ sudo chmod +x

Use the helper script to create a chroot restricted user (frank).

$ sudo ./

Next we need to set the home directory for this scponly user.
please note that the user's home directory MUST NOT be writeable
by the scponly user. this is important so that the scponly user
cannot subvert the .ssh configuration parameters.

for this reason, a writeable subdirectory will be created that
the scponly user can write into.

-en Username to install [scponly]
-en home directory you wish to set for this user [/home/frank]

-en name of the writeable subdirectory [incoming]
creating /home/frank/backup directory for uploading files

Your platform (Linux) does not have a platform specific setup script.
This install script will attempt a best guess.
If you perform customizations, please consider sending me your changes.
Look to the templates in build_extras/arch.
- joe at sublimation dot org

please set the password for frank:
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
if you experience a warning with winscp regarding groups, please install
the provided hacked out fake groups program into your chroot, like so:
cp groups /home/frank/bin/groups

In the above I provided a username (frank) and I accepted the defaults except for the writeable subdirectory (backup) and password.

On my test system, an Ubuntu 11.04 (Natty) desktop install I wasn’t able to connect using scp, or sftp.

$ scp testfile.txt frank@desktop:testfile.txt
frank@desktop's password:
unknown user 1001
lost connection

It turns out I was hit by a reported problem, and it was a simple matter of copying some missing files into the chroot jail:

$ sudo cp -av /lib/i386-linux-gnu/libnss_files* /home/frank/lib/i386-linux-gnu/

Now everything worked. I could scp, sftp and mount using sshfs (one of my favorite utilities).

Bonus round

If you want the writeable subdirectory to be the default directory, simply modify the system /etc/passwd file to have a double slash followed by the directory:


Changing the password is also supported by scponly:

$ ssh -t frank@desktop passwd

5 thoughts on “Restricted shell file server with scponly”

  1. Sweet, success including bonus round. I did have to delete the user and recreate as you suggested. My libnss files were just in /lib, not in /lib/i386-linux-gnu but were easy to find.

  2. If you want to add ssh key based login to your scponly setup, you’ll want to avoid the modification of the default directory – it’s likely to cause more problems than it’s worth.

    To enable key based logins, you’ll need to create a .ssh directory (owned by the user and chmod to 700). Inside of that directory the authorized_keys file must be owned by the user and chmod 600. It appears sshd checks for this and will not use the files if they are incorrectly tagged.

    If you’ve changed the default directory, that’s where the .ssh directory must live. This is why I suggest you do not change it. See for details.

    If you’re trying to diagnose scponly logins, it turns out that you can connect with ssh – it just won’t give you an actual shell. This is useful for figuring out why you can’t authenticate. Additionally, using the -v flag (possibly multiple times) can provide diagnostic information. From there it’s just a matter of doing some A/B comparison between a working system and a non-working one.

    ssh -v -v

  3. John, that’s a good question. I’ve moved from a scponly setup to a makejail setup – so I don’t really have an environment to test in.

    Given my mental model of how cron runs, it probably would work. Generic scripts – probably no, but it depends on how the script is launched.

    The scponly approach changes the login shell that the user gets (when they log in). When cron runs, it’s not logging in – just becoming that user and running a job. I don’t think cron obeys the login shell.

    Then again, this article makes me think cron might not work.

Leave a Reply

Your email address will not be published. Required fields are marked *