Go-live: off-box backup for the license store (Infomaniak, then Litestream) #29

Open
opened 2026-08-25 01:26:59 +00:00 by Cordy · 0 comments
Owner

Split out of #28 so it survives that issue closing. This is the backup layer, deliberately deferred until go-live — no object-storage spend while the store is sandbox-only.

Prerequisite: #28 (SQLite migration) landed, so there is a .db file to back up.

Hard constraint: the license server is a public Infomaniak VPS and stays off the homelab WireGuard mesh. Not Garage. Target is Infomaniak's own object storage over public TLS.

Step 1 — interim, at launch

  • Provision an Infomaniak bucket + keys — Public Cloud Object Storage (S3, s3.pub1.infomaniak.cloud, EC2-style creds) or Swiss Backup (S3/SFTP).
  • Nightly cron on the VPS: sqlite3 licenses.db "VACUUM INTO '/tmp/lic-$(date +%F).db'"aws s3 cp to the bucket, with a retention/rotation lifecycle rule on the bucket.
  • Credentials in /etc/cairn-license/env (0600), never in git. Document the restore runbook.
  • This closes the long-standing "off-box shipping still open" item.

Step 2 — Litestream

  • Replace the nightly snapshot with Litestream (litestream replicate) → the same bucket, as a second systemd unit. Gives ~1 s granularity + point-in-time restore.
  • Note: use the standalone binary / plain replication — the writable VFS needs cgo, which we don't want and don't need here.
  • Zero application code change; it's an ops addition.
  • Document restore (litestream restore) in DEPLOY.md and the wiki.

Acceptance

  • A simulated VPS loss restores the store from the bucket with no more than the agreed data-loss window (a day for Step 1, seconds for Step 2).
  • Restore runbook verified, not just assumed.

Ref: ADR-0001 (cairn/adr/0001-license-server-store-sqlite), gated to #26-launch.

Split out of #28 so it survives that issue closing. This is the **backup layer**, deliberately deferred until go-live — no object-storage spend while the store is sandbox-only. Prerequisite: #28 (SQLite migration) landed, so there is a `.db` file to back up. Hard constraint: the license server is a public Infomaniak VPS and stays **off the homelab WireGuard mesh**. **Not Garage.** Target is Infomaniak's own object storage over public TLS. ## Step 1 — interim, at launch - Provision an **Infomaniak bucket + keys** — Public Cloud Object Storage (S3, `s3.pub1.infomaniak.cloud`, EC2-style creds) or Swiss Backup (S3/SFTP). - Nightly cron on the VPS: `sqlite3 licenses.db "VACUUM INTO '/tmp/lic-$(date +%F).db'"` → `aws s3 cp` to the bucket, with a retention/rotation lifecycle rule on the bucket. - Credentials in `/etc/cairn-license/env` (0600), never in git. Document the restore runbook. - This closes the long-standing "off-box shipping still open" item. ## Step 2 — Litestream - Replace the nightly snapshot with **Litestream** (`litestream replicate`) → the same bucket, as a second systemd unit. Gives ~1 s granularity + point-in-time restore. - Note: use the standalone binary / plain replication — the writable VFS needs cgo, which we don't want and don't need here. - Zero application code change; it's an ops addition. - Document restore (`litestream restore`) in DEPLOY.md and the wiki. ## Acceptance - A simulated VPS loss restores the store from the bucket with no more than the agreed data-loss window (a day for Step 1, seconds for Step 2). - Restore runbook verified, not just assumed. Ref: ADR-0001 (`cairn/adr/0001-license-server-store-sqlite`), gated to #26-launch.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/cairn-license-server#29
No description provided.