# Kestrove: your own end-to-end encrypted password manager server. # # ./setup.sh asks two questions, writes .env and starts everything # docker compose up -d (after filling in .env yourself) # # Two containers: `server` (the sync API; it only ever stores encrypted data) and `web` (Caddy with the # web vault: automatic HTTPS from Let's Encrypt, strict security headers, and /v1 proxied to `server`). # Full guide: https://kestrove.samialabri.com/host.html name: kestrove x-server-image: &server-image ${KESTROVE_REGISTRY:-gitea.samialabri.com/kestrove}/kestrove-server:${KESTROVE_VERSION:-latest} services: server: image: *server-image restart: unless-stopped read_only: true tmpfs: [/tmp] cap_drop: [ALL] security_opt: ["no-new-privileges:true"] volumes: - data:/data environment: RUST_LOG: info KV_PUBLIC_URL: https://${DOMAIN:?Set DOMAIN in .env (run ./setup.sh)} KV_TRUST_PROXY: "1" # One-time code for creating your account in the web vault. Empty: a random one is printed in # `docker compose logs server` on first start. KV_SETUP_CODE: ${KV_SETUP_CODE:-} networks: [internal] web: image: ${KESTROVE_REGISTRY:-gitea.samialabri.com/kestrove}/kestrove-web:${KESTROVE_VERSION:-latest} restart: unless-stopped ports: - "80:80" - "443:443" - "443:443/udp" environment: DOMAIN: ${DOMAIN:?Set DOMAIN in .env (run ./setup.sh)} ACME_EMAIL: ${ACME_EMAIL:?Set ACME_EMAIL in .env (run ./setup.sh)} volumes: - caddy-data:/data - caddy-config:/config networks: [internal] depends_on: [server] # docker compose run --rm -T backup > kestrove-$(date +%F).db # A consistent, integrity-checked copy of the database, taken while the server runs. Your vault inside it # is still end-to-end encrypted: restoring it needs your master password and Secret Key. backup: image: *server-image profiles: [tools] command: ["backup"] read_only: true tmpfs: [/tmp] cap_drop: [ALL] security_opt: ["no-new-privileges:true"] network_mode: none volumes: - data:/data volumes: data: caddy-data: caddy-config: networks: internal: