OpenSSH SFTP Implementation Comparison: internal-sftp vs sftp-server – Key Differences and Deployment Scenarios


3 views

OpenSSH provides two distinct methods for implementing SFTP (SSH File Transfer Protocol):

  1. sftp-server: The traditional standalone executable
  2. internal-sftp: A built-in subsystem that ships with OpenSSH

The original sftp-server is a separate binary typically located at /usr/lib/openssh/sftp-server. This implementation:

  • Runs as a separate process
  • Has been part of OpenSSH for many years
  • Requires explicit path configuration

The internal-sftp implementation:

  • Is compiled directly into the sshd binary
  • Doesn't require a separate executable
  • Uses the same privilege separation model as sshd

Use sftp-server when:

# Legacy systems where internal-sftp isn't available
# Environments requiring specific old version behavior
# Custom chroot setups that were configured for sftp-server

Use internal-sftp when:

# Modern OpenSSH installations (version 5.4+)
# Simplified configuration management
# Better integration with sshd's security features
# Resource-constrained environments (reduces process overhead)

Traditional sftp-server setup:

Subsystem sftp /usr/lib/openssh/sftp-server -l INFO
Match group sftponly
    ChrootDirectory /home/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no

Modern internal-sftp setup:

Subsystem sftp internal-sftp -l VERBOSE
Match group sftponly
    ChrootDirectory /var/sftp/%u
    ForceCommand internal-sftp
    PasswordAuthentication yes
    AllowAgentForwarding no

The internal implementation generally offers:

  • ~15-20% better performance for file transfers
  • Tighter integration with sshd's privilege separation
  • More consistent logging format with the rest of sshd
  • Better handling of connection drops

For permission issues with chroot:

# Check directory ownership:
chown root:root /chroot/directory
chmod 755 /chroot/directory

# For user subdirectories:
mkdir /chroot/directory/uploads
chown user:user /chroot/directory/uploads
chmod 770 /chroot/directory/uploads

To verify which implementation is running:

ps aux | grep sftp
# sftp-server will show as separate process
# internal-sftp runs within sshd process

OpenSSH provides two distinct methods for implementing SFTP (SSH File Transfer Protocol):

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

The traditional method uses a separate binary called sftp-server. This was the original implementation that:

  • Runs as a separate process from the SSH daemon
  • Has been part of OpenSSH for many years
  • May be found in different locations depending on your OS/distribution

The newer internal-sftp is:

  • Built directly into the OpenSSH server (sshd)
  • Runs within the same process space
  • Introduced in OpenSSH 4.9p1
Feature sftp-server internal-sftp
Process isolation Separate process Same process
Performance Slightly slower More efficient
Chroot support Limited Better integrated
Logging Separate logs Integrated with sshd

Use internal-sftp when:

  • You need chroot environments (jailed users)
  • You want better performance
  • You're running modern OpenSSH versions

Use sftp-server when:

  • You're on older systems without internal-sftp
  • You need specific features only available in sftp-server
  • You're debugging and want process isolation

Basic internal-sftp setup with chroot:

Match Group sftponly
    ChrootDirectory /home/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no

Legacy sftp-server configuration:

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

internal-sftp typically shows:

  • 10-15% better transfer speeds
  • Lower memory usage
  • Fewer context switches

internal-sftp provides:

  • Tighter integration with sshd security features
  • Better chroot support
  • More consistent logging

To switch from sftp-server to internal-sftp:

  1. Backup your sshd_config
  2. Replace the Subsystem line
  3. Test with a non-privileged account first
  4. Monitor system logs during transition