Debugging SFTP Connection Failures When SSH Works: Exit Status 127 Explained


3 views

When SSH works but SFTP fails with exit status 127, the first place to check is your sshd_config. The key directive is the Subsystem configuration:

# Verify this path exists on your server
Subsystem sftp /usr/lib/openssh/sftp-server

This particular error typically indicates one of three scenarios:

  1. The SFTP subsystem binary is missing or inaccessible
  2. Permission issues with the SFTP binary or chroot environment
  3. Incorrect path specified in sshd_config

First, confirm the sftp-server binary exists on your VPS:

ssh user@example.org "ls -la /usr/lib/openssh/sftp-server"
# Alternative common locations:
ssh user@example.org "ls -la /usr/libexec/openssh/sftp-server"
ssh user@example.org "ls -la /usr/local/libexec/sftp-server"

If the path is incorrect, update your sshd_config with one of these alternatives:

# For newer OpenSSH versions
Subsystem sftp internal-sftp

# For traditional setups
Subsystem sftp /usr/libexec/openssh/sftp-server

# For chroot environments
Subsystem sftp internal-sftp -l INFO -f AUTH

When the binary exists but still fails, check these aspects:

# Verify executable permissions
ssh user@example.org "stat -c '%A %a %n' /usr/lib/openssh/sftp-server"

# Check SELinux contexts if applicable
ssh user@example.org "ls -Z /usr/lib/openssh/sftp-server"

# Verify library dependencies
ssh user@example.org "ldd /usr/lib/openssh/sftp-server"

For stubborn cases, enable verbose logging in the server's sshd_config:

# Add to sshd_config
LogLevel DEBUG3

Then monitor the logs during connection attempts:

# On the server
tail -f /var/log/auth.log | grep sftp

If OpenSSH's SFTP proves problematic, consider these alternatives:

# Using inetd/xinetd with alternative SFTP servers
Subsystem sftp /usr/sbin/sftp-server

# Modern internal implementation (recommended)
Subsystem sftp internal-sftp

Before restarting sshd, verify these settings:

  • Correct Subsystem path
  • Proper file permissions (755 for directories, 644 for files)
  • User home directory exists and is accessible
  • No conflicting chroot configurations

After making changes, always test with:

sudo sshd -t && sudo systemctl restart sshd

When your SSH connection works perfectly but SFTP fails with exit status 127, it typically indicates a subsystem configuration problem. The error suggests the remote server can't locate or execute the SFTP server binary.

The verbose output shows successful SSH authentication but immediate termination after attempting to start the SFTP subsystem:

debug1: Sending subsystem: sftp
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: Exit status 127
Connection closed

The most likely culprits are:

  • Incorrect SFTP subsystem path in sshd_config
  • Missing sftp-server binary
  • Permissions issues with the sftp-server binary
  • Incorrect SELinux/AppArmor configurations

First, check the current SFTP subsystem declaration in your sshd_config:

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

This path might be incorrect for your distribution. Common alternatives include:

Subsystem sftp /usr/libexec/openssh/sftp-server  # RHEL/CentOS
Subsystem sftp /usr/lib/ssh/sftp-server          # Ubuntu/Debian newer versions
Subsystem sftp internal-sftp                     # Modern alternative

1. Locate the Actual SFTP Binary

SSH into your server and run:

find /usr -name sftp-server -type f

Or use package manager queries:

# For Debian/Ubuntu
dpkg -L openssh-sftp-server | grep sftp-server

# For RHEL/CentOS
rpm -ql openssh-server | grep sftp-server

2. Test the SFTP Subsystem Manually

Try executing the SFTP server binary directly:

/usr/lib/openssh/sftp-server

If it fails with "command not found" or permission errors, you've found your issue.

3. Modern Configuration Alternative

Consider using the built-in SFTP server:

Subsystem sftp internal-sftp

This is often more reliable and performs better. You'll need to restart sshd after making changes:

systemctl restart sshd

Here's a complete SFTP configuration snippet that works for most modern systems:

Subsystem sftp internal-sftp

Match Group sftpusers
    ChrootDirectory /sftp/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no
    PermitTunnel no
    PasswordAuthentication yes

If using the external sftp-server, ensure:

chmod 755 /usr/lib/openssh/sftp-server
chown root:root /usr/lib/openssh/sftp-server

And verify the filesystem containing the binary isn't mounted with noexec.

After making changes, test with:

sftp -vvv user@example.com

Successful output should show the file transfer protocol negotiation instead of immediate termination.