From 880cc24bdedfd6d089a75305da1269a67ae1099b Mon Sep 17 00:00:00 2001 From: jfcheng Date: Sun, 22 Feb 2026 15:38:13 -0500 Subject: [PATCH] feat: Add Vaultwarden config and set PUID to 1044 --- vaultwarden/RESEARCH.md | 43 +++++++++++ vaultwarden/SETUP.md | 44 +++++++++++ vaultwarden/create_vaultwarden_folders.sh | 94 +++++++++++++++++++++++ vaultwarden/docker-compose.portainer.yml | 29 +++++++ vaultwarden/stack.env | 25 ++++++ 5 files changed, 235 insertions(+) create mode 100644 vaultwarden/RESEARCH.md create mode 100644 vaultwarden/SETUP.md create mode 100644 vaultwarden/create_vaultwarden_folders.sh create mode 100644 vaultwarden/docker-compose.portainer.yml create mode 100644 vaultwarden/stack.env diff --git a/vaultwarden/RESEARCH.md b/vaultwarden/RESEARCH.md new file mode 100644 index 0000000..453e3eb --- /dev/null +++ b/vaultwarden/RESEARCH.md @@ -0,0 +1,43 @@ +# Self-Hosted Password Manager Research: Vaultwarden vs Alternatives + +## Conclusion & Recommendation +**Vaultwarden** (formerly bitwarden_rs) is the highly recommended choice for a self-hosted password manager for personal or family use, running on a Synology NAS. + +It provides the premium experience and cross-platform compatibility of Bitwarden without the massive resource overhead of the official enterprise server. + +## Detailed Comparison + +### 1. Vaultwarden +* **Architecture**: A lightweight, community-driven server implementation of the Bitwarden API written in Rust. +* **Resource Usage**: Extremely low CPU/RAM usage. Perfect for a Synology NAS environment. Often requires just a single Docker container. +* **Device Support**: 100% compatible with all official Bitwarden clients: + * Web Vault + * iOS App + * Android App + * Browser Extensions (Chrome, Firefox, Safari, Edge, etc.) + * Desktop Apps (Windows, macOS, Linux) +* **Features**: Includes premium Bitwarden features for free, such as: + * TOTP (Time-based One-Time Passwords) authenticator + * File attachments + * Organization/Family sharing + * YubiKey / WebAuthn support + +### 2. Official Bitwarden Server +* **Architecture**: Commercially supported, enterprise-grade architecture using .NET Core and Microsoft SQL Server. +* **Resource Usage**: Very heavy. A standard deployment spins up over 10 containers (mssql, web, api, identity, admin, sso, etc.) and consumes gigabytes of RAM. Not ideal for a standard NAS unless it has dedicated enterprise resources. +* **Features**: Full enterprise features, directory sync, SSO integrations, commercial support. +* **Pros/Cons**: While it is the "official" server, it is complete overkill for individual or small family usage, making Vaultwarden the pragmatic choice. + +### 3. Passbolt +* **Architecture**: Designed primarily for teams, agencies, and enterprise collaboration with a strong focus on compliance (GDPR, ISO 27001). +* **Security Model**: Uses GnuPG (OpenPGP) for encryption, which is excellent for shared passwords but can be more complex for end-users to manage keys. +* **Device Support**: Offers Web, iOS, Android, and Browser Extensions. However, the mobile experience is often cited as less "seamless" compared to Bitwarden for simple personal use. +* **Ease of Setup**: Complex. It practically requires an SMTP server configuration just to invite your first user and complete the installation process. +* **Pros/Cons**: Excellent for businesses needing granular, role-based password sharing, but overly complex and somewhat rigid for an individual home-lab user. + +## Next Steps for Repository +If you choose to proceed with Vaultwarden, the implementation should follow the repository standards: +1. Create a dedicated `svc-vaultwarden` user on the NAS. +2. Create a `SETUP.md` document for it. +3. Implement an Intelligent Dry-Run script (`create_vaultwarden_folders.sh`). +4. Deploy it via a `docker-compose.portainer.yml` stack grouped with a reverse proxy or cloudflared tunnel for secure remote access. diff --git a/vaultwarden/SETUP.md b/vaultwarden/SETUP.md new file mode 100644 index 0000000..9bdc83a --- /dev/null +++ b/vaultwarden/SETUP.md @@ -0,0 +1,44 @@ +# Service Setup Guide: Vaultwarden + +Vaultwarden is a lightweight, community-driven server implementation of the Bitwarden API, written in Rust. It provides full compatibility with official Bitwarden clients (Web, iOS, Android, Desktop, Extensions). + +## 1. Pre-Setup (Manual) +### Create Service User +- [ ] **Manual**: Create a local user named `svc-vaultwarden` in Synology DSM (Control Panel > User & Group). +- [ ] **Manual**: Give this user read/write access to the `docker` shared folder. + +### Get User IDs +- [ ] **Manual**: SSH into your NAS and run `sudo synouser --get svc-vaultwarden`. +- [ ] **Confirmed IDs**: Locate the `User ID` (PUID) and `Group ID` (PGID). +- [ ] **Action**: Open `create_vaultwarden_folders.sh` and update the `USER_ID="[PUID]:[PGID]"` line. +- [ ] **Action**: Use these values in your Portainer stack environment variables (`stack.env`). + +## 2. Infrastructure Setup +### Run Setup Script +- [ ] **Action**: Run the setup script in Dry-Run mode to verify changes: + ```bash + sudo bash create_vaultwarden_folders.sh + ``` +- [ ] **Action**: Apply the folder creation and ownership settings: + ```bash + sudo bash create_vaultwarden_folders.sh --run + ``` +- **What it does**: + - Creates `/volume1/docker/vaultwarden/data` for the SQLite database and attachments. + - Sets ownership securely to the `svc-vaultwarden` user, ensuring the container writes files non-root. + +## 3. Portainer Deployment +### Environment Variables +- [ ] **Action**: In the Portainer Stack configuration, upload or define the variables from `stack.env`. + - Important: Ensure `DOMAIN` is set correctly for WebAuthn/FIDO2 to function. + - Temporary: Keep `SIGNUPS_ALLOWED=true` initially. + +### Deploy Stack +- [ ] **Action**: Create a new stack named `vaultwarden-stack`. +- [ ] **Action**: Paste the content of `docker-compose.portainer.yml` and deploy. +- [ ] **Verification**: Access the Vaultwarden Web UI at `http://[NAS_IP]:8080`. + +## 4. Post-Setup Security (Crucial) +1. **Create your account**: Navigate to the Web UI, click "Create Account", and register your master email and password. +2. **Disable Signups**: Once your account is created, go back to Portainer, update the stack environment variable `SIGNUPS_ALLOWED=false`, and **Redeploy** the stack. This prevents unauthorized users from registering on your personal instance. +3. **Reverse Proxy / HTTPS**: Vaultwarden **requires** active HTTPS (SSL) for many features like Bitwarden browser extensions or the admin page to load correctly. Point your Traefik/Cloudflared tunnel to this container. diff --git a/vaultwarden/create_vaultwarden_folders.sh b/vaultwarden/create_vaultwarden_folders.sh new file mode 100644 index 0000000..9beb8ff --- /dev/null +++ b/vaultwarden/create_vaultwarden_folders.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# Default to dry-run mode +DRY_RUN=true +if [[ "$1" == "--run" || "$1" == "-r" ]]; then DRY_RUN=false; fi + +if [ "$DRY_RUN" = "true" ]; then + echo "--- DRY RUN MODE ---" + echo "To apply changes, run: sudo bash $0 --run" + echo "--------------------" +fi + +# Configuration +BASE="/volume1/docker/vaultwarden" +# Replace PUID/PGID with the ones from your environment or Synology DSM +USER_ID="1044:65538" # svc-vaultwarden + +# Helper functions +run_mkdir() { + local path=$1 + if [ -d "$path" ]; then + echo "[OK] Folder exists, no changes will be made: $path" + else + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CREATE] Folder: $path" + else + echo "[EXECUTE] Creating folder: $path" + mkdir -p "$path" + fi + fi +} + +run_chown_recursive() { + local owner=$1; local path=$2 + local uid=${owner%%:*}; local gid=${owner#*:} + + # Check if folder exists first + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL SET] Owner to $owner upon creation: $path" + else + echo "[EXECUTE] Setting owner to $owner (recursive): $path" + chown -R "$owner" "$path" + fi + return + fi + + # Check if any file/folder inside diverges from the target ownership + if find "$path" \( ! -uid "$uid" -o ! -gid "$gid" \) | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CHANGE] Owner to $owner (recursive): $path" + else + echo "[EXECUTE] Setting owner to $owner (recursive): $path" + chown -R "$owner" "$path" + fi + else + echo "[OK] Owner is $owner, no changes will be made: $path" + fi +} + +run_chmod_recursive() { + local mode=$1; local path=$2 + + # Check if folder exists first + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL SET] Permissions to $mode upon creation: $path" + else + echo "[EXECUTE] Setting permissions to $mode (recursive): $path" + chmod -R "$mode" "$path" + fi + return + fi + + # Check if any file/folder inside diverges from the target permissions + if find "$path" ! -perm -"$mode" | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CHANGE] Permissions to $mode (recursive): $path" + else + echo "[EXECUTE] Setting permissions to $mode (recursive): $path" + chmod -R "$mode" "$path" + fi + else + echo "[OK] Permissions are $mode, no changes will be made: $path" + fi +} + +# Run tasks +run_mkdir "${BASE}/data" +run_chown_recursive "$USER_ID" "${BASE}" +run_chmod_recursive 750 "${BASE}" + +if [ "$DRY_RUN" = "false" ]; then + echo "Done." +fi diff --git a/vaultwarden/docker-compose.portainer.yml b/vaultwarden/docker-compose.portainer.yml new file mode 100644 index 0000000..b7603e5 --- /dev/null +++ b/vaultwarden/docker-compose.portainer.yml @@ -0,0 +1,29 @@ +version: '3.8' + +services: + vaultwarden: + image: vaultwarden/server:latest + container_name: vaultwarden + restart: always + # Run as the defined Synology user to prevent root file ownership + user: "${PUID}:${PGID}" + environment: + # General + - WEBSOCKET_ENABLED=true + - DOMAIN=${DOMAIN} + - SIGNUPS_ALLOWED=${SIGNUPS_ALLOWED} + # Email (Optional but recommended for invitations & 2FA) + - SMTP_HOST=${SMTP_HOST} + - SMTP_FROM=${SMTP_FROM} + - SMTP_SECURITY=${SMTP_SECURITY:-starttls} + - SMTP_PORT=${SMTP_PORT:-587} + - SMTP_USERNAME=${SMTP_USERNAME} + - SMTP_PASSWORD=${SMTP_PASSWORD} + # Admin Panel + - ADMIN_TOKEN=${ADMIN_TOKEN} + volumes: + - /volume1/docker/vaultwarden/data:/data:rw + ports: + - "8080:80" # Web UI + # Note: Vaultwarden integrates the WebSocket server into the main process in recent versions, + # so exposing port 3012 is no longer required for typical setups unless using reverse proxy splitting. diff --git a/vaultwarden/stack.env b/vaultwarden/stack.env new file mode 100644 index 0000000..c1c22fc --- /dev/null +++ b/vaultwarden/stack.env @@ -0,0 +1,25 @@ +# Synology Execution User +PUID=1044 +PGID=65538 +TZ=America/Toronto + +# Vaultwarden Configuration +# Replace with your actual NAS IP/domain and https +DOMAIN=https://vaultwarden.yourdomain.com + +# SECURITY: Enable signups to create your initial account, then set this to 'false' inside Portainer +SIGNUPS_ALLOWED=true + +# Email Configuration (Optional) +SMTP_HOST=smtp.yourdomain.com +SMTP_FROM=vaultwarden@yourdomain.com +SMTP_SECURITY=starttls +SMTP_PORT=587 +SMTP_USERNAME=your_username +SMTP_PASSWORD=your_password + +# Admin Panel Token (Optional) +# Generate a secure hash using: vaultwarden hash +# Example: +# ADMIN_TOKEN=$$argon2id$$v=19... +ADMIN_TOKEN=your_generated_admin_token