Get started
Pull it. Boot it. Watch something.
Production images live at ghcr.io/returnearly/nominal:latest — amd64 and arm64, published on every master push. App, worker, and scheduler are the same image. Postgres holds the records.
services:
app:
image: ghcr.io/returnearly/nominal:latest
ports:
- "8000:8080"
environment: &env
APP_KEY: base64:your-app-key
APP_URL: http://localhost:8000
DB_CONNECTION: pgsql
DB_HOST: postgres
DB_DATABASE: nominal
DB_USERNAME: nominal
DB_PASSWORD: nominal
QUEUE_CONNECTION: database
INTERFACE_AUTH: none
depends_on: [postgres]
worker:
image: ghcr.io/returnearly/nominal:latest
command: ["php", "artisan", "queue:work", "--queue=checks.local,default"]
cap_add: [NET_RAW]
environment: *env
depends_on: [postgres]
scheduler:
image: ghcr.io/returnearly/nominal:latest
command: ["php", "artisan", "schedule:work"]
environment: *env
depends_on: [postgres]
postgres:
image: postgres:17
environment:
POSTGRES_DB: nominal
POSTGRES_USER: nominal
POSTGRES_PASSWORD: nominal
volumes:
- postgres:/var/lib/postgresql/data
volumes:
postgres:1. Make a key
Generate an APP_KEY and paste it into the Compose file.
docker run --rm ghcr.io/returnearly/nominal:latest php artisan key:generate --show2. Boot it
docker compose up. Admin is at http://localhost:8000/admin. INTERFACE_AUTH=none skips the login page.
3. Make a token
GraphQL and Terraform use Sanctum tokens, not the admin session.
docker compose exec app php artisan nominal:token