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.
| Variable | Required | What it does |
|---|---|---|
DATABASE_URL | yes | PostgreSQL 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_SECRET | yes | Secret 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_URL | yes in production | The 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.
| Variable | Required | What it does |
|---|---|---|
GOOGLE_CLIENT_ID | no | OAuth client ID from Google Cloud. Enables the "Continue with Google" button when paired with the secret. |
GOOGLE_CLIENT_SECRET | no | OAuth 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.
| Variable | Default | What it does |
|---|---|---|
POSTGRES_USER | clerq | Database role the app connects as. |
POSTGRES_PASSWORD | clerq | Database password. Change this before exposing the instance anywhere. |
POSTGRES_DB | clerq | Database name. |
POSTGRES_PORT | 5432 | Host port the database is published on, bound to 127.0.0.1 only. |
APP_PORT | 3000 | Host 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.
| Variable | Value | What it does |
|---|---|---|
NODE_ENV | production | Standard Node production mode. |
PORT | 3000 | Port the app listens on inside the container. |
HOSTNAME | 0.0.0.0 | Binds to all interfaces inside the container. |
NEXT_TELEMETRY_DISABLED | 1 | Disables 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_SECRETandBETTER_AUTH_URL. Everything else has a working default.