Unified Monitoring Stack: Difference between revisions
Wikisailor (talk | contribs) |
Wikisailor (talk | contribs) |
||
| (3 intermediate revisions by the same user not shown) | |||
| Line 469: | Line 469: | ||
As can be noted in the YAML file there are two lines that look suspicious the new accounts and the admin token. These are left as they are for the initial setup but we will change them now. first the new accounts needs to be remedied so that if someone on the Internet stumbles across our vault they don't start filling our password manager with bogus junk. Obviously, we need to create our own account so we logon to <nowiki>https://vault.seaoffate.net</nowiki>. At the vault warden logon screen create the account/s as required. Once all of the accounts are created we can change the line in the environment "SIGNUPS_ALLOWED=true" to SIGNUPS_ALLOWED=false and restart the application. From this point on no new accounts can be created, while the logon screen does continue to show the option to do so it will not actually complete the new account creation process. | As can be noted in the YAML file there are two lines that look suspicious the new accounts and the admin token. These are left as they are for the initial setup but we will change them now. first the new accounts needs to be remedied so that if someone on the Internet stumbles across our vault they don't start filling our password manager with bogus junk. Obviously, we need to create our own account so we logon to <nowiki>https://vault.seaoffate.net</nowiki>. At the vault warden logon screen create the account/s as required. Once all of the accounts are created we can change the line in the environment "SIGNUPS_ALLOWED=true" to SIGNUPS_ALLOWED=false and restart the application. From this point on no new accounts can be created, while the logon screen does continue to show the option to do so it will not actually complete the new account creation process. | ||
====Securing the Admin Logon=== | ====Securing the Admin Logon==== | ||
The next thing to address is the "ADMIN_TOKEN=yoursecret_change_this # Used for the /admin panel" line. The admin logon is accessed from the URL <nowiki>https://vault.seaoffate.net/admin</nowiki> and is be used to configure options for the Vault warden users. There is no username just a password. To avoid posting a password on the Dockge screen we use a password encryption routine supplied by the Vault warden application. to create a password follow these steps | The next thing to address is the "ADMIN_TOKEN=yoursecret_change_this # Used for the /admin panel" line. The admin logon is accessed from the URL <nowiki>https://vault.seaoffate.net/admin</nowiki> and is be used to configure options for the Vault warden users. There is no username just a password. To avoid posting a password on the Dockge screen we use a password encryption routine supplied by the Vault warden application. to create a password follow these steps | ||
| Line 498: | Line 498: | ||
* If an error like "/usr/bin/ssh-copy-id: ERROR: No identities found" use the keygen routine (just accept the defaults) | * If an error like "/usr/bin/ssh-copy-id: ERROR: No identities found" use the keygen routine (just accept the defaults) | ||
ssh-keygen -t ed25519 -C "nigel@raisin" | ssh-keygen -t ed25519 -C "nigel@raisin" | ||
* Create the backup script | * Create the backup script and file locations | ||
mkdir -p ~/scripts | mkdir -p ~/scripts | ||
mkdir -p ~/logs | |||
nano ~/scripts/backup-vault.sh | nano ~/scripts/backup-vault.sh | ||
* Copy the script to the file | * Copy the script to the file | ||
| Line 506: | Line 507: | ||
# Configuration | # Configuration | ||
REMOTE_USER="nigel" | REMOTE_USER="nigel" | ||
REMOTE_HOST="mango.seaoffate.local" | REMOTE_HOST="mango.seaoffate.local" | ||
REMOTE_DIR="/opt/dockge/stacks/vaultwarden/data" | REMOTE_DIR="/opt/dockge/stacks/vaultwarden/data" | ||
BACKUP_DIR="/home/nigel/backups/vaultwarden" | BACKUP_DIR="/home/nigel/backups/vaultwarden" | ||
| Line 516: | Line 517: | ||
echo "Starting Vaultwarden backup from Mango..." | echo "Starting Vaultwarden backup from Mango..." | ||
# | # | ||
# | # Sync files | ||
if rsync -avz -e ssh "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR" "$BACKUP_DIR/latest/"; then | if rsync -avz -e ssh "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR" "$BACKUP_DIR/latest/"; then | ||
echo "Files synced successfully." | echo "Files synced successfully." | ||
# | |||
# Create the timestamped archive | |||
tar -czf "$BACKUP_DIR/vault_backup_$TIMESTAMP.tar.gz" -C "$BACKUP_DIR/latest" . | tar -czf "$BACKUP_DIR/vault_backup_$TIMESTAMP.tar.gz" -C "$BACKUP_DIR/latest" . | ||
# | |||
# Delete files older than 30 days | |||
find "$BACKUP_DIR" -name "vault_backup_*.tar.gz" -mtime +30 -delete | |||
# | |||
echo "Backup complete: $BACKUP_DIR/vault_backup_$TIMESTAMP.tar.gz" | echo "Backup complete: $BACKUP_DIR/vault_backup_$TIMESTAMP.tar.gz" | ||
else | else | ||
Latest revision as of 00:26, 25 February 2026
📖Introduction
Mango, located at 192.168.110.133 on the Infra network, is the unified successor to the Prometheus & Grafana and Victoria triad. It serves as the central hub for the Home Lab's observability. Mango natively scrapes metrics from all Virtual Machines, the Proxmox host(Pear) and the services, stores them in a high-performance VictoriaMetrics time-series database, and provides a Grafana interface for visualization. As an additional step we can manage the Docker installations that have Dockge with one master Dockge installation on Mango and possibly manage any Minecraft servers from this same host.
By consolidating these services, we reduce network overhead and simplify the management of our monitoring infrastructure while maintaining 12-month data retention on a dedicated 500GB storage pool.
🚦Security & Network Architecture
Mango sits within the Infra network. Because it aggregates data from every host in the lab, it is a high-value target.
- Web Interfaces: Grafana (Port 3000) and VictoriaMetrics VMUI (Port 8428) are restricted via pfSense to be accessible only from the MGT network (Cinnamon/Lemon).
- Scraping Flow: Mango acts as the source for all scrape requests. pfSense rules must allow Mango to reach out to Production, VPN, and Terminal networks on specific exporter ports (9100, 9113, 9117, etc.).
- Storage Pool: Data is stored on a dedicated 500GB virtual disk (PearPool), mounted at /mnt/metrics_data to ensure that metric growth never impacts the OS root partition.
🏛️Environment & Storage Setup
The VM was created using the Debian Gold Master template.
- Hostname: Mango
- IP/Gateway: 192.168.110.133 / 192.168.110.1
- Disk 1 (OS): 32GB
- Disk 2 (Data): 500GB (Added via Proxmox)
Storage Initialization To handle the long-term metrics, the 500GB disk was initialized and mounted:
# Identify disk (sdb), format, and mount sudo mkfs.ext4 /dev/sdb sudo mkdir -p /mnt/metrics_data sudo mount /dev/sdb /mnt/metrics_data # Ensure persistence in /etc/fstab /dev/sdb /mnt/metrics_data ext4 defaults 0 2
🔧Installation
⚡VictoriaMetrics Installation
VictoriaMetrics was installed as a native binary (not Docker) to replace both the Prometheus scraper and the Victoria storage VM.
- User & Directory Setup
sudo useradd --no-create-home --shell /bin/false victoriametrics sudo mkdir /etc/victoriametrics sudo chown -R victoriametrics:victoriametrics /etc/victoriametrics /mnt/metrics_data
- Binary Installation
Binaries were retrieved from the VictoriaMetrics GitHub.
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.xx.x/victoria-metrics-linux-amd64-v1.xx.x.tar.gz tar -xvf victoria-metrics-linux-amd64-v1.xx.x.tar.gz sudo mv victoria-metrics-prod /usr/local/bin/victoriametrics sudo chown victoriametrics:victoriametrics /usr/local/bin/victoriametrics
- Service Configuration
sudo nano /etc/systemd/system/victoriametrics.service
[Service] ExecStart=/usr/local/bin/victoriametrics \ --storageDataPath=/mnt/metrics_data \ --retentionPeriod=12 \ --promscrape.config=/etc/victoriametrics/prometheus.yml \ --httpListenAddr=0.0.0.0:8428
Note: The --retentionPeriod=12 ensures one year of history.
🔍Scraping Configuration (prometheus.yml)
VictoriaMetrics uses the standard Prometheus YAML format for its scraper. The file was copied from the older Prometheus host Pineapple and copied to:
sudo nano /etc/victoriametrics/prometheus.yml
Key Change: The evaluation_interval directive was removed as it is not natively supported by the VictoriaMetrics single-binary scraper (it expects vmalert for that).
🧪Target Jobs
The configuration includes the legacy fleet plus the new 2026 additions:
- Infrastructure: Mango (Self), CTNS1.
- Production:
- Reverse proxy (Nginx) Raisin
- Webservers (Apache) Plum, Satsuma, Fig
- Database server (MySQL) Mandarin
- New 2026 Hosts: Blackcurrant (Data & Archive), Quince (AI/Media), Tayberry (OpenAlex).
- Gaming: Apple & Cherry (Minecraft Servers).
- Terminals:
- (NoMachine) Kiwiberry
- (XRDP), Kapok
- (Windows, RDP) Wahoo/Walnut .
Scrape Interval: Set to 120s to balance data resolution with disk I/O and longevity.
Adding the Dockge Targets
we had to update the /etc/victoriametrics/prometheus.yml to include the docker containers
#scrape_configs:
- job_name: 'docker_containers'
static_configs:
- targets:
- 'quince.seaoffate.net:8080' # cAdvisor (AI Stack)
- 'blackberry.seaoffate.net:8080' # cAdvisor (Data Archive)
- 'tayberry.seaoffate.net:8080' # cAdvisor (OpenAlex)
- job_name: 'gpu_metrics'
static_configs:
- targets: ['quince.seaoffate.net:9400'] # DCGM Exporter
- job_name: 'jellyfin'
metrics_path: '/metrics' # Crucial: tells VM where to look on port 8096
static_configs:
- targets: ['quince.seaoffate.net:8096']
Target Agent Installation (Scrapers)
For Mango to collect data, each target VM must run a specific exporter. Most Linux hosts use the node_exporter for OS metrics, while application-specific exporters are used for Nginx, Apache, and MySQL.
Linux Node Exporter (Standard for all VMs)
Installed on all Linux hosts (Raisin, Plum, Satsuma, Apple, Cherry, etc.) to monitor CPU, RAM, and Disk. Any hosts that don't show on the targets webpage need to have the agent installed.
- Install via APT
sudo apt update && sudo apt install -y prometheus-node-exporter
- Enable and Start
sudo systemctl enable --now prometheus-node-exporter
- Verification (Run on target VM)
curl http://localhost:9100/metrics
- Firewall Requirement: Target VM must allow Inbound TCP 9100 from Mango (192.168.110.133).
Nginx (Raisin)
Used to monitor active connections and request rates. the Nginx exporter is a standalone binary that talks to Nginx's stub_status module.
- Enable Nginx Status: On Raisin, edit the Nginx config (e.g., /etc/nginx/sites-available/default) and add this block:
server {
listen 127.0.0.1:8080;
location /metrics {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
sudo nginx -s reload
- Install & Run Exporter
wget https://github.com/nginx/nginx-prometheus-exporter/releases/latest/download/nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz tar -xvf nginx-prometheus-exporter_*.tar.gz sudo mv nginx-prometheus-exporter /usr/local/bin/
- Create a Systemd Service
sudo nano /etc/systemd/system/nginx-exporter.service
Paste this into the service file
[Unit] Description=Nginx Prometheus Exporter After=network.target
[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/bin/nginx-prometheus-exporter \
-nginx.scrape-uri=http://127.0.0.1:8080/metrics
Restart=always
[Install] WantedBy=multi-user.target
Enable the service with
sudo systemctl enable --now nginx-exporter
MySQL (Mandarin)
Used to monitor query throughput and database health.
- Database User: Create a mysqld_exporter user in MySQL with PROCESS, REPLICATION CLIENT, SELECT privileges.
- Configuration: Store credentials in /etc/.mysqld_exporter.cnf.
- Service: Install prometheus-mysqld-exporter via APT.
- Port: TCP 9104
Apache (Plum, Fig, Satsuma)
- Enable Mod Status:
sudo a2enmod status.
- Install Exporter:
sudo apt install prometheus-apache-exporter
- Port: TCP 9117
Windows Exporter (Wahoo & Walnut)
For the Windows 11 desktops, we use the windows_exporter
- Download: Latest .msi from the Prometheus Community GitHub.
- Install: Run the installer; it defaults to port 9182.
- Firewall: The installer typically adds a "Windows Firewall" exception automatically.
Docker & Container App Exporters
Since we are using Dockge to manage our containers on hosts like Quince (AI), Blackcurrant (Archive), and Tayberry (OpenAlex), we should standardize how metrics are pulled from these environments. The most efficient way to do this is to add cAdvisor to each of our Dockge stacks. This allows Mango to "see" inside the Docker engine of that specific VM and report on the health of every individual container (Ollama, Jellyfin, etc.).
Docker Container Monitoring (The Dockge Layer)
For every VM running Dockge, you need to add a Monitoring Stack or add these services to your existing stacks. cAdvisor is the primary agent here; it scrapes resource usage from the Docker socket.
- Create a "Monitoring" Stack in Dockge for Blackberry and Tayberry: In the Dockge UI, create a new stack and use the following
- Container_name: cadvisor
version: "3.8"
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.47.0 # Use a version compatible with your kernel
container_name: cadvisor
restart: unless-stopped
privileged: true
ports:
- 8080:8080
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
- Create a "Monitoring" Stack in Dockge for Quince: In the Dockge UI, create a new stack and use the following
- Container_name: cadvisor
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.47.0
container_name: cadvisor
restart: unless-stopped
privileged: true
ports:
- 8080:8080
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
devices:
- /dev/kmsg
nv-exporter:
image: nvcr.io/nvidia/k8s/dcgm-exporter:3.3.5-3.4.0-ubuntu22.04
container_name: nvidia_exporter
restart: unless-stopped
# Use 'command' to force it to listen on the network interface
command:
- -a
- 0.0.0.0:9400
ports:
- 9400:9400 # Map host 9400 to container 9400
cap_add:
- SYS_ADMIN
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities:
- gpu
networks: {}
Port Summary for Dockge Hosts (these ports must be opened in Pfsense for the exporters to report their status to Mango
- 8080: cAdvisor (Container CPU/RAM/Network)
- 9400: NVIDIA Exporter (GPU VRAM/Temp - Quince only)
Jellyfin monitoring
the switch to enable the metrics is not an option in the WebUI of our version of Jellyfin so we will have to enable it in the xml config. Since our Jellyfin config is mapped to /mnt/docker_data/jellyfin/config, finding the needle in the haystack is much easier. Because we are using the official Jellyfin image, the system.xml file is the principal config of the operation. On your host (Quince), the file you need to edit is right here:
/mnt/docker_data/jellyfin/config/config/system.xml
We could stop the container and modify the .xml directly from the terminal on Quince. We can also use sed to find the false value and make it true without having to hunt through the XML manually, after stopping the container (within dockge) and making a backup:
cd /mnt/docker_data/jellyfin/config/config/ cp system.xml system.xml.bak
Change EnableMetrics from false to true
sed -i 's/<EnableMetrics>false<\/EnableMetrics>/<EnableMetrics>true<\/EnableMetrics>/' system.xml
Now the metrics are switched on we can restart the container app in dockge
Proxmox Host (Pear)
To monitor the physical hardware and ZFS pools:
- Node Exporter: Installed directly on the Proxmox Debian host.
- SMART Metrics: Use the smartctl_exporter_script.sh (as detailed in legacy notes) to pipe drive health into the node_exporter's textfile collector.
Post-Installation validation on Mango
After installing an agent on a target, confirm Mango sees it:
- Open VMUI: http://mango:8428/targets.
- Search for the hostname.
- Status must be "UP". If "Connection Refused," check the service on the target; if "Timeout," check pfSense rules
📈 Grafana Installation
Grafana was installed on the same Mango host to provide the local visualization layer.
- Repository & App Setup
sudo apt install -y apt-transport-https software-properties-common wget wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/grafana.gpg > /dev/null echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list sudo apt update && sudo apt install grafana -y sudo systemctl enable --now grafana-server
🧩Network & Firewall Rules (pfSense)
To allow the new ports to function, pfSense was updated with a new Alias for Monitoring Ports:
- 3000: Grafana UI (remains the same from the previous Grafana installation)
- 8428: VictoriaMetrics UI/API ( The new port added for viewing of the scraping progress as was done by Prometheus web gui)
- 9090: removed the older Prometheus webgui port
Critical Rules
- MGT -> Mango: Allow ports 3000 & 8428 (Access from Cinnamon or other management console).
- Mango -> All Networks:
- Allow port 9100 (Node)
- Allow port 9113 (Nginx)
- Allow port 9117 (Apache)
- Allow port 9104 (MySQL)
- Allow port 9182 (Windows)
- Allow port 8080 (Docker, cadvisor)
- Allow port 9400 (NVIDIA DCGM)
- Allow port 8096 (Jellyfin)
Obviously for clarity the above ports should all have aliases in Pfsense so the rules are easier to read.
🔦Verification Steps
- Check Dockge: Ensure the cadvisor container shows as "Green/Running" in the Dockge UI.
- Service Status: (Confirmed Active/Running).
sudo systemctl status victoriametrics
Targets Check: verify all hosts are Green/UP. We should see the new entries for ports 8080, 9400, etc for the docker containers
http://mango:8428/targets
Data Source: In Grafana, added Prometheus data source pointing to
http://localhost:8428.
Disk Write Check: confirms ingestion of samples to the PearPool disk.
du -sh /mnt/metrics_data
We can verify the various agents are reporting with the curl command from mango. for example to test the docker container on Tayberry is working use: (docker app uses 8080 for its scraper)
curl http://tayberry.seaoffate.net:8080/metrics
We should We could modify the example to test other agents by using a different hostname and/or a different port number for example Tayberry also uses the standard Linux Exporter on 9100 so we could have :
curl http://tayberry.seaoffate.net:9100/metrics
and it should also present a wall of text from tayberry, assuming the the node exporter was installed. If any curl statements that don't work we should check the exporter is installed on the target, the appropriate Pfsense rule is setup and working, and that we have the correct port in the curl. If the curl works but the http://mango:8428/targets does not check the yaml file on mango
Summary of Legacy Retirement
With Mango fully operational:
- Pineapple (.130) services stopped.
- Granadilla (.131) services stopped.
- Victoria (.132) services stopped.
- Lychee identified as legacy and marked for rebuild via new Gold Master Template.
🐋Mango as a Dockge Master
We will also be installing Docker and Dockge so that we can manage all of the docker installations from a single master management interface rather than the three individual Dockge WebGUIs. It transforms Mango from just a monitoring server into a true Management Hub for the entire cluster. Since Mango is running a native VictoriaMetrics install, we need to be careful with Docker installation so it doesn't conflict with your existing systemd services.
The Strategy: The Manager's Desk
We aren't moving the actual containers (like Jellyfin or Ollama) to Mango—those stay on Quince, Blackberry, and Tayberry. Instead, we are setting up Dockge on Mango to act as the single interface that logs into the other three using the Dockge Agent or Remote Contexts.
Phase One Install Docker on Mango
Since Mango is on Debian, we’ll use the official Docker repository to ensure we get the latest Compose features that Dockge relies on. Because Trixie is a testing branch, your wiki needs to be very specific about the "Bookworm" override. Since Mango is running Debian Trixie (13 Testing), and Docker does not yet have a dedicated repository for this codename, we must manually point the repository to the stable Bookworm (12) suite.
- Create Keyring & Set Permissions:
sudo mkdir -p /etc/apt/keyrings sudo chmod 755 /etc/apt/keyrings
Download GPG Key:
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc
Define Repository (The Trixie Override): Note: We explicitly use bookworm here instead of the dynamic $(VERSION_CODENAME) because the Trixie repository does not exist on Docker's servers yet.
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ bookworm stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Install Docker Engine:
sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
- Prepare Storage on Mango: Since we have a 500GB data disk (/mnt/metrics_data), it’s a good idea to store our stack configurations there. This ensures that even if the OS drive (32GB) fills up or needs a wipe, our deployment YAMLs are safe. Create directories on your data disk and create a symlink so the paths look "standard"
sudo mkdir -p /mnt/metrics_data/dockge/data sudo mkdir -p /mnt/metrics_data/dockge/stacks sudo ln -s /mnt/metrics_data/dockge /opt/dockge
- Deploy Master Dockge: Create a directory for the compose file and launch it:
mkdir -p ~/dockge-master && cd ~/dockge-master nano compose.yaml
Paste this configuration:
services:
dockge:
image: louislam/dockge:1
restart: unless-stopped
ports:
- 5001:5001
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/dockge/data:/app/data
- /opt/dockge/stacks:/opt/stacks
environment:
# Tell Dockge where to find the stacks on the HOST
- DOCKGE_STACKS_DIR=/opt/dockge/stacks
Save & close then start it up:
sudo docker compose up -d
The Amalgamation: Linking Quince, Blackberry, & Tayberry
The first thing to do is to allow the Dockge management port through Pfsense from production to Infra by creating an alias of port 5001 and creating the pass rule between the two VLANs. Once the firewall rule is enabled we login to th the Dockge on mango at http://mango:5001, assuming the three remote nodes are running, we will follow these steps to centralize our lab:
- Click the "Add Agent" button on the Dockge Agents panel on the left of the Dockge screen
- Fill in the text boxes with
- http://hostname:5001
- username that would normally be used to login to the Dockge instance
- password
- click connect and wait for the target to login. If it times out check the username/password and check the Pfsense rule is allowing port 5001 from infra to production
Testing Master Dockge
To test and demonstrate the master Dockge management we can install a test application on each of the target nodes. For the test we will use the stack name test-log-viewer and the YAML
services:
dozzle:
container_name: dozzle_test
image: amir20/dozzle:latest
restart: unless-stopped
ports:
- 8888:8080
environment:
- DOZZLE_LEVEL=info
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- Click + Compose
- copy the stack name test-log-viewer
- Use the drop down docker agent to select the remote target node for the application, there should be current(this is the local node mango), Blackberry, Tayberry and Quince all as online
- Paste in the above YAML to the Compose.yaml
- click deploy button and the target node should pull down the application and start
- After proving that the application has been deployed it can be deleted
🔐 Vaultwarden Deployment on Mango
It is time to retire the KeePass file and as we have the new SSL certs and Dockge setup it is time to deploy Vaultwarden. Since our certificates are already synced to Mango, Vaultwarden will be able to start with full HTTPS right out of the gate. We will use the certificates located at /etc/nginx/ssl/seaoffate.net/. Even though they are owned by nigel, the Docker mount will allow Vaultwarden to read them perfectly. We will have backups on a daily schedule to Raisin. The deployment uses a "Full-Chain TLS" model. Encryption is maintained from the client browser all the way to the application container.
🔧Container Deployment (Dockge)
Vaultwarden is deployed via Docker Compose with the ROCKET_TLS feature enabled. This ensures the container itself handles encryption using the wild-card certificates synced from Raisin.
- Open Mango Dockge http://mango:5001
- Click + Compose and name the stack vaultwarden
- Leave Dockge Agent as Current
- Paste the following YAML:
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.seaoffate.net
- SIGNUPS_ALLOWED=true
- ADMIN_TOKEN=yoursecret_change_this # Used for the /admin panel
- ROCKET_TLS={certs="/ssl/fullchain.pem",key="/ssl/privkey.pem"}
- ROCKET_PORT=80
volumes:
- ./data:/data
- /etc/nginx/ssl/seaoffate.net/fullchain.pem:/ssl/fullchain.pem:ro
- /etc/nginx/ssl/seaoffate.net/privkey.pem:/ssl/privkey.pem:ro
ports:
- 443:80
- Click Deploy and the vault warden image will be downloaded
💡By enabling ROCKET_TLS with the public SSL Cert from Letencypt, in the Vaultwarden container on Mango, the container itself is expecting an encrypted connection and connection requests from within our home lab, inside the Pfsense VLANs will also be over TLS and no matter how the lap is reconfigured all passwords will always be passed over an encrypted channel.
🍇 Nginx Reverse Proxy Configuration (Raisin)
Raisin acts as the TLS gateway. It intercepts external requests and passes them to Mango over the internal network. Note We will not allow any http access on port 80 and the default site config elsewhere would drop any clear text connection attempt if any of the firewalls were inadvertently left forwarding port 80 on to Raisin.
- Create a new configuration in the sites-available
sudo nano /etc/nginx/sites-available/vault.seaoffate.net
- Paste the following text to the config
server {
listen 443 ssl;
server_name vault.seaoffate.net;
#
ssl_certificate /etc/letsencrypt/live/seaoffate.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/seaoffate.net/privkey.pem;
#
location / {
proxy_pass https://192.168.110.133:443;
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;
#
# WebSockets for real-time sync
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
- Save & close the vault.seaoffate.net
- Enable the site
sudo ln -s /etc/nginx/sites-available/vault.seaoffate.net /etc/nginx/sites-enabled/
- Test the config:
sudo nginx -t
- Reload Nginx & check the sevice:
sudo systemctl reload nginx sudo systemctl status nginx
💡 Why we use https for the proxy_pass
Since we enabled ROCKET_TLS in the Vaultwarden container on Mango, the container itself is expecting an encrypted connection. By using proxy_pass https://..., Raisin and Mango will talk to each other over an encrypted link inside our network. With the current configuration both Raisin and Mango are physically on the same Proxmox host so very little chance that the communication could be intercepted. However, if at some point the VMs are moved it is be better to keep the channel encrypted end to end rather than as some sources suggest and pass the traffic via http on the backend. It has been noted that most guides that setup services with docker have a tendency to treat security as an after thought or a luxury, even with applications such as this where passwords are being accessed, by terminating the https at the reverse proxy. While that will indeed satisy the Cloudflare "full strict" requirement for end to end SSL, it is a big cheat and security hole that should be recognised as such & avoided. We prefer to use the SSL end to end and use the public cert so we get no browser warnings from within the LAN or outside.
📽️First use and Finalise Vaultwarden
As can be noted in the YAML file there are two lines that look suspicious the new accounts and the admin token. These are left as they are for the initial setup but we will change them now. first the new accounts needs to be remedied so that if someone on the Internet stumbles across our vault they don't start filling our password manager with bogus junk. Obviously, we need to create our own account so we logon to https://vault.seaoffate.net. At the vault warden logon screen create the account/s as required. Once all of the accounts are created we can change the line in the environment "SIGNUPS_ALLOWED=true" to SIGNUPS_ALLOWED=false and restart the application. From this point on no new accounts can be created, while the logon screen does continue to show the option to do so it will not actually complete the new account creation process.
Securing the Admin Logon
The next thing to address is the "ADMIN_TOKEN=yoursecret_change_this # Used for the /admin panel" line. The admin logon is accessed from the URL https://vault.seaoffate.net/admin and is be used to configure options for the Vault warden users. There is no username just a password. To avoid posting a password on the Dockge screen we use a password encryption routine supplied by the Vault warden application. to create a password follow these steps
- Logon to the VM that is hosting the vault warden application (in this case Mango)
ssh nigel@mango
- generate the password hash
docker exec -it vaultwarden /vaultwarden hash
- Type in the password "simplepassword" (or one of your choice) and then confirm it
- An admin token is displayed. ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$ddTHUmxG21CK2r3OHXblLVUokH/2qauOqpLp3+uHSms$4/UZtnSUM3U3dFzyvMVtyYFZgDlnPgqXnd79r0wGd+0'
- Docker compose YAML treats $ as variables so makes a mess of the token. To fix the token copy the long string between the quotation marks and paste it in to notepad or similar and replace each $ with $$. eg
$argon2id$v=19$m=65540,t=3,p=4$ddTHUmxG21CK2r3OHXblLVUokH/2qauOqpLp3+uHSms$4/UZtnSUM3U3dFzyvMVtyYFZgDlnPgqXnd79r0wGd+0
becomes
$$argon2id$$v=19$$m=65540,t=3,p=4$$ddTHUmxG21CK2r3OHXblLVUokH/2qauOqpLp3+uHSms$$4/UZtnSUM3U3dFzyvMVtyYFZgDlnPgqXnd79r0wGd+0
- The final string can be pasted into the YAML line in the environment
- ADMIN_TOKEN=yoursecret_change_this # Used for the /admin panel
becomes
- ADMIN_TOKEN=$$argon2id$$v=19$$m=65540,t=3,p=4$$ddTHUmxG21CK2r3OHXblLVUokH/2qauOqpLp3+uHSms$$4/UZtnSUM3U3dFzyvMVtyYFZgDlnPgqXnd79r0wGd+0 # Used for the /admin panel
- Restart the docker application
- http://vault.seaoffate.net/admin
- Login with the password simplepassword (or whatever was created) in the earlier SSH session just to prove it works.
🚨 If the admin password is lost a new password must be created in the terminal and entered in the YAMl compose file.
🏛️Data Integrity & Backups
Backups are "Pulled" from Mango to Raisin nightly to ensure data redundancy. It should be noted that the SQL Lite file that stores the passwords will encrypt the passwords but not the usernames so it would be better if the backups are kept in a secure location for the purposes of the documentation the backups are assumed to be stored on Raisin but they could be stored anywhere that is most convent & secure with simple adjustments to the procedure.
- From the terminal of Raisin we need a passwordless logon to mango for the backup script to run
ssh-copy-id [email protected]
- If an error like "/usr/bin/ssh-copy-id: ERROR: No identities found" use the keygen routine (just accept the defaults)
ssh-keygen -t ed25519 -C "nigel@raisin"
- Create the backup script and file locations
mkdir -p ~/scripts mkdir -p ~/logs nano ~/scripts/backup-vault.sh
- Copy the script to the file
#!/bin/bash
#
# Configuration
REMOTE_USER="nigel"
REMOTE_HOST="mango.seaoffate.local"
REMOTE_DIR="/opt/dockge/stacks/vaultwarden/data"
BACKUP_DIR="/home/nigel/backups/vaultwarden"
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
#
# Create local backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
#
echo "Starting Vaultwarden backup from Mango..."
#
# Sync files
if rsync -avz -e ssh "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR" "$BACKUP_DIR/latest/"; then
echo "Files synced successfully."
#
# Create the timestamped archive
tar -czf "$BACKUP_DIR/vault_backup_$TIMESTAMP.tar.gz" -C "$BACKUP_DIR/latest" .
#
# Delete files older than 30 days
find "$BACKUP_DIR" -name "vault_backup_*.tar.gz" -mtime +30 -delete
#
echo "Backup complete: $BACKUP_DIR/vault_backup_$TIMESTAMP.tar.gz"
else
echo "ERROR: Rsync failed. No backup created."
exit 1
fi
- Save & close, then make it executable
chmod +x ~/scripts/backup-vault.sh
- Make sure rsync is installed on both Raisin and Mango
- on Raisin
sudo apt update && sudo apt install rsync -y
- login to mango
ssh nigel@mango
- install rsync & exit
sudo apt update && sudo apt install rsync -y exit
- When back on raisin we need to add a new crontab (choose option 1 if asked)
crontab -e
- Add the line to the bottom of the list to run the script every morning at 03:00
# Every morning at 3:00 AM, pull the vault data from Mango 0 3 * * * /home/nigel/scripts/backup-vault.sh >> /home/nigel/logs/vault-backup.log 2>&1
- save & close, we can test the script with
~/scripts/backup-vault.sh ls -lh ~/backups/vaultwarden
There should be at least one backup showing