Configuration Reference
Environment Variables
| Variable | Type | Default | Required | Description |
|---|---|---|---|---|
PORT | number | 4100 | No | HTTP server listen port |
HOST | string | 127.0.0.1 | No | HTTP server bind address (self-hosted only) |
APP_ORIGIN | string | — | No | Admin dashboard CORS origin(s), comma-separated |
API_BASE_URL | string | — | No | Canonical public URL of the Kyqu API for email action links |
DATABASE_URL | string | "" | Yes | PostgreSQL connection string |
DATABASE_MAX_CONNECTIONS | number | 10 | No | PostgreSQL pool size |
SESSION_TTL_DAYS | number | 30 | No | Admin session TTL |
NODE_ENV | string | "development" | No | development or production |
SECURE_COOKIES | boolean | false (dev) / true (prod) | No | Mark cookies Secure |
RATE_LIMIT_WINDOW_MS | number | 60000 | No | Rate-limit window (ms) |
RATE_LIMIT_MAX | number | 120 | No | Max requests per window |
RATE_LIMIT_STORE | string | "memory" (dev) / "postgres" (prod) | No | memory or postgres |
TRUSTED_PROXY | boolean | false (dev) / true (prod) | No | Trust X-Forwarded-For / X-Forwarded-Proto for client IP and email link base URL |
ADMIN_REGISTRATION_OPEN | boolean | true (dev) / false (prod) | No | Allow new admin signups |
EMAIL_DELIVERY_MODE | string | "outbox" (dev) / "smtp" (prod) | No | smtp or outbox |
EMAIL_FROM | string | "Kyqu <noreply@example.com>" | No | Sender address |
SMTP_HOST | string | "" | If SMTP | SMTP server hostname |
SMTP_PORT | number | 587 | No | SMTP server port |
SMTP_SECURE | boolean | false | No | Use TLS for SMTP |
SMTP_USER | string | "" | If SMTP auth | SMTP username |
SMTP_PASS | string | "" | If SMTP auth | SMTP password |
MONITORING_WEBHOOK_URL | string | "" | No | External alert webhook URL |
ENCRYPTION_KEY | string | "" | Yes | 64-char hex key for AES-256-GCM at-rest encryption. Generate: openssl rand -hex 32 |
AUTH_RATE_LIMIT_WINDOW_MS | number | 900000 (15 min) | No | Stricter rate-limit window for credential endpoints |
AUTH_RATE_LIMIT_MAX | number | 10 | No | Max requests per auth window |
Project Auth Settings
These settings are configurable per project via the admin dashboard or API:
| Setting | Type | Default | Description |
|---|---|---|---|
authEnabled | boolean | true | Master auth toggle |
emailPasswordEnabled | boolean | true | Email/password auth |
emailVerificationRequired | boolean | false | Require email verification |
passwordResetEnabled | boolean | true | Password reset flow |
magicLinkEnabled | boolean | false | Magic link auth |
twoFactorEnabled | boolean | false | TOTP 2FA |
allowedOrigins | string[] | [] | CORS origins (empty = unrestricted) |
blocklistedDomains | string[] | [] | Rejected email domains |
whitelistedDomains | string[] | [] | Exclusively allowed email domains |
blocklistedUsernames | string[] | [] | Rejected usernames/emails |
sessionTtlDays | number | 30 | Project user session TTL |
passwordMinLength | number | 10 | Minimum password length |
lockoutEnabled | boolean | true | Account lockout on failed attempts |
lockoutMaxAttempts | number | 5 | Failed attempts before lock |
lockoutWindowMinutes | number | 15 | Lockout window duration |
loginUrl | string | "" | Post-magic-link redirect URL (receives ?session_code=… on browser confirm) |
emailVerifiedUrl | string | "" | Post-verification redirect URL |
passwordResetUrl | string | "" | Password reset form URL |
Rate Limit Route Families
| Route Family | Path Pattern | Rate Limit Bucket |
|---|---|---|
admin-login | /api/admin/login | Separate from other routes |
admin-signup | /api/admin/signup | Separate from other routes |
project-login | /api/projects/*/auth/login | Separate from other routes |
project-signup | /api/projects/*/auth/signup | Separate from other routes |
password-reset | /api/projects/*/auth/password-reset/* | Separate from other routes |
magic-link | /api/projects/*/auth/magic-link/* | Separate from other routes |
api | Everything else | Catch-all bucket |
HTTP Response Headers
| Header | Value | Applied |
|---|---|---|
Access-Control-Allow-Origin | Echoed request origin (never * with credentials) | All requests |
Access-Control-Allow-Credentials | true | All requests |
Access-Control-Allow-Headers | Content-Type, Authorization, x-kyqu-public-key, x-kyqu-csrf-token | All requests |
Access-Control-Allow-Methods | GET, POST, PATCH, DELETE, OPTIONS | All requests |
X-Content-Type-Options | nosniff | All requests |
Referrer-Policy | no-referrer | All requests |
X-Frame-Options | DENY | All requests |
Permissions-Policy | camera=(), microphone=(), geolocation=() | All requests |
Cache-Control | no-store | All requests |
Strict-Transport-Security | max-age=31536000; includeSubDomains | Production only |
RateLimit-Limit | Max requests per window | All requests |
RateLimit-Remaining | Remaining requests | All requests |
RateLimit-Reset | Seconds until reset | All requests |
X-Request-Id | UUID | All requests |