# ============================================================================== # Epicnextcms — Ultimate Speed & Low-Latency Example Configuration # ============================================================================== # --- DATABASE (High Performance Pooling & Strict Timeouts) --- DATABASE_URL="mysql://user:password@localhost:3306/dbname?charset=utf8mb4&connection_limit=150&connect_timeout=5" DATABASE_POOL_SIZE=150 DATABASE_IDLE_TIMEOUT_MS=60000 DATABASE_CONNECT_TIMEOUT_MS=5000 # --- REDIS (Lightning Fast Caching & Sessions) --- REDIS_URL=redis://127.0.0.1:6379?connect_timeout=2 REDIS_CACHE_TTL_DEFAULT=7200 # In-process cache entries kept per instance, evicted least-recently-used. Raise # it if hot keys are evicted while memory headroom remains (default 2000). CACHE_MEMORY_MAX_ENTRIES=2000 # Renders kept per imaging cache directory, counted as .img/.json pairs. A sweep # every 5 minutes brings an over-budget directory back to 90% of this (default 20000). IMAGING_CACHE_MAX_ENTRIES=20000 # --- CORE RUNTIME & PERFORMANCE FLAGS --- NODE_ENV=production PORT=3002 NEXT_TELEMETRY_DISABLED=1 UV_THREADPOOL_SIZE=16 # Production requires this kill switch plus housekeeping.preview.access. HOUSEKEEPING_NEXT_PREVIEW_ENABLED=false # --- HOTEL & URLS --- HOTEL_NAME=EPIC WEB CONTROL APP_URL=http://localhost:3002 AUTH_URL=http://localhost:3002 # --- IMAGER --- # Avatar imager: Polaris-imager (avatar-imaging-pixinode) serves /avatarimage on 8082. IMAGING_UPSTREAM_URL=http://127.0.0.1:8082/avatarimage # Runtime values: changing these only requires recreating the container. IMAGER_URL=http://127.0.0.1:8082/avatarimage BADGE_URL=/swf/c_images/album1584 # Legacy NEXT_PUBLIC_IMAGER_URL / NEXT_PUBLIC_BADGE_URL are still read at runtime. # --- SECURITY & HASHING --- AUTH_SECRET=your-super-secret-auth-key-change-this-min-32-chars APP_KEY=base64:your-app-key-here= # Bcrypt cost factor for new password hashes. BCRYPT_COST=12 # --- ANTI-DDOS (app-layer gate, production only) --- # On by default in production. Set to "false" to disable (not recommended). ANTI_DDOS_ENABLED=true # Per-category request thresholds over the given window (per client IP). ANTI_DDOS_PAGES_LIMIT=300 ANTI_DDOS_PAGES_WINDOW_SEC=60 ANTI_DDOS_API_LIMIT=600 ANTI_DDOS_API_WINDOW_SEC=60 ANTI_DDOS_AUTH_LIMIT=20 ANTI_DDOS_AUTH_WINDOW_SEC=60 # Whole-site safety valve per window (sheds everything for global_halt_ms when hit). ANTI_DDOS_GLOBAL_LIMIT=18000 ANTI_DDOS_GLOBAL_WINDOW_SEC=60 ANTI_DDOS_GLOBAL_HALT_MS=10000 # Violations accumulate inside this window before an IP is hard-blocked. ANTI_DDOS_VIOLATION_WINDOW_SEC=600 ANTI_DDOS_MAX_VIOLATIONS=10 # Escalation tiers "minViolations:ttlSeconds" — how long an offender stays blocked. ANTI_DDOS_BLOCK_TIERS=5:600,20:3600,50:86400 # --- CLOUDFLARE API (automatic edge blocks, optional) --- # When set, the anti-DDoS gate automatically mirrors hard-blocked IPs to the # zone's IP Access Rules so repeat offenders are dropped at the Cloudflare # edge (works on every plan, incl. Free). Token permissions required: # Zone > Zone > Read and Zone > Firewall > Edit CLOUDFLARE_API_TOKEN= CLOUDFLARE_ZONE_ID= # Runtime toggle; leave true to auto-create Cloudflare blocks at the block # threshold. Also overridable live from the admin panel. CLOUDFLARE_AUTO_BLOCK_ENABLED=true # Override for tests/staging (production uses the public endpoint by default). CLOUDFLARE_API_BASE_URL=https://api.cloudflare.com/client/v4 # --- CROWDSEC API (community reputation auto-block, optional) --- # Free CTI API key: https://app.crowdsec.net/ → Settings → CTI API Keys. # When set, the anti-DDoS gate checks the community reputation of repeat # offenders (CTI GET /smoke/{ip}) and immediately hard-blocks known-bad IPs. # Lookups only happen for IPs that already tripped a rate bucket and are # cached in Redis for 1h, so quota usage stays minimal. CROWDSEC_API_KEY= # Runtime toggle for reputation-based auto-blocking (also overridable live # from the admin panel). Requires CROWDSEC_API_KEY. CROWDSEC_AUTO_BLOCK_ENABLED=true # Minimum malevolence score 0-5 (CrowdSec scale; 4-5 = "malicious") before an # IP is treated as known-bad. IPs with false-positive tags are never blocked. CROWDSEC_BLOCK_SCORE=4 # How long a CrowdSec-confirmed bad IP stays blocked (seconds). CROWDSEC_BLOCK_TTL_SECONDS=86400 # Endpoint — override only for tests/staging. CROWDSEC_CTI_BASE_URL=https://cti.api.crowdsec.net/v2 # Daily enrichment-call ceiling (freemium plan ≈ 10k/day). Once today's # counter reaches it, reputation lookups pause until tomorrow so a spread # DDoS cannot silently burn the whole quota. 0 = unlimited. CROWDSEC_CTI_DAILY_QUOTA=10000 # How many new community-reputation blocks within a 5-minute window justify an # ops alert (quota/backoff/report alerts all use HEALTH_ALERT_COOLDOWN_MIN). CROWDSEC_ALERT_BLOCK_BURST=10 # --- CROWDSEC SIGNAL PUSH (share our blocks back, optional) --- # Opt-in: pushes blocked IPs + behaviors to the CrowdSec Central API (CAPI) so # the community blocklist protects other members too. Set to "true" to enable. # Requires watcher credentials — either set both CROWDSEC_REPORT_MACHINE_ID # (48 chars, [A-Za-z0-9]) and CROWDSEC_REPORT_PASSWORD now, or leave them # unset and let the app generate a stable pair persisted in Redis automatically. CROWDSEC_REPORT_ENABLED=false CROWDSEC_REPORT_MACHINE_ID= CROWDSEC_REPORT_PASSWORD= # Optional: attachment key from https://app.crowdsec.net → Console settings — # links our watcher to your account so pushed signals show up there. CROWDSEC_REPORT_ENROLL_KEY= # Central API base — override only for tests/staging. CROWDSEC_CAPI_BASE_URL=https://api.crowdsec.net/v3 # --- CROWDSEC LOCAL (opt-in engine on this Docker host, no proxy changes) --- # App-layer LAPI bouncer: the anti-DDoS gate asks the local engine per client # IP (short-cached) and blocks ban/captcha decisions before its own buckets. # Start everything with `bash cms security`; it writes the key below into .env # and starts the CrowdSec engine bound to 127.0.0.1. Set to "true" to load the # bouncer without the local engine (not recommended). CROWDSEC_LOCAL_ENABLED=false # Host access-log directory mounted into the engine for detection (Nginx only). CROWDSEC_NGINX_LOG_DIR=/var/log/nginx # Change LAPI port AND LAPI URL together when 18080 is already taken. CROWDSEC_LAPI_PORT=18080 CROWDSEC_LAPI_URL=http://127.0.0.1:18080 # Generated by `bash cms security`; keep in .env, never commit a value. CROWDSEC_LAPI_API_KEY= # IP blocklist sync (`bash cms security blocklists`): space-separated URLs, by # default Spamhaus DROP/EDROP, DShield, CINS, Greensnow, StopForumSpam, # blocklist.de, Emerging Threats, abuse.ch Feodo/SSLBL/URLhaus, IPsum, # Firehol ipsets and Tor exit nodes. Requires internet to fetch; detection and # blocking stay local. #CROWDSEC_BLOCKLIST_SOURCES=https://www.spamhaus.org/drop/drop.txt https://example.org/list.txt # Expiration for each blocklist decision (re-synced keeps them fresh). #CROWDSEC_BLOCKLIST_DURATION=24h # Combined cap per sync (safety valve against excessive decisions). #CROWDSEC_BLOCKLIST_MAX_DECISIONS=1000000 # Comma-separated IPs/CIDRs that a sync must always skip (allowlist). #CROWDSEC_BLOCKLIST_ALLOW=1.2.3.4,10.0.0.0/8 # --- PATHS --- BADGE_UPLOAD_DIR=./public/assets/images/badges EMULATOR_JAR_PATH=./emulator/Arcturus.jar EMULATOR_BACKUP_DIR=./backups/emulator EMULATOR_BACKUP_KEEP=7 # Optional mysqldump (jobs-worker daily 03:30). Requires mysqldump on PATH. DB_BACKUP_DIR= DB_BACKUP_KEEP=7 # Minutes between repeat health-fail alerts from jobs-worker (default 15). HEALTH_ALERT_COOLDOWN_MIN=15 # --- RCON (Low Latency Loop) --- RCON_HOST=127.0.0.1 RCON_PORT=3003 EMU_PORT=3004 RCON_TIMEOUT_MS=2000 # --- EMAIL & NOTIFICATIONS --- SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_FROM=no-reply@epicwebcontrol.local # --- ALERTING & MONITORING --- DISCORD_WEBHOOK_URL= ALERT_EMAIL= # --- MODERATION & PAYMENTS --- OPENAI_API_KEY= PAYPAL_CLIENT_ID= PAYPAL_SECRET= PAYPAL_API=https://api-m.sandbox.paypal.com # --- LOGGING --- LOG_LEVEL=error # --- BYPARR (Cloudflare bypass for clone sources) --- BYPARR_URL=http://localhost:8191 # Catalog Studio export: dedicated clean clone on Beta-3 with Git push credentials. CATALOG_GIT_CHECKOUT= # Persistent directory shared by CMS and worker, outside the catalog clone. CATALOG_GIT_STATE_DIR=