A private server may be reachable only through a bastion host. Add a second network boundary, and the route becomes easy to mix up: which username belongs to which machine, where does each key live, and which hop is failing?
This guide starts with an OpenSSH example on a Mac, then describes how the same connection layout maps to a mobile SSH client. All addresses, usernames, and key paths below are illustrative; replace them with your own authorized hosts.
Disclosure: I develop JTerm, an SSH client for iPhone, iPad, and Mac. The OpenSSH examples work independently of JTerm.
1. Write down the route
Suppose the connection path is:
Your device -> public bastion -> internal bastion -> app server
Your device must reach the first bastion. Each bastion must be able to reach the next machine on its SSH port. Authentication is separate at every hop.
For a quick connection with your existing authentication setup:
ssh -J alice@bastion.example.com,bob@10.0.1.10 deploy@10.0.2.20
The comma-separated jump hosts are visited in order. The final argument is the destination; it is not another entry in the jump list. OpenSSH documents this behavior under ssh -J.
2. Give each machine its own configuration
For repeated use, add host entries to your local ~/.ssh/config. This example assumes you already have the matching private keys locally and the corresponding public keys authorized on the appropriate servers.
Host edge-bastion
HostName bastion.example.com
User alice
IdentityFile ~/.ssh/id_ed25519_edge
IdentitiesOnly yes
Host inner-bastion
HostName 10.0.1.10
User bob
IdentityFile ~/.ssh/id_ed25519_inner
IdentitiesOnly yes
Host private-app
HostName 10.0.2.20
User deploy
IdentityFile ~/.ssh/id_ed25519_app
IdentitiesOnly yes
ProxyJump edge-bastion,inner-bastion
Now connect with:
ssh private-app
Set a Port in the relevant host entry if that machine uses a nonstandard SSH port. A destination's settings do not generally apply to its jump hosts, which is why each machine has its own entry. See the ProxyJump configuration reference.
You do not need to copy private keys onto the bastions or enable agent forwarding for this arrangement. Verify unfamiliar host-key fingerprints through a trusted channel before accepting them.
3. Reuse the route for file transfers
OpenSSH SFTP can use the same destination alias:
sftp private-app
Inside the SFTP prompt, this example downloads a readable file from the remote account's home directory:
pwd
ls
get notes.txt ./notes-copy.txt
bye
pwd and ls inspect the remote location. get downloads to your local machine; choose a local filename that will not overwrite something you need. The destination must provide an SFTP subsystem, and your remote account needs permission to read the file. See the SFTP manual.
4. Find the failing hop
Start with the shortest connection, then extend it:
ssh -v edge-bastion
ssh -v -J edge-bastion inner-bastion
ssh -v private-app
A timeout suggests checking reachability, routing, and firewall rules for the next hop. An authentication failure means checking the username and credential for the machine named in the diagnostic output. The -v option helps distinguish those stages.
If authentication succeeds but forwarding is rejected, ask the administrator to check the bastion's forwarding policy, including AllowTcpForwarding, PermitOpen, and any account or key restrictions. An interactive shell working on a bastion does not prove that forwarding is permitted. The relevant server options are documented in sshd_config.
5. Use the same layout on iPhone and iPad
On a touch device, keeping the route and credentials organized matters more than remembering a long command. A useful connection record contains the destination, the ordered jump hosts, and the authentication details for each machine.
JTerm supports ordered multi-hop SSH connections using saved credentials for each hop. It also includes SFTP browsing, uploads, downloads, and inline text editing, alongside saved commands and iCloud sync across Apple devices.
If that fits your workflow, you can find the app and download link on the JTerm website. I would welcome feedback on what is hardest about managing servers from a phone or tablet: setting up the route, working with files, or using the terminal itself?
Top comments (0)