Skip to content

Install with Docker Compose

The same deployment as the Docker guide, expressed as one file you can keep in version control.

compose.yaml

compose.yaml
name: axium

services:
  db:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: axium
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set it in .env}
      POSTGRES_DB: axium-api
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U axium -d axium-api"]
      interval: 5s
      timeout: 3s
      retries: 12

  core:
    image: quay.io/axiumlab/core:${AXIUM_TAG:-latest}
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://axium:${POSTGRES_PASSWORD}@db:5432/axium-api
      MASTER_ENCRYPTION_KEY: ${MASTER_ENCRYPTION_KEY:?generate it with: openssl rand -hex 32}
      AXIUM_LICENSE: ${AXIUM_LICENSE:-}
      # Only when a reverse proxy terminates TLS in front of the core:
      # TRUST_PROXY: "true"
      # PUBLIC_BASE_URL: https://axium-api.your-domain.com
    healthcheck:
      # The image has no curl or wget; bun is the available HTTP client.
      test: ["CMD", "bun", "-e", "fetch('http://127.0.0.1:3000/v1/install/status').then(r => r.json()).then(j => process.exit(j.data.state === 'installed' ? 0 : 1)).catch(() => process.exit(1))"]
      interval: 15s
      timeout: 5s
      start_period: 60s
      retries: 5

  ui:
    image: quay.io/axiumlab/ui:${AXIUM_TAG:-latest}
    restart: unless-stopped
    depends_on:
      - core
    ports:
      - "3001:3001"
    environment:
      # Resolved by the browser, not by this container. Must be reachable from
      # the outside and end in /v1 with no trailing slash.
      API_URL: ${API_URL:-http://localhost:3000/v1}

volumes:
  pgdata:

Health checks

The core image already declares a liveness HEALTHCHECK on /v1/health. The one above replaces it with a readiness check on the schema state. See Health checks.

.env

.env
AXIUM_TAG=v0.1.0
POSTGRES_PASSWORD=change-this
MASTER_ENCRYPTION_KEY=   # openssl rand -hex 32
AXIUM_LICENSE=           # your 40-character hex license
API_URL=http://localhost:3000/v1

Keep .env out of version control: it holds the master key and the database password.

Run it

docker login quay.io
docker compose pull
docker compose up -d
docker compose ps
curl http://localhost:3000/v1/install/status

Then open http://localhost:3001 and continue with First login.

Upgrade

Change AXIUM_TAG in .env and run:

docker compose pull && docker compose up -d

The containers are disposable and the pgdata volume stays where it is. Read Upgrading before moving across a major version.