I'm starting a very little hosting company for a few friends and little clients, nothing big.

I want to give my "clients" the right to manage their files on the server. I hate FTP as it is not secure and it's in my opinion obsolete.

So I'd like to allow my users to connect through SFTP but not allow them to connect through SSH. (I know, I know, SFTP is using SSH). But I was just wondering, is it possible?

So I wouldn't have to install a FTP service on the server and everything would be awesome!

9 Answers 9


Starting with version 4.9 OpenSSH (not available in centos 5.x but ChrootDirectory feature was backported) has an internal-sftp subsystem:

Subsystem sftp internal-sftp

And then block other uses:

Match group sftponly
     ChrootDirectory /upload
     X11Forwarding no
     AllowTcpForwarding no
     AllowAgentForwarding no
     ForceCommand internal-sftp -d /%u

Add your users to the sftponly group. The chroot directory must be owned by root, and cannot be group-writeable, so create a subdirectory for each user that's owned by the appropriate user (if you match their home directory, it will be the default working directory when connecting). I'd also set /bin/false as the user's shell.

As an example, users can then upload single files with:

sftp username@hostname <<< 'put filename.ext /'

(scp will hopefully soon be modified to use sftp so this will become easier)

  • Wow! Super-awesome! I'll test this out and come back here to validate. Thanks a lot!
    – Tommy B.
    Commented Jan 28, 2012 at 20:48
  • 1
    After doing this, my sftponly user cant access by ssh and is able to connect by sftp. However it can't see any file at all! In spite these files have permission for this user. :-( Commented Jan 15, 2015 at 10:17
  • 6
    In case you want to do this and find an entry in your sshd_config with "/usr/lib/openssh/sftp-server" already existing, check here: serverfault.com/questions/660160/… -- internal-sftp is "newer, better and easier"
    – Xosofox
    Commented Jul 16, 2015 at 10:57
  • 1
    Home directory should not only be owned by root, but also has 755 permission (no write access), which makes this chroot additional receipt not usable in most cases. Commented Mar 14, 2020 at 22:12
  • 1
    @leonheess The shell is a user attribute, so you would need to do a batch: sudo groupmems -lg sftponly | sudo xargs -n1 usermod -s /bin/false
    – copycat
    Commented Feb 17, 2021 at 23:13

There is a shell scponly what does this. It can chroot too.

  • This would come great if you need both SFTP users and SSH users. You just replace the shell in /etc/passwd for those restricted only to SFTP.
    – Dragos
    Commented Feb 23, 2012 at 8:12
  • it would be great if you post it here instead of linking it. What if the page goes down? Commented Apr 26, 2021 at 4:17
  • 2
    It's a good approach but the SourceForge package has not been updated since 2011
    – corretge
    Commented Sep 4, 2021 at 8:11
  • The github repository of scponly is here.
    – Fjor
    Commented Mar 14, 2022 at 20:15
  • 3
    this shell is no longer shipped with modern Debian. ssh should be used instead (detailed in another answer).
    – Sam Sirry
    Commented Apr 18, 2022 at 21:53

Checkout rssh which is a fake shell that allows sftp but denies ssh

More about RSSH




You can configure rssh to allow / deny different behaviours like sft, scp etc.

  • Nice. This is the easiest way to config without touching sshd_config at all. Just change the shell in passwd file and done.
    – Tomofumi
    Commented Aug 22, 2018 at 7:47
  • 2
    rssh seems to be obsolete now (there is no this package in debian buster anymore), they say, there is rush instead of it. I did not tried it, i am moving to openssh with internal-sftp. Commented Apr 1, 2020 at 9:59

The solution from Rob Wouters need only a minor change... as I could not comment for lack of points, I'll just reproduce here how it worked for me.

The directory you chroot to in sshd_config, really need to belong to root and not writable by any other user or group. So, if you put

ChrootDirectory /upload/%u

the user directory specified by '%u' must comply to the same rule. If you don't, you'll get "bad ownership or modes for chroot directory" error. Instead, you put only the base directory and pass the user owned and writable directory to the ForceComand. See below:

# override default of no subsystems
#Subsystem      sftp    /usr/lib/openssh/sftp-server
Subsystem       sftp    internal-sftp

Match group sftponly
     ChrootDirectory /upload
     X11Forwarding no
     AllowTcpForwarding no
     AllowAgentForwarding no
     ForceCommand internal-sftp -d /%u

