Self-hosting
Upgrading
Two commands, automatic migrations, and the guarantee that upgrades never touch your data.
git pull
docker compose up -d --build
docker image prune -f
docker builder prune -f # or the equivalent podman commands
If you installed with the one-liner, re-running it does the same thing — including the cache cleanup below.
What happens
- Migrations run automatically on backend startup and are idempotent — a no-op when the schema is already current.
- A rebuild recreates the containers but never the volumes, so your data, secrets, and TLS certificates are preserved.
image prune/builder prunedrop the previous build’s now-untagged image layers and build cache, so a--buildupgrade never leaves disk usage creeping up. Both only remove untagged, unused layers — never a named volume — so this is safe to run every time.- The app version is logged on boot and exposed at
GET /version.
Migration policy
Upgrades must never break a running instance, so schema changes are additive only within a version:
- Add new columns and tables (nullable or with defaults) and migrate data.
- Ship code that works with both the old and the new shape.
- Remove old columns only in a later major release.
Migrations are versioned SQL in apps/backend/drizzle/, replayed at runtime by
src/db/migrate.ts. drizzle-kit is not required inside the container.
One-time step: the AI-scraper-shield release
That release changed the bundled Caddyfile to open an internal admin API the
scraper-shield toggle uses. Caddy only reads that file at startup, and a plain
up -d does not recreate an unchanged service — so recreate the containers once:
docker compose up -d --build --force-recreate
This recreates containers, never volumes, so all data and certificates
survive. If you skip it nothing breaks: the instance runs normally and protection
stays off (the default); you simply cannot switch it on in Admin → Security
until Caddy has been recreated. After that release, normal up -d upgrades
resume.
One-time step: the Redis 8 release
That release moved the bundled Redis from 7.4 to 8. Redis 7.4 is offered only under RSALv2 and SSPLv1, neither of which is an open-source licence; Redis 8 restores AGPLv3 as an option, matching Omicron’s own licence.
Nothing is required of you. Redis 8 reads the files 7.4 wrote, so a normal
git pull && docker compose up -d --build upgrades it in place. The backend logs
a few seconds of ENOTFOUND redis while the container is replaced, then
reconnects on its own.
One-time step: the scraper-shield fixes release
That release changed the bundled Caddyfile again, so it needs the same recreate as the original shield release:
git pull && docker compose up -d --build --force-recreate
A plain up -d leaves Caddy on the old file and the fixes silently do not apply.
What you get once it is recreated:
- The challenge page no longer hangs on “Calculating…” until the reader refreshes.
- Page loads no longer fail with a 500 when the reader’s IP arrives from a private network.
- The challenge signing key is generated once into the
secretsvolume, so restarts and upgrades stop re-challenging readers who already solved one.
Containers are recreated, never volumes, so data and certificates survive. If the shield is on, it drops for a few seconds while Caddy restarts and the backend re-applies it — readers see the site unprotected, not broken.
The release also adds ANUBIS_REDIRECT_DOMAINS. Nothing breaks if you leave it
unset, but a public instance should set it — see
Environment variables.
One-time step: the challenge status-code release
The release that made a challenge answer 503 instead of 200 touches two
files the containers only read at startup — botPolicy.yaml and the
Caddyfile — so it needs the same recreate:
git pull && docker compose up -d --build --force-recreate
A plain up -d leaves the challenge answering 200 with no Retry-After.
Nothing breaks either way; the point of the change is that automated clients —
search engines, uptime monitors, link checkers — stop being told a refusal
succeeded. See
what a challenged request gets back.
If you only edited botPolicy.yaml yourself and want it picked up without
recreating anything else, docker compose restart anubis is enough.
Rolling back
Check out the previous tag and rebuild:
git checkout <previous-tag>
docker compose up -d --build
Never run this on a live instance
docker compose down -v # deletes every volume: database, uploads, secrets, certs
down (without -v) is safe — it stops containers and leaves your data alone.
Checking what you are running
curl localhost:8000/version
docker compose ps
docker compose logs --since 5m backendFound a mistake?Edit this page on GitHub.