# Production deployment and rollback The production host needs only a Compose file, `config.toml`, and persistent data. It does not need a source checkout. ## Files Create an application directory like this: ```text /opt/ushort/ ├── docker-compose.yml ├── config.toml └── data/ ``` Copy [`deploy/docker-compose.prod.yml`](../deploy/docker-compose.prod.yml) to the server as `docker-compose.yml`. For repeatable releases, replace its image tag with the verified multi-architecture digest: ```yaml image: docker.io/sodium/ushort:0.1.1@sha256: ``` Set `db_path = "data/urlshort.db"` and normally keep `production = false` so the executable serves its embedded frontend. Keep `config.toml` owned by the container identity (`1001:1001`) with mode `0400`; the `data` directory must be writable by the same identity. ## Start and validate ```bash cd /opt/ushort docker compose config docker compose pull docker compose up -d docker compose ps docker compose logs --tail=100 ushort curl -i http://127.0.0.1:18082/s/api/health ``` Adjust the health path to match `base_url`. ## Reverse proxy Choose one nginx snippet and include it inside the public `server {}` block: - [`deploy/nginx.path.conf`](../deploy/nginx.path.conf) for a path such as `https://example.com/s`; - [`deploy/nginx.subdomain.conf`](../deploy/nginx.subdomain.conf) for a host such as `https://s.example.com`. Both snippets proxy the frontend, API, and redirects to `127.0.0.1:18082`. They apply `no-store` to the HTML entry point and `no-cache` to static assets. The path snippet is written for `/s`; replace each `/s` location when using a different configured prefix. Test nginx before reloading it: ```bash nginx -t nginx -s reload ``` Then verify the public health endpoint, frontend, static assets, and an existing short-code redirect. [`tests/smoke.sh`](../tests/smoke.sh) exercises the complete trailing-slash route set against a disposable record. ## Update 1. Verify the published image contains both AMD64 and ARM64 manifests. 2. Pull the exact version and digest before changing the running service. 3. Create and integrity-check an online SQLite backup as described in [Data and database compatibility](data.md). 4. Update the image reference and run `docker compose up -d`. 5. Check health, logs, restart count, database integrity, and public routes. ## Rollback Restore the previous image reference and run: ```bash docker compose up -d ``` The schema is release-compatible. If the failed release changed or damaged data, stop the service and restore the pre-update SQLite backup before bringing the previous image back up. Preserve any legitimate writes made after the backup before replacing the database.