Environment Configuration Reference — Docker Compose and Helm

Environment Configuration — Docker Compose & Helm

Focused reference for configuring Fabrixly IDS and the Licensing Portal via .env (Docker Compose) or values.yaml (Helm). No setup steps — just the variables.


Fabrixly Identity Server

Docker Compose — .env file

Docker Compose reads from a .env file in the same directory as docker-compose.yml. Copy .env.example.env and fill in your values.

fabrixly-identity-server/
├── docker-compose.yml
└── .env                ← your config goes here

The compose file maps every variable via ${VAR_NAME} substitution. Variables with :-default have fallbacks; the rest must be set.

Required — must set

Variable Description
SESSION_SECRET Session encryption key — min 32 chars. openssl rand -base64 32
JWT_SECRET JWT signing key — min 32 chars. openssl rand -base64 32
SMTP_HOST SMTP server (e.g. smtp.sendgrid.net)
SMTP_USER SMTP username or API key
SMTP_PASS SMTP password or API key
SMTP_FROM Sender address e.g. "Fabrixly IDS" <no-reply@acme.com>

Optional — have defaults

Variable Default Description
DB_USERNAME admin PostgreSQL username (used by both postgres & backend containers)
DB_PASSWORD admin123 PostgreSQL password
DB_NAME identity_server PostgreSQL database name
DB_SYNC false Auto-sync DB schema on boot — keep false in production
ISSUER https://ids.fabrixly.com/oidc Public OIDC issuer URL — change for production
SMTP_PORT 587 SMTP port
SYSTEM_ADMIN_EMAIL admin@system.com Admin account email (seeded on first boot)
SYSTEM_ADMIN_PASSWORD admin123 Admin account password (seeded on first boot)
AUTO_SEED false Set true on first boot to seed admin + plans. Idempotent — safe to keep on.
SELF_HOSTED false true = license key mode; plan selection hidden in console
LICENSE_KEY (empty) License JWT — required when SELF_HOSTED=true
ENABLE_USER_REGISTRATION true Allow public self-registration

Social login (optional — only if you enable a provider)

Variable Description
GOOGLE_CLIENT_ID Google OAuth App client ID
GOOGLE_CLIENT_SECRET Google OAuth App client secret
GITHUB_CLIENT_ID GitHub OAuth App client ID
GITHUB_CLIENT_SECRET GitHub OAuth App client secret

Minimal .env to get running

SESSION_SECRET=<openssl rand -base64 32>
JWT_SECRET=<openssl rand -base64 32>
SMTP_HOST=smtp.sendgrid.net
SMTP_USER=apikey
SMTP_PASS=SG.xxxx
SMTP_FROM="Fabrixly IDS" <no-reply@acme.com>
AUTO_SEED=true

Helm — values.yaml structure

The chart splits configuration into two blocks: env (plain config map) and secrets (Kubernetes Secret).

helm/fabrixly-ids/
├── values.yaml                          ← defaults (committed to git)
├── values-development.yaml              ← dev overrides
├── values-secrets-development.yaml      ← dev secrets (do NOT commit)
└── values-secrets-production.yaml       ← prod secrets (do NOT commit)

backend.env — plain environment variables

Set these in your values override file. They become a ConfigMap in the pod.

backend:
  env:
    NODE_ENV: production
    PORT: "3000"
    ISSUER: "https://your-domain.com/oidc"   # ← CHANGE
    DB_HOST: "postgresql-service"             # ← matches postgresql subchart service
    DB_PORT: "5432"
    DB_NAME: "identity_server"
    DB_SYNC: "false"
    DB_LOGGING: "false"
    SMTP_HOST: "smtp.sendgrid.net"
    SMTP_PORT: "587"
    SMTP_SECURE: "true"
    SMTP_FROM: "noreply@your-domain.com"      # ← CHANGE
    CONSOLE_URL: "https://your-domain.com"    # ← CHANGE
    AUTO_SEED: "true"                         # seed on first deploy, set false after
    SYSTEM_ADMIN_EMAIL: "admin@system.com"
    SELF_HOSTED: "false"
    LICENSE_KEY: ""
    ENABLE_USER_REGISTRATION: "true"
    # Social login — uncomment to enable:
    # GOOGLE_CLIENT_ID: ""
    # GOOGLE_CLIENT_SECRET: ""
    # GITHUB_CLIENT_ID: ""
    # GITHUB_CLIENT_SECRET: ""

backend.secrets — injected as Kubernetes Secret

These become secretKeyRef env vars in the pod. Put them in a separate file that is NOT committed to git.

# values-secrets-production.yaml  ← add to .gitignore!
backend:
  secrets:
    SESSION_SECRET: "..."      # openssl rand -base64 32
    JWT_SECRET: "..."          # openssl rand -base64 32
    DB_PASSWORD: "..."         # postgres user password
    SMTP_USER: "..."           # smtp user / api key
    SMTP_PASS: "..."           # smtp password / api key
    SYSTEM_ADMIN_PASSWORD: "..." # seeded admin password

postgresql:
  auth:
    password: "..."            # must match backend.secrets.DB_PASSWORD
    postgresPassword: "..."    # postgres superuser password

backend.image — image & tag

