<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.wilsoz.com/index.php?action=history&amp;feed=atom&amp;title=Services%2FVaultwarden</id>
	<title>Services/Vaultwarden - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.wilsoz.com/index.php?action=history&amp;feed=atom&amp;title=Services%2FVaultwarden"/>
	<link rel="alternate" type="text/html" href="https://wiki.wilsoz.com/index.php?title=Services/Vaultwarden&amp;action=history"/>
	<updated>2026-07-06T07:05:19Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://wiki.wilsoz.com/index.php?title=Services/Vaultwarden&amp;diff=8&amp;oldid=prev</id>
		<title>Wikibot: Migrated from services/VAULTWARDEN.md</title>
		<link rel="alternate" type="text/html" href="https://wiki.wilsoz.com/index.php?title=Services/Vaultwarden&amp;diff=8&amp;oldid=prev"/>
		<updated>2026-07-05T18:16:03Z</updated>

		<summary type="html">&lt;p&gt;Migrated from services/VAULTWARDEN.md&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;As of: 2026-07-05 — migrated from `services/VAULTWARDEN.md`&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
= Vaultwarden =&lt;br /&gt;
&lt;br /&gt;
Self-hosted Bitwarden-compatible password manager. The &amp;#039;&amp;#039;&amp;#039;human-facing&amp;#039;&amp;#039;&amp;#039; credential store. (OpenBao is the machine-facing one — see &amp;lt;code&amp;gt;services/OPENBAO.md&amp;lt;/code&amp;gt;.)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Container &amp;amp; Endpoints ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Item&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| Container&lt;br /&gt;
| &amp;lt;code&amp;gt;vaultwarden&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Compose&lt;br /&gt;
| &amp;lt;code&amp;gt;/library/vaultwarden-app/&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Public URL&lt;br /&gt;
| &amp;lt;code&amp;gt;https://vault.wilsoz.com&amp;lt;/code&amp;gt; (via VPS nginx → Tailscale → stronghold)&lt;br /&gt;
|-&lt;br /&gt;
| Internal port&lt;br /&gt;
| 8080&lt;br /&gt;
|-&lt;br /&gt;
| Auth&lt;br /&gt;
| OAuth2 via Authentik (provider PK 10)&lt;br /&gt;
|-&lt;br /&gt;
| Master folder&lt;br /&gt;
| &amp;quot;Stronghold Infrastructure&amp;quot; (all infrastructure credentials)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Claude Code Integration ==&lt;br /&gt;
&lt;br /&gt;
Claude reads Vaultwarden via the &amp;lt;code&amp;gt;bitwarden&amp;lt;/code&amp;gt; MCP server (configured at the user level — works in every Claude session on this machine).&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File&lt;br /&gt;
! Mode&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;~/.config/claude/vaultwarden.env&amp;lt;/code&amp;gt;&lt;br /&gt;
| 600&lt;br /&gt;
| BW_URL, BW_CLIENTID, BW_CLIENTSECRET, BW_EMAIL, BW_PASSWORD&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;~/.config/claude/bw-mcp-start.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
| 700&lt;br /&gt;
| Wrapper that unlocks vault and execs the MCP server&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;~/.config/claude/bw-get.py&amp;lt;/code&amp;gt;&lt;br /&gt;
| 700&lt;br /&gt;
| One-off shell helper (&amp;lt;code&amp;gt;bw-get.py &amp;quot;Item Name&amp;quot; [field]&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;~/.claude.json&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;mcpServers.bitwarden&amp;lt;/code&amp;gt;&lt;br /&gt;
| —&lt;br /&gt;
| Registers the MCP with Claude Code&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/snap/bin/bw&amp;lt;/code&amp;gt;&lt;br /&gt;
| —&lt;br /&gt;
| Bitwarden CLI (snap-installed, official)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/home/mnw/.nvm/versions/node/v22.12.0/lib/node_modules/@bitwarden/mcp-server/&amp;lt;/code&amp;gt;&lt;br /&gt;
| —&lt;br /&gt;
| MCP server (npm-installed globally)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== How the wrapper works ===&lt;br /&gt;
&lt;br /&gt;
# Reads &amp;lt;code&amp;gt;vaultwarden.env&amp;lt;/code&amp;gt; via Python (avoids shell quoting issues with special chars in BW_PASSWORD).&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Refuses to start if &amp;lt;code&amp;gt;BW_URL != https://vault.wilsoz.com&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; — guard against accidentally authing to the wrong server.&lt;br /&gt;
# Runs &amp;lt;code&amp;gt;bw config server&amp;lt;/code&amp;gt; (idempotent) so the CLI is pointed at the self-hosted instance.&lt;br /&gt;
# Logs in via &amp;lt;code&amp;gt;--apikey&amp;lt;/code&amp;gt; (uses BW_CLIENTID/BW_CLIENTSECRET) if not already logged in.&lt;br /&gt;
# Unlocks with &amp;lt;code&amp;gt;bw unlock --passwordenv BW_PASSWORD --raw&amp;lt;/code&amp;gt; and exports &amp;lt;code&amp;gt;BW_SESSION&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Execs &amp;lt;code&amp;gt;node &amp;lt;path&amp;gt;/dist/index.js&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; (not the &amp;lt;code&amp;gt;mcp-server-bitwarden&amp;lt;/code&amp;gt; symlink — see Known Bugs below).&lt;br /&gt;
&lt;br /&gt;
=== Available MCP tools ===&lt;br /&gt;
&lt;br /&gt;
58 tools, covering: &amp;lt;code&amp;gt;lock&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;generate&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;create_item&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;create_folder&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;edit_item&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;edit_folder&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt;, plus organization/group/policy/send management. Used like any other MCP — e.g., &amp;quot;list items matching voip&amp;quot; or &amp;quot;create a new item named X&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Asking the User for Credentials ==&lt;br /&gt;
&lt;br /&gt;
When you need a credential that isn&amp;#039;t in Vaultwarden yet (e.g., a new third-party API key the user just got), &amp;#039;&amp;#039;&amp;#039;never ask the user to paste it in chat&amp;#039;&amp;#039;&amp;#039;. Instead:&lt;br /&gt;
&lt;br /&gt;
=== Pattern: &amp;quot;Save it to Vaultwarden, then I&amp;#039;ll fetch it&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Ask the user to do this:&lt;br /&gt;
&lt;br /&gt;
:Please add it to Vaultwarden:&lt;br /&gt;
:1. Open https://vault.wilsoz.com&lt;br /&gt;
:2. New Item → Folder: &amp;#039;&amp;#039;&amp;#039;Stronghold Infrastructure&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
:3. Name: &amp;lt;code&amp;gt;&amp;lt;service-name&amp;gt;&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;voip.ms&amp;lt;/code&amp;gt;)&lt;br /&gt;
:4. Add fields:&lt;br /&gt;
:   - &amp;lt;code&amp;gt;username&amp;lt;/code&amp;gt; = …&lt;br /&gt;
:   - &amp;lt;code&amp;gt;password&amp;lt;/code&amp;gt; = …&lt;br /&gt;
:   - Custom fields for anything else (e.g., &amp;lt;code&amp;gt;api-key&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;did&amp;lt;/code&amp;gt;)&lt;br /&gt;
:5. Save, then tell me &amp;quot;done&amp;quot;&lt;br /&gt;
:&lt;br /&gt;
:I&amp;#039;ll fetch it from Vaultwarden via the MCP — you never need to paste secrets here.&lt;br /&gt;
&lt;br /&gt;
Then on your side:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
[use bitwarden MCP] list items matching &amp;quot;&amp;lt;service-name&amp;gt;&amp;quot;&lt;br /&gt;
[use bitwarden MCP] get item &amp;lt;id&amp;gt;&lt;br /&gt;
[use vault MCP] write secret/&amp;lt;service-name&amp;gt; with the retrieved fields&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Why this matters ===&lt;br /&gt;
&lt;br /&gt;
* Chat transcripts are logged. Secrets in chat = secrets in logs forever.&lt;br /&gt;
&amp;#039;&amp;#039; The user has explicitly said: &amp;#039;&amp;#039;never store or surface credentials, use Vaultwarden + OpenBao.*&lt;br /&gt;
* If you accidentally print a secret (e.g., via &amp;lt;code&amp;gt;bash -x&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set -x&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cat env-file&amp;lt;/code&amp;gt;, or echoing a fetched variable) — &amp;#039;&amp;#039;&amp;#039;stop, tell the user immediately, and ask them to rotate that credential.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Hard-Won Gotchas ==&lt;br /&gt;
&lt;br /&gt;
=== 1. &amp;lt;code&amp;gt;mcp-server-bitwarden&amp;lt;/code&amp;gt; symlink does not work (v2026.2.0) ===&lt;br /&gt;
&lt;br /&gt;
The npm package installs a symlink at &amp;lt;code&amp;gt;…/bin/mcp-server-bitwarden&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;…/dist/index.js&amp;lt;/code&amp;gt;. The script at the end of &amp;lt;code&amp;gt;index.js&amp;lt;/code&amp;gt; checks &amp;lt;code&amp;gt;process.argv[1].endsWith(&amp;#039;index.js&amp;#039;)&amp;lt;/code&amp;gt; to decide whether to start the server. The symlink path doesn&amp;#039;t end in &amp;lt;code&amp;gt;index.js&amp;lt;/code&amp;gt;, so the server never starts — it just exits silently with code 0.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Workaround:&amp;#039;&amp;#039;&amp;#039; invoke via &amp;lt;code&amp;gt;node&amp;lt;/code&amp;gt; with the full path:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
exec node &amp;quot;$(npm root -g)/@bitwarden/mcp-server/dist/index.js&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Never use &amp;lt;code&amp;gt;bash -x&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;set -x&amp;lt;/code&amp;gt; near &amp;lt;code&amp;gt;source vaultwarden.env&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Bash tracing prints every variable assignment to stderr, including BW_PASSWORD. &amp;#039;&amp;#039;&amp;#039;This will leak the master password into your terminal scrollback, into logs, and into Claude conversation transcripts.&amp;#039;&amp;#039;&amp;#039; Use targeted &amp;lt;code&amp;gt;echo&amp;lt;/code&amp;gt; debugging or &amp;lt;code&amp;gt;python3&amp;lt;/code&amp;gt; parsing instead.&lt;br /&gt;
&lt;br /&gt;
=== 3. &amp;lt;code&amp;gt;bw login&amp;lt;/code&amp;gt; defaults to &amp;lt;code&amp;gt;vault.bitwarden.com&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
If the bw CLI&amp;#039;s local config gets reset (&amp;lt;code&amp;gt;~/.config/Bitwarden CLI/data.json&amp;lt;/code&amp;gt; deleted), it will default to the public Bitwarden cloud. Running &amp;lt;code&amp;gt;bw login&amp;lt;/code&amp;gt; against the wrong server &amp;#039;&amp;#039;&amp;#039;sends your credentials to Bitwarden, Inc.&amp;#039;&amp;#039;&amp;#039; Always run &amp;lt;code&amp;gt;bw config server &amp;quot;$BW_URL&amp;quot;&amp;lt;/code&amp;gt; first. The wrapper script enforces this with a refuse-to-start guard.&lt;br /&gt;
&lt;br /&gt;
=== 4. &amp;lt;code&amp;gt;bw login&amp;lt;/code&amp;gt; vs &amp;lt;code&amp;gt;bw unlock&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;bw login&amp;lt;/code&amp;gt; = authenticate the device to the server (once per device, persisted in &amp;lt;code&amp;gt;data.json&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;bw unlock&amp;lt;/code&amp;gt; = decrypt the local vault cache (once per session, returns BW_SESSION).&lt;br /&gt;
* The MCP server needs both. The wrapper handles login idempotently; unlock runs on every start.&lt;br /&gt;
&lt;br /&gt;
=== 5. &amp;lt;code&amp;gt;bw login&amp;lt;/code&amp;gt; with email + password fails on Vaultwarden ===&lt;br /&gt;
&lt;br /&gt;
Vaultwarden / Bitwarden self-hosted requires &amp;lt;code&amp;gt;bw login --apikey&amp;lt;/code&amp;gt; (client credentials) rather than &amp;lt;code&amp;gt;bw login email password&amp;lt;/code&amp;gt;. The email/password flow expects 2FA prompts and an interactive TTY.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Rotating BW_PASSWORD ==&lt;br /&gt;
&lt;br /&gt;
If the master password leaks (e.g., bash -x mistake):&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;In Vaultwarden web UI:&amp;#039;&amp;#039;&amp;#039; Account Settings → Change Master Password.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;On stronghold:&amp;#039;&amp;#039;&amp;#039; Update &amp;lt;code&amp;gt;~/.config/claude/vaultwarden.env&amp;lt;/code&amp;gt;:&lt;br /&gt;
   ```bash&lt;br /&gt;
   # Edit the line: BW_PASSWORD=&amp;#039;new-password-here&amp;#039;&lt;br /&gt;
   chmod 600 ~/.config/claude/vaultwarden.env  # verify mode still 600&lt;br /&gt;
   ```&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Re-login to bw:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   ```bash&lt;br /&gt;
   bw logout&lt;br /&gt;
   set -a; source ~/.config/claude/vaultwarden.env; set +a&lt;br /&gt;
   bw config server &amp;quot;$BW_URL&amp;quot;&lt;br /&gt;
   bw login --apikey&lt;br /&gt;
   ```&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Next Claude session&amp;#039;&amp;#039;&amp;#039; will pick up the new password from the env file automatically.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;BW_CLIENTSECRET&amp;lt;/code&amp;gt; (API key) is a separate value — only rotate it if it leaks. Rotating it requires regenerating in Account Settings → Security → Keys → View API Key.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Related Docs ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;services/OPENBAO.md&amp;lt;/code&amp;gt; — the machine-facing companion store&lt;br /&gt;
* &amp;lt;code&amp;gt;services/OPENBAO.agent.md&amp;lt;/code&amp;gt; — agent-focused decision tree for credential access&lt;/div&gt;</summary>
		<author><name>Wikibot</name></author>
	</entry>
</feed>