Skip to content

Self-hosted server ​

A self-hosted JoobQUI is one binary, joobqui-selfhosted (./joobqui inside the image), with PostgreSQL and Redis beside it. The Quickstart runs it with Docker Compose; every variable is in Configuration.

The console's Overview page: active workflows, jobs per second, failed jobs, worker nodes, p99 latency, throughput and latency charts.The console's Overview page: active workflows, jobs per second, failed jobs, worker nodes, p99 latency, throughput and latency charts.
The console a self-hosted server serves at /ui/ (mock data).

The Compose deployment ​

The deployment bundle's selfhosted.compose.yml, the file the Quickstart runs:

Drawing the diagram…

The services of the Compose file. Without the redis profile, point REDIS_URL at your own Redis; without https, put your own proxy in front of the app ports.

First start: the setup page ​

With nothing configured, the server needs only a volume for its settings:

sh
docker run -d -p 4000:4000 -v joobqui-data:/data ghcr.io/azutoolkit/joobqui-selfhosted:latest
  1. It prints a one-time setup code in its log ("JoobQ is not set up yet ...") and serves a setup page. The code changes on every restart until setup is finished.
  2. Open the server at its HTTPS address and enter the code. The setup page itself is plain HTTP: put a TLS proxy in front, or open it only from a trusted network.
  3. Enter the public address (https://...) and choose Sign in with JoobQ: the page shows a short code. An admin of an organization with a paid self-hosted licence approves it at app.joobq.io (Open JoobQ). The server fetches its licence itself; no key is copied or pasted. Only approve a code your own server shows you.
  4. Enter Redis and PostgreSQL (Test checks them), then Save and start. The server saves everything encrypted in /data/joobqui.conf (with its key joobqui.key beside it, or JOOBQUI_BOOTSTRAP_KEY), generates SESSION_SECRET, JOOBQUI_SECRETS_KEY and JOOBQUI_PAYLOAD_KEYS itself, and restarts into the console.

Environment variables still work and always win over saved values. A server configured entirely by its environment (as the Compose deployment is) still opens the setup page once, only to connect; with JOOBQUI_ENROLLMENT_TOKEN it connects itself and shows no setup page at all (see Licence and Pro key). JOOBQUI_SETUP=off skips the setup page; a server without a licence then refuses to start and says how to connect it.

What it needs ​

The setup page saves the connections and generates the secrets. To manage them yourself, set them in the environment (the Compose deployment does):

SettingWhy
DATABASE_URLPostgreSQL: accounts, API tokens, the audit log, notification channels. The database must exist; tables and migrations are applied at start (and by every command-line task).
SESSION_SECRETSigns and encrypts the session cookies. With CRYSTAL_ENV=production the server refuses to start unless it is at least 32 characters and not one character repeated (openssl rand -hex 32). Changing it signs everybody out.
REDIS_URL (or REDIS_HOST, REDIS_PORT, REDIS_PASS)JoobQ's data, the live stream, session revocations, throttles, leases, schedule state. Redis 6.2 or newer; no Sentinel or Cluster. Over TLS (rediss://) the certificate chain is checked, not the server name.
A volume at /data (JOOBQUI_DATA_DIR)The settings the setup page saves, encrypted: the licence from Sign in with JoobQ and the secrets the server generates. Back it up with the database. See Licence and Pro key.
JOOBQUI_SDK_TOKEN (or _FILE)The bearer token every SDK worker and producer sends. Without it the gateway answers 503 sdk_token_not_configured. In production a token shorter than 32 characters stops the start.
CRYSTAL_ENV=productionLoads config/joobq.production.yml, adds HSTS and turns on the start-up checks. Set it on every real deployment.

Every other variable is in Configuration. Secrets can be files: NAME_FILE=/run/secrets/name works for DATABASE_URL, SESSION_SECRET, REDIS_URL and JOOBQUI_SDK_TOKEN.

Start, check, stop ​

sh
./joobqui migrate        # apply the migrations and exit (the server also does it at start)
./joobqui                # run the server
./joobqui doctor         # check the database, Redis, the session secret and the licence
./joobqui license:status # the licence: eligible, status, tier, seats, paid_until

Start-up retries the migrations and the event stream for JOOBQUI_BOOT_WAIT_SECONDS (60 by default) while PostgreSQL or Redis does not answer; then it prints one line naming what failed and exits with status 1. On SIGINT or SIGTERM the server stops its background work and the workflow engine before JoobQ, gives its leader leases back so another instance takes over at once, and exits with status 3 when a step failed or ran out of time.

First admin and users ​

Sign-up is closed by default (JOOBQUI_SIGNUP=closed). Make the first account from the command line, with the same environment as the server; the first account is an admin:

sh
./joobqui accounts:create admin@example.com admin            # password from JOOBQUI_ACCOUNT_PASSWORD, or asked twice
./joobqui invites:create 7 --role operator                    # a one-use sign-up invite code

See Accounts, SSO, 2FA, roles and Command line.

Health ​

GET /joobq/health/check (and HEAD) is public and is what a load balancer should check; every other path under /joobq answers 404. GET /api/v1/capabilities (public) says what this server can do, including features.pro.

JoobQ Core is MIT licensed. JoobQ Pro needs a licence key.