Backups, upgrades and recovery¶
Who this is for: hosters (sysadmins).
This page covers two admin jobs: keeping the pieces you cannot easily recreate, and moving to a new version without losing them. It covers both supported ways to run the stack — Docker Compose and Co-op Cloud. New to a term such as volume or service access token? See the Glossary.
What to back up¶
Most of the stack is reproducible from Git, but a few files are secrets or generated state that exist only on the host. Back those up first.
| Item | Where it lives | Why it matters |
|---|---|---|
| Relay private config | secrets/relay.private.json |
Holds room tokens and allowed origins. Losing it means every link you handed out stops working. |
| Speech-service access file | secrets/caption-local.env |
Holds the service access token (CAPTION_API_KEY) and allowed origins. |
| Capture auto-fill file | secrets/relay-tokens.env |
Holds the relay address, room names and room tokens the capture page uses to build editor/audience links. |
| Basic Auth file | secrets/traefik.htpasswd |
Passwords for the optional HTTP Basic Auth overlay. |
| Environment file | .env.production |
Hostnames and the Let's Encrypt email. Tracked by Git, so treat it as non-secret. |
| Orchestration config | traefik.yml, docker-compose*.yml, web/ |
Also tracked by Git; back up with the repository. |
| Downloaded models | Docker volumes caption-local-cache and translation-models |
Large and re-downloadable, so optional to back up. See below. |
| Transcripts | Wherever operators downloaded them | The stack persists nothing automatically; a transcript exists only as a file someone saved. |
The secrets/ directory is git-ignored
Nothing in secrets/ is committed. If you lose the host without a copy,
the relay config and tokens are gone. Store a copy somewhere safe and
private — never in the repository.
The TLS certificates in the letsencrypt volume are not essential to back up:
Let's Encrypt can reissue them, as long as DNS points at the host.
On Co-op Cloud the same secrets and state live inside the app's managed storage
rather than a local secrets/ directory, so back them up through the recipe
instead of copying files by hand.
How models are cached (and how to avoid re-downloading)¶
The speech service downloads its Whisper model on first use. Under Docker the
model lives in the named volume caption-local-cache, mounted at /models; the
UI's translation models live in the translation-models volume. Keeping these
volumes means you never pay the download again.
Models are pinned so a rebuild does not silently change what you run:
- The default
smallmodel is pinned to a fixed Hugging Face revision. - The throughput
basemodel is pinned to its own revision;mediumandlarge-v3are pinned inserver.pytoo. - Other model names fall back to upstream resolution unless you supply a local directory.
To prepare for an offline event, run the stack once while still online so the
volume is populated, then turn on offline mode and recreate the service. To save
disk or bandwidth you can set TRANSLATION_MODELS=none to skip the translation
model download.
Do not delete the volumes by accident
docker compose down -v also removes named volumes, including the cached
models. Only use it when you actually intend to delete the model cache.
A plain docker compose down keeps them.
Backups with Co-op Cloud¶
Co-op Cloud stores the app's state through its own backup mechanism. The generic
command is abra app <domain> backup; consult the caption-ninja recipe for the
exact backup and restore commands and what each one includes. Restoring is a
recipe-specific operation, so follow the recipe rather than copying files.
Upgrading with Docker Compose¶
An upgrade has four steps: save your work, stop the service, bring in the new code or images, and rebuild/recreate. The cached model volumes are kept throughout.
- Save anything in progress. Download pending transcripts; capture pages hold retry caches in memory only.
docker compose --env-file .env.production \
-f docker-compose.yml -f docker-compose.prod.yml down
- Fetch the new orchestration and submodule code. The application code lives
in the
caption-localandcaptionninjasubmodules.
git pull
git submodule update --init --recursive
- Rebuild and start. This pulls or builds images and recreates containers.
docker compose --env-file .env.production \
-f docker-compose.yml -f docker-compose.prod.yml up -d --build
- Smoke-test. Every service should report
healthy.
docker compose --env-file .env.production \
-f docker-compose.yml -f docker-compose.prod.yml ps
After a config-only change, such as editing a label or an env file, recreate just the affected service instead of the whole stack:
docker compose --env-file .env.production \
-f docker-compose.yml -f docker-compose.prod.yml up -d --force-recreate caption-local
Upgrading with Co-op Cloud¶
The generic command is abra app <domain> upgrade. Consult the caption-ninja
recipe for the exact upgrade steps, which version or tag to choose, and whether a
data migration runs first. Take a backup before upgrading, as above.
Recovery and rollback¶
Rollback follows the same shape in reverse. Keep the previous release archive or image before you upgrade, and restore it if the new version misbehaves.
- Docker Compose: restore the previous application files (or the old image
tag) and rebuild with
up -d --build. - Co-op Cloud: restore a recent recipe backup, or deploy the previous version again; the recipe explains how.
- Keep the model volumes and caches in place unless you deliberately want a clean download.
- Verify with
docker compose ps(or the recipe's status command) and one real caption before an event. - Never run
docker compose down -vas part of a rollback: it deletes the model cache.
For a broken relay config under Docker, regenerating secrets/relay.private.json
with init-config.cjs creates fresh room tokens, which invalidates old links — so
a known-good backup is faster. See Troubleshooting for the
permission fix if the relay will not start.