Create KEYS_AND_ACCESS.md as single source of truth for: - Which SSH key to use where (id_ed25519, is-jumper_ed25519, legacy keys) - Access paths and routing (local lab, production J1/J2, emergency public routes) - Key usage matrix and host access chains - Troubleshooting guide for authentication and routing issues Update README.md to: - Point readers to KEYS_AND_ACCESS.md upfront - Simplify to quick start + file structure overview - Consolidate inventory/config generation into concise section - Remove redundant detailed rules (now in dedicated guide) Reduces documentation fragmentation across multiple files in English/Romanian. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@@ -0,0 +1,268 @@ |
||
| 1 |
+# SSH Keys and Access Guide |
|
| 2 |
+ |
|
| 3 |
+Centralized reference for SSH key management and access paths. |
|
| 4 |
+ |
|
| 5 |
+## Key Files Location |
|
| 6 |
+ |
|
| 7 |
+All SSH keys are stored in `~/.ssh/keys/`: |
|
| 8 |
+ |
|
| 9 |
+``` |
|
| 10 |
+~/.ssh/keys/ |
|
| 11 |
+ id_ed25519 → ~/.ssh/id_ed25519 (modern, preferred) |
|
| 12 |
+ id_ed25519_2026-05 |
|
| 13 |
+ id_ed25519_2026-05.pub |
|
| 14 |
+ id_rsa (RSA legacy, 2048-bit) |
|
| 15 |
+ id_rsa_old (deprecated, from 2015) |
|
| 16 |
+ id_rsa_old.pub |
|
| 17 |
+ is-jumper_ed25519 (specific to is-jumper entry point) |
|
| 18 |
+ is-jumper_ed25519.pub |
|
| 19 |
+``` |
|
| 20 |
+ |
|
| 21 |
+## Key Usage Matrix |
|
| 22 |
+ |
|
| 23 |
+| Key | File | Used By | Auth Method | Hosts | |
|
| 24 |
+|-----|------|---------|-------------|-------| |
|
| 25 |
+| **Modern ED25519** | `~/.ssh/id_ed25519` | most systems | pubkey | All modern hosts, J1, J2, local lab | |
|
| 26 |
+| **is-jumper ED25519** | `~/.ssh/keys/is-jumper_ed25519` | is-jumper (entry point) | pubkey + IdentitiesOnly | Entry point `192.168.2.100` | |
|
| 27 |
+| **Legacy RSA** | `~/.ssh/id_rsa` | legacy systems | pubkey | Old hosts still on RSA auth | |
|
| 28 |
+| **Deprecated RSA** | `~/.ssh/keys/id_rsa_old` | final fallback | pubkey | Hosts not yet migrated (being phased out) | |
|
| 29 |
+ |
|
| 30 |
+## Access Paths and Routing |
|
| 31 |
+ |
|
| 32 |
+### 1. Local Lab Setup (192.168.2.0/24) |
|
| 33 |
+ |
|
| 34 |
+**Direct access** — no jump needed: |
|
| 35 |
+ |
|
| 36 |
+``` |
|
| 37 |
+is-jumper (192.168.2.100) |
|
| 38 |
+├─ User: root |
|
| 39 |
+├─ Port: 22 |
|
| 40 |
+├─ Key: ~/.ssh/keys/is-jumper_ed25519 |
|
| 41 |
+├─ IdentitiesOnly: yes |
|
| 42 |
+└─ Routing: SSH_ROUTE=local |
|
| 43 |
+ |
|
| 44 |
+Local dev machines (192.168.2.110-122) |
|
| 45 |
+├─ User: bogdan |
|
| 46 |
+├─ Port: 22 |
|
| 47 |
+└─ Key: ~/.ssh/id_ed25519 |
|
| 48 |
+``` |
|
| 49 |
+ |
|
| 50 |
+Access to is-jumper: |
|
| 51 |
+ |
|
| 52 |
+```bash |
|
| 53 |
+# Direct connection (SSH will use is-jumper_ed25519 via IdentitiesOnly) |
|
| 54 |
+ssh is-jumper |
|
| 55 |
+ |
|
| 56 |
+# Verify key in use: |
|
| 57 |
+ssh -G is-jumper | grep identityfile |
|
| 58 |
+``` |
|
| 59 |
+ |
|
| 60 |
+### 2. Production: Via is-jumper → J1/J2 → Final Hosts |
|
| 61 |
+ |
|
| 62 |
+**Access chain for internal company network (10.253.51.0/24)**: |
|
| 63 |
+ |
|
| 64 |
+``` |
|
| 65 |
+Your machine (local) |
|
| 66 |
+ ↓ (ProxyJump is-jumper) |
|
| 67 |
+is-jumper (192.168.2.100) [VPN client + key guardian] |
|
| 68 |
+ ↓ (SSH forward) |
|
| 69 |
+J1 (10.253.51.50:25904) or J2 (10.253.51.52:25904) [jump hosts] |
|
| 70 |
+ ↓ (SSH forward) |
|
| 71 |
+Final host (voip, porta, radius, etc.) |
|
| 72 |
+``` |
|
| 73 |
+ |
|
| 74 |
+#### Step 1: is-jumper (entry point) |
|
| 75 |
+ |
|
| 76 |
+- **User**: root |
|
| 77 |
+- **Host**: 192.168.2.100 |
|
| 78 |
+- **Port**: 22 |
|
| 79 |
+- **Key**: `~/.ssh/keys/is-jumper_ed25519` |
|
| 80 |
+- **IdentitiesOnly**: yes (forces use of specified key only) |
|
| 81 |
+ |
|
| 82 |
+```bash |
|
| 83 |
+ssh is-jumper |
|
| 84 |
+``` |
|
| 85 |
+ |
|
| 86 |
+#### Step 2: J1/J2 (jump hosts) |
|
| 87 |
+ |
|
| 88 |
+**Reached through is-jumper via ProxyJump**: |
|
| 89 |
+ |
|
| 90 |
+- **User**: bogdan.timofte (jump host default) |
|
| 91 |
+- **Hostname**: 10.253.51.50 (J1) or 10.253.51.52 (J2) |
|
| 92 |
+- **Port**: 25904 |
|
| 93 |
+- **Key**: `~/.ssh/id_ed25519` (offered by SSH client) |
|
| 94 |
+- **ProxyJump**: is-jumper (configured in ~/.ssh/config) |
|
| 95 |
+ |
|
| 96 |
+```bash |
|
| 97 |
+ssh j1 # Routes: local → is-jumper → J1 |
|
| 98 |
+ssh j2 # Routes: local → is-jumper → J2 |
|
| 99 |
+ |
|
| 100 |
+# Interactive jump host session: |
|
| 101 |
+ssh -J is-jumper bogdan.timofte@10.253.51.50 -p 25904 |
|
| 102 |
+``` |
|
| 103 |
+ |
|
| 104 |
+**Verify J1 config**: |
|
| 105 |
+ |
|
| 106 |
+```bash |
|
| 107 |
+ssh -G j1 | grep -E '^(hostname|port|user|proxyjump|identityfile)' |
|
| 108 |
+``` |
|
| 109 |
+ |
|
| 110 |
+#### Step 3: Final Hosts |
|
| 111 |
+ |
|
| 112 |
+**From J1/J2 to actual hosts** (configured in J1's/J2's local SSH config): |
|
| 113 |
+ |
|
| 114 |
+- **User**: varies by host group (bogdan, bogdan.timofte, root, etc.) |
|
| 115 |
+- **Port**: 22 (standard) or 24 (jump hosts default) or custom |
|
| 116 |
+- **Key**: `~/.ssh/id_ed25519` |
|
| 117 |
+- **ProxyJump**: j1 or j2 |
|
| 118 |
+ |
|
| 119 |
+```bash |
|
| 120 |
+# Example: PortaOne database server |
|
| 121 |
+ssh porta-db # → is-jumper → J1 → 193.16.148.11 |
|
| 122 |
+ |
|
| 123 |
+# Example: VoIP PBX |
|
| 124 |
+ssh voip-prov # → is-jumper → J1 → 10.253.51.139 |
|
| 125 |
+ |
|
| 126 |
+# Example: Radius database |
|
| 127 |
+ssh falticeni.radius-db # → is-jumper → J1 → falticeni.radius-db:24 |
|
| 128 |
+``` |
|
| 129 |
+ |
|
| 130 |
+### 3. Emergency Public Routes (j1.next-gen.ro / j2.next-gen.ro) |
|
| 131 |
+ |
|
| 132 |
+If internal VPN is down, use public DNS names: |
|
| 133 |
+ |
|
| 134 |
+```bash |
|
| 135 |
+# Standard (internal VPN) |
|
| 136 |
+ssh j1 # 10.253.51.50:25904 |
|
| 137 |
+ |
|
| 138 |
+# Emergency (public DNS) |
|
| 139 |
+ssh j1.next-gen.ro # j1.next-gen.ro:25904 |
|
| 140 |
+ssh j2.next-gen.ro # j2.next-gen.ro:25904 |
|
| 141 |
+``` |
|
| 142 |
+ |
|
| 143 |
+Both routes go through is-jumper first (no direct connection). |
|
| 144 |
+ |
|
| 145 |
+## Key Migration Status |
|
| 146 |
+ |
|
| 147 |
+### Check which hosts have modern keys |
|
| 148 |
+ |
|
| 149 |
+```bash |
|
| 150 |
+# Test all local lab hosts |
|
| 151 |
+for h in is-baobab is-ebony is-tapia is-jumper is-mazeri is-toltec is-andrafiabe is-anjohibe is-nasturel is-mat; do |
|
| 152 |
+ timeout 2 ssh -o BatchMode=yes "$h" true 2>/dev/null && echo "$h: ✓" || echo "$h: ⚠" |
|
| 153 |
+done |
|
| 154 |
+``` |
|
| 155 |
+ |
|
| 156 |
+### Migrate a host to modern ED25519 key |
|
| 157 |
+ |
|
| 158 |
+```bash |
|
| 159 |
+# Automatic migration (uses legacy key to install modern key) |
|
| 160 |
+tools/migrate-modern-key.sh is-baobab |
|
| 161 |
+ |
|
| 162 |
+# Or migrate all |
|
| 163 |
+tools/migrate-modern-key.sh |
|
| 164 |
+``` |
|
| 165 |
+ |
|
| 166 |
+See [docs/KEY_MIGRATION.md](docs/KEY_MIGRATION.md) for manual procedures. |
|
| 167 |
+ |
|
| 168 |
+## SSH Config Generation |
|
| 169 |
+ |
|
| 170 |
+The `~/.ssh/config` is **auto-generated** from inventory — do not edit manually. |
|
| 171 |
+ |
|
| 172 |
+```bash |
|
| 173 |
+# Regenerate after inventory changes |
|
| 174 |
+python3 tools/generate-configs.py |
|
| 175 |
+ |
|
| 176 |
+# Deploy to ~/.ssh/config |
|
| 177 |
+cp generated/client.conf ~/.ssh/config |
|
| 178 |
+# or use the deploy script: |
|
| 179 |
+tools/deploy-local.sh |
|
| 180 |
+``` |
|
| 181 |
+ |
|
| 182 |
+**Config files generated**: |
|
| 183 |
+ |
|
| 184 |
+| File | Target | Purpose | |
|
| 185 |
+|------|--------|---------| |
|
| 186 |
+| `generated/client.conf` | local client (~/.ssh/config) | local access config | |
|
| 187 |
+| `generated/is-jumper.conf` | is-jumper (via deploy) | is-jumper alias config | |
|
| 188 |
+| `generated/j1.conf` | J1 (server-side) | final host access on J1 | |
|
| 189 |
+| `generated/j2.conf` | J2 (server-side) | final host access on J2 | |
|
| 190 |
+ |
|
| 191 |
+## Troubleshooting |
|
| 192 |
+ |
|
| 193 |
+### "Permission denied (publickey)" |
|
| 194 |
+ |
|
| 195 |
+**Diagnosis**: |
|
| 196 |
+ |
|
| 197 |
+```bash |
|
| 198 |
+# Check which key is being offered |
|
| 199 |
+ssh -vvv porta-db 2>&1 | grep -E "Offering|Authentications" |
|
| 200 |
+ |
|
| 201 |
+# Check ProxyJump chain |
|
| 202 |
+ssh -vvv j1 2>&1 | grep -E "ProxyJump|Connecting" |
|
| 203 |
+``` |
|
| 204 |
+ |
|
| 205 |
+**Solutions**: |
|
| 206 |
+ |
|
| 207 |
+1. **On is-jumper** — verify IdentitiesOnly and key: |
|
| 208 |
+ ```bash |
|
| 209 |
+ ssh -G is-jumper | grep identities |
|
| 210 |
+ ``` |
|
| 211 |
+ Should show: `identitiesonly yes` and `identityfile ~/.ssh/keys/is-jumper_ed25519` |
|
| 212 |
+ |
|
| 213 |
+2. **On J1/J2** — verify modern key is installed: |
|
| 214 |
+ ```bash |
|
| 215 |
+ ssh is-jumper "ssh-keygen -l -f /home/bogdan.timofte/.ssh/authorized_keys" |
|
| 216 |
+ ``` |
|
| 217 |
+ Should include ED25519 fingerprints. |
|
| 218 |
+ |
|
| 219 |
+3. **Regenerate and redeploy config**: |
|
| 220 |
+ ```bash |
|
| 221 |
+ python3 tools/generate-configs.py && cp generated/client.conf ~/.ssh/config |
|
| 222 |
+ ``` |
|
| 223 |
+ |
|
| 224 |
+### "No route to host" (10.253.51.x) |
|
| 225 |
+ |
|
| 226 |
+**Cause**: Trying to access internal IPs directly without is-jumper. |
|
| 227 |
+ |
|
| 228 |
+**Solution**: Verify ProxyJump is configured: |
|
| 229 |
+ |
|
| 230 |
+```bash |
|
| 231 |
+ssh -G vo52 | grep proxyjump |
|
| 232 |
+# Should output: proxyjump j1 |
|
| 233 |
+``` |
|
| 234 |
+ |
|
| 235 |
+### SSH hangs or timeouts |
|
| 236 |
+ |
|
| 237 |
+**For jump hosts** (reduce to 5-10 seconds): |
|
| 238 |
+ |
|
| 239 |
+```bash |
|
| 240 |
+ssh -o ConnectTimeout=5 is-jumper |
|
| 241 |
+ssh -o ConnectTimeout=5 j1 |
|
| 242 |
+``` |
|
| 243 |
+ |
|
| 244 |
+**Check network**: |
|
| 245 |
+ |
|
| 246 |
+```bash |
|
| 247 |
+# is-jumper reachable? |
|
| 248 |
+ping 192.168.2.100 |
|
| 249 |
+ |
|
| 250 |
+# If behind firewall, may need port 22 open to is-jumper |
|
| 251 |
+``` |
|
| 252 |
+ |
|
| 253 |
+## Maintenance Checklist |
|
| 254 |
+ |
|
| 255 |
+- [ ] Keep both `id_ed25519` and `id_rsa_old` until all hosts migrated |
|
| 256 |
+- [ ] After adding new hosts: run `tools/migrate-modern-key.sh <host>` |
|
| 257 |
+- [ ] After inventory changes: regenerate with `python3 tools/generate-configs.py` |
|
| 258 |
+- [ ] Periodically check: `ssh -G <alias>` to verify config without connecting |
|
| 259 |
+- [ ] Never manually edit `~/.ssh/config` — it's auto-generated |
|
| 260 |
+- [ ] Keep keys in `~/.ssh/keys/` with mode `600` |
|
| 261 |
+ |
|
| 262 |
+## References |
|
| 263 |
+ |
|
| 264 |
+- [Ed25519 vs RSA Security](https://ianix.com/pub/ed25519-deployment.html) |
|
| 265 |
+- [OpenSSH Manual](https://man.openbsd.org/ssh) |
|
| 266 |
+- [Project inventory structure](inventory/hosts.yaml) |
|
| 267 |
+- [Key migration procedures](docs/KEY_MIGRATION.md) |
|
| 268 |
+- [Architecture details](ARCHITECTURE.md) (legacy Romanian docs: `.doc/ssh-jump-architecture.md`) |
|
@@ -1,34 +1,44 @@ |
||
| 1 | 1 |
# SSH Infrastructure |
| 2 | 2 |
|
| 3 |
-Source-controlled SSH routing and wrapper configuration for the Next-Gen jump |
|
| 4 |
-infrastructure. |
|
| 3 |
+Source-controlled SSH routing and configuration for multi-user jump infrastructure |
|
| 4 |
+(`is-jumper` gateway → J1/J2 company network → final hosts). |
|
| 5 | 5 |
|
| 6 |
-## Runtime vs project |
|
| 6 |
+**⚠️ New to this project?** Start with [KEYS_AND_ACCESS.md](KEYS_AND_ACCESS.md) — it |
|
| 7 |
+explains which SSH key to use where, and how the access chain works. |
|
| 7 | 8 |
|
| 8 |
-- Project source: `~/Documents/Workspaces/Bogdan/ssh-infrastructure` |
|
| 9 |
-- OpenSSH runtime: `~/.ssh` |
|
| 9 |
+## Quick Start |
|
| 10 | 10 |
|
| 11 |
-Keep secrets and machine-local state out of this repository: |
|
| 11 |
+```bash |
|
| 12 |
+# 1. Access the local jump gateway |
|
| 13 |
+ssh is-jumper |
|
| 14 |
+ |
|
| 15 |
+# 2. From there, reach company network via J1 or J2 |
|
| 16 |
+ssh j1 # or: ssh j2 |
|
| 17 |
+ |
|
| 18 |
+# 3. From J1, reach final hosts |
|
| 19 |
+ssh porta-db # automatic routing: local → is-jumper → J1 → porta-db |
|
| 20 |
+``` |
|
| 21 |
+ |
|
| 22 |
+The `~/.ssh/config` is auto-generated from `inventory/hosts.yaml` — edit the |
|
| 23 |
+inventory, not the config file. |
|
| 24 |
+ |
|
| 25 |
+## File Structure |
|
| 12 | 26 |
|
| 13 |
-- private keys: `~/.ssh/keys/` |
|
| 14 |
-- `authorized_keys` |
|
| 15 |
-- `known_hosts` |
|
| 16 |
-- socket or agent state |
|
| 27 |
+- **Project source**: `~/Documents/Workspaces/Bogdan/ssh-infrastructure` |
|
| 28 |
+- **OpenSSH runtime**: `~/.ssh` (do not commit) |
|
| 17 | 29 |
|
| 18 |
-The runtime `~/.ssh/config` is a generated single-file OpenSSH config. The |
|
| 19 |
-project is the place to edit wrappers, documentation, inventory, and generator |
|
| 20 |
-code. |
|
| 30 |
+Keep secrets and machine-local state out of version control: |
|
| 21 | 31 |
|
| 22 |
-Deploy the local runtime copy with: |
|
| 32 |
+- private keys: `~/.ssh/keys/` (not in git) |
|
| 33 |
+- `authorized_keys`, `known_hosts`, socket state (not in git) |
|
| 34 |
+ |
|
| 35 |
+Deploy the local runtime with: |
|
| 23 | 36 |
|
| 24 | 37 |
```bash |
| 38 |
+# Regenerate ~/.ssh/config from inventory + install wrappers |
|
| 25 | 39 |
tools/deploy-local.sh |
| 26 | 40 |
``` |
| 27 | 41 |
|
| 28 |
-The deploy script generates `generated/client.conf`, installs it as |
|
| 29 |
-`~/.ssh/config`, and installs the wrapper commands into `~/.local/bin`. |
|
| 30 |
-It does not touch keys, `authorized_keys`, or `known_hosts`. |
|
| 31 |
- |
|
| 32 | 42 |
## Version control |
| 33 | 43 |
|
| 34 | 44 |
This directory is the git repository for source files only. Generated configs, |
@@ -44,17 +54,19 @@ git commit |
||
| 44 | 54 |
|
| 45 | 55 |
## SSH Key Management |
| 46 | 56 |
|
| 47 |
-Modern key migration from legacy infrastructure: |
|
| 57 |
+Which key goes where? See [KEYS_AND_ACCESS.md](KEYS_AND_ACCESS.md) for the full matrix. |
|
| 58 |
+ |
|
| 59 |
+Migrate hosts from legacy RSA to modern ED25519: |
|
| 48 | 60 |
|
| 49 | 61 |
```bash |
| 50 |
-# Migrate all legacy hosts to modern key (ed25519) |
|
| 62 |
+# Migrate all legacy hosts |
|
| 51 | 63 |
tools/migrate-modern-key.sh |
| 52 | 64 |
|
| 53 |
-# Migrate specific host |
|
| 65 |
+# Migrate a specific host |
|
| 54 | 66 |
tools/migrate-modern-key.sh is-baobab |
| 55 | 67 |
``` |
| 56 | 68 |
|
| 57 |
-See [docs/KEY_MIGRATION.md](docs/KEY_MIGRATION.md) for detailed procedures. |
|
| 69 |
+Details: [docs/KEY_MIGRATION.md](docs/KEY_MIGRATION.md) |
|
| 58 | 70 |
|
| 59 | 71 |
## Current client layout |
| 60 | 72 |
|
@@ -82,49 +94,46 @@ tools/generate-configs.py |
||
| 82 | 94 |
The `generated/*.conf` files are deploy artifacts. They are ignored by git and |
| 83 | 95 |
can be recreated at any time with `tools/deploy-local.sh`. |
| 84 | 96 |
|
| 85 |
-## Sync from upstream |
|
| 97 |
+## Inventory and Config Generation |
|
| 86 | 98 |
|
| 87 |
-Pull the upstream inventory, apply this machine's local `is-jumper` key override, |
|
| 88 |
-regenerate, and deploy if the inventory changed: |
|
| 99 |
+The single source of truth: |
|
| 89 | 100 |
|
| 90 |
-```bash |
|
| 91 |
-tools/sync-hosts-from-upstream.sh |
|
| 101 |
+```text |
|
| 102 |
+inventory/hosts.yaml ← edit here to add/modify hosts |
|
| 103 |
+ ↓ (python3 tools/generate-configs.py) |
|
| 104 |
+generated/client.conf ← deployed to ~/.ssh/config |
|
| 105 |
+generated/is-jumper.conf ← deployed to is-jumper |
|
| 106 |
+generated/j1.conf ← deployed to J1 |
|
| 107 |
+generated/j2.conf ← deployed to J2 |
|
| 92 | 108 |
``` |
| 93 | 109 |
|
| 94 |
-Defaults: |
|
| 110 |
+### User and Port Defaults |
|
| 95 | 111 |
|
| 96 |
-```text |
|
| 97 |
-UPSTREAM_SSH_TARGET=nextgen@192.168.2.103 |
|
| 98 |
-UPSTREAM_HOSTS_PATH=/home/nextgen/projects/ssh-infrastructure/inventory/hosts.yaml |
|
| 99 |
-LOCAL_IS_JUMPER_IDENTITY_FILE=~/.ssh/keys/is-jumper_ed25519 |
|
| 100 |
-DEPLOY_AFTER_SYNC=1 |
|
| 101 |
-``` |
|
| 112 |
+| Context | User | Port | Notes | |
|
| 113 |
+| --- | --- | --- | --- | |
|
| 114 |
+| Jump hosts (J1, J2) | `bogdan.timofte` | `24` (standard) or `25904` (VPN) | override in inventory | |
|
| 115 |
+| Final hosts | `bogdan` | `22` | most systems; dotted usernames cause issues | |
|
| 116 |
+| Interactive auth (Cisco, OLTs) | varies | `22` | marked with `auth: password_interactive` | |
|
| 102 | 117 |
|
| 103 |
-Useful overrides: |
|
| 118 |
+### Deployment |
|
| 104 | 119 |
|
| 105 | 120 |
```bash |
| 106 |
-UPSTREAM_HOSTS_FILE=/tmp/hosts.yaml tools/sync-hosts-from-upstream.sh |
|
| 107 |
-DEPLOY_AFTER_SYNC=0 tools/sync-hosts-from-upstream.sh |
|
| 108 |
-FORCE_DEPLOY=1 tools/sync-hosts-from-upstream.sh |
|
| 121 |
+# Option 1: Full deploy (recommended) |
|
| 122 |
+tools/deploy-local.sh |
|
| 123 |
+ |
|
| 124 |
+# Option 2: Manual steps |
|
| 125 |
+python3 tools/generate-configs.py # Regenerate configs |
|
| 126 |
+cp generated/client.conf ~/.ssh/config # Install client config |
|
| 109 | 127 |
``` |
| 110 | 128 |
|
| 111 |
-Known defaults captured there: |
|
| 112 |
- |
|
| 113 |
-- jump hosts default to user `bogdan.timofte`; |
|
| 114 |
-- jump hosts default to port `24`, with explicit overrides such as `25904`; |
|
| 115 |
-- final hosts default to user `bogdan` because most distributions do not like |
|
| 116 |
- dotted local usernames; |
|
| 117 |
-- when imported configs disagree between `bogdan` and `root`, `bogdan` wins; |
|
| 118 |
-- final hosts default to port `22`, with explicit overrides where needed. |
|
| 119 |
-- Cisco/TACACS router entries use `auth: password_interactive`; generated SSH |
|
| 120 |
- config marks them so the wrapper does not force `BatchMode=yes`. |
|
| 121 |
-- Imported IFS devices use the canonical hostname already known on the jump |
|
| 122 |
- servers as client-side `HostName`, while IPs remain available as aliases for |
|
| 123 |
- autocomplete. |
|
| 124 |
-- J1/J2 configs inherit the company-managed global compatibility block and |
|
| 125 |
- selected `Match Host` user/port defaults from the jump servers instead of |
|
| 126 |
- duplicating them in generated output. |
|
| 127 |
-- J1/J2 configs only emit host entries when there is an effective override to |
|
| 128 |
- keep on the jump side; hosts that only use inherited defaults are omitted. |
|
| 129 |
-- J1/J2 generated configs are stripped down to functional SSH stanzas only, |
|
| 130 |
- without generated comments or group annotations. |
|
| 129 |
+### Sync from Upstream |
|
| 130 |
+ |
|
| 131 |
+Pull latest `hosts.yaml` from nextgen and redeploy: |
|
| 132 |
+ |
|
| 133 |
+```bash |
|
| 134 |
+tools/sync-hosts-from-upstream.sh |
|
| 135 |
+ |
|
| 136 |
+# Customize: |
|
| 137 |
+DEPLOY_AFTER_SYNC=0 tools/sync-hosts-from-upstream.sh # generate only |
|
| 138 |
+UPSTREAM_SSH_TARGET=user@host tools/sync-hosts-from-upstream.sh # custom source |
|
| 139 |
+``` |
|