Environment Variables
Configuration reference for self-hosting LinkForty Core. Set these in your .env file (or your platform's environment configuration). Only DATABASE_URL is strictly required; everything else has a sensible default or is optional.
Database
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL | Yes | — | PostgreSQL connection string: postgresql://user:password@host:5432/dbname. |
POSTGRES_DB | No | — | Database name (Docker Compose convenience; used to compose DATABASE_URL). |
POSTGRES_USER | No | — | Database user (Docker Compose). |
POSTGRES_PASSWORD | No | — | Database password (Docker Compose). |
POSTGRES_PORT | No | 5432 | Database port (Docker Compose). |
Caching (optional)
| Variable | Required | Default | Description |
|---|---|---|---|
REDIS_URL | No | — | Redis connection string for link caching (redis://host:6379). Omit to disable — Core falls back to direct database queries. |
REDIS_PORT | No | 6379 | Redis port (Docker Compose). |
Server
| Variable | Required | Default | Description |
|---|---|---|---|
NODE_ENV | No | development | Set to production in production (enables SSL behavior and hides internal error details). |
PORT | No | 3000 | Port the server listens on. |
HOST | No | 0.0.0.0 | Bind address. |
CORS_ORIGIN | No | * | Allowed CORS origin(s). Set to your frontend domain in production. |
SERVICE_DOMAIN | No | — | Custom domain used when generating short links. |
JWT_SECRET | No | — | Secret for signing JWTs (if you use Core's authentication). Generate with openssl rand -hex 32. |
Attribution behind a CDN or proxy
| Variable | Required | Default | Description |
|---|---|---|---|
TRUSTED_CLIENT_IP_HEADER | No | unset | Name of the header carrying the authoritative client IP, e.g. cf-connecting-ip. When unset, Core uses the connection IP (request.ip). |
When LinkForty runs behind a CDN or reverse proxy that terminates the connection (Cloudflare, Fastly, a load balancer), the connection IP Core sees is the edge or NAT hop, not the real visitor. Because fingerprint attribution keys on the client IP, this degrades match accuracy — clicks from many visitors collapse onto one proxy IP.
If your proxy injects an authoritative client-IP header, set TRUSTED_CLIENT_IP_HEADER to that header name so Core reads the real client IP instead. Common values:
# Cloudflare
TRUSTED_CLIENT_IP_HEADER=cf-connecting-ip
# Akamai / some CDNs
TRUSTED_CLIENT_IP_HEADER=true-client-ip
Comma-separated header values are handled automatically (Core takes the first entry), and IPv6-mapped IPv4 addresses are normalized.
Set this only when your origin is reachable exclusively through the proxy that sets the header. If clients can reach your server directly, they could spoof the header and forge their IP. When in doubt, leave it unset.
On LinkForty Cloud this is already configured (cf-connecting-ip). You only need this variable for self-hosted deployments behind a CDN.
Mobile app links
These power the .well-known files Core serves for iOS Universal Links and Android App Links. See iOS Universal Links and Android App Links for setup.
| Variable | Required | Default | Description |
|---|---|---|---|
IOS_TEAM_ID | No | — | Apple Developer Team ID. Required to serve apple-app-site-association. |
IOS_BUNDLE_ID | No | — | Your iOS app bundle identifier (e.g. com.yourcompany.yourapp). |
ANDROID_PACKAGE_NAME | No | — | Your Android package name. Required to serve assetlinks.json. |
ANDROID_SHA256_FINGERPRINTS | No | — | Comma-separated SHA-256 signing-certificate fingerprints. |
When the iOS pair is unset, GET /.well-known/apple-app-site-association returns a 404 with a configuration message. The same applies to the Android pair and assetlinks.json.
Example .env
# Database
DATABASE_URL=postgresql://linkforty:your-strong-password@localhost:5432/linkforty
# Caching (optional)
REDIS_URL=redis://localhost:6379
# Server
NODE_ENV=production
PORT=3000
HOST=0.0.0.0
CORS_ORIGIN=https://yourdomain.com
SERVICE_DOMAIN=yourdomain.com
# Attribution behind Cloudflare
TRUSTED_CLIENT_IP_HEADER=cf-connecting-ip
# iOS Universal Links
IOS_TEAM_ID=ABC123XYZ
IOS_BUNDLE_ID=com.yourcompany.yourapp
# Android App Links
ANDROID_PACKAGE_NAME=com.yourcompany.yourapp
ANDROID_SHA256_FINGERPRINTS=AA:BB:CC:DD:...
Related
- Self-Hosting Guide — full deployment walkthrough
- SDK Integration — Universal Links / App Links setup
- Attribution Windows — tune match windows