Deploying on Coolify¶
This deployment runs the kernel, PostGIS, migrations and private S3-compatible object storage. The Android field client is built separately; Coolify hosts the API it synchronizes with.
Security boundary¶
Do not assign a public Coolify domain directly to the kernel service. The
kernel trusts x-clycites-subject, x-clycites-client-id and x-acting-for
because an authentication gateway is required to remove caller-supplied values
and replace them from a validated Authentik token. Publishing the service
directly makes those identities forgeable.
The repository does not yet contain that gateway. The Compose deployment is therefore private by default. A production launch needs a gateway which:
- Terminates TLS and validates the Authentik access token.
- Removes all three identity headers from the inbound request.
- Sets the verified subject and OAuth client identifier from token claims.
- Permits
x-acting-foronly after checking the represented party. - Proxies to
http://kernel:3000on the private Compose network.
Create the resource¶
- In Coolify, create a Docker Compose resource from this repository.
- Set the compose file to
/docker-compose.coolify.ymland the base directory to/. - Add the environment variables below. Use URL-safe random values containing only letters and digits for database passwords because they are interpolated into PostgreSQL URLs.
- Deploy. Do not add a domain to
postgres,minio,minio-init,migrateorkernel.
Required secrets:
| Variable | Purpose |
|---|---|
POSTGRES_PASSWORD |
PostgreSQL schema-owner password |
KERNEL_APP_PASSWORD |
Restricted application-role password |
KERNEL_TRAINING_PASSWORD |
Read-only training-role password |
MINIO_ROOT_USER |
Private object-store access key |
MINIO_ROOT_PASSWORD |
Private object-store secret key |
Generate suitable values locally with openssl rand -hex 32. Keep all five
different. Coolify should mark them as runtime secrets and never expose them in
build logs.
Optional settings include AUDIT_SHIP_URL, AUDIT_SHIP_TOKEN and the
ANCHOR_* variables. Leave anchoring on testnet until the documented mainnet
acknowledgement has been reviewed. Production always runs with seed ingest off
and the special-data consent check on.
First deployment¶
The migrate service waits for PostgreSQL, applies every forward-only migration
and provisions the restricted roles. The kernel starts only after migrations
and private bucket initialization succeed. On later deployments the migration
job verifies checksums and applies only new files.
From another service on the same private network, readiness is available at:
After the Authentik gateway is deployed, assign the public API domain to the gateway and verify that forged identity headers are removed before setting the field build variables:
EXPO_PUBLIC_API_URL=https://api.example.org/v1
EXPO_PUBLIC_OIDC_ISSUER=https://auth.example.org/application/o/field/
EXPO_PUBLIC_OIDC_CLIENT_ID=field-client
EXPO_PUBLIC_ACTING_FOR=<cooperative-party-uuid>
SQLCipher requires an Android development or release build; the client cannot run in Expo Go.
Persistence and backups¶
kernel-pgdata and kernel-objects-data are named persistent volumes. Enable
Coolify backups for both, but retain the repository backup scripts and perform
restore drills: a volume snapshot alone does not prove that PostgreSQL and the
object inventory agree.