Skip to main content

Jump Host and Proxy

In many production environments, internal servers are not directly accessible from the internet. You must route through a bastion host (also called a jump host). SCP supports this natively via -J (ProxyJump) and SSH config.

Architecture​

Your SCP data flows through the bastion host transparently — you interact as if connecting directly to the target.

ProxyJump (-J)​

The -J flag is the modern, recommended way to route through a jump host.

Example: Single Jump Host​

Command:

scp -J user@bastion.example.com ./deploy.tar.gz admin@internal-server:/opt/releases/

Output:

deploy.tar.gz 100% 150MB 32.0MB/s 00:04

Example: Jump Host with Non-Standard Port​

Command:

scp -J user@bastion:2222 ./config.yml admin@10.0.0.50:/etc/app/

Output:

config.yml 100% 2048 1.5MB/s 00:00

Example: Chained Jump Hosts​

Route through multiple bastion hosts in sequence:

Command:

scp -J user@jump1.example.com,user@jump2.example.com ./data.csv admin@target:/imports/

Output:

data.csv 100% 50MB 20.0MB/s 00:02

SSH Config for Jump Hosts​

Define the proxy in ~/.ssh/config so you don't need -J every time:

~/.ssh/config
Host bastion
HostName bastion.example.com
User jump-user
Port 22
IdentityFile ~/.ssh/bastion_key

Host internal-db
HostName 10.0.0.100
User admin
Port 22
IdentityFile ~/.ssh/internal_key
ProxyJump bastion

Example: Using Config Alias​

Command:

scp ./backup.sql internal-db:/backups/

Output:

backup.sql 100% 200MB 28.0MB/s 00:07

No -J needed — the config handles it automatically.

Combining with Other Flags​

All standard SCP flags work with jump hosts:

Example: Jump + Recursive + Compression​

Command:

scp -J user@bastion -rC ./project/ admin@internal:/opt/apps/project/

Output:

index.html 100% 4096 1.5MB/s 00:00
app.js 100% 8192 2.0MB/s 00:00
style.css 100% 2048 1.2MB/s 00:00
package.json 100% 1024 0.8MB/s 00:00

Example: Jump + Port + Identity​

Command:

scp -J admin@bastion:2222 -P 8022 -i ~/.ssh/deploy_key ./release.bin deploy@target:/opt/

Output:

release.bin 100% 500MB 25.0MB/s 00:20

Legacy ProxyCommand​

For older SSH versions without -J support, use ProxyCommand in ~/.ssh/config:

~/.ssh/config (legacy)
Host internal-legacy
HostName 10.0.0.100
User admin
ProxyCommand ssh -W %h:%p bastion

Or inline with -o:

Command:

scp -o "ProxyCommand ssh -W %h:%p bastion" ./file.txt admin@10.0.0.100:/tmp/

Output:

file.txt 100% 4096 1.0MB/s 00:00

Common Pitfalls​

IssueCauseFix
Connection timed outBastion firewall blocks your IPWhitelist your IP in bastion security group
Permission denied on targetKey not authorized on internal hostCopy key to internal server separately
Slow transfersDouble encryption overheadUse faster cipher (-c aes128-gcm@openssh.com)
-J not recognizedOld OpenSSH version (pre-7.3)Upgrade or use ProxyCommand

What's Next?​

Encountering errors? Check Common Errors for solutions to frequent SCP problems.