# Incus Backup UI Dark-mode control plane for Incus VM backups using ZFS block devices, Restic, and S3-compatible storage. Backups include the instance disk or dataset plus Incus metadata captured with `incus config show`, `incus config show --expanded`, `incus info`, and snapshot listing. VM disks are stored as `.raw`; containers are stored as ZFS send streams (`.zfs`). ## Layout - `management/`: Central Express API with cookie login, SQLite storage, node registry, central schedules, and proxy calls to node agents. - `agent/`: Node agent API that runs on each Incus host, validates Incus VMs, runs host commands with `spawn`, persists recent jobs, and enforces one active backup/restore per VM. - `frontend/`: React/Vite dashboard for management login, node management, health, VM status, snapshots, backup jobs, and explicit destructive restore confirmation. - `incus-backup-ui-plan.md`: Product and implementation plan. ## Node Agent ```bash curl -fsSL https://forgejo.digital-droplets.de/philschlo/incus-backup-ui/raw/branch/main/deploy/install-agent.sh | sudo sh ``` The node agent must run on every Incus host with permission to access Incus, ZFS, `/dev/zvol`, Restic, and S3 credentials. In production this usually means running it as root or through a tightly scoped service account with the needed privileges. Set `API_TOKEN` in `agent/.env`; the management server uses that token when calling the agent. The token is required and must be at least 32 characters long. The agent persists recent jobs in SQLite through `AGENT_DATABASE_PATH` (default: `./agent.sqlite`). If the agent restarts while a job is `queued` or `running`, that job is marked `failed` on startup so management can poll a final state and stale VM locks are not kept. The installer clones only the agent-related repository paths and installs `incubator` for updates and diagnostics: ```bash sudo incubator update sudo incubator status sudo incubator logs sudo incubator doctor ``` The agent can serve HTTPS directly for private networks: ```env HTTPS_ENABLED=true TLS_CERT_FILE="/etc/incus-backup-agent/tls.crt" TLS_KEY_FILE="/etc/incus-backup-agent/tls.key" ``` Required commands: - `incus` - `zfs` - `zpool` - `restic` - `udevadm` - `dd` ## Management API ```bash cd management cp .env.example .env npm install npm run dev ``` The management API stores nodes, users, sessions, and central schedules in SQLite. Configure the first admin user through `AUTH_USERNAME` and `AUTH_PASSWORD` before the first start. Startup fails if the initial password is missing. Agent URLs must use `https://` by default. For local development only, set `ALLOW_INSECURE_AGENT_HTTP=true` in `management/.env` to permit `http://` node URLs. For internal/self-signed agent certificates, set `AGENT_CA_FILE` in `management/.env` to the CA certificate that signed the agent certificates. The management API uses Node's built-in SQLite module and requires Node.js 22.5 or newer. Reset an existing admin password without deleting the database: ```bash cd management npm run reset-password -- admin "new-password" ``` ## Frontend ```bash cd frontend npm install npm run dev ``` Set `VITE_API_URL` if the management API is not available at `http://localhost:3100/api`. ## Settings Page The UI includes a Settings page for editing selected node-agent environment values through the management API. The management server forwards those requests to the selected node agent. Changing most node-agent values applies to new API calls and jobs immediately. Changing a node-agent `PORT` requires restarting that agent process. ## Safety Notes Restore is intentionally guarded twice: the agent validates the snapshot against the VM, and the UI requires typing the VM name before sending the restore request. VM restores write the Restic dump to a staged ZFS volume first, then swap it into place with `zfs rename`; the previous volume is kept as a pre-restore rollback copy. Restore jobs are never retried automatically. ## Deployment See `docs/deployment.md` for systemd units, management/agent split, and production setup notes.