Adopt sneak.berlin/go/vaultik vanity import path, README overhaul

Module path changed from git.eeqj.de/sneak/vaultik to
sneak.berlin/go/vaultik (vanity redirect). All imports, ldflags,
Dockerfile, goreleaser config, and docs updated. App data/config
directories now use plain "vaultik" instead of the reverse-DNS name.

README:
- New copy-pasteable quickstart at top: go install, config init,
  age keypair, config set for key + file:// destination, home backup
- All command names in command details are code-quoted
- config set/get gained sequence index support (age_recipients.0)
  so lists are settable from the CLI
- Dockerfile build is CGO_ENABLED=0 to match the pure-Go build
This commit is contained in:
2026-06-10 11:37:23 -07:00
parent cb16d6869f
commit d479bfcd52
66 changed files with 299 additions and 237 deletions

107
README.md
View File

@@ -6,6 +6,32 @@ remote S3-compatible object store. It requires no private keys, secrets, or
credentials (other than those required to PUT to encrypted object storage,
such as S3 API keys) stored on the backed-up system.
## quickstart
```sh
# install
go install sneak.berlin/go/vaultik/cmd/vaultik@latest
# create a default config file (prints the path it wrote to)
vaultik config init
# generate an age keypair; keep key.txt somewhere safe and offline —
# you need it to restore, and the backed-up machine does not need it
age-keygen -o key.txt
grep 'public key' key.txt
# configure the encryption key and backup destination
vaultik config set age_recipients.0 age1YOUR_PUBLIC_KEY_HERE
vaultik config set storage_url "file:///Volumes/usbstick/mybackup"
# back up your home directory (the default config includes a "home"
# snapshot of ~ with sensible excludes)
vaultik snapshot create
# see what you have
vaultik snapshot list
```
Features:
* modern encryption ([age](https://age-encryption.org/), X25519 + XChaCha20-Poly1305)
@@ -38,43 +64,19 @@ Requirements that no existing tool meets:
* encrypted
* s3 compatible without an intermediate step or tool
## install
## daily use
```sh
go install git.eeqj.de/sneak/vaultik@latest
```
## quick start
```sh
# 1. Install
go install git.eeqj.de/sneak/vaultik@latest
# 2. Generate an age keypair (store the private key somewhere safe, offline)
age-keygen -o key.txt
# the public key is printed to stdout and also in key.txt
# 3. Create a default config file
vaultik config init
# Writes to the platform config directory with commented defaults:
# macOS: ~/Library/Application Support/vaultik/config.yml
# Linux: ~/.config/vaultik/config.yml
# root: /etc/vaultik/config.yml
# 4. Edit the config: set age_recipients, snapshots, and storage_url
vaultik config edit # opens $EDITOR
# or set individual values:
vaultik config set storage_url "file:///mnt/backups"
vaultik config get storage_url
# 5. Run your first backup
vaultik snapshot create
# 6. Verify it worked
vaultik snapshot list
# verify a snapshot (shallow: checks all blobs exist)
vaultik snapshot verify <snapshot-id>
# 7. Set up a daily cron job (keeps last 4 weeks of snapshots)
# deep verify (downloads and cryptographically verifies every blob)
VAULTIK_AGE_SECRET_KEY='AGE-SECRET-KEY-...' vaultik snapshot verify --deep <snapshot-id>
# restore (requires the private key)
VAULTIK_AGE_SECRET_KEY='AGE-SECRET-KEY-...' vaultik restore <snapshot-id> /tmp/restored
# daily cron job: back up, keep a 4-week rolling window of snapshots
# 0 3 * * * vaultik snapshot create --cron --prune --keep-newer-than 4w
```
@@ -120,22 +122,22 @@ vaultik version
### command details
**config init**: Write a default config file with commented explanations for
**`config init`**: Write a default config file with commented explanations for
every setting. Writes to the path from `--config`, `$VAULTIK_CONFIG`, or the
platform config directory (`~/Library/Application Support/vaultik/` on macOS,
`~/.config/vaultik/` on Linux, `/etc/vaultik/` as root). Refuses to overwrite an
existing file. Created with mode `0600` since it will contain credentials.
**config edit**: Open the config file in `$EDITOR` (falls back to `vi`).
**`config edit`**: Open the config file in `$EDITOR` (falls back to `vi`).
**config get**: Print a config value addressed by dotted YAML path
**`config get`**: Print a config value addressed by dotted YAML path
(e.g. `vaultik config get s3.bucket`). Non-scalar values print as YAML.
**config set**: Set a scalar config value by dotted YAML path
**`config set`**: Set a scalar config value by dotted YAML path
(e.g. `vaultik config set compression_level 9`). Comments and formatting
in the file are preserved; intermediate maps are created as needed.
**snapshot create**: Perform incremental backup of configured snapshots.
**`snapshot create`**: Perform incremental backup of configured snapshots.
* Optional snapshot names argument to create specific snapshots (default: all)
* `--cron`: Silent unless error (for crontab)
* `--prune`: After backup, drop older snapshots of each backed-up name and
@@ -145,16 +147,16 @@ in the file are preserved; intermediate maps are created as needed.
this duration instead of only the latest (e.g. `4w`, `30d`, `6mo`, `1y`)
* `--skip-errors`: Skip file read errors (log them loudly but continue)
**snapshot list**: List all snapshots with their timestamps and sizes.
**`snapshot list`**: List all snapshots with their timestamps and sizes.
* `--json`: Output in JSON format
**snapshot verify**: Verify snapshot integrity.
**`snapshot verify`**: Verify snapshot integrity.
* Default (shallow): checks that all blobs referenced in the manifest exist in storage
* `--deep`: Downloads and decrypts each blob, verifies chunk hashes against the
encrypted metadata database
* `--json`: Output results as JSON
**snapshot purge**: Remove old snapshots based on criteria. Retention is
**`snapshot purge`**: Remove old snapshots based on criteria. Retention is
per-snapshot-name (`--keep-latest` keeps the latest of each name, not the
latest globally).
* `--keep-latest`: Keep only the most recent snapshot of each name
@@ -162,42 +164,42 @@ latest globally).
* `--snapshot <name>`: Restrict to specific snapshot names (repeat for multiple)
* `--force`: Skip confirmation prompt
**snapshot remove**: Remove a specific snapshot from the local database.
**`snapshot remove`**: Remove a specific snapshot from the local database.
* `--remote`: Also remove snapshot metadata from remote storage
* `--all`: Remove all snapshots (requires `--force`)
* `--dry-run`: Show what would be deleted without deleting
* `--force`: Skip confirmation prompt
* `--json`: Output result as JSON
**snapshot prune**: Clean orphaned data from the local database (files,
**`snapshot prune`**: Clean orphaned data from the local database (files,
chunks, blobs not referenced by any snapshot).
**snapshot cleanup**: Remove stale local snapshot records that have no
**`snapshot cleanup`**: Remove stale local snapshot records that have no
corresponding metadata in remote storage. These are typically left behind
by incomplete or interrupted backups. Does not touch remote storage.
**restore**: Restore files from a backup snapshot.
**`restore`**: Restore files from a backup snapshot.
* Requires `VAULTIK_AGE_SECRET_KEY` environment variable
* Optional path arguments to restore specific files/directories (default: all)
* Preserves file permissions, timestamps, ownership (ownership requires root),
symlinks, and empty directories
* `--verify`: After restoring, verify every file's chunk hashes match
**prune**: Remove unreferenced blobs from remote storage.
**`prune`**: Remove unreferenced blobs from remote storage.
* Scans all snapshot manifests for referenced blobs, deletes any blob not referenced
* `--force`: Skip confirmation prompt
* `--json`: Output stats as JSON
**info**: Display system configuration, storage settings, encryption
**`info`**: Display system configuration, storage settings, encryption
recipients, and local database statistics.
**remote info**: Show detailed remote storage information including per-snapshot
**`remote info`**: Show detailed remote storage information including per-snapshot
metadata sizes, blob counts, and orphaned blob detection.
* `--json`: Output as JSON
**store info**: Display storage backend type and statistics.
**`store info`**: Display storage backend type and statistics.
**database purge**: Delete the local SQLite state database entirely. Remote
**`database purge`**: Delete the local SQLite state database entirely. Remote
storage is unaffected; the next backup will do a full scan and re-deduplicate
against existing remote blobs.
* `--force`: Skip confirmation prompt
@@ -300,7 +302,8 @@ Snapshot IDs follow the format `<hostname>_<snapshot-name>_<RFC3339-timestamp>`
## configuration reference
See `config.example.yml` for a complete annotated example. Key fields:
Run `vaultik config init` to generate a fully commented config file.
Key fields:
| Field | Default | Description |
|-------|---------|-------------|
@@ -313,7 +316,7 @@ See `config.example.yml` for a complete annotated example. Key fields:
| `blob_size_limit` | `10GB` | Maximum blob size before splitting |
| `compression_level` | `3` | zstd compression level (1-19) |
| `hostname` | system hostname | Hostname used in snapshot IDs |
| `index_path` | `~/.local/share/.../index.sqlite` | Local SQLite index path |
| `index_path` | platform data dir | Local SQLite index path |
---