TREK Security Hardening Guide: Production Deployment Options
To secure a production TREK deployment, generate a 256-bit ENCRYPTION_KEY, terminate TLS behind a reverse proxy with FORCE_HTTPS=true, enable two-factor authentication for admin accounts, and verify that TRUST_PROXY is configured to prevent IP spoofing attacks.
TREK is a self-hosted travel-planning platform that requires explicit security configuration when exposed to production workloads. The following hardening options cover data encryption, network transport, authentication controls, and session management as documented in the official wiki/Security-Hardening.md and implemented in src/config/config.schema.ts.
Data Encryption and Secrets Management
Generate and Protect the ENCRYPTION_KEY
TREK uses a 256-bit encryption key to protect API credentials and sensitive data at rest. Generate a secure key using OpenSSL and provide it via the ENCRYPTION_KEY environment variable:
openssl rand -hex 32
On first startup, TREK stores this key in data/.encryption_key. Back up this file separately from your database backups—losing the key renders all encrypted secrets permanently unreadable. Never commit the key to version control or include it in automated database dumps.
Rotate Keys After Exposure
If the encryption key is compromised, follow the procedure documented in wiki/Encryption-Key-Rotation.md to rotate the key without losing existing encrypted data. This process decrypts existing data with the old key and re-encrypts it with the new key atomically.
HTTPS and Reverse Proxy Configuration
Terminate TLS at the Edge
TREK expects TLS termination to occur at a reverse proxy (nginx, Caddy, or Traefik). The proxy must forward the original protocol via the X-Forwarded-Proto header so TREK can enforce secure redirects.
Force HTTPS and Trust Proxy Settings
Set FORCE_HTTPS=true to enable three critical security features:
- 301 redirects from HTTP to HTTPS
- HSTS header with
max-age=31536000 - Secure cookie flag automatically applied to the
trek_sessioncookie
Configure TRUST_PROXY=1 (or the appropriate hop count) so Express.js reads the real client IP from X-Forwarded-For. This prevents attackers from bypassing rate limits by spoofing headers and avoids redirect loops behind load balancers.
Nginx Configuration Example
Configure your reverse proxy to handle WebSocket upgrades and large file uploads for backup restoration:
server {
listen 443 ssl http2;
server_name trek.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location /ws {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
client_max_body_size 500m;
}
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 500m;
}
}
Source: wiki/Reverse-Proxy.md
Authentication and Access Controls
Enable Two-Factor Authentication
Navigate to Admin → Settings → Two-Factor Authentication to enable TOTP-based 2FA for the admin account. Once enabled, all administrative actions require a time-based code from an authenticator app, preventing credential-stuffing attacks even if the password is compromised.
Rotate JWT Secrets on Demand
If session tokens are suspected of being compromised, invalidate all active sessions immediately by rotating the JWT signing secret:
curl -X POST http://localhost:3000/api/admin/rotate-jwt-secret \
-H "Authorization: Bearer <admin-jwt>"
This endpoint is documented in wiki/Security-Hardening.md and forces all users to re-authenticate.
Disable Open Registration
Unless intentionally running a public instance, disable open registration in the admin panel to prevent uncontrolled account creation. Restrict registration to invite-only or manual admin creation.
Session and Password Security
Secure Cookie Configuration
TREK stores sessions as JWTs in an httpOnly cookie named trek_session. The secure flag is automatically set when NODE_ENV=production or FORCE_HTTPS=true. Never set COOKIE_SECURE=false in production—this flag exists only for temporary LAN testing without TLS.
Session duration defaults to 24 hours for standard logins and 30 days for "Remember Me" sessions, configurable via SESSION_DURATION and SESSION_DURATION_REMEMBER.
Password Policy Enforcement
TREK enforces a strict password policy requiring minimum 8 characters with mixed case, digits, and special characters. Common passwords and repetitive strings are rejected at the API level. Passwords are hashed using bcrypt with a cost factor of 12, providing robust protection against brute-force attacks without additional configuration.
Network Security and Rate Limiting
Built-In Rate Limiting
TREK implements in-memory rate limiting on authentication endpoints. Default limits per source IP are:
- Login / Register / Invite: 10 attempts per 15 minutes
- MFA verification / enable: 5 attempts per 15 minutes
- Password change: 5 attempts per 15 minutes
- MCP token creation: 5 attempts per 15 minutes
Accurate rate limiting requires TRUST_PROXY to be set correctly so TREK identifies the true client IP rather than the proxy's internal address.
Content Security Policy Headers
Helmet.js enforces a strict CSP that mitigates XSS and data injection attacks:
default-src 'self'script-src 'self' 'wasm-unsafe-eval'(nounsafe-inline)object-src 'none'frame-src 'none'frame-ancestors 'self'
When FORCE_HTTPS=true, the upgrade-insecure-requests directive is automatically injected to force mixed-content upgrades.
Backup and Monitoring Strategies
Encrypted Backup Procedures
Enable automatic backups via the admin panel and store them off-site. Backup archives contain the encrypted data/.encryption_key file, but you must maintain a separate backup of the key itself. Without the key, database backups containing encrypted API credentials are useless.
Audit Logging and Updates
Review the Audit Log (documented in wiki/Audit-Log.md) periodically for unexpected admin actions or logins from unusual IPs. Subscribe to the GitHub releases feed to apply security updates promptly, as TREK does not auto-update.
Production Environment Variables
Configure these variables for a hardened deployment:
| Variable | Production Value |
|---|---|
ENCRYPTION_KEY |
64-character hex string (256-bit) |
FORCE_HTTPS |
true |
TRUST_PROXY |
1 (or proxy hop count) |
ALLOWED_ORIGINS |
https://trek.example.com |
ALLOW_INTERNAL_NETWORK |
false |
SESSION_DURATION |
24h |
SESSION_DURATION_REMEMBER |
30d |
Source: wiki/Environment-Variables.md
Docker Compose Example
version: "3.8"
services:
trek:
image: ghcr.io/mauriceboe/trek:latest
restart: unless-stopped
environment:
- NODE_ENV=production
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
- FORCE_HTTPS=true
- TRUST_PROXY=1
- ALLOWED_ORIGINS=https://trek.example.com
- SESSION_DURATION=24h
- SESSION_DURATION_REMEMBER=30d
ports:
- "3000:3000"
volumes:
- trek-data:/app/data
volumes:
trek-data:
Summary
- Generate a 256-bit
ENCRYPTION_KEYusingopenssl rand -hex 32and back it up separately from database backups - Terminate TLS at a reverse proxy and set
FORCE_HTTPS=trueto enable HSTS and secure cookies - Configure
TRUST_PROXYto ensure rate limiting and logging see the actual client IP - Enable two-factor authentication for admin accounts and disable open registration unless required
- Monitor the audit log and rotate JWT secrets immediately if session compromise is suspected
- Use the provided nginx configuration to properly handle WebSocket upgrades and large file uploads
Frequently Asked Questions
How do I rotate the encryption key if it was exposed?
Follow the procedure in wiki/Encryption-Key-Rotation.md to perform an atomic rotation that preserves existing encrypted data. The process decrypts all secrets with the old key and re-encrypts them with the new key without service interruption. After rotation, verify that data/.encryption_key contains the new value and update your offline backups immediately.
What reverse proxy settings are required for WebSocket support?
Configure your proxy to upgrade connections for the /ws endpoint by setting proxy_http_version 1.1 and forwarding the Upgrade and Connection headers. Set client_max_body_size to at least 500m to accommodate backup restore uploads. Always forward X-Forwarded-Proto so TREK can detect HTTPS correctly.
How do I invalidate all active user sessions immediately?
Send a POST request to /api/admin/rotate-jwt-secret with an admin JWT in the Authorization header. This invalidates all existing session tokens instantly, forcing every user to re-authenticate. This is the recommended response to suspected session hijacking or credential leaks.
Is TREK's built-in rate limiting sufficient for production?
The built-in memory-based rate limiting (10 attempts per 15 minutes for login, 5 for MFA) is sufficient for single-instance deployments. However, if running multiple TREK instances behind a load balancer, you must implement rate limiting at the reverse proxy or load balancer level, as the in-memory store does not share state between nodes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →