Normalize markdown formatting after the latest main updates.\n\nChecks: python3 scripts/layered_soul.py validate .; npx --yes prettier@3 --check '**/*.md'; git diff --check.
137 lines
5 KiB
Markdown
137 lines
5 KiB
Markdown
---
|
|
name: vaultwarden-secrets
|
|
description: "Self-hosted Vaultwarden + Bitwarden CLI for agent secrets management — storing passwords, API tokens, and SSH passphrases programmatically."
|
|
version: 1.0.0
|
|
author: Sam & Hermes
|
|
platforms: [linux]
|
|
---
|
|
|
|
# Vaultwarden Agent Secrets
|
|
|
|
Self-hosted Vaultwarden server with `bw` CLI for headless agent access to secrets. Replaces pasting tokens into chat.
|
|
|
|
## Setup
|
|
|
|
### Server (Docker)
|
|
|
|
```bash
|
|
docker run -d --name vaultwarden \
|
|
-v /vw-data:/data \
|
|
-p 8080:80 \
|
|
vaultwarden/server:latest
|
|
```
|
|
|
|
Put it behind nginx + Let's Encrypt. Admin page at `/admin`.
|
|
|
|
### First Account
|
|
|
|
First account created via web UI (`https://vault.<domain>`) becomes admin.
|
|
|
|
### Organization + Collections
|
|
|
|
```
|
|
Organization: Clawdie
|
|
Collection: agent-secrets → day-to-day tokens, passwords
|
|
Collection: bootstrap → admin tokens, setup keys (admin only)
|
|
Collection: deploy → deploy secrets (per-host access)
|
|
```
|
|
|
|
### CLI Install
|
|
|
|
```bash
|
|
npm install -g @bitwarden/cli
|
|
bw config server https://vault.<domain>
|
|
```
|
|
|
|
On systems where `node`/`npm` aren't on default PATH (e.g. nvm-managed), use the full path:
|
|
|
|
```bash
|
|
~/.nvm/versions/node/v24.16.0/bin/npm install -g @bitwarden/cli
|
|
export PATH="$HOME/.nvm/versions/node/v24.16.0/bin:$PATH"
|
|
```
|
|
|
|
### Auth — Personal API Key (NOT Organization)
|
|
|
|
Organization API keys (`organization.xxx`) do NOT work with `bw login --apikey` (returns "Organization API Key currently not supported").
|
|
Generate a **personal** API key from web vault → Account Settings → Security → Keys → View API Key.
|
|
This gives a `user.xxx` client_id.
|
|
|
|
```bash
|
|
export BW_CLIENTID="user.xxx"
|
|
export BW_CLIENTSECRET="xxx"
|
|
bw login --apikey
|
|
```
|
|
|
|
After login, `bw status` shows `"status":"locked"`. Unlock with master password via env var:
|
|
|
|
```bash
|
|
export BW_PASSWORD="<master-password>"
|
|
bw unlock --passwordenv BW_PASSWORD
|
|
# Outputs a session key — use it with every command:
|
|
bw list organizations --session "QyeGJoqVLttR..."
|
|
```
|
|
|
|
The `--session` flag is more explicit than `BW_SESSION` env var — avoids leaking session into other commands.
|
|
|
|
### Sync After Web UI Changes
|
|
|
|
Collections/items created via web UI don't appear in CLI until synced:
|
|
|
|
```bash
|
|
bw sync --session "..."
|
|
bw list collections --organizationid <org-id> --session "..."
|
|
```
|
|
|
|
### Creating Items (Piped JSON Pattern)
|
|
|
|
The simple `--username`/`--password` flags on `bw create item` don't accept org items reliably. Use `bw encode` + pipe:
|
|
|
|
```bash
|
|
echo '{"type":1,"name":"item-name","notes":"description","login":{"username":"user","password":"pass","uris":[{"uri":"https://example.com","match":0}]},"organizationId":"<org-guid>"}' | bw encode | bw create item --session "..."
|
|
```
|
|
|
|
### Moving Items Between Collections
|
|
|
|
`bw create item` has no `--collectionid` flag. Items default to the personal vault. To assign to an org collection after creation:
|
|
|
|
```bash
|
|
bw get item <item-guid> --session "..." | python3 -c "
|
|
import sys,json
|
|
d=json.load(sys.stdin)
|
|
d['collectionIds']=['<collection-guid>']
|
|
print(json.dumps(d))
|
|
" | bw encode | bw edit item <item-guid> --session "..."
|
|
```
|
|
|
|
### Retrieving Secrets
|
|
|
|
```bash
|
|
bw get item "item-name" --session "..." | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['login']['password'])"
|
|
```
|
|
|
|
## Pitfalls
|
|
|
|
- **Organization API keys don't work for `bw login`**. Must use personal API key from user account settings.
|
|
- **`bw login --apikey` is interactive** — doesn't accept stdin piping. Use `BW_CLIENTID` + `BW_CLIENTSECRET` env vars.
|
|
- **Session expires**. After login, run `bw unlock --raw` to get a session key, export as `BW_SESSION`. On Vaultwarden you must first log out then log in: `bw logout && bw login --apikey`.
|
|
- **Vaultwarden admin page** is separate from the web vault at `/admin`. First user is auto-admin.
|
|
- **Self-signed certs** require `NODE_TLS_REJECT_UNAUTHORIZED=0` — but prefer Let's Encrypt.
|
|
|
|
## Multi-Agent Usage
|
|
|
|
Each agent host gets its own Bitwarden account (e.g. `hermes-debby@clawdie.si`).
|
|
Add them to the `Clawdie` organization and grant collection access per need.
|
|
Agents authenticate via `bw login --apikey` with their own personal API key.
|
|
No shared credentials, no master passwords in automation.
|
|
|
|
## References
|
|
|
|
| Topic | File | Description |
|
|
| ---------------- | -------------------------------------- | --------------------------------------------------------- |
|
|
| bw CLI Reference | `references/bw-cli-reference.md` | Full bw CLI command reference with pitfalls |
|
|
| bw CLI Quirks | `references/bw-cli-quirks.md` | Option naming gotchas, --apikey pitfall, session behavior |
|
|
| Instance Details | `references/instance-details.md` | vault.smilepowered.org: org/collection IDs, login flow |
|
|
| Instance Config | `references/vault.smilepowered.org.md` | Server setup and configuration details |
|
|
|
|
- Vaultwarden: https://github.com/dani-garcia/vaultwarden
|
|
- Bitwarden CLI: https://bitwarden.com/help/cli/
|