Operations
What to back up
The whole of /data, and nothing else.
Three things live in it:
serelane.db | The database: projects, entries, votes, comments, accounts, sessions |
secret.key | The signing key, generated on first boot unless you set SERELANE_SECRET_KEY |
| uploads | Images attached to entries |
A backup that skips secret.key is not a backup.
That key signs sessions, sign-in links and anonymous cookies.
Restoring without it signs every user out, invalidates every pending sign-in link, and detaches every anonymous identity from the votes and comments it made.
If you would rather not depend on a generated file, set SERELANE_SECRET_KEY yourself and keep it wherever you keep secrets.
Taking a consistent copy
SQLite is being written to while you copy it, and a plain cp of a live database can capture a torn file.
Use SQLite’s own backup, which takes a consistent snapshot of a database in use:
If you would rather not install a SQLite client, stop the container first:
The stop is the point. Copying a running database without .backup is the one way to get a backup that restores into a corrupt instance.
Restoring
Serelane migrates the schema forward at boot, so a backup from an older release restores into a newer binary without a separate step.
The reverse is not true. A database written by a newer release refuses to start on an older binary, with database schema is newer than this binary. That is deliberate: running old code against a schema it does not understand corrupts data slowly rather than failing loudly.
Upgrading
Migrations run automatically at boot, in version order, each in its own transaction, so a failure leaves no half-applied schema.
While any are pending, /readyz reports not-ready. A load balancer watching it keeps traffic off an instance that is still migrating.
Running migrations ahead of the deploy
If you would rather not discover a broken migration while already serving:
That applies what is pending and exits.
Migration safety
A migration that has shipped is never edited, only superseded by a new numbered one. This is enforced in the repository by a test and in CI, and it is why repeating an upgrade is safe: the file that ran on your instance is byte-for-byte the file that ran on everyone else’s.
If a release ever needs to change something an earlier migration did, it does so with a new migration.
Health endpoints
There are two, and they answer different questions.
| Checks | Use it for | |
|---|---|---|
/healthz | That the process can serve HTTP | The container HEALTHCHECK, and any liveness probe |
/readyz | Also the database, and that no migration is pending | A load balancer, and any readiness probe |
Do not use /readyz as a liveness check.
It reports not-ready during a migration, and a liveness probe reading that will restart the instance mid-migration, repeatedly.
The shipped container image already uses /healthz, which is why it stays healthy through an upgrade.