Portable SSH manager with a local encrypted SQLite vault, a Cobra CLI, and a tcell TUI.
- Local-first vault lifecycle:
vault init|keychain enable|keychain disable|keychain status|migrate|change-password - Build metadata reporting with
version - Self-install command:
install [--dir PATH] - CRUD for
host,group,profile,identity,key,forward - Saved host key inspection with
known-host list|delete - Resolved host inspection with
inspect <host> - OpenSSH import via
import openssh --config ~/.ssh/config - Host-level direct key/password auth overrides
- SSH connect flow with:
- password, private key, and ssh-agent auth
- built-in known-host storage in the vault by default, with optional file fallback
ProxyJumpchains- outbound
SOCKS5/HTTP CONNECTproxies - saved and one-shot
-L/-R/-Dforwards - SSH-style debug verbosity via
-v,-vv,-vvv - remote command execution via
exec <host> <command>
- TUI CRUD tabs for
host,group,profile,identity,key,forward,known-host, plus embedded SSH session tabs
$env:GOPROXY='https://goproxy.cn,direct'
go test ./...
go build ./...nermius version prints a build string in the form v{major}.{minor}.{patch}-{branch}-{commit}[-dirty].
CI derives the base v{major}.{minor}.{patch} from VERSION: patch is VERSION's patch plus the number of commits since VERSION was last changed. To reset patch for a new major/minor line, edit VERSION to the new epoch version, such as v0.1.0; that commit builds as v0.1.0, and the next commit builds as v0.1.1.
# 1. Initialize the local encrypted vault.
nermius vault init
# 2. Optionally inspect or enable system keychain enrollment.
nermius vault keychain status
nermius vault keychain enable
# 3. Optionally install the current binary into ~/.local/bin.
nermius install
# 4A. If you already have ~/.ssh/config, import it into the vault.
nermius import openssh --config ~/.ssh/config
# 4B. Or create records interactively instead of importing.
nermius key add -it
nermius identity add -it
nermius host add -it
nermius host add --title prod --hostname prod.example.com --identity ops --key deploy-key
# 5. Inspect the resolved host config before connecting.
nermius host list
nermius inspect my-host
nermius known-host list
nermius version
# 6. Open a shell or run a one-shot remote command.
nermius connect my-host
nermius -vv connect my-host
nermius exec my-host hostname
nermius forward start prod-db
# 7. Open the TUI for browsing objects and sessions.
nermius tuiimport openssh and the interactive add -it flow are alternative ways to populate the vault. Use whichever matches your setup.
Normal read/write commands now auto-unlock:
- first via the enrolled system keychain backend
- otherwise by prompting for the master password
There is no plaintext local session file anymore. On migrated/current vaults, object bodies and secrets are stored in encrypted records; legacy vaults must be upgraded explicitly with nermius vault migrate.
Inside the TUI object tabs:
HOST / GROUP / PROFILE / IDENTITY / KEY / FORWARD / KNOWN-HOSTall support in-screen CRUD modalsEnterconnects onHOST, toggles the selected tunnel onFORWARD, and opens a read-only detail view on every other tabdopens detail,eopens edit,aopens a create formDeleteorxopens delete confirmation; referenced objects are blocked and show who still depends on them/opens a filter prompt for the current tab, andrreloads the lists- reference fields use searchable pickers, and ordered lists such as profiles, forwards, known-host host patterns, and identity auth methods use a dedicated list editor
FORWARDobjects are reusable-L/-R/-Dtunnel definitions with their own Host picker;EnterorSpacestarts/stops the selected tunnel for the lifetime of the current TUI process, and the list showsSTATUSplus a separateREASON
Inside the TUI session view:
- connection prompts such as unknown host-key trust, password, username, and key passphrase stay inside the TUI as modals
- connection progress is shown in the status bar while resolving hosts, dialing, checking known hosts, authenticating, and opening the remote shell
- use the mouse wheel to scroll local shell history
- use
Shift+wheelto force local scrollback when the remote app has mouse tracking enabled - drag to select visible terminal text, including locally scrolled shell history
- use
Shift+dragto force local selection when the remote app has mouse tracking enabled - use
Ctrl+Shift+CandCtrl+Shift+Vfor local copy/paste - alt-screen apps stay isolated from local shell scrollback
- remote
OSC 52, focus reporting, bracketed paste, and cursor-shape changes are forwarded when the remote app enables them
Typical interactive path:
nermius vault init
nermius vault keychain status
nermius key add -it
nermius identity add -it
nermius host add -it
nermius inspect my-host
nermius known-host list
nermius connect my-hostIf you created a vault with an older Nermius build, migrate it once before using regular commands:
nermius vault migrateHost records can also pin how host keys are stored and read:
# Keep host keys entirely inside the encrypted vault.
nermius host add --title prod --hostname prod.example.com --identity ops --known-hosts-backend vault
# Read from the vault first, then fall back to ~/.ssh/known_hosts.
nermius host add --title prod --hostname prod.example.com --identity ops --known-hosts strict --known-hosts-backend vault+fileHosts can also override the selected identity's auth methods directly:
# Reuse the identity username, but force this host to try a specific key first.
nermius host add --title prod --hostname prod.example.com --identity ops --key deploy-key
# Attach a host-specific password override.
nermius host add --title breakglass --hostname prod.example.com --identity ops --password super-secretnermius install
nermius install --dir ~/bin
nermius install --yesinstall copies the currently running executable into ~/.local/bin by default.
- If the target directory does not exist, it asks whether to create it.
- It reports whether that directory is already present in
PATH. - If a file with the same name already exists there, it compares size plus
SHA-256andSHA-512before deciding whether a copy is needed. - If the install directory is not reachable from
PATH, it prints a shell-specific hint for adding it.
vault init still bootstraps the vault with a master password. That master password derives a KEK which wraps the random vaultKey; the vaultKey is what encrypts the actual vault records.
Useful vault commands:
nermius vault keychain status
nermius vault keychain enable
nermius vault keychain disable
nermius vault change-password
nermius vault migrateBehavior notes:
vault keychain enablestores the raw vault unlock material in the platform backend when supported.- normal commands auto-try the enrolled keychain backend first, then fall back to the master password.
vault keychain statusreports both the unlock-material backend and the user-presence backend.- on Windows, unlock material is DPAPI-protected, while read/write authorization uses Windows Hello when available, then the Windows credential prompt, then the master password fallback.
- current-schema vaults use whole-vault encrypted records, so hostnames, usernames, labels, known-host payloads, and secrets are no longer stored as plaintext rows in SQLite.
vault migrateis explicit and creates a backup at<vault>.bak.pre-schema-v2before converting a legacy vault.
The SQLite vault file is portable. The system keychain enrollment is not portable and must be recreated on each machine.
-
On the old machine, find the vault path:
nermius vault keychain status
The default path is usually
%APPDATA%\nermius\vault.dbon Windows,~/Library/Application Support/nermius/vault.dbon macOS, and~/.config/nermius/vault.dbon Linux. -
Copy
vault.dbto the new machine. -
On the new machine, either place it at the default path or pass it explicitly:
nermius --vault C:\path\to\vault.db vault keychain enable -
Enter the master password once to enroll the copied vault into the new machine's keychain.
After that, normal commands can auto-unlock through the new machine's keychain and fall back to the master password if needed.
Notes:
- imported private keys, passwords, identities, profiles, hosts, forwards, and vault-backed known hosts move with
vault.db. - agent-backed auth still depends on the new machine's SSH agent.
- external key file paths and
~/.ssh/known_hostsfile-backed entries are local machine state and must exist separately on the new machine.
nermius no longer depends on the system ssh client for host key storage. By default, resolved hosts use known_hosts.backend = vault+file, which means:
- existing host keys are looked up in the vault first
- then
~/.ssh/known_hostsis checked as a fallback - newly accepted keys are written back into the vault
Useful commands:
# Inspect all saved host keys from both backends.
nermius known-host list
# Only inspect the vault-backed host keys.
nermius known-host list --source vault
# Remove one host key by host, fingerprint, or file:<line> ID.
nermius known-host delete 192.168.1.202You can override storage per host or profile through the known_hosts object:
{
"policy": "strict",
"backend": "vault",
"path": "~/.ssh/known_hosts"
}Use backend: "vault" if you want the host to stay fully self-contained on machines that do not even have OpenSSH installed.
connect, exec, and tui accept a global verbosity flag modeled after ssh:
nermius -v connect my-host
nermius -vv connect my-host
nermius -vvv exec my-host "uname -a"-v prints high-level SSH decisions such as host key acceptance. -vv adds host key backend details and preferred host key algorithms. -vvv also includes low-level auth method selection.
Saved FORWARD objects are standalone tunnels. Each one has a host_ref, which is the SSH transport/intermediate host used to establish the tunnel.
nermius forward add -it
nermius forward start prod-dbforward start runs in the foreground and keeps the tunnel open until Ctrl+C. If an established tunnel disconnects unexpectedly, Nermius retries up to 5 times before surfacing the final error. TUI FORWARD toggles are also process-local; they close when the TUI exits. Saved Host/Profile.forward_ids remain visible in resolved config for organization and inspection, but saved forwards no longer auto-start when opening a shell. One-time CLI forwards still work with connect/exec:
nermius connect my-host -L 15432:db.internal:5432
nermius connect my-host -D 1080Host:
{
"title": "prod",
"hostname": "prod.example.com",
"profile_ids": ["profile-uuid"],
"identity_ref": "identity-uuid",
"key_ref": "key-uuid",
"password": "super-secret",
"forward_ids": ["forward-uuid"]
}Forward:
{
"name": "prod-db",
"host_ref": "host-uuid",
"type": "local",
"listen_host": "127.0.0.1",
"listen_port": 15432,
"target_host": "db.internal",
"target_port": 5432,
"enabled": true
}Identity:
{
"name": "ops",
"username": "ubuntu",
"methods": [
{
"type": "key",
"key_id": "key-uuid"
},
{
"type": "agent"
}
]
}