Home / Docs / Secrets & Integrations

Secrets & Integrations

Solo & Teams

Bring your own vault. Servonaut never stores your SSH keys or secret values — they live in your Bitwarden Password Manager (or Secrets Manager) and the CLI resolves them locally at the moment you need them.

Trust model in one sentence

Servonaut backend stores where a credential lives (which vault, which item id). The value never leaves your machine.

How it works

Each server in your inventory can carry a credential reference: a tiny pointer (provider, item id, optional collection id) that tells the CLI which Bitwarden record to fetch when you SSH in. The pointer is the only thing stored on servonaut.dev. The actual SSH private key, BWS access token, and secret values are pulled by the CLI directly from your vault — over your Bitwarden session, with your unlock password — and dropped into a 0600-permissioned tmpfile that's deleted automatically when the session ends.

Stored on servonaut.devStored in your Bitwarden vaultStored on disk during use
provider: bitwarden_pm
item_id: uuid
collection_id (optional)
vault URL (if self-hosted)
SSH private key
BWS access token
Secret values (DB passwords, API keys…)
Temp keyfile (0600, deleted on session end, 24h stale sweeper)

Supported providers

  • Bitwarden Password Manager (bw) — the consumer vault. Free tier of Bitwarden is enough to store an SSH key. Self-hosted Bitwarden servers are supported via a custom Vault URL.
  • Bitwarden Secrets Manager (bws) — Bitwarden's developer secrets product. Useful when you want machine-readable secrets distinct from your personal password vault. Configured exactly like Password Manager. One-time tooling setup: servonaut secrets install bws installs the bws CLI for you (Homebrew on macOS, Cargo on Linux; elsewhere it prints the upstream install URL).
  • Local fallback — if no credential ref is configured for a server, the CLI falls back to ~/.ssh/ key discovery exactly like before.
Why Bitwarden first?

It's open-source, has a free tier suitable for individuals, supports both consumer (Password Manager) and developer (Secrets Manager) workflows, and ships first-class CLIs (bw and bws) that Servonaut integrates with directly. Support for additional vault providers is planned.

Personal vs. team scope

Every integration is scoped to either you (your personal vault, your servers) or your team (the team's shared vault, the team's shared servers). Both scopes behave identically from the TUI and CLI — each is stored and audited separately.

ScopeUse it whenRequired plan
Personal Solo developer with their own AWS/OVH/Hetzner instances Solo or Teams
Team-shared Multiple team members need to SSH the same boxes with a rotated key Teams (paid seat)

The /account/integrations wizard

First-time setup happens through a single wizard at /account/integrations. No JSON files, no env vars to remember. The wizard has four cards depending on your plan:

  1. Personal SSH Key Config — point the CLI at your personal Bitwarden vault for SSH keys.
  2. Personal Secrets Config — same, for non-SSH secrets (DB passwords, API keys) you want resolved by name.
  3. Team SSH Key Config — visible only to team owners/admins. Sets the vault used when team members SSH a shared server.
  4. Per-server credential refs — for each personal or team server, paste the Bitwarden item id of the key. The CLI uses this exact key for that exact instance.
The BWS access token is yours, forever

The wizard never asks for your BWS_ACCESS_TOKEN or Bitwarden unlock password — it stores only the name of the env var to read (default: BWS_ACCESS_TOKEN; you can change the name in the wizard if your environment uses a different one). The token itself sits in your shell environment or your password manager.

Setup in five minutes

  1. Install the Bitwarden CLI on your machine. Servonaut uses it to talk to your vault.
    macOS / Linux
    $ npm install -g @bitwarden/cli # or: brew install bitwarden-cli / snap install bw $ bw login # your Bitwarden email + master password $ export BW_SESSION=$(bw unlock --raw)

    See the Bitwarden CLI install guide for other platforms.

  2. Store your SSH key in Bitwarden as a native SSH Key item. In the Bitwarden vault UI (Web or Desktop), pick Vault → New item → SSH Key and paste your OpenSSH private key body into the Private Key field. Save the item and copy the resulting item id — you'll paste it into Servonaut's "Manage SSH Ref" form in the next step.
    Already have keys in ~/.ssh?

    Skip the manual copy-paste — the TUI can import your existing local keys (including passphrase-protected ones) straight into your vault. See Importing existing keys below.

    Requires a native SSH Key item (Bitwarden 2023.10 or newer)

    Servonaut reads the key from the item's Private Key field. Legacy Secure Notes with the key pasted into the notes field are not supported — the CLI will return a BwItemShapeError. If you need notes-blob support, file an issue.

  3. Open the integrations wizard at /account/integrations. Pick "Bitwarden Password Manager", leave the Vault URL blank for the SaaS version (or paste your self-hosted URL), and hit Save SSH config.
  4. Attach a credential ref to a server. Open one of your instances in the "Servers" section of the wizard, paste the Bitwarden item id, and save. (You can also do this without leaving the terminal — press k on the instance in the TUI; see below.)
  5. Connect using the ref. Launch the TUI with servonaut, select the instance, and press S (or choose SSH Connect from the Server Actions dashboard). Or from a script:
    CLI
    $ servonaut ssh i-0a1b2c3d4e5f6g7h8 # resolves ref → fetches key from Bitwarden → writes tmpfile → exec ssh

