Quick Start
Get coreX Platform running in minutes with Docker Compose. This guide covers deployment, first login, and your first config apply.
Prerequisites
- A Linux host with Docker and the Docker Compose plugin installed
- Ports 80, 443, 3000, 8000, and 8404 available (configurable)
1. Clone the Repository
git clone https://github.com/ne4u/corex_manager.git
cd corex_manager
Copy the example environment file and edit it:
cp .env.example .env
The .env.example file documents every configurable variable with inline comments. The tables below group them by category. At minimum, set the secrets marked required before starting the stack in production.
Generate strong secrets
Generate random values for SECRET_KEY, MCP_SECRETS_KEY, VECTOR_SECRETS_KEY, RESP_TRANSFORM_KEY, and the MCP tokens with:
python -c “import secrets; print(secrets.token_urlsafe(32))”
Core
| Variable | Default | Description |
|---|
DATABASE_URL | sqlite:///data/haproxy_manager.db | SQLAlchemy database URL. Use PostgreSQL for HA/production. |
HAPROXY_CONFIG_PATH | /app/data/haproxy.cfg | Path where the generated HAProxy config is written. |
HAPROXY_SOCKET_PATH | /var/run/haproxy.sock | HAProxy stats socket used by the control plane. |
CERT_DIR | /app/certs | Directory holding TLS certificates. |
DATA_DIR | ./data | Base directory for persistent data bind mounts (haproxy config, postgres, valkey, varnish). |
SECRET_KEY | (random) | Required for production. JWT signing key. |
ADMIN_PASSWORD | (random) | Admin user password. Generated and logged on first start if unset. |
LOG_LEVEL | INFO | Backend log level. |
Valkey (Redis-compatible cache/store)
| Variable | Default | Description |
|---|
VALKEY_HOST | valkey | Valkey hostname. |
VALKEY_PORT | 6379 | Valkey port. |
VALKEY_DB | 0 | Valkey database index. |
VALKEY_PASSWORD | (empty) | Set a strong password to require auth on the Valkey network. |
Rate Limiting & Tasks
| Variable | Default | Description |
|---|
RATE_LIMIT_REQUESTS | 100 | Max requests per window per identity. |
RATE_LIMIT_WINDOW | 60 | Rate limit window in seconds. |
TASK_QUEUE_ENABLED | true | Enable the Valkey-backed async task queue. |
Certificates
| Variable | Default | Description |
|---|
AUTO_RENEW_ENABLED | true | Enable automatic certificate renewal. |
AUTO_RENEW_INTERVAL_SECONDS | 86400 | Renewal check interval (24h). |
Coraza SPOA WAF
| Variable | Default | Description |
|---|
CORAZA_SPOA_ENABLED | true | Enable the Coraza WAF SPOA. |
CORAZA_SPOA_HOST | coraza-spoa | Coraza SPOA hostname. |
CORAZA_SPOA_PORT | 9000 | Coraza SPOA port. |
CORAZA_SPOA_TARGETS | coraza-spoa:9000 | SPOA targets passed to HAProxy. |
CORAZA_SPOA_APP | haproxy-waf | SPOA application name. |
CORAZA_SPOA_CONFIG_PATH | data/coraza-spoa.yaml | Coraza SPOA config file. |
CORAZA_SPOA_AUTO_RESTART | true | Auto-restart the SPOA on failure. |
CORAZA_SPOE_CONFIG_PATH | data/coraza.cfg | HAProxy SPOE config file. |
CORAZA_SPOA_LOG_PATH | data/coraza-spoa.log | Coraza JSON event log path. |
WAF_RULE_VERSION_MAX_PER_RULE | 10 | Max WAF rule snapshots kept per rule (0 = unlimited). |
CRS_DIR | data/crs | OWASP CRS directory. |
CRS_SNAPSHOT_MAX | 5 | Max CRS snapshots retained. |
CUSTOM_RULES_DIR | data/custom-rules | Custom WAF rules directory. |
RULE_SET_DOWNLOAD_INTERVAL_SECONDS | 300 | Remote rule set download interval. |
CAPTCHA
| Variable | Default | Description |
|---|
CAPTCHA_SERVICE_URL | http://cap:3000 | Cap CAPTCHA service URL (Native provider). |
CAPTCHA_SERVICE_PUBLIC_URL | http://localhost:3001 | Legacy public URL (kept for backward compatibility). |
CAPTCHA_CHALLENGE_URL | /_cap/challenge | Challenge URL path on the HAProxy listener. |
CAPTCHA_SITE_KEY | (empty) | Cap site key. |
CAPTCHA_SECRET | (empty) | Cap secret. |
CAPTCHA_PROXY_PATH | /_cap | Path prefix for proxying captcha traffic through HAProxy. |
CAPTCHA_WIDGET_CDN_URL | https://cdn.jsdelivr.net/npm/@cap.js/widget@0.1.57/cap.min.js | CDN URL for the Cap widget script. |
CAPTCHA_API_BACKEND_HOST | api | Backend API host for challenge/verify proxy. |
CAPTCHA_API_BACKEND_PORT | 8000 | Backend API port for challenge/verify proxy. |
CAP_ADMIN_KEY | (empty) | Required if Cap service is enabled. Strong random key. |
RECAPTCHA_SITE_KEY | (empty) | reCAPTCHA (Google) site key. |
RECAPTCHA_SECRET | (empty) | reCAPTCHA secret. |
RECAPTCHA_VERSION | v2 | reCAPTCHA version. |
RECAPTCHA_MIN_SCORE | 0.5 | reCAPTCHA v3 minimum score. |
TURNSTILE_SITE_KEY | (empty) | Cloudflare Turnstile site key. |
TURNSTILE_SECRET | (empty) | Cloudflare Turnstile secret. |
MaxMind GeoIP
| Variable | Default | Description |
|---|
MAXMIND_LICENSE_KEY | (empty) | MaxMind license key for GeoIP DB downloads. |
GEOIP_DOWNLOAD_INTERVAL_HOURS | 24 | GeoIP DB refresh interval. |
GEOIP_DB_PATH | data/GeoLite2-Country.mmdb | GeoIP Country DB path. |
ASN_DB_PATH | data/GeoLite2-ASN.mmdb | GeoIP ASN DB path. |
Security Lists & Rules
| Variable | Default | Description |
|---|
SECURITY_LISTS_DIR | data/lists | Security list files directory. |
SECURITY_LISTS_FEED_POLL_INTERVAL_SECONDS | 300 | Dynamic feed poll interval. |
SECURITY_RULES_BLOCK_STATUS | 403 | HTTP status returned by block rules. |
Audit
| Variable | Default | Description |
|---|
AUDIT_PAYLOAD_MAX_BYTES | 16384 | Max bytes captured per audit payload. |
Metrics
| Variable | Default | Description |
|---|
HAPROXY_MASTER_SOCKET_PATH | /var/run/haproxy-master.sock | HAProxy master socket path. |
HAPROXY_MAXCONN | 100000 | Max HAProxy connections. Lower if memory is limited. |
METRICS_SAMPLE_INTERVAL_SECONDS | 30 | HAProxy metrics sample interval. |
METRICS_RETENTION_DAYS | 7 | HAProxy metrics retention. |
WAF_METRICS_SAMPLE_INTERVAL_SECONDS | 10 | WAF metrics sample interval. |
WAF_METRICS_RETENTION_DAYS | 7 | WAF metrics retention. |
WAF_LOG_RETENTION_LINES | 500 | Max raw coraza-spoa.log lines kept (0 = unlimited). |
Caching
| Variable | Default | Description |
|---|
DISK_CACHE_ENABLED | false | Enable Varnish disk cache sidecar. |
CACHE_METRICS_SAMPLE_INTERVAL_SECONDS | 30 | Cache metrics sample interval. |
CACHE_METRICS_RETENTION_DAYS | 7 | Cache metrics retention. |
VARNISH_CONTAINER_NAME | varnish | Varnish container name. |
VARNISH_PORT | 6081 | Varnish port. |
VARNISH_VCL_PATH | data/varnish/default.vcl | Varnish VCL config path. |
VARNISH_STORAGE_SIZE | 1G | Varnish storage size. |
HAPROXY_CONTAINER_NAME | corex | HAProxy container name (used by Docker SDK). |
Vector Log Pipeline
| Variable | Default | Description |
|---|
VECTOR_IMAGE | timberio/vector:0.58.0-alpine | Vector container image. |
VECTOR_SYSLOG_TARGET | vector:601 | HAProxy coreX log stream target. |
VECTOR_SECRETS_KEY | (falls back to SECRET_KEY) | Encryption key for sink credentials. |
| Variable | Default | Description |
|---|
RESP_TRANSFORM_ENABLED | false | Enable the response transform Rust Lua module. |
RESP_TRANSFORM_DIR | data/resp-transform | Response transform module directory. |
RESP_TRANSFORM_RELOAD_INTERVAL_SECONDS | 30 | Module reload check interval. |
RESP_TRANSFORM_FALLBACK_KEY_ENV | RESP_TRANSFORM_KEY | Env var name for tokenize-mode fallback AES key. |
RESP_TRANSFORM_KEY | (empty) | AES-256 key (≥32 bytes) for encrypt-mode and tokenize fallback. |
CORS & Session
| Variable | Default | Description |
|---|
CORS_ALLOWED_ORIGINS | http://localhost:3000 | Comma-separated allowed CORS origins. |
SESSION_TIMEOUT_MINUTES | 30 | GUI session timeout. |
SESSION_WARNING_SECONDS | 60 | Session expiry warning countdown. |
Data Plane API
| Variable | Default | Description |
|---|
DATAPLANE_API_ENABLED | true | Enable the HAProxy Data Plane API. |
DATAPLANE_API_USER | admin | Data Plane API user. |
DATAPLANE_API_PASSWORD | (empty) | Required when enabled. Strong password. |
DATAPLANE_API_CA_BUNDLE | (empty) | Optional CA bundle for verifying the Data Plane TLS cert. |
HAProxy Stats Auth
| Variable | Default | Description |
|---|
HAPROXY_STATS_USER | (empty) | Stats page user (set both to enable auth on :8404). |
HAPROXY_STATS_PASS | (empty) | Stats page password. |
API Armor
| Variable | Default | Description |
|---|
API_ARMOR_ENABLED | false | Enable API Armor (toggled via Global Options GUI). |
API_ARMOR_MAX_BODY_BYTES | 1048576 | Max request body size for inspection. |
API_ARMOR_MODULE_ENABLED | true | Use the Rust Lua module vs pure-Lua fallback. |
API_ARMOR_DIR | data/api-armor | API Armor data directory. |
API_ARMOR_PROFILE_LOG_PATH | data/api-armor/profiling.log | Profiling log path. |
API_ARMOR_PROFILE_LOG_MAX_BODY_BYTES | 4096 | Max body bytes captured per profile log entry. |
API_ARMOR_PROFILE_LOG_MAX_SIZE_MB | 100 | Max profiling log size. |
API_ARMOR_SCHEMA_LEARN_INTERVAL_SECONDS | 30 | Schema learning interval. |
API_ARMOR_SCHEMA_LEARN_MIN_SAMPLES | 100 | Min samples before a schema is materialized. |
API_ARMOR_SCHEMA_LEARN_RETENTION_DAYS | 30 | Learned schema retention. |
API_ARMOR_PROFILE_RETENTION_DAYS | 30 | Behavioral profile retention. |
API_ARMOR_PROFILER_INTERVAL_SECONDS | 30 | Profiler sampler interval. |
MCP Gateway & Server
| Variable | Default | Description |
|---|
MCP_GATEWAY_ENABLED | false | Enable the MCP gateway proxy (policy/DLP/guardrails). |
MCP_SECRETS_KEY | (empty) | Required when gateway enabled. Encrypts server auth secrets. |
MCP_SELF_REGISTER | true | Auto-register the mcp-server into the gateway on startup. |
COREX_MCP_TOKEN | (empty) | Bearer token for direct mcp-server connections (optional). |
MCP_SERVICE_TOKEN | (empty) | Shared secret bypassing per-user rate limits on in-process calls. |
Auth0 IdP
| Variable | Default | Description |
|---|
AUTH0_DOMAIN | (empty) | Auth0 tenant domain. |
AUTH0_CLIENT_ID | (empty) | Auth0 client ID. |
AUTH0_CLIENT_SECRET | (empty) | Auth0 client secret. |
AUTH0_SECRET | (empty) | Auth0 session secret. |
AUTH0_MCP_AUDIENCE | (empty) | Auth0 API identifier MCP clients request tokens for. |
AUTH0_SYNC_ENABLED | false | Enable Auth0 user sync. |
AUTH0_SYNC_TEAM_ID | (empty) | Team ID for synced users. |
High Availability (HA)
Disabled by default. When HA_ENABLED=true, deploy with docker compose -f docker-compose.yml -f docker-compose.ha.yml up -d. See Docker Swarm and Kubernetes for HA on orchestrators.
| Variable | Default | Description |
|---|
HA_ENABLED | false | Enable HA mode (second HAProxy, Coraza, Valkey replica, Sentinel, keepalived). |
HAPROXY_INSTANCES | (empty) | Semicolon-separated name=url[,user[,password]] inventory. |
HAPROXY_PEER_PORT | 10000 | HAProxy peer port for stick-table replication. |
HA_TOPOLOGY | single | Topology: single, single-host, or multi-host. |
HAPROXY_HA_REPLICAS | 1 | HAProxy replica count (informational). |
VALKEY_HA_REPLICAS | 1 | Valkey replica count (informational). |
CORAZA_HA_REPLICAS | 1 | Coraza replica count (informational). |
KEEPALIVED_VIP | (empty) | Floating IP clients connect to. |
KEEPALIVED_VIRTUAL_ROUTER_ID | 51 | VRRP virtual router ID. |
KEEPALIVED_PRIORITY | 100 | Priority for the primary instance. |
KEEPALIVED_PRIORITY_2 | 90 | Priority for the secondary instance. |
KEEPALIVED_INTERFACE | eth0 | Network interface for VRRP. |
KEEPALIVED_AUTH_PASSWORD | (empty) | Shared VRRP auth password (all instances must match). |
KEEPALIVED_PEER_ADDRESSES | (empty) | Comma-separated peer IPs for unicast VRRP. |
KEEPALIVED_ADVERT_INT | 1 | VRRP advert interval (seconds). |
KEEPALIVED_PREEMPT | true | Allow the higher-priority instance to reclaim MASTER. |
KEEPALIVED_TRACK_SCRIPT | (empty) | Optional health check script path. |
VALKEY_SENTINEL_ENABLED | false | Enable Valkey Sentinel for primary/replica failover. |
VALKEY_SENTINEL_HOSTS | (empty) | Comma-separated Sentinel host:port list. |
VALKEY_SENTINEL_SERVICE | mymaster | Sentinel monitored master name. |
CORAZA_SPOA_TARGETS_HA | coraza-spoa:9000,coraza-spoa2:9000 | Coraza SPOA targets for HA mode. |
Docker Swarm mode
Set SWARM_MODE=true when deploying with docker stack deploy. See Docker Swarm.
| Variable | Default | Description |
|---|
SWARM_MODE | false | Enable Swarm mode (skips keepalived; ingress mesh provides VIP + failover). |
SWARM_API_IMAGE | corex-api:latest | Swarm API image name (override if using a registry). |
SWARM_HAPROXY_IMAGE | corex-haproxy:latest | Swarm HAProxy image name. |
SWARM_FRONTEND_IMAGE | corex-frontend:latest | Swarm frontend image name. |
SWARM_HAPROXY_REPLICAS | 2 | HAProxy replicas (HA + Swarm). |
SWARM_CORAZA_REPLICAS | 2 | Coraza SPOA replicas (HA + Swarm). |
SWARM_VALKEY_REPLICA_REPLICAS | 1 | Valkey replica count (HA + Swarm). |
SWARM_SENTINEL_REPLICAS | 3 | Sentinel replicas for quorum (HA + Swarm). |
3. Get a Free MaxMind GeoIP License Key
coreX Platform uses MaxMind’s GeoLite2 Country and ASN databases for GeoIP-based security rules, country blocking, and ASN-based rate limiting. The databases are free but require a MaxMind license key to download.
- Sign up for a free MaxMind account at www.maxmind.com
- After verifying your email, generate a license key in your account settings
- Set it in your
.env:
MAXMIND_LICENSE_KEY=your_license_key_here
- coreX Platform downloads the GeoIP and ASN databases on startup and refreshes them every 24 hours
Why set this up now?
GeoIP and ASN databases power GeoIP security lists, ASN-based WAF rate limiting, and country-level access rules. Setting the key before the first start means these features work out of the box — no restart needed later.
4. Start the Stack
docker compose up -d --build
This starts the core services plus optional ones depending on your .env:
| Service | Port | Description |
|---|
frontend | 3000 (HTTP), 3443 (HTTPS) | React web GUI |
api | 8000 | FastAPI control plane |
corex | 80 (HTTP), 443 (HTTPS/HTTP3), 8404 (stats), 5555 (Data Plane API) | HAProxy data plane |
coraza-spoa | — | Coraza WAF SPOA (internal) |
valkey | — | In-memory store: caching, rate limits, tokens (internal) |
postgres | 5432 | PostgreSQL database |
cap | 3001 | Cap CAPTCHA service (when CAPTCHA is enabled) |
varnish | — | Varnish disk cache (internal, when DISK_CACHE_ENABLED=true) |
vector | — | Vector log pipeline (internal, when configured) |
mcp-gateway-rs | 8089 | MCP gateway proxy (when MCP_GATEWAY_ENABLED=true) |
mcp-server | 8082 | coreX MCP server exposing the control plane (when MCP_GATEWAY_ENABLED=true) |
5. Log In
Open your browser to http://<host>:3000 and log in with:
- Username:
admin
- Password: the value of
ADMIN_PASSWORD from your .env file (or admin if unset)
Change the default password
For production deployments, always set ADMIN_PASSWORD in your .env file before starting the stack. If left unset, a random password is generated and printed in the API logs.
6. Add a Listener
- Navigate to Configuration > Listeners
- Click Add Listener
- Enter a name (e.g.
web-frontend)
- Set bind address to
0.0.0.0 and port to 80
- Select protocol
http
- Click Save
7. Add a Backend
- Navigate to Configuration > Backends
- Click Add Backend
- Enter a name (e.g.
web-servers)
- Select protocol
http
- Select algorithm
roundrobin
- Click Save
- Click Servers on the backend row
- Add a server: name
web1, address 127.0.0.1, port 8080
- Click Save
8. Apply Configuration
- Navigate to the Dashboard (home page)
- Click Preview to see the generated HAProxy config
- Review the config, then click Apply Config
- Watch the task toast in the bottom-right corner for progress
- Once applied, HAProxy is live and routing traffic
Config snapshots
Every Apply Config creates a config snapshot. You can revert to any previous snapshot from Management > Snapshots.
Service URLs
After deployment, the services are available at:
| Service | URL | Notes |
|---|
| Web GUI (HTTP) | http://<host>:3000 | React frontend |
| Web GUI (HTTPS) | https://<host>:3443 | React frontend over TLS |
| API | http://<host>:8000 | FastAPI control plane |
| HAProxy (HTTP) | http://<host>:80 | Data plane ingress |
| HAProxy (HTTPS) | https://<host>:443 | Data plane ingress over TLS |
| HAProxy (HTTP/3) | https://<host>:443 | QUIC/HTTP3 over UDP (443/udp) |
| HAProxy Stats | http://<host>:8404 | Stats page (set HAPROXY_STATS_USER/PASS to enable auth) |
| Data Plane API | https://<host>:5555/v3 | HAProxy Data Plane API (when DATAPLANE_API_ENABLED=true) |
| CAPTCHA | http://<host>:3001 | Cap challenge service (when CAPTCHA enabled) |
| MCP Gateway | http://<host>:8089/mcp | Tools appear as corex-manager__* (when MCP_GATEWAY_ENABLED=true) |
| MCP Server | http://<host>:8082/mcp | Direct MCP server; requires Authorization: Bearer <COREX_MCP_TOKEN> |
| PostgreSQL | <host>:5432 | Database (bind to 127.0.0.1 in production) |
Production hardening
Bind admin/internal ports (8000, 8404, 5555, 5432, 8082, 8089) to 127.0.0.1 in docker-compose.yml to prevent public access. Only the frontend (3000/3443) and HAProxy data plane (80/443) should be publicly exposed.
Next Steps