backend:
  image:
    repository: kumaravinit/zero
    tag: "ids-backend-1.0.1"     # or "ids-backend-latest"
    pullPolicy: IfNotPresent

console:
  image:
    repository: kumaravinit/zero
    tag: "ids-console-1.0.1"

Install command

helm install fabrixly-ids ./helm/fabrixly-ids \
  -f helm/fabrixly-ids/values.yaml \
  -f helm/fabrixly-ids/values-production.yaml \
  -f helm/fabrixly-ids/values-secrets-production.yaml \
  --namespace fabrixly-ids --create-namespace

Licensing Portal

Docker Compose — .env file

zero-licencing-portal/
├── docker-compose.yml
└── .env                ← your config goes here

The compose DB connection string is built automatically inside the file: DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_NAME}

You do NOT need to set DATABASE_URL yourself when using compose.

Required — must set

Variable Description
ISSUER IDS OIDC issuer URL — e.g. http://your-ids-host:3000/oidc
CLIENT_SECRET OIDC client secret registered in IDS for this portal
SESSION_SECRET Session key — openssl rand -base64 32
IDS_BASE_URL IDS API base URL (no /oidc) — e.g. http://your-ids-host:3000
IDS_ADMIN_PASSWORD IDS system admin password
PRIVATE_KEY RSA private key (PKCS#8 PEM) for signing license JWTs

Optional — have defaults

Variable Default Description
CLIENT_ID licensing-portal-client OIDC client ID registered in IDS
REDIRECT_URI http://localhost:3005/callback OAuth callback URL — change for production
DB_USERNAME admin Postgres username
DB_PASSWORD admin123 Postgres password
DB_NAME licensing_db Postgres database name (keep separate from IDS DB)
IDS_ADMIN_EMAIL admin@system.com IDS admin email
Note: The licensing portal postgres runs on host port 5433 (not 5432) to avoid clashing with IDS postgres if both are on the same machine.

Generating PRIVATE_KEY

node -e "
const c = require('crypto');
const { privateKey } = c.generateKeyPairSync('rsa', {
  modulusLength: 2048,
  privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
});
console.log(privateKey);
"

In .env, use single quotes to preserve newlines:

PRIVATE_KEY='-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAA...
-----END PRIVATE KEY-----'

Minimal .env to get running

ISSUER=https://ids.fabrixly.com/oidc
CLIENT_SECRET=licensing_portal_secret
SESSION_SECRET=<openssl rand -base64 32>
IDS_BASE_URL=https://ids.fabrixly.com
IDS_ADMIN_PASSWORD=admin123
PRIVATE_KEY='-----BEGIN PRIVATE KEY-----
<your key here>
-----END PRIVATE KEY-----'

Helm — values.yaml structure

zero-licencing-portal/helm/zero-licencing-portal/
└── values.yaml    ← edit this (or pass an override file)

env — plain environment variables

env:
  nodeEnv: production
  port: 3005
  issuer: "https://your-ids-domain.com/oidc"         # ← CHANGE
  clientId: "licensing-portal-client"
  redirectUri: "https://licensing.your-domain.com/callback"  # ← CHANGE
  # Cluster-internal DNS to reach IDS backend
  idsBaseUrl: "http://fabrixly-ids-backend.fabrixly-ids.svc.cluster.local:3000"
  idsAdminEmail: "admin@system.com"

secrets — injected as Kubernetes Secret

secrets:
  sessionSecret: "..."       # openssl rand -base64 32
  databaseUrl: "postgresql://admin:password@fabrixly-ids-postgresql.fabrixly-ids.svc.cluster.local:5432/licensing_db"
  idsAdminPassword: "..."    # IDS admin password
  privateKey: |              # full RSA PEM block
    -----BEGIN PRIVATE KEY-----
    MIIEvQIBADA...
    -----END PRIVATE KEY-----
Important: The databaseUrl in the Helm chart connects the portal to the IDS PostgreSQL pod using Kubernetes cluster DNS (fabrixly-ids-postgresql.fabrixly-ids.svc.cluster.local). The database name must be different from IDS (licensing_db). If you want fully isolated storage, point it to a separate PostgreSQL instance.

image — image & tag

image:
  repository: kumaravinit/zero
  tag: "licensing-portal-1.0.1"   # or "licensing-portal-latest"
  pullPolicy: IfNotPresent

Install command

helm install zero-licensing ./helm/zero-licencing-portal \
  -f helm/zero-licencing-portal/values.yaml \
  --namespace zero-licensing --create-namespace

Quick Summary: What Goes Where

Concern Docker Compose Helm
Non-secret config .env file values.yamlenv: block
Secrets .env file (keep secure) Separate values-secrets.yamlsecrets: block → K8s Secret
Image version Override image: line in compose image.tag in values
DB connection (IDS) Auto-wired via service name postgres DB_HOST: postgresql-service
DB connection (Portal compose) Auto-built inside compose file secrets.databaseUrl
First-boot seed AUTO_SEED=true backend.env.AUTO_SEED: "true"
Self-hosted mode SELF_HOSTED=true + LICENSE_KEY=... backend.env.SELF_HOSTED: "true" + LICENSE_KEY

Subscribe to The Fabrixly Blog

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe