Deployment
Docker + Traefik. Assumes Traefik already runs in Docker with a working HTTPS
entrypoint/cert resolver, and you control a domain. Full detail:
DEPLOY.md in the main repo — this page is the condensed path.
0. Prerequisites
- Docker + Docker Compose on the server.
- Traefik watching a Docker network (default assumed name:
proxy). - DNS
A/AAAArecords formanga-api.<domain>(API) and, if using the web UI,manga.<domain>— both pointing at the server. - Repo copied to the server (needs
backend/,docker-compose.yml,docker-compose.prod.yml,.env.example).
docker network ls | grep proxy || docker network create proxy
1. Configure .env
cp .env.example .env
sed -i "s|^API_TOKEN=.*|API_TOKEN=$(openssl rand -hex 32)|" .env
Required vars: API_TOKEN, ALLOWED_ORIGINS, MANGA_API_HOST,
MANGA_WEB_HOST (needed even if the web UI stays off — its Traefik label has
no fallback). Full var table: Backend-API.
1b. Web UI (optional)
MANGA_WEB_HOST=manga.<domain>
WEB_PASSWORD=<openssl rand -base64 18>
Leaving WEB_PASSWORD unset is safe — web routes never register, / 404s,
the userscript API is unaffected. See Web-UI for what the password gates.
Rotating API_TOKEN or WEB_PASSWORD logs every browser session out
(sessions are stateless, keyed off both).
2. Build + start
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
Always pass both -f flags — the prod override alone is not standalone (it
drops the published port and adds Traefik labels).
docker compose -f docker-compose.yml -f docker-compose.prod.yml ps
docker logs manga-api --tail 20 # expect: "listening on :8080 ..."
3. Verify over HTTPS
curl -s https://manga-api.<domain>/healthz # -> ok
curl -s -o /dev/null -w '%{http_code}\n' https://manga-api.<domain>/bookmarks # -> 401
TOKEN=$(grep -E '^API_TOKEN=' .env | cut -d= -f2)
curl -s -H "Authorization: Bearer $TOKEN" https://manga-api.<domain>/bookmarks # -> []
curl -s -i -X OPTIONS -H 'Origin: https://asurascans.com' \
-H 'Access-Control-Request-Method: PUT' \
https://manga-api.<domain>/bookmarks/x | grep -i access-control
All must pass — valid TLS is non-negotiable (mixed content blocks the
userscript's fetch() otherwise).
4–5. Configure and install the userscript
See Userscript — set API_BASE/API_TOKEN in the file, install on
Bromite.
6. Smoke-test the full loop
Bookmark on Asura → confirm via curl /bookmarks on the server → open a
chapter, confirm progress updates → open Demonic, confirm the same bookmark
shows there.
Updating
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
SQLite data persists in the named volume bookmarks-data across rebuilds.
Troubleshooting
See Troubleshooting.