Configuration
Environment variables and server setup
Overview
LinkedRecords is configured primarily through environment variables. This guide covers all available configuration options. For a step-by-step deployment walkthrough, see Self-Hosting.
Quick Start
For local development, download the Docker Compose file from the repository and start the stack:
This starts PostgreSQL and LinkedRecords on port 6543 with a built-in mock OIDC
provider (AUTH_DEV_MODE). The test accounts alice@example.com,
bob@example.com, and charlie@example.com are available with one-click login.
The Docker Compose setup is for local development only. It includes a mock OIDC provider with test accounts and should not be used in production.
Server
| Variable | Description | Default |
|---|---|---|
PORT | Port the server listens on | 6543 |
SERVER_BASE_URL | Public URL of the LinkedRecords server | - |
FRONTEND_BASE_URL | URL of the frontend application (required; also used as CORS origin fallback and for OIDC redirects) | - |
HTTPS | Set to true to terminate TLS in the Node.js server itself | false |
SSL_KEY | PEM-encoded private key (required if HTTPS=true) | - |
SSL_CRT | PEM-encoded certificate (required if HTTPS=true) | - |
Most deployments terminate TLS at a reverse proxy or load balancer and leave
HTTPS unset.
Database Configuration
LinkedRecords uses PostgreSQL for data storage. The connection is configured with the standard PostgreSQL environment variables:
| Variable | Description | Default |
|---|---|---|
PGHOST | PostgreSQL host | localhost |
PGPORT | PostgreSQL port | 5432 |
PGUSER | Database user | - |
PGPASSWORD | Database password | - |
PGDATABASE | Database name | - |
The database schema is created automatically on server start; no separate migration step is needed.
For tests and quick experiments without a PostgreSQL server, an embedded PGlite database can be used instead:
| Variable | Description | Default |
|---|---|---|
USE_PGLITE | Set to true to use embedded PGlite instead of PostgreSQL | false |
PGLITE_DATA_DIR | Data directory for PGlite (setting this also enables PGlite) | in-memory |
Authentication (OIDC)
LinkedRecords supports any OpenID Connect compliant identity provider (Auth0, Okta, Keycloak, ...):
| Variable | Description | Required |
|---|---|---|
AUTH_ISSUER_BASE_URL | OIDC provider URL | Yes |
AUTH_CLIENT_ID | OAuth client ID | Yes |
AUTH_CLIENT_SECRET | OAuth client secret | Confidential client mode |
AUTH_COOKIE_SIGNING_SECRET | Secret for signing session cookies | Confidential client mode |
AUTH_TOKEN_AUDIENCE | Expected aud claim of bearer tokens | Public client mode |
ALLOW_HTTP_AUTHENTICATION_HEADER | Set to true to accept bearer tokens via the Authorization header | Public client mode |
AUTH_IDP_LOGOUT | Set to true to also destroy the session at the identity provider on logout | No |
AUTH_DEV_MODE | Set to true to mount a built-in mock OIDC provider at /dev-oidc with one-click test accounts. Development only. | No |
Confidential Client Mode
For same-domain setups where the frontend and backend share a domain, the session is kept in an HttpOnly cookie:
Public Client Mode
For cross-domain setups (SPA on a different domain than the API), the SPA stores the access token and sends it as a bearer token:
CORS Configuration
For cross-domain access, configure allowed origins. If CORS_ORIGIN is not
set, FRONTEND_BASE_URL is used.
| Variable | Description | Default |
|---|---|---|
CORS_ORIGIN | Allowed origin as a single URL string or JSON array of URLs | value of FRONTEND_BASE_URL |
Redis Configuration (Optional)
Redis is not required for a single-instance deployment. Configure it when running multiple LinkedRecords instances behind a load balancer, so real-time updates reach clients connected to other instances (Socket.IO Redis Streams adapter):
| Variable | Description | Default |
|---|---|---|
REDIS_HOST | Redis host; setting this enables the Redis adapter | - |
REDIS_USERNAME | Redis username | - |
REDIS_PASSWORD | Redis password | - |
S3/MinIO Configuration (Optional)
For blob storage, configure S3-compatible object storage:
| Variable | Description | Default |
|---|---|---|
S3_ENDPOINT | S3-compatible endpoint hostname | - |
S3_PORT | Endpoint port | - |
S3_BUCKET | Bucket name (must already exist) | - |
S3_ACCESS_KEY | Access key ID | - |
S3_SECRET_KEY | Secret access key | - |
S3_USE_SSL | Use TLS when talking to the endpoint (true/false) | true |
S3_COPY_FROM_BL_ATTRIBUTE_TABLE | One-time migration: copy existing blobs from PostgreSQL to S3 on startup | false |
If S3 is not configured, blob values are stored in PostgreSQL (with reduced performance for large files). Configuring S3 is recommended.
Quota Configuration
Control storage limits per accountable user or organization:
| Variable | Description | Default |
|---|---|---|
DEFAULT_STORAGE_SIZE_QUOTA | Default storage quota in MB | 500 |
QUOTA_COUNT_KV_RECORDS | Set to true to count key-value record storage against the accountee's quota | false |
QUOTA_COUNT_LT_RECORDS | Set to true to count long-text record storage against the accountee's quota | false |
Blob storage always counts against the quota. See Quotas for how quota accounting works.
Payment Integration (Optional)
For paid quota upgrades with Paddle:
| Variable | Description |
|---|---|
PADDLE_API_KEY | Paddle API key |
PADDLE_API_URL | Paddle API URL (e.g. https://sandbox-api.paddle.com for testing) |
PADDLE_NOTIFICATION_SECRET | Webhook signing secret used to verify /payment_events notifications |
Performance Tuning
| Variable | Description | Default |
|---|---|---|
ENABLE_AUTH_RULE_CACHE | Set to true to cache authorization lookups in memory. Can require a lot of memory. | false |
SHORT_LIVED_ACCESS_TOKEN_SIGNING | A signing secret. When set, short-lived signed read tokens are issued with query results and used to authorize real-time subscriptions, reducing database load. | not set |
Complete Example Configuration
Development
The simplest way to get these is docker compose up (see Quick Start above).
Equivalent manual configuration:
Production
OIDC Provider Setup
Auth0
- Create an Application (Regular Web Application for confidential, SPA for public)
- Configure Allowed Callback URLs:
https://your-backend.com/callback - Configure Allowed Logout URLs:
https://your-app.com - Configure Allowed Web Origins:
https://your-app.com - Get the Client ID and Client Secret
Other Providers
LinkedRecords works with any standard OIDC provider:
- Okta: Use the OIDC metadata URL
- Keycloak: Configure a client with appropriate scopes
- Google: Create OAuth 2.0 credentials
Health Check
There is no dedicated health endpoint. GET /oidc/discovery is served without
authentication and is suitable as a liveness probe:
Logging
LinkedRecords logs structured JSON to stdout using pino. Request and response headers are redacted. Use your platform's log collector to ship and filter the output.