My project needs me to disable sftp for some users, but those users still need to connect over ssh. Does anyone know how to implement this?

I've seen suggestions to change the file at /etc/ssh/sshd_config, but I'm not sure what to change.

migrated from stackoverflow.com Jul 15 '11 at 19:49

This question came from our site for professional and enthusiast programmers.

  • The only way I could imagine doing this would be to use an MLS policy in SELinux and restrict exactly what files, directories and sockets a person can access, execute, etc. I would do this in combination with a highly restrictive iptables policy that uses the module owner for outbound access. This assumes you are going to be pen tested by a red-team. If everyone accessing your system always obeys the rules and never has mal-intent, then my approach would be heavy handed and overly complex. – Aaron Nov 28 '16 at 15:20

In general doing this is bad security practice for reasons that others have listed. However, the point of your assignment, I think, is to teach you that you can have conditional config sections based on various criteria.

The way to do this is using a Match conditional block*.

Match User bob
Subsystem   sftp  /bin/false

See sshd_config(5) under the Match section for more information, and matching on Group.

*There's more than one way to do it.

  • 7
    It's not working for me. Error: Directive 'Subsystem' is not allowed within a Match block – chrw Jan 22 '13 at 9:38
  • Wrong answer because Subsystem is not allowed in Match block – mikep Aug 1 at 10:24

This doesn't make any sense, it is security through useless obscurity. Any user that can SSH will be able to transfer any file that they are able to read via the SSH session. You will also be able to write, if you have permissions to do so.

As can example, you can download /etc/passwd via ssh using the following method (no scp/sftp session required): ssh foo@bar.com "cat /etc/passwd" > passwdcopy

If you can see it on your screen via SSH, then you can easily copy it as a file.

The only way this would make sense is if you have a custom restricted shell that enforces a security policy.

However, the inverse of this does make sense (disabling ssh shell but leeaving scp/sftp enabled) because you are not able to execute arbitrary commands via sftp/scp that you can via an ssh shell.

PS: I'm assuming the SSH shell you are granting is a standard shell that allows arbitrary execution. If this is not the case then see this: How to disable sftp subsystem for a specific user or group? and take a look at the Subsystem config option of sshd_config.

Match Group nosft
Subsystem   sftp  /bin/false

I prefer to use a group for this.

It is useful in combination with users who have restricted shells. I sometimes give ssh access to a client so that they can access a sql-dump of their database by setting their shell to a script that dumps their data. Cutting them off from scp also seems to be a smart idea. They don't have access to running cat to transfer a file over ssh.

  • 3
    Directive 'Subsystem' is not allowed within a Match block – Patryk Dec 8 '14 at 10:33
  • Wrong answer because Subsystem is not allowed in Match block – mikep Aug 1 at 10:27

It is possible to enable SFTP globally, and disabling SFTP for only some users.

This does not work if you want your user to get a regular shell prompt. Nor does it make sense, as you could circumvent most stuff if you have shell access. It will only work if you only want to give access to a specific program.

I personally need this because I want to give access to some git repositories over SSH, and I like to disable systems that are not needed. In that case SFTP is not needed.


To match a set of users, you could configure SSH with the Match keyword. From the sshd_config(5) manual:


        The arguments to Match are one or more criteria-pattern pairs or the
        single token All which matches all criteria.  The available criteria
        are User, Group, Host, LocalAddress, LocalPort, and Address.  The
        match patterns may consist of single entries or comma-separated
        lists and may use the wildcard and negation operators described in
        the PATTERNS section of ssh_config(5).


A couple of examples:

  • Match User eva matches the "eva" user
  • Match User stephen,maria matches the "stephen" and "maria" users
  • Match Group wheel,adams,simpsons matches the "wheel", "adams", "simpsons" groups

If you want more information, there are loads in the sshd_config(5) manual.

Forced command

Normally you get the user's login shell when you connect via SSH, but SSH can be configured to force a certain command. The command is forced for any SSH connection, including SFTP, and thus you might have the option to force the command you want.

The command to force can be configured with the ForceCommand keyword. From the sshd_config(5) manual:

        Forces the execution of the command specified by ForceCommand,
        ignoring any command supplied by the client and ~/.ssh/rc if
        present.  The command is invoked by using the user's login shell
        with the -c option.  This applies to shell, command, or subsystem
        execution.  It is most useful inside a Match block.  The command
        originally supplied by the client is available in the
        SSH_ORIGINAL_COMMAND environment variable.  Specifying a command of
        “internal-sftp” will force the use of an in-process sftp server that
        requires no support files when used with ChrootDirectory.  The
        default is “none”.

So you can force the constrained command you want using ForceCommand <your command>. For example:

Match User kim
        ForceCommand echo 'successful login man, congrats'


In my case where I want to give git access, I only need the user to have access to git-shell. This is the section that disables SFTP for my git users, along with some security options:

Match Group git

        # have to do this instead of setting the login shell to `git-shell`,
        # to disable SFTP
        ForceCommand /usr/bin/git-shell -c "$SSH_ORIGINAL_COMMAND"

        # disable stuff we don't need
        AllowAgentForwarding no
        AllowTcpForwarding no
        AllowStreamLocalForwarding no
        PermitOpen none
        PermitTunnel no
        PermitTTY no
        X11Forwarding no
  • 1
    This doesn't answer the OP's question, but it was very helpful for me to achieve what I want to achieve in my own use-case – Kidburla May 11 '18 at 22:09
  • I don't agree. OP's question is "How to disable sftp for some users, but keep ssh enabled?", and this answer explains one way to do that. Glad you found it helpful anyway! – aude May 13 '18 at 10:31
  • By your own admission it "does not work if you want your user to get a regular shell prompt". so this doesn't meet the OP's requirement of "keep ssh enabled" – Kidburla May 13 '18 at 22:44
  • That's a good point. I guess I came to terms with this solution because of "Nor does it make sense, as you could circumvent most stuff if you have shell access.". But I did not find a way to exactly what OP asks, I agree now. – aude May 15 '18 at 17:11
  • Here's a fuller version of this answer: serverfault.com/a/817482 – aude May 15 '18 at 17:12
Match User bob
MaxSessions 0

Tested and working on CentOS 6.6. Note that Subsystem is not allowed with Match at least on newer CentOS versions. The manpage for sshd_config lists the limited keywords that are allowed with the Match condition.


You can look at scponly to do the reverse, allow only scp/sftp but no shell access.

I agree with @Nathan above, this doesn't make a whole lot of sense. If you are dead set, try editting your /etc/ssh/sshd_config file and removing/commenting out the following line:

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


give no home directory for user

usermod username -d /bin/false

Change Subsystem sftp /usr/libexec/openssh/sftp-server in file /etc/ssh/sshd_config to Subsystem sftp /dev/null/usr/libexec/openssh/sftp-server

Then restart the ssh

service ssh restart

it works for me, debian.


In the ~/authorized_key configure the user key as follow:

command="/bin/bash" ssh-rsa AAAAB3Nz.........

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.