Importing existing keys from ~/.ssh

If your SSH keys already live in ~/.ssh, you don't have to copy-paste each one into the Bitwarden UI by hand. The TUI's Bitwarden SSH Vault manager imports them for you — including passphrase-protected keys — as native Bitwarden SSH items.

Launch servonaut, open the 🗝 BW SSH Vault manager from the sidebar, and choose Import keys (a):

  1. Pick a directory. A picker opens at your home directory with ~/.ssh prefilled. Any directory works.
  2. Review the scan. Servonaut scans the directory (non-recursive) for private keys and lists each one with its type and fingerprint. Unencrypted keys are pre-selected; passphrase-protected keys show a 🔒 marker and are opt-in — tick the ones you want.
  3. Enter passphrases. For each selected encrypted key you're asked for its passphrase once, so it can be decrypted for upload. The passphrase is used in memory only — never logged, written to disk, or passed on a command line. A wrong passphrase just re-prompts; Skip leaves that key out.
  4. Import. Selected keys are created as SSH items in your Servonaut vault folder and a sync runs so they appear on your other devices.
What the import does — and doesn't
  • Your original files are untouched — the import reads your key files; it never modifies or deletes them.
  • Vault encryption replaces the file passphrase — the imported copy is protected by your Bitwarden vault's encryption, so anyone who can unlock your vault can use the key, exactly like every other item in it.
  • The key goes to your vault, not to us — key material is uploaded to wherever your vault lives (bitwarden.com or your self-hosted server), end-to-end encrypted by Bitwarden. Servonaut's servers never see it.
  • Duplicates are skipped by fingerprint — a key whose SHA256 fingerprint already exists in your vault is shown as already in vault and isn't created twice.

Managing credentials in the TUI

Day to day, you manage and use credential refs without leaving the TUI. Launch servonaut, find the server in the instance list (press / to search), and work from there:

  • Attach or rotate a ref — press k on the selected instance to open the SSH-ref form (add / edit / delete). The same actions are available as Manage SSH Ref on the per-instance Server Actions dashboard (click the instance row to open it).
  • Verify a ref — press v to run the verify probe in a modal: it checks that the key resolves from your vault and that the server accepts it, then shows the result. The instance list's SSH-verify column reflects the most recent run (green check / red mark / dash for never verified).
  • Use the refS opens an SSH session, and every credential-backed action on the Server Actions dashboard (Run Command, SCP Transfer, log streaming, file browsing) resolves the same ref automatically.
  • Configure the vault offline — the Settings screen (🔧) has a "Bitwarden SSH Vault" section that edits the same config the web wizard writes, reachable without a browser.
WhereKeyAction
Instance listkManage SSH ref for the selected instance (add / edit / delete)
Instance listvVerify SSH against the selected instance (opens probe modal)
Instance rowSSH-verify column shows green / red / dash based on the most recent verify
Settings"Bitwarden SSH Vault" section — same config the web wizard writes, reachable offline
Why both web and TUI?

The web wizard is the canonical surface for first-time setup and team-admin actions. The TUI covers everything you do afterwards — rotating a key, verifying a server, opening sessions — so you never have to alt-tab to a browser.

Automating with the CLI

Every flow above is also scriptable for CI runners, cron jobs, and headless boxes. Sign the machine in once with servonaut login — it's fully headless (prints a URL and short code you approve from a browser on any device) — and the session is shared by the CLI, the TUI, and the MCP server. Pressing Ctrl+C during any command cancels cleanly with exit code 130.

servonaut ssh <instance-id>

SSH into an instance using its credential ref. Resolution is three-tier:

  1. Personal credential ref attached to the instance (your config)
  2. Team credential ref attached to the instance (shared with the team)
  3. Local ~/.ssh/ key discovery (the legacy path)

Whichever resolves first wins. The fetched key is written to a temp file with 0600 permissions, used to open the SSH session, and deleted when the session ends. A 24-hour stale sweeper cleans up any tmpfile orphaned by a hard crash.

servonaut servers verify <id>

