When dealing with servers that restrict access to SFTP-only (without full SSH shell access), traditional rsync-over-SSH methods fail with protocol errors. The fundamental issue stems from rsync's requirement for a clean bidirectional communication channel that pure SFTP doesn't provide.
Attempting rsync -av /source ssh user@remotehost:/target/
on SFTP-only hosts typically yields:
protocol version mismatch -- is your shell clean?
rsync error: protocol incompatibility (code 2)
ssh-dummy-shell: Command not allowed
1. Using rclone as SFTP Wrapper
The most robust solution is using rclone which natively supports SFTP:
# First configure rclone
rclone config
# Create new SFTP remote
n) New remote
name: sftpbackup
type: sftp
host: your.sftp.server
user: yourusername
# Then sync:
rclone sync /local/path sftpbackup:remote/path
2. FUSE-based Approach (for Advanced Users)
While slower, this method provides rsync compatibility:
# Mount remote SFTP as local filesystem
sshfs -o sftp_server=/usr/lib/openssh/sftp-server user@host:/remote/path /local/mount
# Now use regular rsync
rsync -av /source /local/mount/target
# Remember to unmount after
fusermount -u /local/mount
For large file transfers:
- rclone supports multi-threaded transfers with
--transfers=N
- Compression can be enabled with
--compress
- Consider
--checksum
for better sync accuracy
Tool | SFTP Support | Delta Transfer | Speed |
---|---|---|---|
rclone | Excellent | Partial | Fast |
lftp | Yes | No | Medium |
csync2 | With plugin | Yes | Slow |
For mission-critical deployments, consider setting up a minimal SSH access with:
Match User backupuser
ForceCommand internal-sftp
ChrootDirectory /backups
PermitTunnel no
X11Forwarding no
AllowTcpForwarding no
This allows rsync-over-SSH while maintaining security constraints.
When attempting to use rsync with servers that only allow SFTP access (no full SSH shell), you'll encounter the frustrating "protocol version mismatch" error. This occurs because rsync fundamentally relies on SSH shell access for its transport layer protocol handshake.
rsync -av /source sshuser@remotehost:/target/
# Output:
# protocol version mismatch -- is your shell clean?
# rsync error: protocol incompatibility (code 2)
The diagnostic test confirms the server's limitation:
ssh remotehost /bin/true > out.dat
# Contents of out.dat:
# ssh-dummy-shell: Command not allowed
Traditional rsync solutions like SSHFS mounting are impractical due to performance issues:
- High latency on file operations
- Unreliable for large transfers
- No native delta-transfer benefits
Option 1: lftp Mirroring
A robust alternative that supports SFTP's delta-transfer capabilities:
lftp -u user,password sftp://remotehost -e "
mirror --reverse --delete --only-newer /local/path /remote/path;
quit"
Option 2: rclone with SFTP Backend
Configuration example for ~/.config/rclone/rclone.conf:
[sftp-remote]
type = sftp
host = remotehost
user = username
pass = password
key_pem = ~/.ssh/id_rsa
Sync command with checksum verification:
rclone sync -P --checksum /local/path sftp-remote:/remote/path
Option 3: Paramiko-based Python Script
For custom delta-transfer implementation:
import paramiko
from stat import S_ISDIR
def sftp_sync(local_path, remote_path):
transport = paramiko.Transport(('host', 22))
transport.connect(username='user', password='pass')
sftp = paramiko.SFTPClient.from_transport(transport)
for root, dirs, files in os.walk(local_path):
remote_root = os.path.join(remote_path, os.path.relpath(root, local_path))
try:
sftp.stat(remote_root)
except IOError:
sftp.mkdir(remote_root)
for file in files:
local_file = os.path.join(root, file)
remote_file = os.path.join(remote_root, file)
local_mtime = os.path.getmtime(local_file)
try:
remote_attr = sftp.stat(remote_file)
if local_mtime <= remote_attr.st_mtime:
continue
except IOError:
pass
sftp.put(local_file, remote_file)
When forced to use SFTP instead of native rsync:
- Expect 30-50% slower transfer speeds
- Memory usage increases for large directory trees
- No hard link preservation capability
For critical production systems, consider requesting temporary SSH access from administrators specifically for rsync operations.