Self-hosting

Fliq is open source and runs the whole stack — API, scheduler, and Postgres — from one docker compose. No Clerk account, no Redis, no managed services. The only prerequisite is Docker.

This guide mirrors the README in core-api and is verified against a clean clone.

1. Clone and start

git clone https://github.com/fliq-sh/core-api.git && cd core-api

# Build + start Postgres, run migrations, then bring up the server + scheduler.
docker compose --profile migrate --profile app up --build

The migrate profile runs the database migrations once and exits; the app profile then starts the API server and the scheduler. When it settles, the API is live on http://localhost:8080:

curl localhost:8080/health
# {"status":"ok","version":"dev","time":"..."}

2. Get a first credential — no Clerk

Self-hosted Fliq authenticates with HS256 JWTs signed by JWT_SECRET (set in docker-compose.yml). Mint one for any user id; the first authenticated request auto-provisions that user with free credits.

SECRET='dev-only-change-me-0123456789abcdef0123456789'   # must match the server's JWT_SECRET
b64() { openssl base64 -A | tr '+/' '-_' | tr -d '='; }
h=$(printf '{"alg":"HS256","typ":"JWT"}' | b64)
p=$(printf '{"sub":"local-user","exp":%d}' "$(($(date +%s)+31536000))" | b64)
s=$(printf '%s.%s' "$h" "$p" | openssl dgst -sha256 -hmac "$SECRET" -binary | b64)
JWT="$h.$p.$s"

# Exchange the JWT for a long-lived API token (fliq_sk_*) you can use everywhere:
curl -s -X POST localhost:8080/tokens \
  -H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
  -d '{"name":"self-host"}'
# → {"token":"fliq_sk_...", ...}

3. Schedule a job

Use the fliq_sk_* token the same way you would against the hosted API:

curl -X POST localhost:8080/jobs \
  -H "Authorization: Bearer fliq_sk_..." -H 'Content-Type: application/json' \
  -d '{"url":"https://httpbin.org/post","method":"POST","scheduled_at":"2030-01-01T00:00:00Z"}'

From here, everything in the Quickstart and API Reference applies unchanged — the self-hosted API is the same binary as the hosted one.

Configuration

Everything is env-driven; the compose file sets sane local defaults. The vars that matter when self-hosting:

VarPurpose
DATABASE_URLPostgres connection string
JWT_SECRETHS256 signing secret for local auth (min 32 chars) — change it
CLERK_JWKS_URLset only to use Clerk RS256 auth instead of the HS256 path
WORKER_COUNT / POLL_INTERVAL_SECscheduler concurrency + poll cadence
STRIPE_*optional — only needed for paid top-ups

Running the binaries directly

Prefer not to use Docker for the app processes? Bring up only Postgres, run the migrations, then run the two Go binaries — see the Local dev section of the core-api README.

View core-api on GitHub