From 66eafd9d3c729597440ef5dd9ab97d0d739d62f9 Mon Sep 17 00:00:00 2001 From: brasse b Date: Fri, 10 Apr 2026 13:54:39 +0200 Subject: [PATCH] docs: add production deployment example with volumes and .env - docker/docker-compose.prod.yml: pulls image from 192.168.0.19:5000, mounts config/, wiki/ and db/ as separate volumes, health check, TZ support - .env.example: fully commented template for all env vars - .gitignore: ignore .env, always track .env.example - README: deployment section with step-by-step guide, volume table, backup commands - config.go: default db_path to /data/db/archivum.db (matches prod volume layout) Co-Authored-By: Claude Sonnet 4.6 --- .env.example | 51 +++++++++++++++++++ .gitignore | 2 + README.md | 82 +++++++++++++++++++++++++++++++ backend/internal/config/config.go | 6 +++ docker/docker-compose.prod.yml | 81 ++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+) create mode 100644 .env.example create mode 100644 docker/docker-compose.prod.yml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..88731ad --- /dev/null +++ b/.env.example @@ -0,0 +1,51 @@ +# ── Archivum — environment variables example ────────────────────────────────── +# Copy to .env and edit before running docker-compose.prod.yml +# +# cp .env.example .env +# +# Lines starting with # are comments and are ignored. +# ────────────────────────────────────────────────────────────────────────────── + + +# ── Registry ─────────────────────────────────────────────────────────────────── +# Address of your private Docker registry. +REGISTRY=192.168.0.19:5000 + +# Image tag to pull. Use a specific digest in production for reproducible deploys. +# IMAGE_TAG=sha256:abc123... +IMAGE_TAG=latest + + +# ── Host paths ───────────────────────────────────────────────────────────────── +# Base directory — all data lives under this path. +# Adjust to wherever you want to store Archivum data on the host. +ARCHIVUM_BASE=/opt/archivum + +# Configuration directory (config.json, settings.json). +# The Setup Wizard will create config.json here on first access. +ARCHIVUM_CONFIG=/opt/archivum/config + +# AsciiDoc wiki files + git repository root. +ARCHIVUM_WIKI=/opt/archivum/wiki + +# SQLite database directory. +# The database file will be created as archivum.db inside this directory. +ARCHIVUM_DB=/opt/archivum/db + + +# ── Network ──────────────────────────────────────────────────────────────────── +# Port exposed on the host. Access the app at http://:HOST_PORT +HOST_PORT=8080 + + +# ── File system permissions ───────────────────────────────────────────────────── +# UID and GID of the user that owns the host directories above. +# Run `id` on the host to find the correct values. +# Using 1000:1000 is fine if you created the directories as your own user. +PUID=1000 +PGID=1000 + + +# ── Timezone ─────────────────────────────────────────────────────────────────── +# Used for git commit timestamps. See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +TZ=Europe/Stockholm diff --git a/.gitignore b/.gitignore index 1077f43..15c5ac7 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ backend/internal/graph/models_gen.go config.json settings.json *.db +.env +# .env.example is intentionally tracked — it contains no secrets # go.sum is intentionally committed once populated by go mod tidy diff --git a/README.md b/README.md index 73c8b0f..24a303c 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,88 @@ npm run dev | `PUID` | `1000` | File system user ID | | `PGID` | `1000` | File system group ID | +## Production Deployment + +### Directory layout on the host + +``` +/opt/archivum/ +├── config/ +│ └── config.json ← written by Setup Wizard on first access +├── wiki/ ← AsciiDoc files + git repository +└── db/ + └── archivum.db ← SQLite database (auto-created) +``` + +### Steps + +```bash +# 1. Create host directories +mkdir -p /opt/archivum/{config,wiki,db} + +# 2. Set ownership to match PUID/PGID (default 1000:1000) +chown -R 1000:1000 /opt/archivum + +# 3. Copy and edit the environment file +cp .env.example .env +# Edit .env — at minimum check PUID, PGID and HOST_PORT + +# 4. Allow the insecure local registry (if not already done) +# Add to /etc/docker/daemon.json: +# { "insecure-registries": ["192.168.0.19:5000"] } +# Then: sudo systemctl restart docker + +# 5. Pull and start +docker compose -f docker/docker-compose.prod.yml pull +docker compose -f docker/docker-compose.prod.yml up -d + +# 6. View logs +docker compose -f docker/docker-compose.prod.yml logs -f +``` + +Open `http://:8080` and complete the Setup Wizard. + +### Example `.env` + +```dotenv +REGISTRY=192.168.0.19:5000 +IMAGE_TAG=latest + +ARCHIVUM_CONFIG=/opt/archivum/config +ARCHIVUM_WIKI=/opt/archivum/wiki +ARCHIVUM_DB=/opt/archivum/db + +HOST_PORT=8080 +PUID=1000 +PGID=1000 +TZ=Europe/Stockholm +``` + +> A fully commented template is available at [`.env.example`](.env.example). + +### Volumes at a glance + +| Container path | Maps to (default) | Purpose | +|---|---|---| +| `/config` | `/opt/archivum/config` | `config.json` (backend) + `settings.json` (frontend) | +| `/data/wiki` | `/opt/archivum/wiki` | AsciiDoc source files + git repo | +| `/data/db` | `/opt/archivum/db` | SQLite database (`archivum.db`) | + +### Backup + +```bash +# Wiki content (git repo — just rsync or tar) +tar czf archivum-wiki-$(date +%F).tar.gz /opt/archivum/wiki + +# Database +cp /opt/archivum/db/archivum.db archivum-db-$(date +%F).db + +# Config +cp /opt/archivum/config/config.json archivum-config-$(date +%F).json +``` + +--- + ## VS Code Tasks Open the Command Palette (`Ctrl+Shift+P`) → **Tasks: Run Task**: diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go index c85741a..057425a 100644 --- a/backend/internal/config/config.go +++ b/backend/internal/config/config.go @@ -49,6 +49,12 @@ func Load(path string) (*Config, error) { cfg.ListenAddr = ":4000" } + // Default DB path to the dedicated db volume so it can be backed up + // independently of the wiki content. + if cfg.DBPath == "" { + cfg.DBPath = "/data/db/archivum.db" + } + return &cfg, nil } diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml new file mode 100644 index 0000000..c2e2f50 --- /dev/null +++ b/docker/docker-compose.prod.yml @@ -0,0 +1,81 @@ +# ── Production deployment example ───────────────────────────────────────────── +# +# Uses the pre-built image from your private registry. +# Copy this file to your server and run: +# +# docker compose -f docker-compose.prod.yml up -d +# +# Prerequisites on the host: +# - Create the directories listed under "volumes" (or adjust paths in .env) +# - Populate config/config.json (see README for the JSON schema) +# OR leave it empty and the Setup Wizard will create it on first access. +# +# ── Directory layout this file expects ──────────────────────────────────────── +# +# /opt/archivum/ (or whatever ARCHIVUM_BASE points to) +# ├── config/ +# │ └── config.json ← backend configuration (auto-created by wizard) +# ├── wiki/ ← AsciiDoc source files (git repo lives here) +# └── db/ +# └── archivum.db ← SQLite database (auto-created on first start) +# +# ── Quick start ──────────────────────────────────────────────────────────────── +# cp .env.example .env # edit to match your environment +# mkdir -p /opt/archivum/{config,wiki,db} +# docker compose -f docker-compose.prod.yml pull +# docker compose -f docker-compose.prod.yml up -d +# ────────────────────────────────────────────────────────────────────────────── + +services: + archivum: + image: ${REGISTRY:-192.168.0.19:5000}/archivum:${IMAGE_TAG:-latest} + container_name: archivum + restart: unless-stopped + + ports: + - "${HOST_PORT:-8080}:4000" + + environment: + # Path inside the container where config.json is looked up. + DOCKER_PATH: /config + + # Path inside the container where the Vue SPA is served from. + # Change only if you override the Dockerfile. + UI_DIR: /srv/archivum/ui + + # Match the UID/GID of the user that owns the host directories. + PUID: ${PUID:-1000} + PGID: ${PGID:-1000} + + # Optional: set TZ for correct git commit timestamps. + TZ: ${TZ:-Europe/Stockholm} + + volumes: + # ── Configuration ────────────────────────────────────────────────────── + # config.json (backend) and settings.json (frontend) live here. + # The Setup Wizard writes config.json here on first run. + - ${ARCHIVUM_CONFIG:-/opt/archivum/config}:/config + + # ── Wiki files (AsciiDoc source + git repo) ──────────────────────────── + # This directory becomes the git repository root. + # Map it to wherever you want the .adoc files to live on the host. + - ${ARCHIVUM_WIKI:-/opt/archivum/wiki}:/data/wiki + + # ── SQLite database ──────────────────────────────────────────────────── + # Mounting the db directory separately makes it easy to back up the + # database independently of the wiki content. + - ${ARCHIVUM_DB:-/opt/archivum/db}:/data/db + + # Optional: limit resource usage on a Raspberry Pi 5. + # deploy: + # resources: + # limits: + # cpus: "2.0" + # memory: 512M + + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:4000/health"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s