Nolixan

Self-host & deployment

Run Nolixan yourself — required and optional environment variables, secure-by-default settings, and the knobs that matter for production.

Nolixan runs as a FastAPI backend (Postgres + optional Redis) and a Next.js frontend. You can run it locally with Docker Compose or deploy to your own cloud. This page is the configuration reference; everything is driven by environment variables read in app/config.py.

Required

In staging/production, the app fails to start if these are missing or insecure:

VariablePurpose
DATABASE_URLPostgreSQL async URL (postgresql+asyncpg://…)
SECRET_KEYJWT (HS256) signing key — boot fails if left as secret
NOLIXAN_ENCRYPTION_KEYAES-256 key for credential encryption (base64, 32 bytes)
FIREBASE_PROJECT_IDFirebase project for ID-token verification
ENVIRONMENTdevelopment | staging | production | test

Generate keys:

# encryption key (32 bytes, base64)
python -c "import os,base64; print(base64.b64encode(os.urandom(32)).decode())"
# receipt signing key (32-byte hex)
python -c "import secrets; print(secrets.token_hex(32))"

Governance & security

Secure-by-default — you mostly turn these off deliberately, not on:

VariableDefaultPurpose
RECEIPT_SIGNING_KEYunsetEd25519 seed for signed receipts. Unset → receipts are unsigned.
POLICY_DEFAULT_DENY_WRITEStrueFail-closed: deny write actions with no matching allow policy
POLICY_BACKENDdslPolicy engine: embedded dsl or remote opa (set OPA_URL, OPA_DECISION_PATH)
KEYSTORE_BACKENDsoftwareCredential key custody: software or kms (set KMS_KEY_ID)
WEBHOOK_REQUIRE_SIGNATUREtrueReject inbound webhooks without a valid signature
EGRESS_ALLOW_PRIVATE_HOSTSfalseSSRF guard. Allow private/loopback ranges only for on-prem internal targets.
DEFAULT_ACTION_COST_CENTS1Cost charged per action against spend budgets (0 disables)
AUTH_RATE_LIMIT_PER_MINUTE20Per-IP auth brute-force throttle

Infrastructure (optional, graceful degradation)

VariableDefaultPurpose
REDIS_URLunsetDistributed locking, pub/sub, and the ARQ worker. Unset → in-memory (single-pod only); required for multi-pod
STRIPE_SECRET_KEYunsetBilling. Unset → billing/rate-limit features degrade gracefully
MAILGUN_API_KEY / MAILGUN_DOMAINunsetEmail (invites, approval notifications). Unset → email skipped
STORAGE_BACKENDlocallocal or s3 (set S3_BUCKET, S3_REGION)
ALLOWED_ORIGINSlocalhostComma-separated CORS origins
NOLIXAN_CALLBACK_URLlocalhostOAuth callback URL
LOG_LEVEL / LOG_FORMATinfo / textUse json for log aggregation
SENTRY_DSN, OTEL_EXPORTER_OTLP_ENDPOINTunsetError tracking / OpenTelemetry export
DB_POOL_SIZE / DB_MAX_OVERFLOW5 / 10Connection pool tuning

Run it

# backend
cd src/backend
alembic upgrade head           # run migrations
uvicorn app.main:app --port 8000
 
# frontend
cd src/frontend
npm run build && npm start

Migrations run automatically on startup, and the app loads provider manifests, the action registry, and (if REDIS_URL is set) the background worker. For on-prem/regulated deployments, the combination of KEYSTORE_BACKEND=kms, POLICY_DEFAULT_DENY_WRITES=true, signed receipts, and self-hosting keeps sensitive data and execution inside your boundary.

On this page