Skip to content
latest
Command Line / latest

Build and Deploy

andurel build produces the production web binary and every compiled asset. It does not build the queue, migration, or SSR processes; build those with go build when the application uses them.

What andurel build does

1andurel build --version 1.2.3

The command runs these steps in order:

  1. Downloads templ and generates Go from .templ files (email templates and the Inertia root document).
  2. Runs narsilc when domains/**/*.sql contains annotated queries.
  3. Compiles the Tailwind classes used by email templates into inline styles.
  4. For an Inertia project, installs JavaScript dependencies and runs the package's build script. The package manager comes from andurel.toml: pnpm install --frozen-lockfile, npm ci, or bun install --frozen-lockfile. The scaffold's Vite build emits the client assets and the SSR bundle under assets/dist.
  5. Downloads Go modules.
  6. Compiles ./cmd/app with CGO_ENABLED=0 and GOOS=linux, writing a binary named after the module in the project root.

The version comes from --version, or from git describe --tags --always --dirty when the flag is omitted. It is injected as main.appVersion with -ldflags.

Build the other processes

Production may run up to four process types. andurel build only produces the first.

1CGO_ENABLED=0 GOOS=linux go build -o andurel-site-queue ./cmd/queue
2CGO_ENABLED=0 GOOS=linux go build -o migrate ./cmd/migrate
3CGO_ENABLED=0 GOOS=linux go build -o andurel-site-ssr ./cmd/ssr
  • cmd/queue runs River workers, periodic jobs, telemetry, and email senders.
  • cmd/migrate applies the embedded migrations once and exits.
  • cmd/ssr is the production owner of the Node SSR bundle. Build it only when pages opt into SSR. It starts the bundle at INERTIA_SSR_LISTEN (default http://127.0.0.1:13714), and the web process calls it at INERTIA_SSR_URL.

Use a Node runtime at or above INERTIA_SSR_MINIMUM_MAJOR (22 by default) for the SSR process.

Release sequence

  1. Run andurel build.
  2. Run the migrate binary against the release database.
  3. Start the queue process.
  4. Start the SSR process if any page uses SSR.
  5. Start the web process.

Deploy the binaries as separate processes. They share PostgreSQL and the telemetry backend, but each owns its lifecycle and shutdown. Apply migrations deliberately before traffic reaches code that expects the new schema, and back up important data before destructive changes.

Environment

Set ENVIRONMENT=production; it enables secure session cookies and refuses the development-only Mailpit email provider.

ENVIRONMENT=production
HOST_PRIMARY=example.com
PROTOCOL=https

DB_HOST=db.internal
DB_PORT=5432
DB_NAME=andurel_site
DB_USER=andurel
DB_PASSWORD=secret
DB_SSL_MODE=require

SESSION_KEY=<hex key>
SESSION_ENCRYPTION_KEY=<hex key>
SESSION_MAX_AGE=604800
TOKEN_SIGNING_KEY=<secret>
PEPPER=<secret>
PREVIOUS_PEPPERS=

EMAIL_PROVIDER=smtp
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=apikey
SMTP_PASSWORD=secret
SMTP_TLS=starttls

CACHE_DRIVER=redis
CACHE_REDIS_ADDR=redis.internal:6379

OTLP_TRACES_ENDPOINT=https://collector.example.com

EMAIL_PROVIDER=mailpit is refused in production. Session keys must be hexadecimal. PREVIOUS_PEPPERS keeps rotated passwords verifiable until they are rehashed at login. Use the Redis cache driver when running more than one web replica so auth rate limits are shared.

Behind a reverse proxy, set HTTP_TRUSTED_PROXIES to the proxy IPs or CIDRs and keep the public Host header intact. Add extra origins with CORS_ALLOWED_ORIGINS and CSRF_TRUSTED_ORIGINS.

Health and shutdown

GET /api/health calls storage.Health on the database and returns the result. Point the platform's readiness check at it, and keep liveness checks limited to process health so a brief database outage does not restart every instance.

The web process starts the HTTP serve loop through lifecycle.Run with WithBlockingStart, so SIGTERM stops accepting connections and drains in-flight requests. The queue process stops its processor before closing PostgreSQL and telemetry. Give the platform enough termination time for requests and jobs to finish cleanly.