I needed to provide multiple users FTP logins, some able to write, some only to read, to a single FTP root directory. I very much wanted that they not see of the file system anything above that directory. After searching—it appears this is a common problem—I defined the user_local config option as the root directory and confined the users to that directory using the chroot_local_users option, or chroot jail. This basically works.

My problem is that, though I do not know why, relying on chroot jail for security is frowned upon generally and most importantly by (at least one member of) the kernel development team.

So, how can I confine my login users to (even) seeing nothing above the defined root directory without chroot jail?? (this is the "secure" part of the question alluded to in the title)

Also, for security reasons (that I do not yet understand), modern versions of vsftpd do not allow the user's root directory to be writable, thus leaving two options: 1. or to disable the security feature and leave the root writeable or 2. to remove the write bits from the root and create a writable sub-directory therein. The former is playing with fire and the latter is ugly and error prone (users trying to write into the root and getting errors…) I chose the latter.

So, how is FTP service done right? Meaning how can users be prevented from seeing irrelevant parts of the file system in secure way? Is FTP an inherently insecure way of distributing files? If so, is there a better way. Trying to get this right…

  • 1
    Note that "chroot" generally refers to a login chroot jail, not showing only a subset of the system through a specific service (FTP, say). You don't generally say that Apache serves files out of a chroot either; it serves them out of the document root, which accomplishes the same thing: restricting what portions of the system ordinary users can access through the service in question. This difference of terms might be a contributing factor in your confusion.
    – user
    May 21, 2013 at 14:04
  • @MichaelKjörling Thank you for that. That does clear up chroot for me and helps me better understand the problem. With apache, there is no concept of users logging in. a client makes a request and the apache process serves the request out of a defined subset of the file system, good. FTP has users logging in, granting them access to the file system. No doubt, I'm missing something, but I don't see how what you wrote illuminates my issue. But if you have a solution--the problem is all over the internet--please share for the benefit of all or point me to where I can research it and report back. May 21, 2013 at 14:13
  • The point is that both services expose a part of the server's file system to remote users. A quick Google for "vsftp restrict directory access" brought up this thread which recommends to "consider instead using virtual users, combined with the user_config_dir and user_sub_token parameters". I am not familiar with vsftpd, but it looks like local_root might also be useful, especially in combination with user_config_dir.
    – user
    May 21, 2013 at 14:57

5 Answers 5


Note: This solution works well for me and is easy to set-up. Assuming you use vsFTPd.

I jailed all users to their home directory and shared a folder called "Shared" between all of them.

  1. Jail users to their home directly

    $ sudo vi /etc/vsftpd/vsftpd.conf

    Make Sure that this is the following configuration:


    Restart vsftpd:

    $ sudo service vsftpd restart
  2. Create a shared folder for all users and give 'ftp' permissions

    $ cd /var/ftp
    $ mkdir shared
    $ chmod 777 shared/
    $ chgrp ftp shared/
    $ chown ftp shared/
  3. Allow jailed users to have access to that shared folder

    Let's take the example of a jailed user Sam:

    Assuming that you are root at the moment.

    $ su - sam
    $ cd /home/sam
    $ mkdir Shared
    $ exit

    You're now back to root.

    $ mount -o bind /var/ftp/shared /home/sam/Shared

    Add sam to ftp group

    $ usermod -a -G ftp sam

    Repeat the process to add other users to "Shared" folder.

Sam will now have access to his own Home folder and will have an additional "Shared" folder that all other users can be given access to.


This question is all over the internet with no clear cut solution that I've found.

So here is where I stand on this now (I will update as I find out more).

Seems the fundamental problem is that FTP has users logging in and manipulating the file system, as opposed to an http client simply sending requests to an http service process.

So, it's very difficult to limit an FTP user from doing things his user has rights to do on the system were he to log in regularly. FTP users need to have execute rights for directories beyond where we want to limit his view access so that he can write or read from the his lower level branch. So the only easy way to limit his view access is to put him in chroot jail.

Chroot jail is not secure because it only "modifies pathname lookups for a process and its children so that any reference to a path starting '/' will effectively have the new root, which is passed as the single argument, prepended onto the path" but "the current working directory is left unchanged and relative paths can still refer to files outside of the new root." source http://lwn.net/Articles/252794/

What that means in a security context and how dangerous that really is relative to the FTP daemon and user rights I cannot say, but it does mean that the 'jail' in 'chroot jail' is a misnomer.

