Skip to content

Set up Tier 2

Use a release containing the versioned cloud-processing client and a matching cloud service. An older server will reject processing.v1 calls; a successful /health response alone does not prove compatibility.

Set SCANI_DEPLOYMENT_TIER=2, SCANI_PUBLIC_URL=https://your-scani-hostname and SCANI_S3_PUBLIC_URL=https://your-storage-hostname and SCANI_CLOUD_API_KEY in your shell, then run scripts/self-host.sh. Supply the key through your normal secret manager or a hidden shell prompt; do not paste it into a committed file. Configure your HTTPS reverse proxy for the public URL.

The installer generates local infrastructure secrets, keeps SeaweedFS, and writes COMPOSE_FILE=docker-compose.prod.yml:docker-compose.tier2.yml into .env. The overlay excludes the local data-provider and mail catcher. Use Docker Compose 2.20 or later, which supports optional service dependencies.

Set these on both API and worker:

SCANI_DEPLOYMENT_TIER=2
SCANI_CLOUD_URL=https://api.cloud.scani.xyz
SCANI_CLOUD_API_KEY=<your Scani Cloud key>

Keep your DATABASE_URL, REDIS_URL, all S3_* values, ENCRYPTION_KEY, BETTER_AUTH_SECRET, JOBS_HMAC_SECRET and LOG_ID_PEPPER. API and worker must use the same bucket and encryption key. Set FRONTEND_URL and BACKEND_URL to the same HTTPS origin, with no path. The bundled nginx proxies /api to the API service. Tier 2 auth links must stay on that same origin so an email cannot claim one instance while linking to another.

SeaweedFS exposes only its authenticated S3 endpoint on loopback port 9000. Set S3_PUBLIC_ENDPOINT to your browser-reachable HTTPS S3 origin (the installer uses SCANI_S3_PUBLIC_URL). Route that origin to 127.0.0.1:9000, preserving the original Host header and request path for S3 signatures. Do not expose the filer, master or administration ports. The compose default includes your S3 endpoint in CSP_CONNECT_SRC. If you override that variable, include the S3 origin alongside 'self' or the browser will block uploads before they reach S3. This does not make the bucket public.

For example, Caddy on the Docker host:

scani.example.com {
reverse_proxy 127.0.0.1:8080
}
files.example.com {
reverse_proxy 127.0.0.1:9000
}

Set the app and S3 URLs to those two origins. Ensure the browser can send OPTIONS, PUT and GET requests to the S3 origin; SeaweedFS handles S3 CORS. An existing MinIO installation needs the storage migration before switching its bucket endpoint.

Do not supply upstream provider keys or an SMTP/Fastmail account. Tier 2 uses the cloud for these operations. The local DATA_PROVIDER_API_KEY generated by the installer is unused while the local data-provider is disabled.

For explicit compose commands, include both files:

Terminal window
docker compose -f docker-compose.prod.yml -f docker-compose.tier2.yml config --services
docker compose -f docker-compose.prod.yml -f docker-compose.tier2.yml --profile migrate run --rm migrate
docker compose -f docker-compose.prod.yml -f docker-compose.tier2.yml up -d

config --services should include SeaweedFS, Postgres, Redis, API, worker and frontend, and exclude data-provider and mailpit.

Verify sign-in email, upload/import of a small document, a price refresh and a wallet query. Confirm the uploaded object is in your bucket. A health check alone does not exercise these boundaries.