Skip to main content

Self-hosting

IdentSphere is a single, self-contained binary. You run it on your own infrastructure, against your own Postgres — your users, sessions, secrets, and audit log never leave your perimeter. This page gets you from zero to a running instance with an admin console.

One container

docker run -p 4000:4000 \
-e DATABASE_URL=postgres://user:pass@host:5432/identsphere \
-e IDENTSPHERE_JWT_SECRET="$(openssl rand -hex 32)" \
-e IDENTSPHERE_PUBLIC_BASE_URL=https://auth.yourcompany.com \
-e IDENTSPHERE_FROM_EMAIL=no-reply@yourcompany.com \
-e IDENTSPHERE_AUTO_MIGRATE=true \
-e IDENTSPHERE_INITIAL_OWNER_EMAIL=you@yourcompany.com \
ghcr.io/identsphere/server:latest

The image bundles everything — the API and the admin console. No separate frontend deploy, no Node, no CDN.

VariableRequiredPurpose
DATABASE_URLPostgres connection string
IDENTSPHERE_JWT_SECRETToken signing key — 32+ bytes, back it up
IDENTSPHERE_PUBLIC_BASE_URLCanonical public URL (email links, OAuth redirects, JWT issuer)
IDENTSPHERE_FROM_EMAILTransactional sender address
IDENTSPHERE_AUTO_MIGRATEApply DB migrations on boot (else run identsphere migrate up)
IDENTSPHERE_INITIAL_OWNER_EMAILBootstrap the first platform admin — see Admin console
IDENTSPHERE_COOKIES_SECUREtrue in production (HTTPS)

Full list: Environment reference.

The admin console

Once running, open:

https://auth.yourcompany.com/admin

The server serves the console itself, on the same origin as the API — exactly how Keycloak, PocketBase, and Supabase Studio work. There's no separate URL to configure and no CORS to set up. See Admin console for first-login + how to lock it down.

Don't want the console exposed? Set IDENTSPHERE_SERVE_ADMIN=false and it won't be served at all.

Migrations

Migrations are plain, idempotent SQL. Either set IDENTSPHERE_AUTO_MIGRATE=true (applied on boot) or run them explicitly:

docker run --rm --entrypoint /identsphere ghcr.io/identsphere/server:latest \
migrate up --database-url "$DATABASE_URL"

TLS, scaling, and what you own

  • Put it behind TLS (Caddy/nginx/your cloud LB). Set IDENTSPHERE_COOKIES_SECURE=true once you're on HTTPS.
  • Reverse-proxy header trust. Rate-limiting and any IP allowlist read the client IP from X-Forwarded-For. That's only trustworthy if a proxy you control sets it — terminate at a proxy that strips client-supplied XFF.
  • Your data, your keys. The DB, the JWT signing key, OAuth tokens, audit logs, and any provider secrets all live in your Postgres / your env. IdentSphere makes no outbound calls to us — there is no phone-home.

Next