4.0 KiB
vaultik
vaultik
is a incremental backup daemon written in Go. It
encrypts data using an age
public key and uploads each encrypted blob
directly to a remote S3-compatible object store. It requires no private
keys, secrets, or credentials stored on the backed-up system.
what
vaultik
walks a set of configured directories and builds a
content-addressable chunk map of changed files using deterministic chunking.
Each chunk is streamed into a blob packer. Blobs are compressed with zstd
,
encrypted with age
, and uploaded directly to remote storage under a
content-addressed S3 path.
No plaintext file contents ever hit disk. No private key is needed or stored locally. All encrypted data is streaming-processed and immediately discarded once uploaded. Metadata is encrypted and pushed with the same mechanism.
why
Existing backup software fails under one or more of these conditions:
- Requires secrets (passwords, private keys) on the source system
- Depends on symmetric encryption unsuitable for zero-trust environments
- Stages temporary archives or repositories
- Writes plaintext metadata or plaintext file paths
vaultik
addresses all of these by using:
- Public-key-only encryption (via
age
) requires no secrets (other than bucket access key) on the source system - Blob-level deduplication and batching
- Local state cache for incremental detection
- S3-native chunked upload interface
- Self-contained encrypted snapshot metadata
how
-
install
go install git.eeqj.de/sneak/vaultik@latest
-
generate keypair
age-keygen -o agekey.txt grep 'public key:' agekey.txt
-
write config
source_dirs: - /etc - /home/user/data exclude: - '*.log' - '*.tmp' age_recipient: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx s3: endpoint: https://s3.example.com bucket: vaultik-data prefix: host1/ access_key_id: ... secret_access_key: ... region: us-east-1 backup_interval: 1h # only used in daemon mode, not for --cron mode full_scan_interval: 24h # normally we use inotify to mark dirty, but # every 24h we do a full stat() scan min_time_between_run: 15m # again, only for daemon mode index_path: /var/lib/vaultik/index.sqlite chunk_size: 10MB blob_size_limit: 10GB index_prefix: index/
-
run
vaultik backup /etc/vaultik.yaml
vaultik backup /etc/vaultik.yaml --cron # silent unless error
vaultik backup /etc/vaultik.yaml --daemon # runs in background, uses inotify
cli
vaultik backup /etc/vaultik.yaml
vaultik restore <bucket> <prefix> <snapshot_id> <target_dir>
vaultik prune <bucket> <prefix>
vaultik fetch <bucket> <prefix> <snapshot_id> <filepath> <target_fileordir>
VAULTIK_PRIVATE_KEY
must be available in environment forrestore
andprune
does not
- Store any secrets on the backed-up machine
- Require mutable remote metadata
- Use tarballs, restic, rsync, or ssh
- Require a symmetric passphrase or password
- Trust the source system with anything
does
- Incremental deduplicated backup
- Blob-packed chunk encryption
- Content-addressed immutable blobs
- Public-key encryption only
- SQLite-based local and snapshot metadata
- Fully stream-processed storage
restore
vaultik restore
downloads only the snapshot metadata and required blobs. It
never contacts the source system. All restore operations depend only on:
VAULTIK_PRIVATE_KEY
- The bucket
The entire system is restore-only from object storage.
prune
Run vaultik prune
on a machine with the private key. It:
- Downloads the most recent snapshot
- Decrypts metadata
- Lists referenced blobs
- Deletes any blob in the bucket not referenced
This enables garbage collection from immutable storage.
license
WTFPL — see LICENSE.