# SSH Infrastructure

Source-controlled SSH routing and wrapper configuration for the Next-Gen jump
infrastructure.

## Runtime vs project

- Project source: `~/Documents/Workspaces/Bogdan/ssh-infrastructure`
- OpenSSH runtime: `~/.ssh`

Keep secrets and machine-local state out of this repository:

- private keys: `~/.ssh/keys/`
- `authorized_keys`
- `known_hosts`
- socket or agent state

The runtime `~/.ssh/config` is a generated single-file OpenSSH config. The
project is the place to edit wrappers, documentation, inventory, and generator
code.

Deploy the local runtime copy with:

```bash
tools/deploy-local.sh
```

The deploy script generates `generated/client.conf`, installs it as
`~/.ssh/config`, and installs the wrapper commands into `~/.local/bin`.
It does not touch keys, `authorized_keys`, or `known_hosts`.

## Version control

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:

```bash
git status
git add inventory schema scripts tools .doc README.md .gitignore
git commit
```

## Current client layout

```text
~/.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.

## Source of Truth

The structured source of truth starts in:

```text
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`.

## Sync from upstream

Pull the upstream inventory, apply this machine's local `is-jumper` key override,
regenerate, and deploy if the inventory changed:

```bash
tools/sync-hosts-from-upstream.sh
```

Defaults:

```text
UPSTREAM_SSH_TARGET=nextgen@192.168.2.103
UPSTREAM_HOSTS_PATH=/home/nextgen/projects/ssh-infrastructure/inventory/hosts.yaml
LOCAL_IS_JUMPER_IDENTITY_FILE=~/.ssh/keys/is-jumper_ed25519
DEPLOY_AFTER_SYNC=1
```

Useful overrides:

```bash
UPSTREAM_HOSTS_FILE=/tmp/hosts.yaml tools/sync-hosts-from-upstream.sh
DEPLOY_AFTER_SYNC=0 tools/sync-hosts-from-upstream.sh
FORCE_DEPLOY=1 tools/sync-hosts-from-upstream.sh
```

Known defaults captured there:

- jump hosts default to user `bogdan.timofte`;
- jump hosts default to port `24`, with explicit overrides such as `25904`;
- final hosts default to user `bogdan` because most distributions do not like
  dotted local usernames;
- when imported configs disagree between `bogdan` and `root`, `bogdan` wins;
- final hosts default to port `22`, with explicit overrides where needed.
- Cisco/TACACS router entries use `auth: password_interactive`; generated SSH
  config marks them so the wrapper does not force `BatchMode=yes`.
- Imported IFS devices use the canonical hostname already known on the jump
  servers as client-side `HostName`, while IPs remain available as aliases for
  autocomplete.
- J1/J2 configs inherit the company-managed global compatibility block and
  selected `Match Host` user/port defaults from the jump servers instead of
  duplicating them in generated output.
- J1/J2 configs only emit host entries when there is an effective override to
  keep on the jump side; hosts that only use inherited defaults are omitted.
- J1/J2 generated configs are stripped down to functional SSH stanzas only,
  without generated comments or group annotations.
