Skip to content

Operate a self-hosted Chorus

This guide covers operating a self-hosted Chorus after it is deployed: getting the first person signed in, configuring authentication, upgrading safely, and the cookie and reverse-proxy settings that matter behind HTTPS. For how to stand a deployment up, see Deploy in production or Deploy with Docker.

A fresh deployment has no accounts yet. Set DEFAULT_USER and DEFAULT_PASSWORD to enable a built-in email/password login that bypasses single sign-on:

Terminal window
DEFAULT_USER='admin@example.com' \
DEFAULT_PASSWORD='choose-a-strong-password'

When both variables are set, the login page shows an email/password form. On the first successful login, Chorus auto-provisions the user and its company from the email, so no manual setup is needed to get in.

The built-in login is a bootstrap mechanism, not a permanent account system. Once real accounts exist — or once single sign-on is configured — turn it off by unsetting both DEFAULT_USER and DEFAULT_PASSWORD and restarting Chorus. With the pair removed, the built-in email/password form no longer appears and access goes through your configured identity provider instead.

Two kinds of authentication are configured at the deployment level.

The /admin SuperAdmin panel is bootstrapped from environment variables, not from a database account:

| Variable | Description | | --- | --- | | SUPER_ADMIN_EMAIL | Email for the SuperAdmin account that can reach the /admin panel. | | SUPER_ADMIN_PASSWORD_HASH | Bcrypt hash of the SuperAdmin password (never the plaintext). |

Generate the hash and pass it as SUPER_ADMIN_PASSWORD_HASH:

Terminal window
node -e "console.log(require('bcryptjs').hashSync('your-password', 10))"

Single sign-on is not configured through environment variables. The SuperAdmin configures OIDC per company from the /admin panel, and the settings are stored in the database. Each company has its own issuer, client ID, and enable toggle. Chorus uses PKCE and does not require a client secret. So the deployment-level bootstrap gets the SuperAdmin in, and the SuperAdmin then enables SSO for each company from the admin panel — no separate secret provisioning at the deployment layer.

Chorus applies pending database migrations automatically at startup (prisma migrate deploy). You do not run migrations by hand — starting a new version applies whatever is outstanding before the web application begins serving.

To upgrade:

  1. Back up your database first. For an external PostgreSQL, take a backup; for an embedded or volume-backed database, back up the data volume.
  2. Pull the new version — npm update -g @chorus-aidlc/chorus for the npm package, or pull the new container image for a Docker deployment.
  3. Restart Chorus. Migrations apply automatically on boot, then the app starts.

Two settings matter when Chorus runs behind TLS termination or a reverse proxy:

| Variable | Set to | When | | --- | --- | --- | | COOKIE_SECURE | true | The site is served over HTTPS (including behind a proxy that terminates TLS). Secure cookies are only sent over encrypted connections. | | COOKIE_SECURE | false | Only for trusted, internal HTTP-only networks. Cookies are then sent over unencrypted HTTP, so never use this on the public internet. | | NEXTAUTH_URL | The public base URL | Chorus runs behind a reverse proxy. Set it to the externally visible address (for example https://chorus.example.com) so redirects and links resolve correctly. |