- Rust 99.3%
- Shell 0.7%
|
|
||
|---|---|---|
| assets | ||
| src | ||
| tests | ||
| .drone.yml | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
SSH Manager
SSH Manager is a small Rust interactive CLI (crate ssh-manager-rs, binary ssh-manager) for organizing SSH hosts under ~/.ssh/conf, generating per-host keys, and updating host config files without manually editing a large ~/.ssh/config.
What It Solves
It helps when your SSH setup starts getting messy:
- too many hosts in one config file
- host keys scattered around
~/.ssh - repeated manual
ssh-keygenandauthorized_keyswork - awkward key rotation and cleanup
SSH Manager keeps each host in its own directory and gives you a simple menu-driven way to manage them.
What It Does
- lists hosts in a table sorted by resolved IP (no row numbers) with columns Host, User, Port, Via (Proxy) (
ProxyJump, a trimmedProxyCommand, or-), HostName, and IP Address; per-host files still live under~/.ssh/conf/<label>/(see Layout) - groups the inventory by network scope (private/local vs public vs unresolved) with optional separator lines between groups (see Inventory separators)
- the main menu shows a live connectivity table (DNS, ping, TCP port, SSH) with color-coded columns above the menu; Test configurations summarizes that view; Connect to Host opens an interactive SSH session using the selected host’s config (
ssh -F … <Host>) - adds a new host config
- generates a per-host
ed25519key - installs the new public key on the remote server
- edits an existing host: tabulated current values, aligned prompts, and a host picker with columns lined up; the edit picker omits resolved IP from each line
- rotates a host key
- removes a host and its local folder
Layout
Managed hosts live under ~/.ssh/conf/<host>/.
Example:
~/.ssh/conf/
web-01/
config
id_ed25519
id_ed25519.pub
If ~/.ssh/config does not exist yet, the app creates one that includes Include conf/*/config, a Host * block with connection defaults, and ControlPath ~/.ssh/s/%C (the app ensures ~/.ssh/s/ exists). See [src/config.rs](src/config.rs) for the full default template.
Run
From the repository root:
cargo run
Flags
--no-divideror--no-dividers— omit the horizontal rules between inventory groups in the host table (including the live connectivity table above the menu). Example:cargo run -- --no-divider
Inventory separators (local vs remote)
When more than one scope is present, the host table inserts ASCII separator lines (+---+---+…) between blocks, in this order:
- Private / local — RFC 1918 private IPv4, loopback, IPv4 link-local, CGNAT (100.64.0.0/10), IPv6 unique local, and IPv6 link-local.
- Remote / public — other routable addresses.
- Unresolved — no mapped IP for display (or unparseable).
Within each block, rows stay sorted by resolved IP, then host label. If only one scope has hosts, no extra separators are drawn.
To show one continuous table without those separators, start the app with --no-divider or --no-dividers (see Flags).
Main screen
Each time the menu appears, the screen is cleared and you see:
- SSH Host Inventory (Sorted by IP address.) — the table of hosts (or an empty table with a warning if none are configured).
- A blank line, then SSH Config Manager Menu (the title includes the app version from
Cargo.toml, e.g.v0.1.15) — an interactive list (on a normal terminal: ↑/↓ or j/k to move, Enter to choose, number keys 1–N to jump to an item, q quits to the last item).Nis the number of menu entries (seeMENU_OPTIONSandMENU_TITLEin the source). With 10 or more entries, type the multi-digit index (digits within about 400ms of each other); a short pause finalizes a single-digit jump.
Menu options (current order):
Connect to HostAdd a HostEdit a HostRegenerate KeyRemove HostTest configurationsExit
The selected line is marked with **›** at the left.
Example: host list
What the inventory table looks like when hosts exist (same column headers as HEADERS in the source):
SSH Host Inventory (Sorted by IP address.)
+-------------+--------+------+----------------+------------------+----------------+
| Host | User | Port | Via (Proxy) | HostName | IP Address |
+-------------+--------+------+----------------+------------------+----------------+
| prod-web-01 | deploy | 22 | - | 10.0.0.15 | 10.0.0.15 |
| db-primary | root | 2222 | bastion | db.internal | 10.0.0.21 |
+-------------+--------+------+----------------+------------------+----------------+
| edge-box | admin | 22 | - | edge.example.com | 203.0.113.8 |
+-------------+--------+------+----------------+------------------+----------------+
If both private/local and public hosts exist, a separator row (like the line between db-primary and edge-box above) appears between the groups. Use --no-divider to print a single block without those lines.
Typical Flow
- Run
cargo run - Choose
Add a Host - Enter the host label, hostname, user, and port
- Choose whether to generate a new key
- Optionally copy the public key to the remote server
- Connect later with normal SSH, for example
ssh prod-web-01
Tests
cargo test --offline
Build
cargo build --release --offline
The release binary is target/release/ssh-manager.