Installation¶
ReoVault is deployed with Docker Compose, and only with Docker Compose. One
image holds everything: the archiver and scheduler, the web API, the built
dashboard, and a pinned reolink-cli. Running from a source checkout without
Docker is a development setup, see Contributing.
Docker Compose¶
ReoVault is published as a signed image for linux/amd64 and linux/arm64
at ghcr.io/wiebe-vandendriessche/reovault. You don't need to clone the
repository, two files are enough:
mkdir reovault && cd reovault
curl -fsSLO https://raw.githubusercontent.com/wiebe-vandendriessche/reovault/main/compose.yaml
mkdir -p config data/config data/vault data/staging data/reolink-cli secrets
curl -fsSL https://raw.githubusercontent.com/wiebe-vandendriessche/reovault/main/reovault.example.toml -o config/reovault.toml
# edit config/reovault.toml: your [[devices]], and set [web] email (set-password needs it)
echo -n "a passphrase, not the camera's" > secrets/reovault_master_passphrase.txt
docker compose run --rm reovault key init
docker compose up -d
docker compose exec reovault reovault web set-password
Create config/reovault.toml and the data/ folders yourself before the first
docker compose command, as above. If Docker has to create a missing bind
mount itself, it makes a root-owned folder, which the container (running as
uid 1000) can't write to.
If your user isn't uid 1000, run sudo chown -R 1000:1000 data once.
compose.yaml supports two deployment modes. Pick one, both are first-class:
- Direct port publish (LAN/VPN access, no reverse proxy). Uncomment
ports:and the twoREOVAULT_WEB__*lines below it. Plain HTTP has no certificate, so the session cookie must not require TLS (REOVAULT_WEB__COOKIE_SECURE=false) or login silently fails. The browser accepts the login redirect but drops aSecurecookie sent over HTTP, which just bounces you back to/login. Restricting exposure (firewall, VPN, trusted LAN only) is then on you, same as any other self-hosted app you publish a port for. - Reverse proxy (Traefik, Nginx Proxy Manager, Caddy, ...) on a shared
Docker network, the active default in
compose.yaml. SetREOVAULT_WEB__FORWARDED_ALLOW_IPSto the proxy's own address (never"*", see Security).
./config/ holds reovault.toml and is mounted read-write: the dashboard's
Settings page writes changes back into the file (comments and layout kept,
the previous version saved as reovault.toml.bak), and edits made to the
file by hand are applied live. ./data/{config,vault,staging} and ./data/reolink-cli
(reolink-cli's own credential registry, written to when a camera is added
from the Devices page) are bind mounts holding everything that must survive an
upgrade: database, master key, dashboard password, and the archive itself.
./secrets/reovault_master_passphrase.txt is a Docker secret file. Never
commit it, and back up data/config/master.key together with the passphrase:
losing either makes the archive unrecoverable.
The image bakes in a version-pinned, checksum-verified reolink-cli release;
reovault doctor asserts it at startup. reovault daemon is the container's
entrypoint and supervises the reolink-gateway sidecar in-process, so
nothing else needs to run alongside it.
Upgrading¶
docker compose pull && docker compose up -d
:latest follows the newest release. To upgrade on your own schedule
instead, pin a version in compose.yaml (for example
ghcr.io/wiebe-vandendriessche/reovault:0.4.0) and bump it after reading the
release notes.
Before 1.0 the config schema can still change between releases.
From 0.3 to 0.4¶
reovault.toml moves into a folder that is mounted read-write, so the
dashboard can write settings back into it:
mkdir -p config && mv reovault.toml config/ && sudo chown -R 1000:1000 config
Then update compose.yaml (the volumes: line is now - ./config:/etc/reovault)
and docker compose up -d. On first start, settings you changed in the 0.3
dashboard (schedules, retention, alert rules, cameras added from the
dashboard) are written into reovault.toml once; from then on the file is
the single source of truth. Until the folder is writable, the dashboard shows
settings read-only and nothing is migrated.
Verifying the image¶
Release images are signed keylessly with cosign by the release workflow, and carry an attested CycloneDX SBOM:
cosign verify ghcr.io/wiebe-vandendriessche/reovault:0.4.0 \
--certificate-identity-regexp '^https://github\.com/wiebe-vandendriessche/reovault/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
Each GitHub Release
also has the SBOM (sbom.cdx.json) and the vulnerability scan report
(results.sarif) attached.
Building from source¶
Clone the repository, then in compose.yaml comment out the image: line
and uncomment the build: block below it. docker compose up -d --build
builds and starts it; everything else above stays the same.
Alerts¶
ReoVault can tell you when archiving needs attention: a failed run, recordings
that failed or were quarantined, clips on a camera's SD card at risk of being
overwritten before they're archived, or the camera gateway being down. Channels are configured in reovault.toml (or
REOVAULT_ALERTS__* env vars), with anything secret in a file, the same way
as the master passphrase:
[alerts]
ntfy_url = "https://ntfy.sh/your-private-topic"
# ntfy_token_file = "/run/secrets/ntfy_token"
# webhook_url_file = "/run/secrets/alert_webhook" # Slack/Discord URLs work as-is
# smtp_host = "smtp.example.com"
# smtp_user = "reovault@example.com"
# smtp_password_file = "/run/secrets/smtp_password"
# smtp_to = ["you@example.com"]
Mount each secret file with a compose secrets: entry (see the commented
example in compose.yaml). Which conditions alert, and how often an open
alert reminds you, is set from the dashboard under Settings, Alerts, which
also has a "Send test" button. See Configuration.
First-run checklist¶
- Either
reovault.tomlhas a[[devices]]entry whosealiasmatches onereolink-cli device addalready registered, or you add the first camera from the dashboard's Devices page after startup. REOVAULT_MASTER_PASSPHRASE(orREOVAULT_MASTER_PASSPHRASE_FILE/ Docker secret) is set.reovault key initneeds it.reovault doctorpasses before anything camera-facing is attempted.[web] emailis set, andreovault web set-passwordis run before exposing the dashboard. Until a password is set, the API answers 503 and the dashboard says so (the healthcheck still works).