Self-hosting

Environment variables

Clerq is configured entirely through environment variables, so the same build runs in development, staging and production. This page lists every variable the app actually reads. If a setting is not on this page, the app does not read it.

When you run the bundled docker-compose.yml, the compose-level variables in the last section are assembled into the application variables for you - you generally only set POSTGRES_PASSWORD, BETTER_AUTH_SECRET and BETTER_AUTH_URL.

Application variables

These are read by the app (and the migration step) at runtime.

VariableRequiredWhat it does
DATABASE_URLyesPostgreSQL connection string, e.g. postgresql://clerq:password@host:5432/clerq. Read by the app and by drizzle-kit when applying migrations. Under docker-compose this is built for you from the POSTGRES_* values and points at the internal postgres service - you do not set it yourself there.
BETTER_AUTH_SECRETyesSecret key used to sign session cookies and the short-lived signed invoice-PDF download links. Use at least 32 random characters. Rotating it signs everyone out and invalidates any outstanding PDF links.
BETTER_AUTH_URLyes in productionThe external base URL your instance is reached on, e.g. https://clerq.example.com. Used for authentication callbacks and redirects. It must match the scheme, host and port your users actually use. Defaults to http://localhost:3000 for local runs.

Generating BETTER_AUTH_SECRET

openssl rand -base64 32

The app logs a warning if the secret is shorter than 32 characters or looks low-entropy. Treat that warning as an error for any instance other people can reach.

Optional: Google sign-in

Google SSO is strictly optional. Self-hosting never requires a third-party account - email and password sign-in always works. The Google button only appears when both variables below are set; leave them unset to hide it.

VariableRequiredWhat it does
GOOGLE_CLIENT_IDnoOAuth client ID from Google Cloud. Enables the "Continue with Google" button when paired with the secret.
GOOGLE_CLIENT_SECRETnoOAuth client secret that pairs with the client ID above.

The authorized redirect URI to register with Google is <BETTER_AUTH_URL>/api/auth/callback/google. See Going to production for the full setup.

Compose-level variables

These are read by the bundled docker-compose.yml itself (not by the app directly). Compose uses them to build the database, bind host ports, and construct DATABASE_URL. Set them in the .env file next to the compose file.

VariableDefaultWhat it does
POSTGRES_USERclerqDatabase role the app connects as.
POSTGRES_PASSWORDclerqDatabase password. Change this before exposing the instance anywhere.
POSTGRES_DBclerqDatabase name.
POSTGRES_PORT5432Host port the database is published on, bound to 127.0.0.1 only.
APP_PORT3000Host port mapped to the app container's port 3000.

Set automatically by the image

The production image sets these for you. You normally never change them, but they are listed here so nothing is hidden.

VariableValueWhat it does
NODE_ENVproductionStandard Node production mode.
PORT3000Port the app listens on inside the container.
HOSTNAME0.0.0.0Binds to all interfaces inside the container.
NEXT_TELEMETRY_DISABLED1Disables Next.js telemetry.

What Clerq does not need

To save you searching for settings that do not exist:

  • No SMTP or email configuration. Clerq sends no email. Team invitations are shareable links you send yourself, and invoices are exported as PDFs rather than emailed. There is no mail server to configure.
  • No currency-API key. Exchange rates come from the European Central Bank's public reference rates, fetched server-side with no key and no account.
  • No object storage. Logos and expense receipts are stored inline in the database, so there is no S3 bucket or blob store to run.
  • No sign-up toggle today. There is no environment variable to disable new registrations. If your instance is internet-facing and you do not want open sign-ups, put it behind your own access control - see Going to production.

The shortest viable production config is three lines: POSTGRES_PASSWORD, BETTER_AUTH_SECRET and BETTER_AUTH_URL. Everything else has a working default.