The channel form has three inputs all named 'name' (one per kind
section: webhook / ntfy / smtp), but only the visible kind's input
is filled in. PostForm.Get returns the first regardless of
emptiness, so editing an ntfy or smtp channel always read '' from
the (hidden, unfilled) webhook section's name input and rejected
with 'name required'.
Add firstNonEmpty helper that scans the slice for the first
non-blank value. Same flavour of bug as the enabled checkbox fix
in 6466f8c — both fall out of having multiple inputs share a name
across the per-kind sub-forms.
restic-manager
Self-hosted, browser-based, single-pane-of-glass for managing restic backups across a fleet of Linux and Windows endpoints.
Status: pre-alpha. Phase 0 (project bootstrap) complete; Phase 1 (MVP) in progress. See
spec.mdfor the design andtasks.mdfor the roadmap.
What it does (target)
- Central visibility into backup state for every endpoint
- Trigger any restic operation remotely (
backup,forget,prune,check,unlock,snapshots,stats,diff,restore) - Manage per-host backup schedules from the UI
- Live job progress streamed back to the UI
- Restore wizard (browse snapshots, pick paths, restore to original or alternate host)
- Repo health surfacing (size, dedup ratio, last check, lock state)
- Alerting on failure or staleness
- Cross-platform agent (Linux + Windows)
- Ransomware-resistant repo access via append-only credentials
Architecture (one-line summary)
A small Go control-plane on the Proxmox host, lightweight Go agents on each
endpoint that hold an outbound WebSocket to the control-plane, and a
restic/rest-server on Unraid that holds the actual backup data. The
control-plane never touches backup bytes.
Full architecture diagram and component breakdown:
spec.md §3.
Repository layout
cmd/server/ control-plane binary
cmd/agent/ endpoint agent binary
internal/api shared API types (REST + WS envelopes)
internal/server/ HTTP, WS, UI handlers
internal/agent/ service integration, restic runner, local scheduler
internal/restic restic CLI wrapper
internal/store SQLite persistence
internal/crypto secret encryption
internal/auth passwords, sessions, agent tokens
web/ server-rendered templates + static assets
deploy/ Dockerfile, docker-compose.yml, install scripts
design/ UI wireframes (Phase 0 design pass)
Local development
Requires Go 1.25+ (built and tested on 1.26). The floor is set by
modernc.org/sqlite v1.50.
make build # builds cmd/server and cmd/agent into ./bin
make test # runs go test ./...
make lint # runs golangci-lint
make run-server # runs the server (dev defaults)
License
PolyForm Noncommercial 1.0.0 — see LICENSE. Free for personal,
hobby, research, educational, governmental, and other noncommercial use.
Commercial use requires a separate license.