Centralized reference for SSH key management and access paths.
~/.ssh/keys/
id_ed25519 → ~/.ssh/id_ed25519 (modern, preferred)
id_ed25519_2026-05
id_ed25519_2026-05.pub
id_rsa (RSA legacy, 2048-bit)
id_rsa_old (deprecated, from 2015)
id_rsa_old.pub
is-jumper_ed25519 (specific to is-jumper entry point)
is-jumper_ed25519.pub
⚠️ IMPORTANT: The primary authentication for the company network (J1/J2) is a physical hardware security key (card/smartcard) mounted only on is-jumper (192.168.2.100).
/run/user/0/gnupg/S.gpg-agent.ssh (on is-jumper)You cannot access J1/J2 directly from your local machine. The connection must go through is-jumper, which holds the only valid physical key for the company network.
| Key | Location | Used By | Purpose | Auth Method |
|---|---|---|---|---|
| Physical card (RSA 4096) | Hardware on is-jumper only | J1, J2, company network | Primary auth for nextgen network | Hardware smartcard via GPG agent |
| is-jumper ED25519 | ~/.ssh/keys/is-jumper_ed25519 |
Your machine → is-jumper | Access the entry point | pubkey + IdentitiesOnly |
| Modern ED25519 | ~/.ssh/id_ed25519 |
Local lab, final hosts | Secondary/fallback auth | pubkey |
| Legacy RSA | ~/.ssh/id_rsa |
Legacy systems | Transitional | pubkey |
| Deprecated RSA | ~/.ssh/keys/id_rsa_old |
Very old hosts | Final fallback | pubkey |
Key insight: You authenticate TO is-jumper with your local ED25519 key, but once on is-jumper, the system uses the physical hardware key to authenticate to the company network (J1/J2).
Direct access — no jump needed:
is-jumper (192.168.2.100)
├─ User: root
├─ Port: 22
├─ Key: ~/.ssh/keys/is-jumper_ed25519
├─ IdentitiesOnly: yes
└─ Routing: SSH_ROUTE=local
Local dev machines (192.168.2.110-122)
├─ User: bogdan
├─ Port: 22
└─ Key: ~/.ssh/id_ed25519
Access to is-jumper:
# Direct connection (SSH will use is-jumper_ed25519 via IdentitiesOnly)
ssh is-jumper
# Verify key in use:
ssh -G is-jumper | grep identityfile
Access chain for internal company network (10.253.51.0/24):
Your machine (local)
↓ (ED25519 pubkey)
is-jumper (192.168.2.100) [VPN client + physical card key guardian]
↓ (SSH agent forwarding + physical card RSA 4096)
J1 (10.253.51.50:25904) or J2 (10.253.51.52:25904) [jump hosts]
↓ (SSH forward)
Final host (voip, porta, radius, etc.)
Critical: You cannot connect to J1/J2 directly from your local machine because the physical hardware key is only on is-jumper. All company network access must go through is-jumper first.
Authenticate to is-jumper with your local ED25519 key:
~/.ssh/keys/is-jumper_ed25519ssh is-jumper
Once logged in, is-jumper has access to the physical card key via GPG agent at /run/user/0/gnupg/S.gpg-agent.ssh.
SSH agent forwarding connects your SSH client to is-jumper's physical card:
SSH_AUTH_SOCK=/run/user/0/gnupg/S.gpg-agent.sshbogdan.timofte (company network default)ssh j1 # Routes: local → is-jumper → J1 (using is-jumper's physical key)
ssh j2 # Routes: local → is-jumper → J2 (using is-jumper's physical key)
The SSH config handles this automatically — you don't need to manually set up agent forwarding. The wrapper or ProxyJump chain uses is-jumper's physical key to authenticate.
Verify J1 config:
ssh -G j1 | grep -E '^(hostname|port|user|proxyjump)'
From J1/J2 to actual hosts (configured in J1's/J2's local SSH config):
~/.ssh/id_ed25519# Example: PortaOne database server
ssh porta-db # → is-jumper → J1 → 193.16.148.11
# Example: VoIP PBX
ssh voip-prov # → is-jumper → J1 → 10.253.51.139
# Example: Radius database
ssh falticeni.radius-db # → is-jumper → J1 → falticeni.radius-db:24
If internal VPN is down, use public DNS names:
# Standard (internal VPN)
ssh j1 # 10.253.51.50:25904
# Emergency (public DNS)
ssh j1.next-gen.ro # j1.next-gen.ro:25904
ssh j2.next-gen.ro # j2.next-gen.ro:25904
Both routes go through is-jumper first (no direct connection).
# Test all local lab hosts
for h in is-baobab is-ebony is-tapia is-jumper is-mazeri is-toltec is-andrafiabe is-anjohibe is-nasturel is-mat; do
timeout 2 ssh -o BatchMode=yes "$h" true 2>/dev/null && echo "$h: ✓" || echo "$h: ⚠"
done
# Automatic migration (uses legacy key to install modern key)
tools/migrate-modern-key.sh is-baobab
# Or migrate all
tools/migrate-modern-key.sh
See docs/KEY_MIGRATION.md for manual procedures.
The ~/.ssh/config is auto-generated from inventory — do not edit manually.
# Regenerate after inventory changes
python3 tools/generate-configs.py
# Deploy to ~/.ssh/config
cp generated/client.conf ~/.ssh/config
# or use the deploy script:
tools/deploy-local.sh
Config files generated:
| File | Target | Purpose |
|---|---|---|
generated/client.conf |
local client (~/.ssh/config) | local access config |
generated/is-jumper.conf |
is-jumper (via deploy) | is-jumper alias config |
generated/j1.conf |
J1 (server-side) | final host access on J1 |
generated/j2.conf |
J2 (server-side) | final host access on J2 |
⚠️ First check: Do you have access to is-jumper?
ssh is-jumper "echo access ok"
If this fails, the issue is your local ED25519 key or is-jumper authentication. Fix that first.
If is-jumper works but J1 fails:
The issue is likely the physical card key is not properly exposed or SSH agent forwarding isn't working.
Diagnosis:
# 1. Check if you can reach is-jumper
ssh is-jumper
# 2. From is-jumper, verify the physical card is available
ssh is-jumper "ls -la /run/user/0/gnupg/S.gpg-agent.ssh"
# Should exist and be readable
# 3. Check J1 connectivity with verbose output
ssh -vvv j1 2>&1 | grep -E "ProxyJump|Offering|Authentications|Trying"
Solutions:
is-jumper's SSH agent not running: ```bash ssh is-jumper "ps aux | grep gpg-agent"
SSH config not set up for agent forwarding:
ssh -G j1 | grep proxyjumpForwardAgent yes is set (check generated config)Physical card key not accessible:
SSH on your machine not supporting agent forwarding: ```bash
ssh -A is-jumper ```
The issue: Your local ED25519 key isn't authorized on is-jumper.
Verify your key is present:
ls -la ~/.ssh/keys/is-jumper_ed25519
cat ~/.ssh/keys/is-jumper_ed25519.pub
Check that is-jumper has your key:
ssh is-jumper "cat ~/.ssh/authorized_keys | grep -i ed25519"
If your key isn't there, it needs to be added by the is-jumper administrator.
Cause: Trying to reach J1/J2 directly without going through is-jumper.
Check ProxyJump:
ssh -G j1 | grep proxyjump
# Must show: proxyjump is-jumper
If not, regenerate config: python3 tools/generate-configs.py && cp generated/client.conf ~/.ssh/config
For jump hosts (reduce to 5-10 seconds):
ssh -o ConnectTimeout=5 is-jumper
ssh -o ConnectTimeout=5 j1
Check network:
# is-jumper reachable?
ping 192.168.2.100
# If behind firewall, may need port 22 open to is-jumper
id_ed25519 and id_rsa_old until all hosts migratedtools/migrate-modern-key.sh <host>python3 tools/generate-configs.pyssh -G <alias> to verify config without connecting~/.ssh/config — it's auto-generated~/.ssh/keys/ with mode 600.doc/ssh-jump-architecture.md)