From a2a0dfaa58cca45efe3c2e7e40358e19900f7f59 Mon Sep 17 00:00:00 2001 From: ashisgreat22 Date: Wed, 18 Mar 2026 03:15:34 +0100 Subject: [PATCH] docs: update Vaultwarden plan with nginx extraLocations fix Co-Authored-By: Claude Opus 4.6 --- .../plans/2026-03-18-vaultwarden.md | 358 ++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 docs/superpowers/plans/2026-03-18-vaultwarden.md diff --git a/docs/superpowers/plans/2026-03-18-vaultwarden.md b/docs/superpowers/plans/2026-03-18-vaultwarden.md new file mode 100644 index 0000000..d9c8907 --- /dev/null +++ b/docs/superpowers/plans/2026-03-18-vaultwarden.md @@ -0,0 +1,358 @@ +# Vaultwarden Module Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add Vaultwarden password manager as a NixOS module with Podman container, Nginx reverse proxy, and SOPS secrets. + +**Architecture:** Podman container running vaultwarden/server image with HTTP and WebSocket ports, integrated with existing Nginx module for reverse proxy and TLS, using SOPS for admin token secret management. + +**Tech Stack:** NixOS, Podman, Nginx, SOPS-nix, Vaultwarden + +--- + +## File Structure + +| File | Purpose | +|------|---------| +| `modules/nginx.nix` | Modify - add `extraLocations` option for WebSocket support | +| `modules/vaultwarden.nix` | New module - defines options and container config | +| `modules/default.nix` | Add import for vaultwarden module | +| `configuration.nix` | Enable module, declare SOPS secrets/templates | + +--- + +### Task 1: Extend Nginx Module for Extra Locations + +**Files:** +- Modify: `modules/nginx.nix` + +- [ ] **Step 1: Add `extraLocations` option to domain submodule** + +Add a new option after `extraConfig` (around line 46): + +```nix + extraLocations = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule { + options = { + proxyPass = lib.mkOption { + type = lib.types.str; + description = "Proxy target URL"; + }; + extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + description = "Extra Nginx config for this location"; + }; + }; + }); + default = { }; + description = "Additional location blocks to add to this virtual host"; + }; +``` + +- [ ] **Step 2: Update virtualHosts generation to include extraLocations** + +Replace the `virtualHosts` block (lines 76-87) with: + +```nix + virtualHosts = lib.mapAttrs' (domain: opts: { + name = domain; + value = { + enableACME = true; + forceSSL = true; + + locations = { + "/" = { + proxyPass = "http://127.0.0.1:${toString opts.port}"; + extraConfig = opts.extraConfig; + }; + } // lib.mapAttrs' (locPath: locOpts: { + name = locPath; + value = { + proxyPass = locOpts.proxyPass; + extraConfig = locOpts.extraConfig; + }; + }) opts.extraLocations; + }; + }) cfg.domains; +``` + +- [ ] **Step 3: Verify syntax** + +Run: `nix-instantiate --parse modules/nginx.nix` +Expected: No parse errors + +- [ ] **Step 4: Commit** + +```bash +git add modules/nginx.nix +git commit -m "feat(nginx): add extraLocations option for WebSocket support + +Co-Authored-By: Claude Opus 4.6 " +``` + +--- + +### Task 2: Create Vaultwarden Module File + +**Files:** +- Create: `modules/vaultwarden.nix` + +- [ ] **Step 1: Create module file** + +```nix +# Vaultwarden Module (Podman) +# Provides: Bitwarden-compatible password manager +# +# Usage: +# myModules.vaultwarden = { +# enable = true; +# port = 8222; +# websocketPort = 3012; +# domain = "vault.example.com"; +# }; + +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.myModules.vaultwarden; +in +{ + options.myModules.vaultwarden = { + enable = lib.mkEnableOption "Vaultwarden password manager"; + + domain = lib.mkOption { + type = lib.types.str; + example = "vault.example.com"; + description = "Public domain for Vaultwarden"; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 8222; + description = "HTTP port for Vaultwarden web interface"; + }; + + websocketPort = lib.mkOption { + type = lib.types.port; + default = 3012; + description = "WebSocket port for real-time sync"; + }; + }; + + config = lib.mkIf cfg.enable { + # Enable podman + myModules.podman.enable = true; + + # Vaultwarden container + virtualisation.oci-containers.containers."vaultwarden" = { + image = "vaultwarden/server:latest"; + ports = [ + "127.0.0.1:${toString cfg.port}:80" + "127.0.0.1:${toString cfg.websocketPort}:3012" + ]; + environmentFiles = [ + config.sops.templates."vaultwarden.env".path + ]; + environment = { + SHOW_PASSWORD_HINT = "false"; + SIGNUPS_ALLOWED = "true"; + }; + volumes = [ + "vaultwarden-data:/data" + ]; + }; + + # Register with Nginx (using extraLocations for WebSocket) + myModules.nginx.domains."${cfg.domain}" = { + port = cfg.port; + extraLocations."/notifications/hub" = { + proxyPass = "http://127.0.0.1:${toString cfg.websocketPort}"; + extraConfig = '' + proxyHttpVersion 1.1; + proxySetHeader Upgrade $http_upgrade; + proxySetHeader Connection "upgrade"; + ''; + }; + }; + }; +} +``` + +- [ ] **Step 2: Verify file was created** + +Run: `cat modules/vaultwarden.nix | head -20` +Expected: Module header and options visible + +- [ ] **Step 3: Commit module file** + +```bash +git add modules/vaultwarden.nix +git commit -m "feat: add Vaultwarden module (Podman) + +Co-Authored-By: Claude Opus 4.6 " +``` + +--- + +### Task 3: Register Module in default.nix + +**Files:** +- Modify: `modules/default.nix` + +- [ ] **Step 1: Add vaultwarden import** + +Edit `modules/default.nix` to add `./vaultwarden.nix` to imports: + +```nix +# Module exports +{ + imports = [ + ./system.nix + ./podman.nix + ./nginx.nix + ./searxng.nix + ./openclaw-podman.nix + ./vaultwarden.nix + ]; +} +``` + +- [ ] **Step 2: Verify syntax** + +Run: `nix-instantiate --parse modules/default.nix` +Expected: No parse errors + +- [ ] **Step 3: Commit** + +```bash +git add modules/default.nix +git commit -m "feat: register Vaultwarden module in default.nix + +Co-Authored-By: Claude Opus 4.6 " +``` + +--- + +### Task 4: Configure Vaultwarden in configuration.nix + +**Files:** +- Modify: `configuration.nix` + +- [ ] **Step 1: Add Vaultwarden module configuration** + +Add after the OpenClaw section (around line 95): + +```nix + # === Vaultwarden === + myModules.vaultwarden = { + enable = true; + port = 8222; + websocketPort = 3012; + domain = "vault.ashisgreat.xyz"; + }; +``` + +- [ ] **Step 2: Add SOPS secret declaration** + +Add after the OpenClaw secrets (around line 100): + +```nix + sops.secrets.vaultwarden_admin_token = { }; +``` + +- [ ] **Step 3: Add SOPS template** + +Add after the openclaw.env template (around line 108): + +```nix + sops.templates."vaultwarden.env" = { + content = '' + ADMIN_TOKEN=${config.sops.placeholder.vaultwarden_admin_token} + ''; + }; +``` + +- [ ] **Step 4: Verify configuration builds** + +Run: `nixos-rebuild build --flake .#nixos` +Expected: Build succeeds without errors + +- [ ] **Step 5: Commit** + +```bash +git add configuration.nix +git commit -m "feat: enable Vaultwarden with secrets configuration + +Co-Authored-By: Claude Opus 4.6 " +``` + +--- + +### Task 5: Add Admin Token Secret (Manual) + +**Files:** +- Modify: `secrets/secrets.yaml` (encrypted) + +- [ ] **Step 1: Edit secrets file** + +Run: `nix-shell -p sops --run "sops secrets/secrets.yaml"` + +- [ ] **Step 2: Add vaultwarden_admin_token** + +Add this entry to the YAML file: +```yaml +vaultwarden_admin_token: "your-secure-admin-token-here" +``` + +Replace `your-secure-admin-token-here` with a strong password/token. + +- [ ] **Step 3: Save and exit** + +The file will be re-encrypted automatically. + +--- + +### Task 6: Deploy and Verify + +- [ ] **Step 1: Deploy configuration** + +Run: `sudo nixos-rebuild switch --flake .#nixos` +Expected: Deployment succeeds + +- [ ] **Step 2: Verify container is running** + +Run: `sudo podman ps | grep vaultwarden` +Expected: Container listed as running + +- [ ] **Step 3: Verify web interface** + +Run: `curl -I http://127.0.0.1:8222` +Expected: HTTP 200 response + +- [ ] **Step 4: Final commit (if any changes)** + +```bash +git status +# If secrets.yaml was modified (git tracks encrypted version): +git add secrets/secrets.yaml +git commit -m "chore: add Vaultwarden admin token secret + +Co-Authored-By: Claude Opus 4.6 " +``` + +--- + +## Summary + +After completing all tasks: +1. Nginx module supports extra locations for WebSocket endpoints +2. Vaultwarden will be accessible at `https://vault.ashisgreat.xyz` +3. WebSocket sync enabled for real-time updates +4. Admin panel accessible at `/admin` with the configured token +5. SQLite database persisted in Podman volume `vaultwarden-data`