114 lines
3.8 KiB
Markdown
114 lines
3.8 KiB
Markdown
# Vaultwarden Deployment (rayserver)
|
|
|
|
Complete worked example for deploying Vaultwarden (Bitwarden-compatible password manager) on rayserver infrastructure.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Browser → VPS (vault.graj-media.com:443, nginx SSL)
|
|
↳ Tailscale → Home server (100.93.253.36:3446, nginx SSL)
|
|
↳ Vaultwarden (127.0.0.1:8812, Docker)
|
|
```
|
|
|
|
## Docker Compose
|
|
|
|
```yaml
|
|
services:
|
|
vaultwarden:
|
|
image: vaultwarden/server:latest
|
|
container_name: vaultwarden
|
|
restart: unless-stopped
|
|
volumes:
|
|
- /mnt/seagate8tb/docker/vaultwarden:/data
|
|
ports:
|
|
- "127.0.0.1:8812:80"
|
|
environment:
|
|
- DOMAIN=https://vault.graj-media.com
|
|
- SIGNUPS_ALLOWED=false
|
|
- WEBSOCKET_ENABLED=true
|
|
- LOG_FILE=/data/vaultwarden.log
|
|
- LOG_LEVEL=warn
|
|
```
|
|
|
|
**Key settings:**
|
|
- `DOMAIN` — must match the public URL for correct invite links and CORS
|
|
- `SIGNUPS_ALLOWED` — enable temporarily for account creation, disable after
|
|
- `WEBSOCKET_ENABLED` — required for live sync with browser extensions
|
|
- Bind to `127.0.0.1` — all access goes through nginx
|
|
|
|
## Nginx WebSocket Configuration
|
|
|
|
Vaultwarden uses WebSocket for the notifications hub. The nginx config needs a dedicated location block for `/notifications/hub` with `Upgrade` and `Connection` headers, plus a separate block for the negotiate endpoint:
|
|
|
|
```nginx
|
|
server {
|
|
listen 3446 ssl;
|
|
server_name vault.graj-media.com;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/grajmedia.duckdns.org/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/grajmedia.duckdns.org/privkey.pem;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
client_max_body_size 128M;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8812;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
location /notifications/hub {
|
|
proxy_pass http://127.0.0.1:8812;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
}
|
|
|
|
location /notifications/hub/negotiate {
|
|
proxy_pass http://127.0.0.1:8812;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
}
|
|
}
|
|
```
|
|
|
|
Without the WebSocket blocks, browser extensions can't maintain a live sync connection — they'll work for manual syncs but won't push changes in real-time.
|
|
|
|
## Admin Token Setup
|
|
|
|
After first deployment, set the admin token via Docker environment variable. The token MUST be hashed with argon2id:
|
|
|
|
```bash
|
|
# Generate random token
|
|
ADMIN_TOKEN=$(openssl rand -hex 32)
|
|
|
|
# Hash with argon2id using the Vaultwarden container
|
|
HASHED=$(echo -n "$ADMIN_TOKEN" | sudo docker exec -i vaultwarden /vaultwarden hash)
|
|
|
|
# Add to docker-compose.yml environment section
|
|
# - ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$...'
|
|
# Then restart: sudo docker compose up -d
|
|
```
|
|
|
|
Access admin panel at `https://vault.graj-media.com/admin` — use the raw (unhashed) token to log in.
|
|
|
|
## Post-Deploy Steps
|
|
|
|
1. **Open signups temporarily**: set `SIGNUPS_ALLOWED=true`, restart container
|
|
2. **Create user account**: visit https://vault.graj-media.com, register
|
|
3. **Disable signups**: set `SIGNUPS_ALLOWED=false`, restart container
|
|
4. **Configure Bitwarden apps**: Settings → Self-hosted → Server URL: `https://vault.graj-media.com`
|
|
|
|
## Bitwarden Client Setup
|
|
|
|
All official Bitwarden clients support self-hosted servers:
|
|
- **Browser extension**: Settings → Self-Hosted Environment → Server URL
|
|
- **Desktop app**: Settings → Self-Hosted Environment
|
|
- **Mobile (iOS/Android)**: Settings → Self-Hosted Environment
|
|
|
|
Enter `https://vault.graj-media.com` as the server URL. No trailing slash.
|