It appears that with a deep handle on linux, it's possible by defining process and user rights... to 'use' chroot in this security context, but neither I nor the myriad internet denizens struggling with this are 'there' yet.

It's also possible to harden chroot jail to where it really behaves like jail--To quote kernel developer Alan Cox, "chroot is not and never has been a security tool. People have built things based upon the properties of chroot but extended (BSD jails, Linux vserver) but they are quite different.You could probably write yourself an LSM module to do this too." I am not 'there' yet, but I do suspect that this in the end is 'the' solution, and I'd also hazard that the distribution ftp sites handle security along these or similar lines.

Practically speaking, all I can do now is use chroot jail, relying on that my server is a low priority target if one at all, and that my users are basically trustworthy. My security strategy will be to limit the damage one can do, if they do break out of the jail. Which entails configuring users appropriately, possibly virtual users, and perhaps running the whole service in a virtual machine.

As I progress in my studies, I hope to harden the chroot() concept via an LSM or the like for security, and I do note that according to the Alan Cox quote above BSD already has a 'jails' concept, so I'd might look into BSD for my FTP needs.


Here's how I created a jailed sftpuser for clients to sftp files to my server:

  1. Create the sftpgroup

    # groupadd sftpusers
  2. Create the sftpuser:

    # useradd -g sftpusers -d /incoming/client1 -s /sbin/nologin \
          client1srs passwd client1srs
  3. Modify user and make the user sftp onluy and put in sftp jail

    # usermod -g sftpusers -d /incoming -s /sbin/nologin client1srs
  4. Setup sftp-server Subsystem in sshd_config

    Modify /etc/ssh/sshd_config and comment out:

    # #Subsystem       sftp    /usr/libexec/openssh/sftp-server
  5. Then add the following:

    Subsystem       sftp    internal-sftp
  6. Specify Chroot Directory for Group

    Add the following lines at the end of /etc/ssh/sshd_config:

    Match Group sftpusers
           ChrootDirectory /sftp/%u
           ForceCommand internal-sftp
  7. Create SFTP home directory

    # mkdir /sftpdir/client1srs/incoming
    # chown client1srs:sftpusers /sftpdir/client1srs/incoming
  8. Restart sshd

    # /sbin/service sshd restart

Another possible if general answer (which may be wrong/impossible, I'm really hoping for feedback):

Create a separate partition to act as the root for the FTP users. Have nothing but relevant directories in this root partition. Use ACL's to remove execute permissions for all the FTP users for all the directories on the other partitions. Install the FTP server on the regular partition, so that the FTP user's partition isn't cluttered up with the program files.

This way the FTP users will only see the new partition's root, which I can structure as elegantly as I choose.


The short answer: use mandatory- or role-based-access control. See update 2 below.

Yes, ftp is inherently insecure. sftp and scp address some of that insecurity, though not the issue that concerns you of hiding parts of the filesystem. Maybe what you need is an NFS volume?

According to the vsftpd faq, the problem with chroot is it gives the user read/write control of what becomes the root filesystem.

vsftpd provides hide_file and deny_file settings which can be used to hide files and render them inaccessible respectively using pattern matching. As the documentation states, these options "are very simple and should not be used for serious access control--the filesystem's permissions should be used in preference."

Depending on what your users need to do over ftp, you might also be able to boost the security of your site by limiting ftp users' activity with vsftpd's cmds_allowed or cmds_denied.

You could run your ftp daemon inside a docker container, with the data directory from the host mounted in the container. The user will see the entire container, but nothing else from the host. It might be possible to use xinetd to spawn a dockerized vsftpd process for each client connection. Then everything in the container but the mounted data volume would be completely ephemeral and would disappear as soon as the connection is closed.

Update: FTP uses a separate connection for data transfer. To run an FTP server inside docker, one would have to ensure it could still negotiate and establish the data connection. This could be done by running the container with --net=host, or conceivably with additional network configuration both inside and outside the container. To spawn docker ftp containers on demand using xinetd as I suggested above, such configuration would have to be done on the fly for each container.

Update 2: Docker is not a security guarantee. Exploits have been discovered, and security is not the primary goal of the project. It would probably be best if using a container to run your ftpd as an unprivileged user.

The real solution is to supplement the access control mechanism on your server with AppArmor, SELinux, or GrSecurity. I believe any one of those should be a sufficient solution without containers, chroots, or jails.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .