Deployment
Deployment
From a fresh server to a running, hardened Cbox ID instance. This is an identity provider — the guidance here is deliberately security-first.
Requirements
- PHP 8.4+ with
ext-sodiumandext-openssl(the crypto layer needs both;cbox-id:doctorfails loudly if either is missing). - A database — PostgreSQL or MySQL in production (not SQLite).
- A cache/queue backend — Redis recommended (sessions, rate limits, queues).
- TLS terminated in front of the app. Passkeys (WebAuthn) and secure cookies require HTTPS; the platform assumes it.
See Requirements for the full, composer.json-backed list.
1. Install the code
composer install --no-dev --optimize-autoloader
2. Bootstrap
The guided installer generates the crypto master key, asks the few questions that
matter (issuer URL, passkey domain/origin), writes them to .env, runs migrations,
and mints the first signing key:
php artisan cbox-id:install
Prefer a non-interactive deploy? Set the environment variables yourself (see
Configuration) and run
php artisan migrate --force instead — cbox-id:install is the convenience path,
not a requirement.
3. Optimize for production
php artisan config:cache
php artisan route:cache
php artisan event:cache
Re-run these on every deploy after the code and .env are in place.
4. Create the first platform operator
A platform operator is the identity above every environment — it administers
environments, tenant organizations, and other operators. On a fresh install visit
/operator/login: with no operator yet it shows a one-time "create the first
operator" form (serialized behind a lock so only one can win the bootstrap), then
that path closes permanently. Immediately enroll a strong credential — this is the
most sensitive account on the system.
From the operator console, create your environment(s) and use Provision admin
on each to seed its first organization and owner-admin. Those org admins then sign
in at /login. (Because whoever reaches /operator/login first on a fresh,
internet-exposed deploy claims root, complete this step before exposing the host,
or bootstrap the operator on a private network first.)
5. Run the workers
The platform relies on the queue (webhook delivery, the event outbox, async audit work) and the scheduler (key retirement, cleanups):
php artisan queue:work --tries=3 # under a supervisor (systemd/supervisord)
php artisan schedule:run # from cron, every minute
6. Verify
php artisan cbox-id:doctor
In production this also checks the hardening posture: APP_DEBUG off, secure +
encrypted session cookies. Treat any ✗ as release-blocking. A green doctor plus a
reachable /.well-known/openid-configuration means you're live.
Reverse proxy notes
- Terminate TLS; forward the real scheme/host (
X-Forwarded-Proto/-Host) and configure Laravel's trusted proxies (TRUSTED_PROXIES, see Configuration) so issuer URLs and cookieSecureflags are correct. - The discovery, JWKS, token, introspection, SCIM and SAML ACS endpoints are all served by the app — no separate service to route.
Where to go next
- Configuration — the env reference and secure defaults.
- Day-2 operations — backups, key rotation, upgrades, break-glass.