Getting started

Quick start

Run auth-service locally with Docker Compose in a few minutes, or from source for development.

Two ways to get a local instance: the published image (nothing to build) or the source tree with hot reload.

Option A — Docker Compose (published image)

Create the environment file

git clone https://github.com/circle-rd/auth-service.git
cd auth-service
cp .env.example .env

Edit .env for a local stack:

DOMAIN=localhost
PUBLIC_SCHEME=http
BETTER_AUTH_URL=http://localhost:3001

BETTER_AUTH_SECRET=<output of: openssl rand -base64 32>
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=<at least 12 characters, not the .env.example placeholder>
POSTGRES_PASSWORD=<any value>

Start the stack

docker compose pull
docker compose up -d

PostgreSQL starts first, then auth-service applies its migrations, creates the superadmin and listens on http://localhost:3001.

Verify

curl http://localhost:3001/health
# → {"status":"ok","version":"<x.y.z>"}

curl http://localhost:3001/.well-known/openid-configuration

Open http://localhost:3001/auth and sign in with ADMIN_EMAIL and ADMIN_PASSWORD:

Then continue with Managing applications to register your first OAuth client.

Option B — from source (development)

Prerequisites: Node.js 22+, pnpm 10+, Docker.

Start PostgreSQL only

Compose reads .env and requires BETTER_AUTH_SECRET for the whole file, so create .env first (see option A).

pnpm install
docker compose up -d postgres

Configure the environment

pnpm dev reads .env without variable expansion, so write final values (the ${DOMAIN} references of .env.example are only expanded by Docker Compose):

BETTER_AUTH_URL=http://localhost:3001
DATABASE_URL=postgres://auth:<POSTGRES_PASSWORD>@localhost:5433/<POSTGRES_DB>

Keep ADMIN_EMAIL, ADMIN_PASSWORD and BETTER_AUTH_SECRET as in option A.

Apply the schema

In development the server does not migrate by itself, so apply the migrations once and after each schema change:

pnpm db:migrate

Start the backend

pnpm dev

The server restarts on every change (tsx watch) and listens on http://localhost:3001. The superadmin is created on first boot.

Start the admin frontend (optional)

cd frontend
pnpm install
pnpm dev

Vite serves the Vue admin SPA with hot reload on http://localhost:5173 and proxies API calls to port 3001. To work on the UI without any backend, run VITE_USE_MOCK=true pnpm dev: every API call is answered with fictional demo data.

Without the Vite server, the backend serves the SPA itself from frontend-dist/ once you ran pnpm build:frontend.

Available scripts

ScriptDescription
pnpm devBackend with hot reload
pnpm buildBackend TypeScript and frontend SPA
pnpm build:server / pnpm build:frontendOnly the backend, or only the frontend
pnpm startRun the compiled backend (dist/)
pnpm db:generateGenerate a Drizzle migration from schema changes
pnpm db:migrateApply pending migrations
pnpm db:pushPush the schema without migration files (throwaway databases only)
pnpm testUnit tests (Vitest)
pnpm test:integrationIntegration tests (an ephemeral PostgreSQL container is started by testcontainers)
pnpm test:e2ePlaywright end-to-end tests
pnpm lint / pnpm format:checkESLint and Prettier checks
pnpm llm:setup, llm:provision, llm:smoke, llm:reconcileLiteLLM gateway tooling, see LiteLLM gateway
Copyright © 2026