Now, when the user logs in, the internal-sftp will change de current directory to the right place.


I use the method of specifying the user shell as /bin/false as mentioned. However, you must ensure that /bin/shell is in /etc/shells. Then it works ssh=no ftp=ok.

I also use vsftpd and add this
chroot_local_user=YES to /etc/vsftpd/vsftpd.conf so that ftp-ers can't see date other then their own.

Advantage to these simple changes are no annoying config to ssh config for each user.

  • This doesn't answer the question. sftp is not the same thing as the protocol provided by vsftpd, which is a completely different service. Commented Dec 17, 2023 at 8:15

Configuring ssh to enable only sftp for some selected users is a good idea and it works properly, provided that you you install either scponly or rssh.

rssh works fine, unless you need to configure jail, in this case try to follow instruction provided by CHROOT manuals is crazy, leading to "copy" large parts of system executables and library just below "each user jail", including rssh shell itself. It is a space-wasting method.

scponly needs a deep understanding in configuration leading to ever-present problem of login rejection in case of jail setup.

The straightforward way to allow "ftp" functionalities with jail properly working, SSL/TLS support for secure transactions and login is to use an "old-but-working" VSFTPD, which installs quickly and cleanly and offers all configurability as needed and, last but not least: it works!



You can modify /etc/passwd and give that user a fake shell so that he can not use ssh.

  • 12
    Did you test this?
    – splattne
    Commented Jan 29, 2012 at 8:49
  • 10
    When I try setting the shell to /bin/false neither ssh or sftp works
    – Brad Mace
    Commented Mar 14, 2013 at 22:34
  • 2
    /bin/false is to disallow any sort of login, that is not the correct approach here. The accepted answer from Rob Wouters' is how you should limit users to SFTP only, not by changing the shell. If you did want to change the shell @Stone's asnwer would be a good idea.
    – Baldrick
    Commented Aug 7, 2014 at 10:46
  • 1
    so WHAT shell should be used assuming /bin/bash is not acceptable and /bin/false or /sbin/nologin deny access?
    – Putnik
    Commented Nov 20, 2017 at 23:07
  • Does not answer the question, I'm afraid. Commented Dec 15, 2023 at 7:50

Don't forget to find the line UsePAM yes and comment it:

#UsePAM yes

Without disabling this, your SSH server would crash on reloading/restarting. Since you do not need fancy functions of PAM, this is fine.

  • 1
    Commenting out lines that you don't understand is generally a bad idea. If you don't know what PAM is for, just leave it set however your distro has it set as a default.
    – mbbush
    Commented Nov 10, 2020 at 5:22
  • Why? / why not? unclear
    – MrR
    Commented Dec 6, 2021 at 9:23

This is the way i set up SFTP and disallowing SSH.

please do the following:

  1. First create sftp user and group sftp

  2. Create separate directory as root for the SFTP files: sudo mkdir -p /home/sftpdir

  3. Have a tested sshd_config file that allows SSH over port 22 but also SFTP on random port for security reasons

#$OpenBSD: sshd_config,v 1.101 2017/03/14 07:19:07 djm Exp $
# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Port 38250 Port 22 PasswordAuthentication no 
ChallengeResponseAuthentication no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'. UsePAM yes X11Forwarding yes PrintMotd no
# Allow client to pass locale environment variables AcceptEnv LANG LC_*
#DenyUsers sftpuser

# override default of no subsystems Subsystem       sftp    internal-sftp 
Match group sftp 
Match User sftpuser 
Match LocalPort 38250 
ForceCommand internal-sftp 
ChrootDirectory /home/sftpdir 
PermitTunnel no 
AllowAgentForwarding no 
X11Forwarding no    
AllowTcpForwarding no
  1. Restart and check status of sshd service
    sudo service sshd restart
    service sshd status
  1. Create a Shell file. Add execution to echo a notification message

    sudo touch /bin/sftponly
    echo -e '#!/bin/sh\necho "This account is limited to SFTP access only."' | sudo tee -a  /bin/sftponly

  1. Give execution permissions and append to shells file
    sudo chmod a+x /bin/sftponly
    echo "/bin/sftponly" | sudo tee -a /etc/shells
  1. finally Test and you should not be able to connect.

  2. A template to use SFTP client with a SSH key and basic verbosity:

    sftp -v -oPort=$RANDOM_PORT -i ~/.ssh/$SSH_KEY.pem sftpuser@$HOST

You must log in to answer this question.

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