Source-controlled SSH routing and configuration for multi-user jump infrastructure
(is-jumper gateway → J1/J2 company network → final hosts).
⚠️ New to this project? Start with KEYS_AND_ACCESS.md — it explains which SSH key to use where, and how the access chain works.
# 1. Access the local jump gateway
ssh is-jumper
# 2. From there, reach company network via J1 or J2
ssh j1 # or: ssh j2
# 3. From J1, reach final hosts
ssh porta-db # automatic routing: local → is-jumper → J1 → porta-db
The ~/.ssh/config is auto-generated from inventory/hosts.yaml — edit the
inventory, not the config file.
~/Documents/Workspaces/Bogdan/ssh-infrastructure~/.ssh (do not commit)Keep secrets and machine-local state out of version control:
~/.ssh/keys/ (not in git)authorized_keys, known_hosts, socket state (not in git)Deploy the local runtime with:
# Regenerate ~/.ssh/config from inventory + install wrappers
tools/deploy-local.sh
This directory is the git repository for source files only. Generated configs, local state, keys, known hosts, and handoff notes stay out of version control.
Track source changes with:
git status
git add inventory schema scripts tools .doc README.md .gitignore
git commit
Which key goes where? See KEYS_AND_ACCESS.md for the full matrix.
Migrate hosts from legacy RSA to modern ED25519:
# Migrate all legacy hosts
tools/migrate-modern-key.sh
# Migrate a specific host
tools/migrate-modern-key.sh is-baobab
Details: docs/KEY_MIGRATION.md
~/.ssh/config
~/.local/bin/ssh
~/.local/bin/scp
~/.local/bin/sftp
The wrapper sources stay versioned in scripts/ inside the project; deploy
installs executable copies into ~/.local/bin and removes the obsolete
~/.ssh/scripts runtime layout from older checkouts.
The structured source of truth starts in:
inventory/hosts.yaml
schema/hosts.schema.json
tools/generate-configs.py
The generated/*.conf files are deploy artifacts. They are ignored by git and
can be recreated at any time with tools/deploy-local.sh.
The single source of truth:
inventory/hosts.yaml ← edit here to add/modify hosts
↓ (python3 tools/generate-configs.py)
generated/client.conf ← deployed to ~/.ssh/config
generated/is-jumper.conf ← deployed to is-jumper
generated/j1.conf ← deployed to J1
generated/j2.conf ← deployed to J2
| Context | User | Port | Notes |
|---|---|---|---|
| Jump hosts (J1, J2) | bogdan.timofte |
24 (standard) or 25904 (VPN) |
override in inventory |
| Final hosts | bogdan |
22 |
most systems; dotted usernames cause issues |
| Interactive auth (Cisco, OLTs) | varies | 22 |
marked with auth: password_interactive |
# Option 1: Full deploy (recommended)
tools/deploy-local.sh
# Option 2: Manual steps
python3 tools/generate-configs.py # Regenerate configs
cp generated/client.conf ~/.ssh/config # Install client config
Pull latest hosts.yaml from nextgen and redeploy:
tools/sync-hosts-from-upstream.sh
# Customize:
DEPLOY_AFTER_SYNC=0 tools/sync-hosts-from-upstream.sh # generate only
UPSTREAM_SSH_TARGET=user@host tools/sync-hosts-from-upstream.sh # custom source