Sanity-checks the credential resolution and connectivity for one instance, without dropping you into a shell. Runs bw get item locally to confirm the key fetches, then ssh -o BatchMode=yes -o ConnectTimeout=N to confirm the key actually authenticates against the box. The outcome is reported to your account so the dashboard and TUI status column can show the green checkmark.

Exit codeMeaningResult shown on your dashboard?
0Verified — key resolves and SSH connects.Yes
1Verified-failure — probe ran end-to-end but the Bitwarden item is missing (not found) or SSH refused the key (auth failed: firewall, wrong user, key not in authorized_keys).Yes
2Fatal config — couldn't run the probe at all: no credential ref stored, Bitwarden CLI not installed, vault locked, or machine not signed in (run servonaut login).No

servonaut secrets

Two helpers for the secrets backends themselves:

  • servonaut secrets status — prints your plan, your secrets entitlement, and which secrets provider is currently active (local or Bitwarden). Run this first when anything misbehaves.
  • servonaut secrets install bws — one-time install of the Bitwarden Secrets Manager CLI (Homebrew on macOS, Cargo on Linux; prints the upstream URL on other platforms).

For AI agents (MCP)

AI agents interact with your servers through the Servonaut MCP server (servonaut --mcp, or remotely via the servonaut connect relay). The same trust model holds: agents only ever see credential references — tools that need SSH (run a command, fetch logs, transfer a file) resolve the actual key locally on the machine running the CLI, exactly as an interactive session would. Secret values never transit servonaut.dev, even when a hosted agent or a team-mate dispatches the tool call over the relay.

Headless connect from the vault — no local key required. When an instance has a stored personal Bitwarden ref, the SSH-backed tools (run a command, fetch logs, transfer a file, the incident-response probes) resolve the key straight from your vault and prefer it over local ~/.ssh discovery — so an agent, or a servonaut connect relay, on a machine with no key files can still connect. Because a headless process can't prompt for your master password, this needs an ambient BW_SESSION: run bw unlock and export BW_SESSION in the environment the MCP server (or the relay) runs in. The resolved key is written to a 0600 temp file only for the duration of a single tool call, then deleted (zero-overwritten); the audit entry tags the connection key_source=bw_personal. If the vault is locked or the Bitwarden CLI isn't present, the tool silently falls back to local key discovery, so an existing local setup never breaks. Personal refs resolve on the headless surface today; team-shared refs do not yet.

Tool access is governed by the standard guard levels, and every call — including relay-dispatched calls from headless AI chat sessions — is recorded in the local audit log at ~/.servonaut/mcp_audit.jsonl. When the relay listener executes tool calls with no human present, approval is policy-driven via relay.ai_tool_auto_approve in your config.json. See the MCP server docs for the full tool list and guard-level matrix.

Audit & change tracking

Every change made through the integrations wizard is recorded in your audit log: who changed it, what changed (full diff — minus secret values, which never reach us), and when. Team owners can review the trail from the team dashboard.

The CLI also detects when your team's secrets config has changed since it last fetched it and refreshes automatically — you'll see "team secrets config changed since last fetch — refreshing" in the TUI when an admin rotates something.

Troubleshooting

"Error: bw command not found"

Install the Bitwarden CLI: npm install -g @bitwarden/cli on most systems, brew install bitwarden-cli on macOS, or snap install bw on Linux. See the Bitwarden CLI install guide for other platforms. Install the Bitwarden CLI separately — Servonaut does not bundle it.

"BwItemShapeError: BW item ... has no SSH key field"

The credential ref points at a Bitwarden item that isn't a native SSH Key item. Servonaut requires a native SSH Key item (Bitwarden 2023.10 or newer) and reads the key from the item's Private Key field. Open the item in Bitwarden, delete it, and re-create it as Vault → New item → SSH Key with the private key in the Private Key field.

"Bitwarden vault is locked"

Run bw unlock (or bw login if you've never authenticated on this machine) and export the resulting session token to BW_SESSION. The CLI reads it from your environment.

"Verify exits 1 — connection refused"

The credential ref resolves fine, but the SSH daemon refused the key. Check: the right username (ubuntu vs root vs cloud-specific default), security-group/firewall rules allowing your IP, and the public key actually being present in the server's ~/.ssh/authorized_keys.

"My team has a shared vault, but I don't see it"

Team credential refs only resolve for active members on a paid Teams seat. Check, in order: your membership isn't still pending (accept the invite from the Account → Teams screen), your role grants access to the shared servers, and the team's plan is current. servonaut secrets status shows what your account is entitled to right now. If the config was just changed by an admin, simply reopen the TUI — it refreshes a stale team config automatically.

"Personal Bitwarden integration requires a Solo or Teams subscription"

Secrets integrations are available on the Solo and Teams plans. See Pricing for the per-plan breakdown.

Documentation