Skip to content
by

Docs

Configuration

What the installer writes to deploy/.env, and the few settings you might change.

The installer writes your whole configuration for you, so on most installs you never touch it. This page explains what's in it, the few settings you might change, and how to apply a change.

Almost everything else is configured in the admin, not in a file: your email (Resend), payment gateways, file storage, Turnstile, branding and the rest live under Settings, stored in the database and encrypted. See First run and the Settings reference.

Where it lives#

Your configuration is one file, deploy/.env, in the folder you installed from. To find it:

sudo clientos env

The installer writes it once, on the first install, and never overwrites it. Updates leave it alone too.

Keep deploy/.env private, and keep a copy somewhere safe. CREDENTIAL_SECRET in it encrypts every key you save in Settings. Lose it and those keys can't be read back, so you'd have to paste them all again. Every clientos backup includes a copy.

Applying a change#

Edit the file as root, then run:

sudo clientos start

That recreates whatever the change affects. clientos restart is not enough: it restarts the containers with the configuration they already had.

The API checks its configuration when it starts. If a value is missing or unsafe, it refuses to start and its log, sudo clientos logs api, begins with Invalid environment: and names each problem.

Settings you might change#

VariableWhat it does
MAIL_POSTAL_ADDRESSYour agency's postal address, added to commercial email. US CAN-SPAM rules require one, and its absence is a spam signal. Set it before you launch.
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRETGoogle sign-in for clients. Both or neither. See below.
EXTRA_TRUSTED_PROXIESOnly if you put Cloudflare's proxy (orange cloud) in front: Cloudflare's address ranges, separated by spaces. See Cloudflare's proxy. Empty otherwise.
SUBNETThe private network the containers share. The installer picks one that clashes with nothing on the server. Change it only if you add a VPN or network that overlaps it, then run sudo clientos stop and sudo clientos start.
SETUP_KEYThe key the setup page asks for. Meaningless once setup is done.

Settings written for you#

Leave these as the installer wrote them unless a page in these docs tells you otherwise.

VariableWhat it is
PORTAL_DOMAINYour client portal's address. The API and your files are served on it too.
ADMIN_DOMAINYour team's address.
DOMAINThe domain both addresses are under. Sign-in covers it, and your license is bound to it. Don't change these three on a running install; see Moving to another domain. (A server installed before addresses were chosen in the browser has only DOMAIN, and answers on portal., admin., api. and files. under it.)
ACME_EMAILWhere Let's Encrypt writes if a certificate renewal fails.
CLIENTOS_VERSIONThe release this server runs. clientos update and clientos rollback change it.
CLIENTOS_VERSION_PREVIOUSThe release before the last update, kept for clientos rollback.
CLIENTOS_LICENSE_KEYYour license key. ClientOS is downloaded with it, and the setup page activates it.
POSTGRES_PASSWORDThe database owner's password. Only the migration step uses it.
APP_DB_PASSWORDThe API's own, more limited database login. The migration step sets it on every start.
REDIS_PASSWORDRedis.
MINIO_PASSWORDThe file store's root password. The API never receives it.
STORAGE_SECRETThe API's own key to the file store, limited to its one bucket.
SESSION_SECRETSigns every session and sign-in code. Changing it signs everybody out.
CREDENTIAL_SECRETEncrypts every key saved in Settings. To change it, follow Rotating the credential secret.
CREDENTIAL_SECRET_PREVIOUSEmpty, except during a rotation of CREDENTIAL_SECRET.
FORWARDED_IP_SECRETLets the apps pass each visitor's real address to the API for rate limiting.

Everything else, such as the public addresses, the cookie domain and the allowed origins, is worked out from these three, so there's nothing to keep in step.

Google sign-in for clients#

Optional. Lets clients sign in with a Google account that matches the email address you invited. Clients can't sign up through Google. The Google button appears only when both values are set.

  1. In Google Cloud Console, create an OAuth client of type Web application.

  2. Add this as an authorized redirect URI, with your own domain:

    https://YOUR_PORTAL/v1/auth/callback/google
    
  3. Put the client ID and secret in GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in deploy/.env.

  4. Run sudo clientos start.

What isn't set here#

Some things look like they belong in deploy/.env but don't:

  • Email. There's no mail setting in the file. Mail goes out only through the Resend account you connect at Settings → Integrations → Resend.
  • Cloudflare R2. Files go to the server's own storage until you save a bucket at Settings → Storage.
  • NODE_ENV. ClientOS always runs in production mode. If you add NODE_ENV with any other value, the API refuses to start.

The API also refuses to start if any of these are set: RESEND_API_KEY, R2_ACCOUNT_ID, R2_BUCKET, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_PUBLIC_BASE_URL, S3_ENDPOINT, LICENSE_SERVER_URL, LICENSE_PUBLIC_KEY, DEMO_ROLE=on, E2E_JOBS=on, or DATABASE_ROLE_CHECK set to anything but strict. Remove the line and run sudo clientos start.

Example#

What the installer writes, for clients.youragency.com and team.youragency.com. Your secrets are long random strings.

DOMAIN='youragency.com'
PORTAL_DOMAIN='clients.youragency.com'
ADMIN_DOMAIN='team.youragency.com'
ACME_EMAIL='[email protected]'

POSTGRES_PASSWORD=...
APP_DB_PASSWORD=...
REDIS_PASSWORD=...
MINIO_PASSWORD=...
STORAGE_SECRET=...

SESSION_SECRET=...
CREDENTIAL_SECRET=...
CREDENTIAL_SECRET_PREVIOUS=
FORWARDED_IP_SECRET=...

SETUP_KEY=...

CLIENTOS_VERSION=1.4.0
CLIENTOS_LICENSE_KEY=CLOS-XXXX-XXXX-XXXX-XXXX

SUBNET=10.213.0.0/24

EXTRA_TRUSTED_PROXIES=
MAIL_POSTAL_ADDRESS=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=