- Go 84.2%
- TypeScript 12.2%
- PowerShell 1.7%
- Shell 1.5%
- CSS 0.2%
- Other 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| api | ||
| build | ||
| cmd | ||
| configs | ||
| docs | ||
| internal | ||
| trust | ||
| web | ||
| .gitattributes | ||
| .gitignore | ||
| buf.gen.yaml | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
kBackup
kBackup is a self-contained, cross-platform (Windows + Linux) deduplicating, content-addressed, encrypted, block-level backup suite: a background service owns all scheduling and job execution, and a terminal UI is a thin client to it. It targets file-tree and raw volume/disk image sources, local/S3/SFTP repositories, and uses only embedded local storage (no external/server databases).
The implemented and tested surface includes repository CRUD and durable
configuration overlays, scheduling and progress, notifications, maintenance
operations, service settings, file and image backup/restore, file extraction,
and snapshot mounts, exposed through kbackupd over named-pipe/unix-socket
gRPC, the terminal UI, and an optional embedded web UI.
On Windows, an exclusion-aware system source captures the OS volume through
required VSS consistency and records recovery metadata for a fresh-disk WinPE
restore. It remains preview pending the qualification described in
docs/system-backup-windows.md.
Operational and qualification status
kBackup currently supports one active host/process per repository. Repository lock objects are advisory conflict detection, not backend-enforced fenced leases; concurrent writers on independent hosts are unsupported.
Safe-host tests, deterministic Linux/Windows release preflights, and scoped
disposable Linux and Windows development-artifact qualification have passed for
the recorded cells. This includes Debian/Fedora package and device exercises,
Windows Go/installer exercises, and an exact q37.3 WinPE build, Secure Boot,
negative-target, dry-run, whole-disk restore, and complete logical-byte
comparison. See docs/qualification.md for the exact
scope and evidence identities.
The project is still not production-ready. The initial v1.0.0 target is a
controlled-distribution, amd64, local-backend, file-tree profile on the exact
Windows 11 Enterprise 25H2/NTFS and Debian 13/ext4 cells that pass final
acceptance. Its remaining blockers are the offline public trust ceremony, exact
self-managed-signed artifacts, destructive local-repository fault tests,
measured scale limits, independent release-worker reproducibility, and final
Windows/Debian acceptance. S3/SFTP, RPM/Fedora, raw image/CBT, mounts, rescue,
physical hardware, pre-release repository migration, and other unqualified
cells are preview/unsupported rather than v1.0.0 blockers. See the
initial support profile.
Operator documentation:
- normal operations and maintenance
- recovery and incident handling
- repository format-v3 migration status
- reverse-proxy deployment
- initial production support profile
- release procedure and evidence
- self-managed release trust
- production qualification matrix
- raw whole-disk rescue behavior
- Windows CBT limitations and Linux dm-era setup
Architecture summary
kbackupd (the service) owns a chunk/pack/index repository engine (keyed
BLAKE3 content addressing, zstd+AEAD packs, binary sorted index segments,
with a rebuildable Pebble local cache), a scheduler and job queue, and a
gRPC IPC surface (named pipe on Windows, unix socket on Linux). kbackup
(the TUI, Bubble Tea-based) is a thin client over that IPC surface. Backup
sources are either file trees (FastCDC chunking) or raw volume/disk images
(fixed-size cluster-aligned blocks, changed-block tracking); all
full/differential/incremental runs produce independently restorable,
deduplicated snapshots under one repository format. Full design, the
milestone build order (M0-M14), and rationale live in the project's
approved architecture plan (kept outside this repo, in the maintainer's
local plan store).
Repository layout
cmd/contains the service, terminal client, and support command entrypoints.internal/contains private Go packages grouped by subsystem.api/proto/defines the RPC contract;api/gen/contains generated Go code.web/contains the web client source, tests, and generated API bindings.configs/contains example runtime configuration.build/contains release, packaging, signing, CI, and qualification tooling.trust/contains public release trust material and its authenticated manifest.docs/contains operator, release, recovery, support, and qualification guides.
Build & test
go build ./...
go vet ./...
go test ./...
The web UI's compiled assets (web/dist) are generated and ignored. Release
builds recreate them and embed them into kbackupd. For a local release-style
daemon build:
cd web
npm ci
npm run typecheck && npm run lint && npm run test && npm run build
cd ..
go build -tags webdist ./cmd/kbackupd
Ordinary Go builds use a small fallback page so the Go toolchain does not depend on Node. The platform release drivers perform the production web build automatically.
During development, run the Vite dev server (it proxies /api to a locally
running kbackupd with the web UI enabled on 127.0.0.1:9898):
cd web && npm run dev
Web UI
kbackupd can serve an embedded React web UI (management parity with the
terminal client) over its own HTTP(S) listener. It is disabled by default.
On the TUI's first connection, choose Enable for the local-only default
(127.0.0.1:9898). The TUI then shows a one-time owner setup link. Open it
to choose the administrator password; the token is carried in the URL
fragment, removed from the address bar immediately, and never sent in an
HTTP request. The TUI Settings tab can enable or disable the listener and
edit its advanced TLS/proxy settings while it is disabled.
The owner-only <state_dir>/web-setup-token file remains a manual fallback.
The daemon logs only that file's path, never the token. A web: block in the
base config can also provide the initial settings (see
configs/kbackup.example.yaml); later TUI edits are stored in the service
overlay without rewriting the base file.
Loopback listeners serve plain HTTP; any other bind address requires TLS
(web.tls) or an explicit web.insecure_http: true acknowledgment.
Sessions are in-memory, so restarting the service signs everyone out. To
reset a lost admin password, stop the service, delete
<state_dir>/web-auth.json, and start it again to get a fresh setup token
(this resets only the web login, never repository encryption keys).
Notifications
Notification channels are deliberately limited to transports whose complete
send path can be bounded: smtp, webhook, and eventlog. Generic provider
router URLs are rejected because their cancellation behavior cannot be proven.
SMTP destinations use this form:
smtp://[user:password@]host[:port]/?from=sender@example.com&to=recipient@example.com
smtps://[user:password@]host[:port]/?from=sender@example.com&to=recipient@example.com
smtp:// requires STARTTLS (default port 587); smtps:// starts TLS
immediately (default port 465). Repeat to for additional recipients.
Webhooks accept absolute HTTP(S) URLs, never follow redirects, optionally sign
the JSON body with the configured HMAC secret, and reject response bodies over
64 KiB.
Delivery is best effort and does not change a completed job result. The daemon uses four workers and a queue of 64 deliveries, makes one bounded attempt and at most one retry, and logs a drop if the queue is full or shutdown has stopped admission. A shutdown deadline that expires while a delivery is still active is reported as a service failure; it is not treated as successful cancellation. Returned errors expose no provider details. Internal logs retain provider detail only after removing URLs, credentials, and signatures and bounding it to 8 KiB. The configuration file still contains channel credentials and must retain owner-only permissions.
Check a config file
go run ./cmd/kbackupd --check-config --config configs/kbackup.example.yaml
Repair scheduler catch-up state
A missing scheduler-state.json is valid on a fresh installation, but an
existing zero-byte, truncated, malformed, unsupported, unreadable, or invalid file
fails daemon startup rather than silently discarding catch-up history. Preserve
the reported file for incident analysis. If the history cannot be recovered,
stop the daemon and explicitly reset it:
kbackupd repair-scheduler-state --config /path/to/kbackup.yaml --confirm-loss-of-catch-up-history
The command atomically archives the original beside it as
scheduler-state.json.pre-repair, refuses to overwrite an earlier archive, and
writes a valid empty versioned state. The reset cannot reconstruct missed runs;
review affected schedules and run required jobs manually before restarting the
daemon.
Regenerating the gRPC/protobuf code
api/gen/*.go and web/src/gen/*.ts are generated from
api/proto/*.proto and checked in. Generator versions are pinned in
build/ci/tool-versions.env and the web lockfile. Install the locked Buf
package and exact Go plugins, then regenerate after editing a .proto file:
npm ci --prefix web
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.2
$env:PATH = "$PWD\web\node_modules\.bin;$env:USERPROFILE\go\bin;$env:PATH"
pwsh api/gen.ps1
npm --prefix web run generate:proto
api/gen.ps1 verifies the pinned tool versions and atomically replaces the Go
output so deleted schemas cannot leave stale bindings. CI regenerates both
output trees in a temporary directory and rejects any difference.
Running kbackupd
kbackupd is the background service; install/uninstall/start/stop
register/control it as an OS service (Windows Service Control Manager /
systemd), and run executes it directly in the foreground:
go run ./cmd/kbackupd run --config configs/kbackup.example.yaml
License
Copyright (c) Leon Stöwer. kBackup is licensed under the WTFPL, version 2.