End-to-end-encrypted sync for your SSH workflow — hosts, ~/.ssh/config
entries, snippets, and port-forwards, kept in sync across all your machines. One
small binary that is both the client CLI and the self-hostable relay server.
Think 1Password for your SSH setup: you keep using ssh exactly as you do
today, but your host aliases, jump-hosts, snippets, and forwards follow you from
laptop to laptop — encrypted so the sync server never sees them in the clear.
- ✅ You live in the terminal and want your
sshconfig to sync across machines without trusting a cloud provider with it. - ✅ You want a shared, encrypted set of hosts/snippets for a team (see shares).
- ✅ You want to self-host the sync relay, or trust that even a hosted one is zero-knowledge.
- ❌ You want a GUI terminal, tabs, SFTP, or a mobile shell — that's Termius /
iTerm / your terminal emulator. sshvault is a config-and-secrets layer under
ssh, not a terminal client. It never opens shells for you (non-goals).
sshvault is not a Termius replacement — it has no terminal, no tabs, no
built-in SFTP. What it does replace is the part of Termius people are often
least comfortable with: syncing your SSH hosts, snippets, and keys through a
company's cloud, behind a subscription. sshvault does that sync end-to-end
encrypted, self-hostable, and free — then hands off to the ssh you already use.
| Termius | sshvault | |
|---|---|---|
| Sync hosts / snippets / port-forwards | ✅ | ✅ |
| Team sharing | ✅ (paid) | ✅ (encrypted shares) |
| Encrypted key sync | ✅ | ✅ (opt-in, zero-knowledge) |
| Server can read your data | Trust their cloud | ❌ never — zero-knowledge relay |
| Self-host the sync server | ❌ | ✅ (one binary) |
| Terminal emulator / tabs / SFTP | ✅ | ❌ — use your own ssh |
| Mobile / GUI app | ✅ | ❌ — CLI only |
| Price | Freemium / subscription | Free, open source |
If what you liked about Termius was the terminal UI, keep using it — sshvault
sits happily underneath any client that reads ~/.ssh/config. If what you wanted
was your SSH setup to follow you across machines without handing it to someone
else's server, that's exactly what this is.
- E2EE, zero-knowledge relay. Every record is XChaCha20-Poly1305 ciphertext before it leaves your machine; the relay stores opaque blobs and device public keys, nothing password-shaped, no decryption path.
- Offline-first. All commands work against the local encrypted log;
syncreconciles whenever a relay is reachable. Conflicts resolve with field-level last-writer-wins (property-tested: commutative, associative, idempotent). - Your
~/.ssh/configstays yours.sshvault applywrites a managedsshvault.confand adds a singleIncludeline — it never edits your config. - Multi-device with real revocation. Enroll devices with an out-of-band short
code;
device revoke --rotatemints a new vault-key epoch for forward secrecy. - Team shares. Named compartments visible only to their members; removing a member rotates the share key.
- Private keys stay put. Syncs key metadata only and actively rejects anything that looks like private key material.
See docs/architecture.md, docs/crypto-design.md, and docs/threat-model.md for the design.
From crates.io (needs a Rust toolchain, 1.89+):
cargo install sshvaultPrebuilt binaries — grab the archive for your platform from the
latest release,
unpack, and put sshvault on your PATH.
From source:
git clone https://github.com/being-cheema/sshvault
cd sshvault && cargo install --path .Docker (handy for running the relay):
docker compose up -d # builds + starts the relay on :8787, data in a named volumesshvault init # prints a 24-word recovery phrase — store it offline
sshvault host add web --hostname web.example.com --user deploy
sshvault snippet add logs 'journalctl -fu app' --description "tail app logs"
sshvault fwd add pg 5432:localhost:5432 --host web
sshvault apply # writes ~/.ssh/sshvault.conf + Include
ssh web # just works
sshvault snippet run logsOr watch it end-to-end: scripts/demo.sh runs the whole
quickstart — including two-device sync — against a local relay in a temp dir.
# somewhere reachable (or localhost to try it):
sshvault serve --addr 0.0.0.0:8787 --db relay.db
# first machine
sshvault sync --relay https://relay.example.com # enrolls + syncs; URL is remembered
sshvault syncd --apply # optional: follow changes live
# second machine
sshvault device enroll --vault <vault-id> --relay https://relay.example.com
# it prints a short code; on the first machine:
sshvault device approve <code>device list shows enrolled devices; device revoke <code> locks one out.
Add --rotate to also mint a new vault-key epoch so the revoked device cannot
read anything written afterward (forward secrecy — needs your recovery phrase).
See the revocation semantics in the threat model.
Lost every device? sshvault recover --relay <url> + your recovery phrase
restores the vault on a fresh machine.
sshvault export prints your data as plaintext JSON (you own your data);
sshvault import file.json merges it back, skipping duplicates.
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test # unit + property tests (10k cases/law) + integration gates
cargo auditFound a vulnerability? Please report it privately — see SECURITY.md. Don't open a public issue for security bugs.
Dual-licensed under MIT or Apache-2.0, at your option.