Why are there two ways to setup SFTP with OpenSSH and when to use which? Is there any difference between them?

I mean the first one is using a lib from OpenSSH and the second one says "use the internal", so it is also OpenSSH?

Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp

3 Answers 3


Both sftp-server and internal-sftp are part of OpenSSH. The sftp-server is a standalone binary. The internal-sftp is just a configuration keyword that tells sshd to use the SFTP server code built-into the sshd, instead of running another process (what would typically be the sftp-server).

The internal-sftp was added much later (OpenSSH 4.9p1 in 2008?) than the standalone sftp-server binary. But it is used in the default configuration file now. The sftp-server is now redundant and is kept probably for backward compatibility only.

I believe there's no reason to use the sftp-server for new installations.

From a functional point of view, the sftp-server and internal-sftp are almost identical. They are built from the same source code.

The main advantage of the internal-sftp is, that it requires no support files when used with ChrootDirectory directive.

Quotes from the sshd_config(5) man page:

  • For Subsystem directive:

    The command sftp-server implements the SFTP file transfer subsystem.

    Alternately the name internal-sftp implements an in-process SFTP server. This may simplify configurations using ChrootDirectory to force a different filesystem root on clients.

  • For ForceCommand directive:

    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.

  • For ChrootDirectory directive:

    The ChrootDirectory must contain the necessary files and directories to support the user's session. For an interactive session this requires at least a shell, typically sh, and basic /dev nodes such as null, zero, stdin, stdout, stderr, and tty devices. For file transfer sessions using SFTP no additional configuration of the environment is necessary if the in-process sftp-server is used, though sessions which use logging may require /dev/log inside the chroot directory on some operating systems (see sftp-server for details).

Another advantage of the internal-sftp is a performance, as it's not necessary to run a new sub-process for it.

It may seem that the sshd could automatically use the internal-sftp, when it encounters the sftp-server, as the functionality is identical and the internal-sftp has even the above advantages. But there are edge cases, where there are differences.

Few examples:

  • Administrator may rely on a login shell configuration to prevent certain users from logging in. Switching to the internal-sftp would bypass the restriction, as the login shell is no longer involved.

  • Using the sftp-server binary (being a standalone process) you can use some hacks, like running the SFTP under sudo.

  • For SSH-1 (if anyone is still using it), Subsystem directive is not involved at all. An SFTP client using SSH-1 tells the server explicitly, what binary the server should run. So legacy SSH-1 SFTP clients have the sftp-server name hard-coded.

  • 1
    "internal-sftp ... is used in the default configuration file now." No, it's not. From the man pages: "By default no subsystems are defined." From the default config included with the openssh source: Subsystem sftp /usr/libexec/sftp-server.
    – miken32
    Feb 15, 2023 at 18:29
  • Here is the argument why sftp-server is the default: bugzilla.mindrot.org/show_bug.cgi?id=3397 TL;DR: To separate the memory images, to protect the sshd parent process in case of an error in the SFTP server code.
    – MichaIng
    Feb 28 at 20:22

There exist alternative SFTP implementations that can be used together with OpenSSH:


You can lock an authorized_key to the external sftp-server.

command="/usr/libexec/openssh/sftp-server" ssh-rsa AAAA…== [email protected]

When you do, your user can sftp, but cannot scp or ssh:

$ sftp host:/etc/group /tmp
Connecting to host...
Fetching /etc/group to /tmp/group
/etc/group                                    100%  870     0.9KB/s   00:00

Attempting to do anything else will just hang:

$ scp host:/etc/group /tmp
Killed by signal 2.

$ ssh host uptime
Killed by signal 2.

Alas, there is no easy way for a key to be locked to a chroot unless the sshd_config is modified. This would be really cool for a user to be able to do without the intervention of the system manager.

  • 4
    ForceCommand internal-sftp should achieve the same
    – ptman
    Jun 9, 2016 at 7:13
  • 3
    Handy thing there is that without chroot you can use sshfs host:/home/user/.ssh ~/hackme to edit all those settings back to open access if you change your mind later.
    – sh1
    Sep 23, 2017 at 6:15
  • 1
    the more important part of @sh1 's point is that if you're going to lock the user down to only sftp in their own .ssh/authorized_keys file, you'd better make sure to chroot them somewhere that .ssh isn't accessible, or they can just replace their authorized_keys file with something more permissve
    – erik258
    Nov 21, 2019 at 14:51
  • 1
    If all you want to do is lock an account to use SFTP only, just give their account the default shell /sbin/nologin
    – Phx
    Dec 30, 2019 at 13:20
  • chown root:group authorized_keys && chmod 0440 authorized_keys
    – MichaIng
    Feb 20, 2022 at 13:12

You must log in to answer this question.

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