Self-hosted Web Application Firewall covering system deployment, configuration management, security policies, and daily operations.
This is the multi-page printable view of this section. .
Product Documentation
- 1: CheeseWAF
- 1.1: Architecture & Working Principles
- 1.2: Deployment & Installation
- 1.2.1: Linux Deployment (systemd)
- 1.2.2: Docker Compose Deployment
- 1.2.3: Windows Deployment
- 1.2.4: macOS Deployment
- 1.3: Quick Start Guide
- 1.3.1: System Setup & Initialization
- 1.3.2: Onboard Your First Site
- 1.3.3: Connect Large Language Models
- 1.4: Core Concepts
- 1.5: Site Management & Reverse Proxy
- 1.6: Gateway Adapters
- 1.7: Security Protection Policies
- 1.8: API Security & Governance
- 1.9: Edge Optimization: Headers, Caching & Compression
- 1.10: TLS & Certificate Management
- 1.11: ALAP Asynchronous Review & Self-Learning
- 1.12: Plugins & CRP Specification
- 1.13: Observability, Logging & Threat Attack Map
- 1.14: High Availability & Cluster Federation
- 1.15: Commercial Platform Architecture
- 1.16: Storage & Scheduler Architecture
- 1.17: Web Management Console
- 1.18: Standalone Control Runtime
- 1.19: Command-Line Interface & Interactive TUI
- 1.20: RESTful Management API Reference
- 1.21: Configuration File Reference
- 1.22: Operations & Security Hardening
- 1.23: Building from Source & Developer Guide
- 1.24: Open-Source License & Ecosystem Repositories
- 1.25: Feedback & Security Reporting
- 1.26: Words from the Developer
- 1.26.1: Words from the Developer
This section provides comprehensive technical documentation and operational references for CheeseSec products.
1 - CheeseWAF
CheeseWAF is a commercial-grade self-hosted Web Application Firewall (WAF) distributed as a single Go core binary. The system utilizes a decoupled dual-plane architecture with an embedded lightweight persistent store for management state and supports external PostgreSQL as an asynchronous access-log sink.
Architecturally, CheeseWAF separates the Data Plane request forwarding path from the Management Plane and the asynchronous ALAP review pipeline. The cheesewaf process orchestrates both planes concurrently: the Data Plane executes bounded, low-latency synchronous inspection and reverse proxying, while the Management Plane hosts the management API, Web console, and background review workers—ensuring synchronous HTTP request paths are never blocked by remote LLM inference.
Official releases are available on GitHub Releases. The project is open-source under the Apache License 2.0.
Why CheeseWAF
Modern Web security solutions usually force teams into painful tradeoffs:
- Traditional Regex WAFs (e.g., ModSecurity / CRS): Maintaining thousands of regular expressions is tedious. Attackers bypass signatures using character case variations, malformed encodings, or SQL comments. False positives are frequent, forcing operators to constantly tune exception lists.
- Synchronous LLM WAFs: Routing every HTTP request to an LLM adds 500 ms to 2 s of latency to each response, burns API token budgets, and risks full outages whenever external endpoints experience latency spikes.
- Heavy Container Stacks (e.g., SafeLine / 雷池): Requiring 5 to 10 Docker containers (Tengine, Postgres, Redis, management daemons) consuming 1 to 2 GB+ of RAM, which quickly overburdens budget cloud instances and small VPSs.
- Commercial Cloud WAFs (e.g., Cloudflare / Cloud Provider WAFs): All traffic must route through third-party infrastructure, raising privacy, data residency, and compliance concerns. Bandwidth billing is unpredictable, and air-gapped operation is impossible.
CheeseWAF takes a balanced approach: an in-process AST semantic parser provides sub-millisecond inline blocking, while an out-of-band LLM auto-pilot (ALAP) reviews ambiguous samples in the background and synthesizes persistent custom rules without adding latency to live requests.
Comparison Overview
| Dimension | Regex WAF (e.g., ModSecurity) | Synchronous LLM WAF | Heavy Container Stack | Commercial Cloud WAF | CheeseWAF |
|---|---|---|---|---|---|
| Detection Engine | Regex pattern matching | Synchronous LLM per request | Regex + statistical analysis | Signature sets + threat feed | AST syntax analysis + Async LLM Auto-Pilot (ALAP) |
| Inline Latency Added | 1–10 ms | 500–2000 ms (high) | 2–15 ms | Dependent on CDN routing | < 1 ms (sub-millisecond, zero model wait) |
| API / Token Cost | None | Extremely high (all traffic) | None | Bandwidth & tier billing | Low (reviews only ambiguous samples out-of-band) |
| Evasion & False Positives | Easily bypassed by encodings | Prone to hallucinations | Complex rule maintenance | Vendor-dependent updates | Parses syntax trees; immune to obfuscation; FPR < 0.8% |
| Footprint & Deployment | Requires custom Nginx build | External API dependency | 5–10 containers, 1–2 GB+ RAM | Cloud-only | Single binary / single container, embedded SQLite, tens of MB RAM |
| Architectural Disruption | Bound to web server | Modifies primary traffic path | Replaces primary gateway | DNS / reverse proxy takeover | Runs as standalone reverse proxy or sidecar via adapterd |
| Data Privacy & Compliance | Local | Full traffic sent to external API | Local | Traffic traverses public cloud | 100% on-premises; optional private self-hosted LLM |
| Air-gapped Environments | Supported | Not supported (requires cloud API) | Partially supported | Not supported | Fully supported with offline Ed25519 CRP verification |
Core Mechanisms
- High-Performance Data Plane Inspection: Incoming requests undergo multi-layer recursive decoding before entering the Abstract Syntax Tree (AST) semantic engine. Identified SQL injection, Cross-Site Scripting (XSS), Remote Code Execution (RCE), and malicious payloads are blocked in sub-millisecond to microsecond timeframes.
- Asynchronous ALAP Threat Review: After the client receives its response, ambiguous samples or payloads embedded in large text blocks are enqueued into a background review pipeline. Configured LLMs (compatible with the OpenAI Response / Chat Completions APIs and Anthropic Messages API) perform in-depth semantic reasoning.
- Closed-Loop Rule Synthesis: Samples evaluated as high (
high) or critical (critical) threats can be approved manually or via auto-agreement. Site-level auto-agreement persists a site-scoped custom payload rule; global IP denylists and client soft-fingerprint actions remain explicit operator decisions.
Default Network Listeners
CheeseWAF exposes services on the following default listener endpoints:
| Plane / Service | Default Address | Description |
|---|---|---|
| Data Plane | http://127.0.0.1:8080 | Ingests business traffic, performs synchronous security inspection, and proxies upstream |
| Management Plane | https://PUBLIC_IP:9443/setup → https://PUBLIC_IP:9443/SECURITY_ENTRY | Initialization uses fixed /setup with a one-time token; after setup, the symbol-free security entry signs a Cookie and redirects to login |
| Cluster Plane | https://127.0.0.1:9444 | Optional TLS/mTLS interconnect when cluster.enabled: true; it handles node identity, health/heartbeat, topology, and orchestration hooks but is not a general site/policy replication channel |
| Local Controller | http://127.0.0.1:17943 | Local loopback auxiliary controller port for Windows and macOS desktop environments |
Documentation Roadmap
1.1 - Architecture & Working Principles
Traditional signature-based Web Application Firewalls rely heavily on expansive regular expression libraries. These approaches incur high rule maintenance costs and remain susceptible to bypasses via multi-layer encoding, nested syntax, and character obfuscation. Conversely, invoking Large Language Models (LLMs) synchronously within the real-time request path introduces unacceptable network latency and availability bottlenecks.
To address these challenges, CheeseWAF adopts a decoupled dual-plane architecture with asynchronous out-of-band threat review, combining deterministic, sub-millisecond blocking with deep semantic intelligence.
Dual-Plane Architecture
Data Plane
The Data Plane processes incoming HTTP/1.1, HTTPS, and HTTP/3 traffic through an ordered, high-performance pipeline:
- Network & Identity Filtering: Evaluates IP access control lists, GeoIP country bans, and client soft-fingerprints.
- Access Control & Anti-Scraping: Enforces bot challenges, sharded sliding-window counter rate limits, and waiting room scheduling.
- AST Semantic Analysis: Parses recursively decoded parameters into language syntax trees for attack detection.
- Reverse Proxying: Dispatches validated requests to the configured backend upstream servers.
The Data Plane operates strictly within the critical request path, adhering to deterministic execution and never blocking on external LLM calls.
Management Plane
The management plane provides administrative and observability capabilities through a dedicated listener endpoint:
/setupInitialization Wizard: Guides initial deployment and provisions administrator credentials.- Web Management Console: Serves a modern, responsive React-based single-page application.
- RESTful Management API: Powers automation scripts and third-party operational integrations under the
/apinamespace. - Metrics & Observability: Exports Prometheus metrics and provides health check probes.
For security reasons, keep server.admin_public set to false unless TLS encryption is enabled and strict network-level access controls (such as IP whitelisting or private networks) are in place.
Asynchronous ALAP Threat Review
After the Data Plane completes response delivery to the client, CheeseWAF enqueues selected samples into the background ALAP (AI Large-Language-Model Auto Pilot) review pipeline:
- High-Severity Blocked Samples: Deterministic standalone attack payloads blocked at paranoia level 5.
- Embedded Feature Samples: Mixed-context requests allowed at paranoia levels 2–4 that contain suspicious patterns within larger text blocks.
- Borderline Samples: Traffic marked by the semantic engine as low-confidence or near decision thresholds.
Background workers asynchronously query the configured LLM for deep contextual analysis. Security operators can review decisions in the console or enable auto-agreement to persist confirmed threats as long-term defensive rules. See ALAP and Review Queue.
Delivery Components & Single-Binary Distribution
CheeseWAF ships as a self-contained single binary (BusyBox model) delivering all core security engines, management services, and interactive utilities:
| Component | Role & Functionality |
|---|---|
cheesewaf | Primary server process; default command is serve to launch data and management listeners in one process |
waf-cli | Same binary (or symbolic link); default command launches the interactive TUI management panel |
cheesewaf-gui | Local service controller for Windows and macOS (binds exclusively to loopback) |
| Web Console | Modern React application embedded within the binary and hosted by the management listener |
| Storage Engines | Embedded SQLite for management state persistence; supports external PostgreSQL for asynchronous access logs |
| CRP Local Staging | Offline Ed25519 signature verification and content-addressed staging via crp verify and crp stage |
Related Documentation
1.2 - Deployment & Installation
CheeseWAF can be deployed as a system service, containerized workload, or standalone binary across all major platforms. Choose the deployment method that aligns with your infrastructure:
Release Package Matrix & Distribution Strategy
Beginning with stable releases (v0.3.9+), CheeseWAF enforces a server-first distribution model: stable releases prioritize certified Linux server packages accompanied by Sigstore cryptographic signatures and SBOM attestations. Windows and macOS desktop packages are provided as optional operator-side builds.
Pre-compiled production binaries can be downloaded directly from GitHub Releases:
| Release Package | Target Platform & Architecture |
|---|---|
cheesewaf-amd64-linux-*.tar.gz | Linux x86_64 architecture |
cheesewaf-arm64-linux-*.tar.gz | Linux ARM64 architecture |
cheesewaf-loong64-linux-*.tar.gz | Linux LoongArch architecture |
cheesewaf-amd64-darwin-*.tar.gz / .dmg | macOS Intel architecture |
cheesewaf-arm64-darwin-*.tar.gz / .dmg | macOS Apple Silicon architecture |
cheesewaf-amd64-windows-*.exe | Windows x86_64 standalone executable |
cheesewaf-arm64-windows-*.exe | Windows ARM64 standalone executable |
cheesewaf-amd64-windows-*.zip | Windows x86_64 portable ZIP archive |
cheesewaf-arm64-windows-*.zip | Windows ARM64 portable ZIP archive |
cheesewaf-amd64-windows-*-setup.exe | Windows x86_64 NSIS graphical installer |
cheesewaf-arm64-windows-*-setup.exe | Windows ARM64 NSIS graphical installer |
Following installation, proceed to Quick Start to complete system initialization and onboard your first reverse proxy site.
1.2.1 - Linux Deployment (systemd)
This guide covers Linux physical servers, cloud instances, and virtual machines. The online installer selects a language, detects the CPU architecture, downloads the latest stable release, verifies its checksum, installs the systemd service when available, and prints the first-setup URLs. Use the offline path when the target host cannot reach GitHub.
1. One-line installation (recommended)
Copy and paste this command. The installer opens an interactive prompt for language selection and then downloads, verifies, and installs the matching server release:
When already running as root, omit sudo:
The script reads language, install-root, and entry-name input from /dev/tty, so interactive answers are not consumed as script source. For unattended provisioning, set the documented CHEESEWAF_* environment variables and invoke the downloaded script; never put passwords or setup tokens in shell arguments or history.
To install a specific stable or beta tag, set CHEESEWAF_RELEASE (the v prefix is optional):
During the interactive flow, choose an application install root after selecting the language. Entering /opt/cheesewaf, for example, places the binary, Web assets, runtime configuration, data, and logs under bin/, web/, config/, data/, and logs/ beneath that root. Press Enter to keep the split FHS layout shown below. The systemd unit remains under /etc/systemd/system unless CHEESEWAF_UNIT_DIR is explicitly overridden.
For automation, set CHEESEWAF_INSTALL_DIR before invoking the installer. Individual CHEESEWAF_PREFIX, CHEESEWAF_WEB_DIR, CHEESEWAF_CONFIG_DIR, CHEESEWAF_DATA_DIR, and CHEESEWAF_LOG_DIR values take precedence for their respective paths:
Install roots must be absolute dedicated directories whose path components contain only ASCII letters, digits, ., _, or -; shared system directories and paths containing shell metacharacters are rejected.
The installer will:
- Ask for 中文 or English and check Linux, architecture, disk space,
curl,tar,sha256sum,awk, andodprerequisites. - Download the selected server archive from GitHub Releases and verify its single matching
SHA256SUMSentry. A failed verification stops before installation or service startup. - Install the binary, Web Console, runtime configuration, and systemd unit, then create the non-login
cheesewafservice account. - Generate an HTTPS management listener, a one-time setup token, and a safe entry path. The entry path accepts ASCII letters and digits only; a random value is generated by default, and a custom value is accepted only when it passes the same validation.
- Start the service when
systemdis available, check the listener and health state, and print the version, architecture, installation paths, service state, public management URL, detected private management URLs, token lifetime, and next steps. Withoutsystemd, the files are installed but the service is reported as not started.
Save the complete setup URL printed at the end. On an interactive terminal the installer prints the public setup URL and the secure-entry URL; it also prints each detected private-address setup URL. In a non-interactive run, secrets are withheld from stdout and stored in the root-only install-secrets.txt receipt; set CHEESEWAF_SHOW_SECRETS=1 only when the output is protected. The token is short-lived and is revoked immediately after first setup. Do not paste the complete URL into tickets, screenshots, shell history, or logs.
2. First setup and public entry
During initialization, open the https:// URL printed by the installer. The setup URL always uses the fixed /setup path:
ONE_TIME_TOKEN is the one-time bootstrap token. The browser reads the token from the URL fragment, clears it from the address bar, and sends it in the X-CheeseWAF-Setup-Token header. The token is never placed in query parameters, cookies, or localStorage.
After setup completes, open https://PUBLIC_IP:9443/SECURITY_ENTRY. The security entry contains ASCII letters and digits only; it is generated by default or accepted as a validated custom value. The entry endpoint signs an access Cookie and redirects to the login page. Keep the setup route and the post-setup security entry as separate paths.
The management plane uses HTTPS and binds publicly by default for this installation path. The installer writes the detected public host to admin.env; set CHEESEWAF_ADMIN_PUBLIC_HOST when the host has no directly assigned public address (for example, behind NAT or a reverse proxy). Restrict security groups, firewalls, and any reverse proxy to trusted administration networks before exposing port 9443 to the Internet. A locally generated certificate may cause a browser warning on first access; replace it with a trusted certificate for production use.
After setup completes, the bootstrap token is invalid. If the URL is lost before an administrator is created, reset it on the host:
Use the new URL printed by the command. The old URL cannot be recovered.
Running the installer again against an existing configuration performs an upgrade. It keeps the existing listener, TLS settings, sites, policies, and security-entry path; choose the same install root or set the same CHEESEWAF_*_DIR overrides so the intended service is upgraded.
3. Verify the installation
Confirm that the version and architecture match the target host and that the expected process owns the management port. After first setup, add the first protected site and configure the data-plane listener from the Console.
Default FHS paths:
| Path | Purpose |
|---|---|
/usr/local/bin/cheesewaf | Main binary |
/usr/local/bin/waf-cli | CLI symlink |
/usr/share/cheesewaf/web | Web Console assets |
/etc/cheesewaf/cheesewaf.yaml | Runtime configuration copy |
/var/lib/cheesewaf | Data, certificates, and bootstrap state |
/var/log/cheesewaf | Access and audit logs |
With CHEESEWAF_INSTALL_DIR=/opt/cheesewaf, the corresponding application paths are /opt/cheesewaf/bin/cheesewaf, /opt/cheesewaf/web, /opt/cheesewaf/config/cheesewaf.yaml, /opt/cheesewaf/data, and /opt/cheesewaf/logs.
4. Offline or manual installation
On a connected machine, download the architecture-specific .tar.gz, SHA256SUMS, and (when publishing signatures) signature files from GitHub Releases, then transfer them to the target host. Verify the files in the download directory, extract the archive, and run the installer:
The offline script still asks for the language and entry path locally, generates the setup token, and starts the service; it does not attempt to download another release. On a host without systemd, copy the binary and web/dist into your process manager’s paths and start the service there. Keep a runtime configuration copy and a dedicated data directory; never edit the tracked configs/cheesewaf.yaml template in place.
Do not use unverified binaries, third-party mirrors, or stale installer scripts. A complete Linux archive contains cheesewaf, Web assets, configuration templates, the systemd unit, and this installer; stop and download the archive again if any item is missing.
1.2.2 - Docker Compose Deployment
This guide covers deploying CheeseWAF on containerized infrastructure. The repository provides a hardened Dockerfile and Compose example; the example builds the image locally. Do not treat cheesewaf:dev as a vendor-signed or registry-published image unless you have separately verified the image provenance. The runtime is configured to run as an unprivileged user (UID 10001) with a read-only root filesystem.
Compose Configuration
Reference deploy/docker/docker-compose.yml:
When building locally, ensure the build context points to the root of the CheeseWAF repository so both the frontend (web/) and backend Go modules build successfully.
The sample 8080:8080 mapping publishes the data-plane listener on all Docker host interfaces. Put it behind an intentional firewall/reverse-proxy policy, or bind it to a controlled interface; only the admin mapping is loopback-bound by default.
Launching & Initialization
Start the container daemon and view logs:
On initial startup, the container generates self-signed TLS certificates for the admin API. This Compose file binds the admin port to the Docker host’s loopback interface (127.0.0.1:9443), so open https://127.0.0.1:9443/setup on the Docker host. From another machine, set CHEESEWAF_SSH_TARGET to your SSH target and create a tunnel with ssh -N -L 9443:127.0.0.1:9443 "$CHEESEWAF_SSH_TARGET", then use the same local URL; if you intentionally change the port binding, apply an appropriate access-control policy. You can also run the CLI wizard inside the container:
While first-install setup is pending, the container log never prints the setup token or complete URL. It shows only the base /setup URL, the protected /var/lib/cheesewaf/setup.url path, and an opaque receipt. Read the complete URL from that mode 0600 file within its 10-minute validity period. After setup completes, the token is revoked; expired setup.url files are cleaned up.
Stopping containers with docker compose -f deploy/docker/docker-compose.yml down safely preserves SQLite data, certificates, and log streams inside the named volumes cheesewaf-data and cheesewaf-logs. If storage.postgresql is configured, it receives external access-log records; the Docker volume still contains the management database for the default storage.profile: temporary. The reserved production profile currently fails closed at startup.
1.2.3 - Windows Deployment
CheeseWAF offers three distribution options for Windows, each utilizing the identical core engine and protection capabilities:
1. Single-File CLI & Native Windows Service
Designed for rapid testing, automated scripts, or native Windows Service hosting:
Native Windows Service Awareness
cheesewaf serve includes native Windows Service state machine integration (golang.org/x/sys/windows/svc):
- When invoked by the Windows Service Control Manager (SCM), the process automatically identifies service mode, seamlessly handling SCM
StopandShutdownsignals with zero external service wrappers (like NSSM or WinSW). - The default service name is
CheeseWAF.
2. Portable Zip Archive
The portable package bundles default configuration templates and compiled Web Console assets:
- Extract
cheesewaf-amd64-windows-*.zipto your target directory (e.g.,D:\CheeseWAF). - Run terminal setup and start the server:
When first-install setup is pending, the process log shows only the base /setup URL, the protected data\setup.url path, and an opaque receipt. Read the complete URL from the mode 0600 file within its 10-minute validity period. After setup completes, the token is revoked; expired setup.url files are cleaned up.
3. NSIS Graphical Installer (Recommended)
Ideal for workstation or production servers requiring guided installation and Windows Service registration:
- Run the
cheesewaf-amd64-windows-*-setup.exeinstaller (use thearm64variant on Windows ARM64). - Follow the wizard prompts. The installer registers the
CheeseWAFWindows service in manual (start= demand) mode; start or stop it explicitly from the Service Control Manager or withsc.exe. - Upon uninstallation, the
data\directory containing your databases and certificates is retained by default to prevent accidental data loss.
Local Helper Controller (GUI)
cheesewaf-gui is a lightweight browser-based local controller for managing the lifecycle of the underlying service:
- Network Security: Strictly binds only to the local loopback address
127.0.0.1:17943. - Key Features: Service start/stop/restart, status and PID display, direct access to the Web Console, and a shortcut to the configuration directory.
- Process Model: The controller starts the local
cheesewaf serveprocess when requested; it is not a second management backend.
Once started, open http://127.0.0.1:17943/ in your browser to view the local desktop controller dashboard.
1.2.4 - macOS Deployment
CheeseWAF supports two primary deployment mechanisms on macOS:
1. DMG Graphical Installer
Ideal for local testing, development, and desktop workstations:
- Download the DMG matching your CPU architecture:
cheesewaf-arm64-darwin-*.dmgfor Apple Silicon (M-series), orcheesewaf-amd64-darwin-*.dmgfor Intel Macs. - Open the DMG image and drag CheeseWAF into your Applications folder.
- Launch CheeseWAF from Launchpad or Spotlight.
Gatekeeper Guidance: A release is signed and notarized only when the build has a Developer ID identity and Apple notarization credentials. The packaging script intentionally falls back to ad-hoc signing without notarization when those credentials are unavailable. Verify the exact downloaded artifact with its published signature metadata before deployment. For an ad-hoc developer build that triggers macOS security prompts, Control-click the app icon, select “Open”, and confirm the prompt.
Upon launching, the DMG application runs a lightweight browser-based local controller bound to loopback at http://127.0.0.1:17943/. It provides process start/stop/restart controls, status monitoring, and shortcuts to the Web Console and configuration directory. Default runtime data is saved under ~/Library/Application Support/CheeseWAF.
2. Command-Line Archive (tar.gz)
Ideal for headless servers, developer terminal workflows, or automated scripts:
If first-install Web setup is still pending, process output shows only the base /setup URL, the protected data/setup.url path, and an opaque receipt. Read the complete URL from the mode 0600 file within its 10-minute validity period. After setup completes, the token is revoked; expired setup.url files are cleaned up.
Once initialized, navigate to http://127.0.0.1:9443/ to log into the Web Console.
1.3 - Quick Start Guide
Start with the one-line Linux installer. It asks for a language, downloads and verifies the latest stable release, creates a public HTTPS management entry, and prints a short-lived setup URL. Then follow these three steps:
The installer asks for an application root after the language prompt. Enter /opt/cheesewaf to keep the binary, Web assets, configuration, data, and logs together, or press Enter to use the standard FHS layout. It prints public and detected private setup addresses; use CHEESEWAF_RELEASE=vX.Y.Z[-beta] when you need a specific release. See the Linux installation guide for automation variables, upgrades, and security-entry handling.
Keep the complete HTTPS setup URL private. Its URL fragment contains a one-time token that the browser converts to the X-CheeseWAF-Setup-Token header; it is revoked after setup. If the server cannot reach GitHub, use the signed archive and checksum files from the release page and follow the offline installation section.
CheeseWAF’s Data Plane provides deterministic AST semantic protection immediately after startup, even without an LLM connected. Before configuring the ai block, the ALAP review queue simply remains idle.
1.3.1 - System Setup & Initialization
Following a fresh installation, CheeseWAF requires initial administrator provisioning and hardware baseline profiling. CheeseWAF provides both a Terminal CLI Wizard and a Web GUI Wizard.
Option 1: Terminal Setup Wizard (Recommended)
Run the interactive setup command directly in your terminal:
1. Automated Hardware Probing & Profiling
The wizard inspects host resources (logical CPU cores, visible RAM, and an 8 MiB sequential write test) and recommends a runtime profile:
low(Lightweight): Best for 1–2 CPU cores / 1–2 GB RAM; requests exceeding inspection budgets automatically fall back here.smart(Smart, default): Recommended for standard servers (2–4 CPU cores / 4–8 GB RAM); dynamically tunes inspection depth based on request risk.medium(Balanced): Fixed inspection depth 2 with a 50 ms timeout per request.high(Performance): Best for 4+ CPU cores / 8+ GB RAM on core gateways; performs full deep semantic analysis.custom(Custom): Allows manual tuning of inspection depth and timeout budgets.
The probe runs for at most 30 seconds. If it times out, is cancelled, or the Web probe request fails, the wizard recommends the conservative low tier. In non-interactive mode, --skip-probe also selects low unless an explicit --profile is provided.
2. Guided Credentials & Transactional Safety
- Username: Enter a username of 3–32 ASCII characters. It must start with an ASCII letter, end with an ASCII letter or digit, and contain only ASCII letters, digits,
.,_, and-. Non-ASCII characters, Unicode whitespace, control characters (Cc), and format/invisible characters (Cf) are rejected; the server preserves the exact value and does not trim or lowercase it. - Password: New passwords need at least 10 characters and at least 3 of 4 classes: uppercase, lowercase, non-repeating digits, and special characters. Common or simple patterns are rejected, and the password cannot equal or contain the username. The Web review step shows that a password is set; it never displays the password, a password hash, a system master key, or an administrator credential digest.
- Optional integrations: The interactive terminal wizard can apply selected GeoIP, Prometheus
/metrics, and VictoriaLogs settings when it commits the configuration. The Web wizard records integration choices in the setup draft for review; it does not apply them to the live configuration. Configure supported integrations after setup from the relevant System Settings, Storage, or Monitoring pages. The PostgreSQL option is an asynchronous access-log sink, not the management database. - Transactional Cleanliness: Configuration, database, certificate, and administrator state are accumulated in memory and are committed only at the final step. Aborting does not leave partial setup state. The selected CLI language is a separate user preference and may be persisted in
data/cli.lang; this file is not the runtime configuration or management database.
3. Headless Scripted Automation
For CI/CD pipelines or cloud-init automation, use non-interactive command-line flags:
Note: In automated mode,
--yesstrictly requires--password-stdinto guarantee that the administrator password satisfies the credential policy. Upon completion, the wizard prints the canonicalhttp://orhttps://panel URL according to the current administrative TLS state.
Option 2: Browser Web Wizard
1. Open the Setup URL
During initialization, open the https://PUBLIC_IP:9443/setup#setup_token=ONE_TIME_TOKEN URL printed by the installer. The setup route is always /setup; the token is one-time and short-lived.
The management plane is HTTPS and publicly reachable by default for the one-line installation path. Restrict port 9443 with cloud security groups, host firewalls, and an administrator IP allowlist before production use. Replace a locally generated certificate with a trusted certificate when the service is put on a public hostname.
The URL fragment carries a short-lived one-time token. The browser reads it, clears the address bar, and sends it only in X-CheeseWAF-Setup-Token; it is never placed in a query parameter, cookie, or localStorage. The token is revoked after setup and the protected setup.url file is removed or invalidated.
After setup, open https://PUBLIC_IP:9443/SECURITY_ENTRY. The entry contains ASCII letters and digits only, is generated by default or accepted after validation, signs an access Cookie, and redirects to the login page. Keep the setup route and the post-setup security entry as separate paths.
The setup token remains required in X-CheeseWAF-Setup-Token until setup completes, when it is revoked. If CHEESEWAF_SETUP_TOKEN was set before startup, keep that value out of logs and shell history. The browser reads setup_token from the URL fragment, clears it from the address bar, and sends it only in that header.
If you open bare /setup, paste the token from the protected file. It remains in page memory and is cleared after submission. Never put the token in a query parameter or include it in tickets, screenshots, or logs.
2. Create Root Administrator Account
Follow the on-screen steps:
- Enter a username that follows the canonical username rule above.
- Enter a password of at least 10 characters that satisfies at least 3 of the 4 password classes and does not contain the username.
- Review the summary. It shows the username, that the password is set, the environment check, and selected integrations; it does not display the password, a password hash, a system master key, or an administrator credential digest.
3. Configure Admin Network Boundaries
- Keep
server.admin_tlsenabled and restrict ingress using cloud security groups, host firewall rules, and IP allowlists. - If you intentionally need loopback-only administration, override
server.admin_listento127.0.0.1:9443and use an SSH tunnel; this is an explicit hardening choice, not the default one-line path.
Upon completing initialization, navigating to the admin endpoint redirects to the Web Console login view. Local credentials can subsequently be managed using waf-cli or cheesewaf user.
The generated configuration may contain an update.ota.server value, but OTA is disabled by default and the current binary has no updater worker. It cannot download or install rules or binaries through OTA; keep update.ota.enabled: false.
1.3.2 - Onboard Your First Site
Log in to the Web console and navigate to Sites → New Site to configure your first reverse proxy service:
1. Configure Public Domains
Enter the public hostnames used by your clients (e.g., app.example.com). CheeseWAF matches incoming HTTP Host headers against the configured sites[].domains list.
2. Configure Backend Upstream Origins
Specify the origin server address and port (e.g., 10.0.0.10:8000). When multiple upstreams are defined, the system distributes traffic according to the configured load balancing policy (round_robin by default).
3. Set Baseline Paranoia Level
New sites default to paranoia level 3 (Smart Standard Mode); if the current wizard exposes this option, leave it at 3. In this mode, the system blocks high-confidence standalone payloads while allowing embedded features through to asynchronous ALAP review, ensuring business continuity while collecting threat data.
4. Save & Hot-Reload
Click Save Site. CheeseWAF dynamically reloads site definitions in memory without terminating the main daemon or interrupting active connections.
After saving, update your DNS records or local hosts file to point the domain to the CheeseWAF Data Plane listener (http://127.0.0.1:8080 by default) to verify end-to-end reverse proxy forwarding.
For health checks, automatic SSL issuance, and path rewrite configurations, see Sites & Reverse Proxy.
1.3.3 - Connect Large Language Models
CheeseWAF’s ALAP (AI Large-Language-Model Auto Pilot) engine integrates with industry-standard LLM APIs to perform out-of-band semantic reasoning on suspicious and borderline traffic.
In the Web management console, navigate to the AI section and configure the following parameters:
| Setting | Configuration Key | Description & Examples |
|---|---|---|
| Enable AI | ai.enabled | Master toggle for ALAP functionality (boolean) |
| Provider | ai.provider | API protocol dialect: openai or anthropic |
| Base URL | ai.api_base | API Base URL (e.g., https://api.openai.com/v1) |
| Allow Private Endpoint | ai.allow_private_api_base | Allows connecting to private/local LLM gateways (Ollama, LocalAI; defaults to false) |
| API Key | ai.api_key | Secret access token / API key provided by your LLM vendor |
| Model Name | ai.model | Model identifier (e.g., gpt-4o-mini, claude-3-5-sonnet-latest) |
| Auto-Agreement | sites[].waf.semantic_policy.auto_agree | When enabled, threats evaluated as high or critical are automatically persisted as defensive rules |
Legacy configuration migration: The old ai.base_url and ai.auto_agree keys are not read by the current release. Move ai.base_url to ai.api_base, and move the approval setting to each site’s sites[].waf.semantic_policy.auto_agree; save the configuration and reload/restart the service as required.
Best Practices & Security Guidelines
- Enforce Asynchronous Execution: Always maintain
ai.async: truein your configuration to guarantee that the Data Plane never blocks real-time traffic while waiting for model inference. - Connection Testing: Before enabling rules, click Test Connection in the console to validate network routing, DNS resolution, and credential authentication.
- Gradual Rollout of Auto-Agreement: Keep
sites[].waf.semantic_policy.auto_agreedisabled during initial deployment. Review samples manually in the threat queue for 1–2 weeks to verify evaluation fidelity before enabling automated rule generation.
For details on assistant tool approvals, review queues, and automated self-learning, see ALAP & Review Queue.
1.4 - Core Concepts
This section introduces the foundational architecture and evaluation mechanics of CheeseWAF. Prior to tuning production paranoia levels or configuring advanced security policies, reviewing these concepts is strongly recommended:
1.4.1 - Traffic Pipeline & Two-Phase Execution
CheeseWAF separates traffic processing into two distinct flows: the Synchronous Detection Pipeline and the Asynchronous Out-of-Band Review Loop. Within the synchronous path, CheeseWAF employs a high-performance Two-Phase Pipeline architecture to achieve microsecond-level short-circuit drops while preserving high throughput for deep AST parsing:
flowchart TB
Client[Client Request] --> Ingress[Ingress HTTP / HTTPS / HTTP3]
subgraph Phase1 [Phase 1: Pre-Filters (Sequential / Short-Circuit / Priority < 290)]
IP{IP / Geo / Fingerprint} -->|Pass| Bot{Bot Challenge / RateLimit}
Bot -->|Pass| Rules{Custom Rules Priority 250}
end
Ingress --> IP
IP -->|Blacklisted| Block[Render Block Page]
Bot -->|Trigger Challenge| Challenge[Solve Challenge / Waiting Room]
Challenge -->|Verified| Rules
Rules -->|Match Block| Block
subgraph Phase2 [Phase 2: Semantic Group (Parallel Worker Pool / Deterministic Merge / Priority >= 290)]
Sem[AST Semantic Analyzers: SQL / XSS / RCE / LFI / NoSQL / SSTI etc.]
end
Rules -->|Clean| Sem
Sem --> Shape{Payload Context}
Shape -->|Isolated Attack Level 2~5| Block
Shape -->|Embedded Attack Level 5| Block
Shape -->|Embedded Attack Level 2~4| Pass[Pass & Enqueue Asynchronously]
Shape -->|Clean| Origin[Forward to Backend Upstream]
Pass --> Origin
Pass -.-> Queue[ALAP Review Queue]
Sem -.->|Level 5 Blocked Sample| Queue
Queue --> LLM[LLM Reasoning & Attribution]
LLM --> Review{Decision}
Review -->|High / Critical| Rule[Generate Protective Rules]
Review -->|Low / False Positive| Dismiss[Dismiss / Allowlist]
Rule -.-> IPTwo-Phase Pipeline Architecture
To ensure deterministic latency guarantees under high concurrent load, the detection pipeline partitions all registered detectors by Priority into two separate execution phases:
1. Phase 1: Pre-Filters (Priority < 290)
- Components: IP Access Control, GeoIP, Soft Client Fingerprinting, Bot Challenges, Rate Limiting, and the Custom Regex Rule Engine (Priority 250).
- Execution Model: Strictly sequential single-threaded execution.
- Fast Short-Circuiting: If any pre-filter returns
ActionBlock, the request is immediately dropped and the pipeline terminates. The request never reaches the AST semantic parsing stage, allowing reconnaissance probes and known signatures to be discarded within microseconds.
2. Phase 2: Semantic Group (Priority >= 290)
- Components: Deep syntax analyzers for SQL injection, Cross-Site Scripting (XSS), Remote Code Execution (RCE), Local File Inclusion (LFI), NoSQL injection, Server-Side Template Injection (SSTI), SSRF, and XXE.
- Execution Model:
- Shared Worker Pool: Dispatched across a shared worker pool (bounded at 8 workers) to maximize multi-core CPU efficiency without unbounded goroutine proliferation.
- Context Forking: Each detector executes with a forked
RequestContext, guaranteeing data race immunity forMetadataandResultswrites. - Deterministic Merge: Once parallel evaluations conclude, results are merged in strict priority order, ensuring 100% deterministic decision-making and logging.
Pipeline Timeout & Budget Protection
- 100ms Hard Timeout: A global 100ms pipeline deadline guarantees that adversarial payloads cannot cause request processing hangs.
- Analysis Budget Depletion Policy (
budget_exhausted_policy): If deep parsing cannot finish within the deadline, the fallback policy takes effect:auto: Follows the globalweb_attackpolicy level.open: Fails open to preserve application availability while recording metrics.observe: Logs observation details without a hard drop.closed: Security-first challenge or strict block.
- Overload Guarding: Built-in guard monitors detect backpressure and return
ErrDetectionOverload, protecting the primary service from cascading degradation.
Asynchronous Review Loop (ALAP)
The asynchronous path runs completely decoupled from real-time reverse proxying:
- Sample Dispatch: Embedded samples passed under Paranoia Levels 2–4 and blocked samples under Level 5 are delivered to the review queue after response delivery.
- LLM Intent Extraction: Background workers issue inference requests to extract threat semantics and confidence scores.
- Closed-Loop Rule Derivation: Manual review decisions can promote a verified sample to the selected payload, URI, IP, or fingerprint rule. Site-level automated adoption is narrower: it writes a site-scoped custom payload rule only.
For detailed configuration options of individual detectors, see Protection; for setting up AI models, see ALAP Review.
1.4.2 - Paranoia Level Mechanism
CheeseWAF allows configuring the paranoia level independently for each reverse proxy site via sites[].waf.paranoia_level. Supported values range from 0 to 5, with 3 (Standard Smart Protection) recommended as the production baseline.
The paranoia level mechanism balances high threat detection rates with false-positive suppression. When inspecting decoded parameter values, the AST semantic engine executes tiered responses based on payload morphology (Isolated vs. Embedded).
Two Independent Knobs:
waf.paranoia_level(0–5) drives the AST semantic engine itself—determining how strictly the engine identifies attack payload morphology (Isolated vs. Embedded features).- Ingress proxy enforcement actions are driven by an entirely separate setting:
protection_policy.web_attack(off,low,smart,high,strict, defaultsmart). It dictates downstream action thresholds (severity and confidence cutoffs, aggregate risk scoring, and failure policies when the 100ms detection budget is exhausted). The two controls are completely decoupled.
Paranoia Levels Comparison
| Level | Policy Profile | Isolated Payload | Embedded Payload | Auto-Promotion |
|---|---|---|---|---|
| 0 | Record Only | Log alert & allow | Log alert & allow | No |
| 1 | Observation Mode | Log alert & allow | Log alert & allow | No |
| 2 | Basic Defense | Block immediately | Allow, enqueue for ALAP review | No |
| 3 | Smart Standard (Recommended) | Block immediately | Allow, enqueue for ALAP review | No |
| 4 | Active Defense | Block immediately | Allow, trigger auto-promotion & review | Yes (promotes to 5) |
| 5 | Strict Defense | Block immediately | Block immediately, enqueue for review | Already maximum |
Dynamic Auto-Promotion Mechanism
At Paranoia Level 4, when suspicious embedded payloads are detected within live traffic, the system proactively promotes the site to Level 5 (Strict Mode) for a configurable duration defined by promote_seconds (e.g., 300 seconds) to prevent reconnaissance-stage exploitation.
- State Persistence: The promotion deadline timestamp is stored in local management storage and persists across service restarts; access logs can stream asynchronously to external PostgreSQL.
- Automatic Decay: Once the promotion window elapses without subsequent suspicious triggers, the site seamlessly reverts to its baseline Level 4 configuration.
Level 5 Review Constraints
Samples blocked under Paranoia Level 5 are submitted to the ALAP review queue with a blocked status tag:
- Non-Retroactive Release: Because the connection was physically terminated, operators cannot mutate the sample status to “Allowed”.
- Rule Synthesis: Upon review, confirmed threats can be exported into permanent global defense rules (including signature patterns, URL path filters, IP blacklists, or client soft-fingerprints).
1.4.3 - Isolated vs. Embedded Payloads
In modern web applications, user submissions vary widely in structure. In community forums, developer blogs, or technical support tickets, legitimate users frequently submit code snippets, SQL queries, or log entries. Applying strict signature matching to such content inevitably causes widespread false positives.
To resolve this challenge, CheeseWAF’s AST semantic engine evaluates the contextual proportion and structural wrapping of decoded parameter values, categorizing detections into Isolated Payloads or Embedded Payloads.
Payload Morphologies
1. Isolated Payloads
An isolated payload indicates that the parameter value consists almost entirely of an attack pattern without legitimate surrounding business text.
- Typical Scenario: Direct inputs into search boxes or login fields such as
UNION SELECT 1,2,3or' OR 1=1 --. - Wrapping Evaluation: Even when attackers prepend/append light obfuscation—such as
@, trailing semicolons, or${...}wrappers—the engine still classifies the value as isolated if the payload dominates the syntax tree. - Enforcement: Under Paranoia Levels 2 through 5, isolated payload detections trigger an immediate block.
2. Embedded Payloads
An embedded payload occurs when suspicious syntax constructs are enclosed within larger natural language text, documentation, or product descriptions.
- Typical Scenario: A user posting in a technical forum discussing database tuning by quoting an example SQL query, or an article referencing a Log4j JNDI string.
- Enforcement: Under standard paranoia levels (2–4), the engine allows the request and asynchronously enqueues the sample to ALAP, preserving user experience while maintaining vigilance. Under strict mode (Level 5), embedded hits are blocked immediately.
Gadget Coverage & Engineering Scope
To ensure complete operational clarity, the following outlines the exact engineering boundaries of the current feature isolation implementation:
- Targeted Gadgets: Dedicated gadget isolation analyzers currently cover PHP/JSP dynamic webshells, Log4j JNDI injection, and short quoted/predicate SQL injection (constrained to fragments under 96 runes/characters).
- Document Shape Guards: Attack vectors such as XSS, Remote Code Execution (RCE), Server-Side Template Injection (SSTI), Server-Side Request Forgery (SSRF), and XML External Entity (XXE) are evaluated by specialized Document Shape Guards, operating independently of the short-gadget analyzer.
- Evidence Fallback: Detections classified as
embeddedbypass inline blocking below Level 5. Unclassified or ambiguous hits adhere strictly to deterministicblockableHitevidence rules and are never silently downgraded to embedded status. - Operational Guidance: Isolation mitigates false positives on known gadgets in rich-text workflows. For strictly structured API endpoints, enabling higher paranoia levels or schema validation remains recommended.
1.4.4 - Unified Management Surfaces & Authorization
CheeseWAF provides three dedicated management surfaces tailored for visual operations, headless terminal maintenance, and automated CI/CD workflows:
| Management Surface | Role & Intended Scenarios | Access & Invocation |
|---|---|---|
| Web Console | Visual operations, security policy management, real-time log querying, and attack map visualization | Access the configured HTTP/HTTPS management URL after setup. Docker Compose uses HTTPS at https://127.0.0.1:9443/ on the Docker host loopback (use an SSH tunnel for remote access). |
| CLI / TUI | Headless server administration, jump boxes, and rapid interactive terminal troubleshooting | Execute waf-cli or cheesewaf cli to launch the interactive terminal interface |
| RESTful API | CI/CD automation, external monitoring integration, and orchestration pipelines | Invoke /api/... endpoints using Session Cookie or Bearer API token authentication |
Unified Identity & RBAC Matrix
When setup.three_end_unified: true is configured, CheeseWAF synchronizes identity and authorization across all three surfaces:
- Universal User Credentials: Administrator and operator accounts provisioned in the Web console can be used directly for TUI login and API authentication.
- Consistent RBAC Enforcement: API Tokens created in the console’s System Management section inherit the exact RBAC permission matrix defined in
apisec.permissions. - Granular Roles: Built-in default roles include
admin(holding full["*"]permissions) andreadonly(scoped to["read:*", "read:cluster"]). - Exact identity fields: Usernames use the canonical 3–32 ASCII-character form documented in the CLI reference. Roles must exactly match configured
apisec.permissionskeys; leading/trailing/embedded Unicode whitespace, control characters (Cc), format/invisible characters (Cf), and permission expressions such as*or:are rejected. The server never trims or case-normalizes identity fields.
Operational Audit Trail
When apisec.audit.enabled: true is active, all configuration mutations, policy changes, and user management operations initiated via the Web Console, TUI, or REST API are written to the structured audit log specified by apisec.audit.path, ensuring enterprise-grade auditability.
Related Documentation
1.5 - Site Management & Reverse Proxy
In CheeseWAF, a Site is the fundamental administrative unit for reverse proxying and application security policies. A site binds inbound domain names (Host) to one or more backend origin upstreams (Upstream).
Provisioning Methods
- Web Console: Visual configuration, upstream monitoring, and policy tuning under the Sites page.
- RESTful API: Programmatic lifecycle automation via
GET/POST /api/sitesandGET/PUT/DELETE /api/sites/{id}. - Nginx Config Importer: Call
POST /api/nginx/importto parse and import existing Nginxserverblocks directly.
YAML Configuration vs. REST API Schema Note:
- YAML Configuration (
cheesewaf.yaml): Upstreams are structured objects (upstreams: [{address: "127.0.0.1:8080", weight: 1}]) and WAF settings are nested underwaf. - REST API DTO (
POST /api/sites): Uses a flat structure whereupstreamsis a string array (["http://127.0.0.1:8080"]) and WAF settings are flattened (waf_enabled,waf_mode,paranoia_level). Submitting nested objects directly to the REST API will return an unmarshaling error.
Site Configuration Schema
| Property | YAML Key Path | Type & Description |
|---|---|---|
| Site ID | sites[].id | Unique alphanumeric string identifier |
| Site Name | sites[].name | Human-readable site label |
| Bound Domains | sites[].domains | String array matching the inbound HTTP Host header |
| Origin Upstreams | sites[].upstreams[].address | Backend destination (host:port), supporting weight proportions |
| Dedicated Port | sites[].listen_port | Metadata field (for nginx import and UI display; WAF process routes traffic on primary listeners) |
| Load Balancing | sites[].loadbalance | Algorithm choice: round_robin, weighted, ip_hash, least_conn |
| Enabled | sites[].enabled | Boolean toggle; false halts reverse proxying for this site |
| WAF Enabled | sites[].waf.enabled | Whether request inspection is active |
| WAF Mode | sites[].waf.mode | block (drop malicious requests), monitor (record only; log accepted as alias), or off |
| Paranoia Level | sites[].waf.paranoia_level | Inspection strictness from 0 (disabled) to 5 (maximum paranoia), default 3 |
| Semantic Engines | sites[].waf.semantic_engines | Independent engine toggles for sql, xss, rce, lfi, xxe, ssrf, nosql, ssti |
| Custom Rules | sites[].waf.custom_rules | Site-scoped RE2 rules (supports batch CLI and Web UI import/export) |
| Path Rewriting | sites[].waf.rewrite | Internal silent path rewrite or HTTP 3xx redirection rules |
| Health Check | sites[].waf.health_check | Active probe path, check interval, and healthy/unhealthy thresholds |
| Trusted CIDRs | sites[].waf.access_control.trusted_cidrs | Fronting CDN/LB CIDR subnets for trusted client IP extraction |
Load Balancing Algorithms
For sites fronting multiple backend upstreams, sites[].loadbalance provides four distribution strategies:
round_robin(Default): Inbound requests rotate sequentially through all healthy upstreams. Ideal for identical backend server instances.weighted(Weighted Round-Robin): Requests are apportioned according toupstreams[].weight(e.g., a 3:1 weight distributes 3 out of every 4 requests to the primary upstream).ip_hash(Source IP Hash): Consistent hashing based on the client’s verified IP address keeps subsequent requests from the same user pinned to the same backend for session statefulness.least_conn(Least In-Flight Connections): Dynamically routes incoming traffic to the healthy upstream with the fewest active, incomplete requests, mitigating connection backlog on slow endpoints.
Upstream Health Checking
When health_check.enabled: true is set, CheeseWAF periodically issues HTTP health probes to each configured upstream path (health_check.path):
- When probe failures reach
unhealthy_threshold, the node is temporarily marked unhealthy and removed from the active routing pool. - Once the node recovers and consecutive successes meet
healthy_threshold, traffic dispatch automatically resumes. - If all upstreams fail health probes, fail-open fallback may retry only a safe, empty
GETorHEADrequest against configured upstreams. Non-idempotent methods (such asPOST/PUT) or any request carrying a body are not replayed.
Path Rewriting & Redirects
Rewriting rules define a matching regex pattern, a target replacement, and a redirect_code:
- Silent Rewrite (
redirect_code: 0): The URI path is modified transparently before reaching the backend upstream without altering the browser address bar. - External Redirect (
redirect_code: 301or302): Directly responds with an HTTP redirection header to the client.
Site Custom Rules Integration
Each site manages an isolated list of custom_rules:
- Visually configured or uploaded via the Rules page in the Web Console.
- Automated through CI/CD pipelines, for example
export CHEESEWAF_SITE_ID='site-demo'; export CHEESEWAF_RULES_FILE='rules.yaml'; cheesewaf rules import --site "$CHEESEWAF_SITE_ID" --file "$CHEESEWAF_RULES_FILE". - Evaluated in Phase 1 at Priority 250, short-circuiting malicious probes before syntax tree generation.
1.6 - Gateway Adapters
CheeseWAF-Adapters provides Go-first, self-hosted gateway adapters for CheeseWAF. It completely separates gateway-specific glue code from the core detection engine. By running as a lightweight daemon (adapterd) beside your reverse proxy or workload, it translates gateway-specific protocols into a standardized, versioned HTTP inspection contract and maps core security decisions back to native gateway responses.
Architecture & Design Principles
- Self-Hosted & Sidecar-First: Operates without external SaaS control planes or vendor dependencies. By default,
adapterddeploys as a local loopback process (127.0.0.1:9080) directly alongside the gateway. - Ultra-Thin Adapter Boundary: Focuses exclusively on protocol translation and response mapping. It never duplicates detectors, AST parsers, signature tables, or management state; all security decisions remain centralized in CheeseWAF core.
- Fail-Closed by Default: When the CheeseWAF core service is unreachable or encounters timeouts, the adapter returns HTTP
503 Service Unavailable. Traffic is never silently allowed unless explicitly configured. - Bounded Request Body Handling: By default, request bodies are not forwarded to the core. When explicitly enabled, body inspection is capped at a strict boundary (default 64 KB). Truncated payloads are flagged with
BodyTruncated=true; if the core returnsallowor times out, the adapter rejects the request with HTTP413 Request Entity Too Large. - Security Credentials & Network Policy: Gateway callers authenticate using the dedicated
X-CheeseWAF-Adapter-TokenHTTP header (never viaAuthorization: Bearer), restricted to validated CIDR blocks configured inCHEESEWAF_ADAPTER_TRUSTED_PROXY_CIDRS.
Versioned Inspection Contract (v1)
The adapter communicates with the CheeseWAF core via contracts/inspection/v1:
- Inline Inspection Endpoint: Accessible by default at
/api/v1/adapter/inspect, receiving normalized client metadata, TLS fingerprints, and bounded body content within a strict latency budget (default 100ms). - Core Security Actions:
allow: Permits the request and forwards it upstream.block: Terminates the request and renders a configured block page or status code.challenge: Triggers client verification (such as silent JS challenge or CAPTCHA).log: Permits the request while recording an audit entry (normalized to monitoring mode).
- Asynchronous Telemetry Endpoint: Hosted at
/api/v1/adapter/telemetry, receiving rate-limited, best-effort events without impacting real-time forwarding throughput.
Gateway Integration Examples
1. NGINX auth_request Configuration
Use NGINX’s ngx_http_auth_request_module to authorize incoming requests with adapterd:
2. Envoy ext_authz Configuration
Configure Envoy’s external authorization HTTP filter in the filter chain:
When Envoy indicates x-envoy-auth-partial-body: true, the adapter flags the body as incomplete and rejects the request with HTTP 413 unless the core explicitly blocks it, preventing large-payload truncation bypasses.
Runtime Configuration Reference
| Variable / Flag | Default Value | Description |
|---|---|---|
CHEESEWAF_ADAPTER_LISTEN / --listen | 127.0.0.1:9080 | Local network address for the adapter daemon |
CHEESEWAF_CORE_URL / --core-url | Required | Address of the self-hosted CheeseWAF data plane or core inspection service |
CHEESEWAF_CORE_INSPECT_PATH | /api/v1/adapter/inspect | Core inline inspection API path |
CHEESEWAF_CORE_TELEMETRY_PATH | /api/v1/adapter/telemetry | Core telemetry reporting endpoint |
CHEESEWAF_CORE_HEALTH_PATH | /healthz | Core health endpoint used for /readyz probe delegation |
CHEESEWAF_CORE_TOKEN | Empty | Bearer token used by adapterd to communicate with the core |
CHEESEWAF_ADAPTER_TOKEN | Empty | Dedicated token required from gateways in X-CheeseWAF-Adapter-Token |
CHEESEWAF_ADAPTER_TRUSTED_PROXY_CIDRS | 127.0.0.1/32,::1/128 | Trusted CIDR list permitted to provide forwarded client IP headers |
CHEESEWAF_ADAPTER_REQUEST_TIMEOUT | 100ms | Maximum execution budget for inline decisions |
CHEESEWAF_ADAPTER_FAIL_MODE | closed | Fail mode when core is offline: closed (HTTP 503) or open (HTTP 204) |
CHEESEWAF_ADAPTER_FORWARD_BODY | false | Enables bounded request body inspection |
CHEESEWAF_ADAPTER_MAX_BODY_BYTES | 65536 | Maximum body capture limit (64 KB) |
CHEESEWAF_ADAPTER_FORWARD_SENSITIVE_HEADERS | false | Permits forwarding credentials (Cookie/Authorization) to the core |
Roadmap
- Streaming Protocol: Envoy
ext_procadapter for streaming inspection of large request bodies and dynamic response header mutations. - Kubernetes Integration: Dedicated Kubernetes Sidecar Controller supporting automated injection and routing via Pod Annotations.
- Ecosystem Gateways: Native integrations for Kong, Apache APISIX, and Traefik.
1.7 - Security Protection Policies
CheeseWAF provides a defense-in-depth architecture spanning from network-level controls to application semantic analysis. Baseline protection policies are defined globally in protection and protection.policy, with support for granular per-site overrides via sites[].waf.protection_policy.
1.7.1 - AST Semantic Analysis Engine
CheeseWAF’s primary detection capability is powered by an Abstract Syntax Tree (AST) grammar analysis architecture rather than traditional brittle regular expressions. Inbound payloads undergo multi-layer recursive decoding (URL encoding, Unicode normalization, hex, and nested Base64) before being parsed into domain-specific syntax trees to evaluate true payload semantics.
Through systematic evaluation and remediation against 7 external real-world corpora using an independent Corpus Fidelity Classifier, the semantic engine achieves an independently verified 97.08% True Positive Rate (TPR).
Engine Configuration Matrix
Individual specialized semantic engines can be toggled per site via sites[].waf.semantic_engines:
| Engine Key | Attack Scope & Deep Detection Capabilities |
|---|---|
sql | SQL Injection: Major SQL dialect grammar parsing; integrated XPath injection parser; heavy time-blind injection detection (Cartesian product / generate_series); whitespace comment truncation resilience |
xss | Cross-Site Scripting: HTML/SVG tag balance analysis; fully split protocol scheme detection (detects scattered tokens like j a v a s c r i p t: and CDATA/HTML comment interspersal); obfuscated javascript: URI concatenation regex; dynsrc/lowsrc attribute probes; JavaScript string escaping; malformed event handler inspection |
rce | Command & Code Injection: Comprehensive command table alignment (including id, ls, echo, netstat, lsof); newline command chains; automatic basename extraction for absolute executable paths; ; + system function calls |
lfi | File Inclusion & Path Traversal: POSIX and Windows absolute path traversal (smart Program Files exclusion to eliminate false positives); deep UTF-8 folding; SSI server-side includes (<!--#exec) |
nosql | NoSQL Injection: Deep HTTP request header analysis (e.g., X-User-Filter); MongoDB shell escaping; isolation of malicious operators from legitimate query filter operators |
ssti | Template Injection: Jinja2, Twig, and common template grammar trees; quoted operand probes; direct expression detection when entire value is a template expression |
ssrf | Server-Side Request Forgery: URI parameter schema inspection; full request body URL detection treating the whole body as a potential fetch sink |
xxe | XML External Entity: DOCTYPE entity declarations, SYSTEM/PUBLIC external resource references, and parameter entity attacks |
webshell | Webshell & Malicious Scripts: Combines PHP execution primitive analysis with Shannon entropy measurement ($\ge$ 5.2) to accurately flag high-entropy Base64 one-liners and obfuscated droppers while eliminating false positives on repeated strings, JWT tokens, and minified code |
In production, keeping core engines enabled is recommended. If a service clearly lacks a specific stack (such as a static site without SQL backends), disabling that engine saves CPU cycles.
Latency Engineering & Pre-Filter Gating
To deliver deep syntax parsing without sacrificing microsecond-level latency, CheeseWAF employs several algorithmic safeguards:
- Cheap Substring Gating: Prior to expensive AST generation or complex regular expressions, constant-time substring pre-filters discard benign traffic in microseconds.
- Worker Pool & Request Context Forking: In Phase 2, semantic analyzers run concurrently over bounded worker goroutines with isolated context copies, merging results deterministically by priority.
- 100ms Hard Budget Deadline: If oversized adversarial inputs consume parsing time, the global deadline prevents request processing hangs and triggers the configured fallback policy.
Analysis Budget & Allowlists
Fine-grained controls in sites[].waf.semantic_policy allow tuning parsing behavior:
budget_exhausted_policy: Fallback action when syntax analysis exhausts its budget:auto(derives from web_attack level),open(availability-first pass),observe(log only), orclosed(challenge/strict block).path_allowlist: URI path prefixes that bypass semantic analysis entirely.param_allowlist: Parameter keys excluded from deep AST inspection.
Migration note: The canonical location is sites[].waf.semantic_policy.budget_exhausted_policy. Values left in older, non-canonical configuration locations are not read; move them manually under each site’s waf.semantic_policy block. When migrating legacy values, map pass to open, and map block or challenge to closed (the current closed mode prefers a challenge when analysis cannot finish). Leave the field empty or set it to auto to derive the effective action from the site’s web_attack level.
Global limits can be configured in sites[].waf.performance, including max_body_bytes (default 8MB), max_header_bytes, and proxy_timeout.
Outbound Response Inspection (Data Leak Prevention)
sites[].waf.response inspects upstream HTTP response bodies to prevent sensitive credential exposure:
- Detection Scope: Discovers AWS Access Keys, generic leaked credential patterns, and any additional patterns configured for the site. The built-in default set includes password/secret-key patterns; PEM private-key detection is available when explicitly included in
sensitive_patterns(the shipped site template does not enable it by default). - Pattern Precedence: When
sites[].waf.response.sensitive_patternsis non-empty, it replaces the built-in defaults rather than extending them; include every pattern you need in the site-level list. - Tuning Advice: For large file downloads or streaming media, restrict response inspection to JSON/HTML content types via path patterns.
For classification semantics regarding isolated attacks vs embedded long-text inputs, see Isolated vs. Embedded Payloads.
1.7.2 - Custom Regex Rules
The Custom Rule Engine operates as a Phase 1 Pre-Filter in the request pipeline (engine priority 250). It executes prior to the AST Semantic Analysis Engine (priority 290+). Custom rules are designed to intercept high-frequency reconnaissance, scanner headers, and custom application path blocks. When a rule triggers with a block action, execution short-circuits immediately, eliminating unnecessary AST parsing overhead.
You can manage custom rules visually in the Rules section of the Web Console (sites[].waf.custom_rules), via the cheesewaf rules CLI utility, or using REST APIs.
Configuration Example
Field Reference & Valid Enumerations
| Field | Type | Description & Validation Constraints |
|---|---|---|
id | String | Globally unique rule ID within the site. If omitted during import, the engine generates one automatically |
name | String | Human-readable rule title for logging and UI display |
pattern | String | Regular expression pattern (Go RE2 syntax; max 16KB per pattern, max 4096 compiled instructions) |
location | String | Target inspection location. Strictly limited to: uri, query, header, body, cookie (default uri) |
action | String | Action on match. Strictly limited to: block, log, challenge (default block) |
severity | String | Threat level: low, medium, high, critical (default medium) |
priority | Integer | Rule execution priority (-1,000,000 to 1,000,000). Lower numbers execute first |
enabled | Boolean | Rule enable flag (default true) |
Deterministic Enforcement & Policy Bypass
Custom rules represent explicit administrative intent rather than probabilistic detector signals. Within the data plane pipeline:
- Direct Execution: When a request matches a custom rule, the engine unconditionally and immediately executes the designated action (
block,challenge, orlog). - Exempt from Policy Thresholds: Unlike semantic detections, custom rule actions bypass
protection_policy.web_attackgates (such as minimum severity thresholds, model confidence filters, or aggregate risk score ceilings), guaranteeing deterministic enforcement as configured.
Security Constraints & Quota Limits
To prevent malformed or unbounded rules from causing performance degradation, the configuration validator enforces strict boundaries:
- Resource Limits: A single site supports up to 256 custom rules (
maxCustomRulesCount = 256). Import document size must not exceed 1MB, and total pattern length across all rules cannot exceed 256KB. The imported document must explicitly define thecustom_rulesroot key. - ReDoS Immunity: Backed by Go’s
regexp(RE2 guarantees linear-time execution, eliminating catastrophic backtracking ReDoS). Expressions exceeding 4096 compiled program instructions are rejected. - Deduplication Check: Rule IDs must be unique within each site. Duplicate
location + patterncombinations are strictly rejected. - Content-Disposition Sanitization: When exporting rule archives (
GET /api/rules/export), output filenames are strictly sanitized against an[A-Za-z0-9._-]whitelist, preventing HTTP response header injection and directory traversal attacks.
Batch Import, Export & Template Generation
CheeseWAF provides seamless CLI and Web UI workflows for importing and exporting rules in YAML and JSON:
1. CLI Management
2. Web Management Console
In the Rules page of the Web Console, click the Import / Export button in the header:
- Drag and drop or upload local
.yamlor.jsonrule definition files. - Inspect syntax validation and preview differences prior to committing.
- Download a full JSON or YAML rule backup with a single click.
Operational Best Practices
- Focus on Definitive Signatures: Use custom rules for known static probes (admin interfaces, sensitive files, scanner fingerprints). Defer complex application injection patterns (SQL injection, XSS) to the AST semantic engine.
- Leverage Short-Circuiting: Order high-confidence malicious signatures with lower
prioritynumbers to drop bad traffic early, minimizing server CPU load.
1.7.3 - IP, GeoIP & Client Fingerprinting
CheeseWAF enforces network-layer access controls at the outermost boundary of the request pipeline. Manage these controls visually under IP in the Web console, or define them in the configuration file under protection.ip.
Static Access Lists & Base Configuration
- IP Whitelist (
whitelist): Matching client IPs bypass subsequent IP restrictions, GeoIP rules, threat intel, bot challenges, and rate limiting (the semantic engine pipeline continues to inspect payloads for application security). - IP Blacklist (
blacklist): Matching client IPs are blocked at the network entry point, returning a block page without consuming semantic engine resources.
GeoIP Country Restrictions
Block traffic from specific countries using offline MaxMind MMDB databases:
- Set
geoip.enabledtotrue. - Point
geoip.databaseto a valid Country MMDB file path (e.g.,./data/GeoLite2-Country.mmdb). - Specify ISO 3166-1 alpha-2 two-letter country codes in
blocked_countries(e.g.,["US", "RU"]).
Threat Intelligence Integration
Import third-party threat intelligence IP feeds directly into CheeseWAF. The Web console supports automated scheduled synchronization, manual updates, and connectivity tests. Query intelligence status for specific IPs via the REST endpoint POST /api/ip/threat-intel/lookup.
Client Soft-Fingerprinting & Trusted Proxies
- Client Soft-Fingerprints: The Data Plane computes lightweight fingerprints based on client User-Agent and Accept-Language headers (sha256 8-byte prefix). ALAP review can persist malicious fingerprints as defense rules to serve as corroborating evidence.
- Trusted Upstream Proxies: When CheeseWAF is deployed behind a CDN, cloud load balancer, or reverse proxy, configure
sites[].waf.access_control.trusted_cidrsortrusted_proxy_providersto correctly extract client IP addresses fromX-Forwarded-Forheaders.
1.7.4 - Bot Challenges & CAPTCHA Mitigation
Modern web applications constantly face malicious automated traffic, including AI web scrapers, credential stuffing attacks, and automated vulnerability scanners. CheeseWAF provides multi-layered bot mitigation and challenge capabilities. Configure policies in the Web console under Bot Challenge and CAPTCHA Lab, or declare them in protection.bot and console.login.captcha.
Traffic Challenge Configuration
| Configuration Parameter | Description |
|---|---|
js_challenge | Issues silent JavaScript challenge and sets clearance cookie upon validation |
captcha | Overlays interactive CAPTCHA validation on top of JS challenge |
captcha_type | Challenge mechanism: pow (Proof of Work), slider (sliding puzzle), or image (character glyphs) |
cookie_name | Name of the authorization clearance cookie; defaults to cheesewaf_js_clearance |
path_prefixes | List of URI path prefixes where challenges are strictly enforced |
exempt_path_prefixes | Whitelist of URI prefixes exempt from challenges (e.g., /health) |
suspicious_user_agents | User-Agent substring matches that immediately escalate to full human verification |
Do not check challenge signing secret values into version control. When the value is empty or a known placeholder, setup/startup generates a strong runtime secret and persists it in the protected runtime configuration or runtime secret file according to the selected deployment; it is not an in-memory-only guarantee. Keep the runtime path and permissions private.
Challenge Types & Interaction Mechanisms
- Proof of Work (PoW / Altcha): Clients compute a cryptographic hash challenge in the browser background and submit the nonce via the
X-CheeseWAF-Altcharequest header. This is fully frictionless for real users while making automated concurrent scraping computationally prohibitive. - Sliding Puzzle (Slider): Analyzes mouse drag trajectories and validates minimum drag timing thresholds (configured via
slider_captcha_*). - Character Image (Image): Supports configurable string lengths, image dimensions, and audio assistance limits.
- Experimental Behavioral Tests: Includes gesture curves, scratch-off, and icon point-and-click puzzles. Verify user experience in the console CAPTCHA Lab before rolling out to production traffic.
Custom background images and iconography can be uploaded via /api/captcha/assets.
Management Console Login Defense
console.login.captcha protects the Web Management Console login endpoint (completely isolated from business data plane traffic), supporting slider puzzles with optional PoW verification.
The source template enables the management-login slider CAPTCHA by default (console.login.captcha.enabled: true). After initialization, the first browser login therefore requires completing the human-verification challenge in addition to the username and password. For local test fixtures only, set console.login.captcha.enabled: false in a runtime configuration copy and restart; do not disable this control in production merely to bypass acceptance checks.
Additionally, enable console.login.security_entry to obscure the management portal behind an obfuscated path and pre-shared authorization cookie.
Waiting Room Queue Scheduling
Enable waiting_room: true and specify waiting_room_max_active to gracefully hold excess concurrent clients in an organized queue during flash sales or traffic surges, preventing origin resource exhaustion. The waiting room is effective only when the global protection.policy.bot_cc policy is not off and its action is challenge; enabling the site waiting-room flag alone is not sufficient. See Rate Limiting.
1.7.5 - Rate Limiting & Traffic Shaping
CheeseWAF integrates a high-performance sharded sliding-window counter rate limiting algorithm on the Data Plane to smooth out traffic spikes and mitigate HTTP flood / CC attacks. Configuration is located under protection.ratelimit, and can be updated dynamically via PUT /api/protection/ratelimit.
Base Configuration Example
| Parameter | Type | Description |
|---|---|---|
enabled | Boolean | Master switch for Data Plane rate limiting |
requests | Integer | Baseline request quota permitted within the rolling window |
window | Duration | Calculation time window (e.g., 60s, 1m) |
burst | Integer | Extra burst capacity accommodating temporary traffic surges |
This module enforces global/client-level traffic shaping on the Data Plane. For fine-grained rate limits targeting specific API endpoints (HTTP method + path), see API Security Rate Limits.
Limit Exceeded Actions
When a client’s request rate exceeds the sharded sliding-window counter capacity, the system executes one of the following actions:
- HTTP 429 Block Page: Responds immediately with HTTP 429 Too Many Requests and a customized error page.
- Waiting Room Scheduling: If Waiting Room Mechanism is active and the global
protection.policy.bot_ccpolicy is enabled with actionchallenge, excess requests are smoothly queued rather than dropped.
During initial rollout, use generous limits and observe 1–2 weeks of production traffic before tightening requests and burst thresholds.
1.7.6 - Access Control Lists (ACL)
Access Control Lists (ACL) execute at the front of the traffic processing pipeline, offering ultra-low overhead filtering to immediately reject known diagnostic endpoints, probe paths, or enforce mandatory request headers. Configure ACLs under protection.acl, or update them dynamically via PUT /api/protection/acl.
Configuration Example
Schema Attributes
| Field | Description |
|---|---|
method | Target HTTP method (e.g., GET, POST); leave empty to match any method |
path_prefix | Matching URI path prefix (e.g., /debug, /actuator) |
header | HTTP header key to evaluate; leave empty if unconstrained |
header_value | Expected or rejected value for the specified header |
action | Action on match: block, log, or challenge |
severity | Threat severity recorded in security logs and audit events |
ACL evaluates enabled rules in declaration order, using case-normalized method checks, literal URI-prefix comparisons, and exact case-insensitive header-value comparisons. For complex regex-based pattern matching, use Custom Regex Rules.
1.7.7 - Block Pages & HTML Sanitization
When an inbound request is blocked by IP reputation, ACLs, Bot defense, or the AST semantic engine, CheeseWAF renders a structured block page response. Managed under block_page, templates can be visually previewed, edited, and deployed within the Block Pages view in the Web Console.
Basic Configuration
Template Lifecycle & Sandboxed Previews
- Built-In Modern Designs: Enumerate built-in response templates via
GET /api/block-pages/templates. - Sandboxed Rendering: Preview custom templates safely in an isolated iframe (
POST /api/block-pages/preview) prior to publishing globally. - Custom HTML Uploads: Call
POST /api/block-pages/uploadto upload custom branding, or revert to defaults viaDELETE /api/block-pages/custom.
HTML Sanitization Standards (SanitizeBlockPageHTML)
To prevent custom block pages from introducing Stored XSS or phishing vectors, CheeseWAF enforces strict sanitization on all custom HTML inputs before persistence:
1. Tag Whitelist
Only safe layout and typographic tags are permitted:
- Structure:
html,head,body,title,main,section,header,footer,div,span - Typography:
h1–h6,p,strong,em,b,i,small,pre,code,br,hr - Lists & Tables:
ul,ol,li,table,thead,tbody,tfoot,tr,th,td - Assets & Style:
a,img,style,meta
2. Active Script & Event Stripping
- Zero Scripts: All
<script>elements and HTML comments are completely removed. - Event Handler Neutralization: Attributes prefixed with
on(e.g.,onclick,onload,onerror) are excised. - Form Action Protection:
formaction,action, andmethodattributes are stripped to prevent credential-harvesting forms. - Redirect Prevention:
<meta>elements only permit thecharsetattribute;http-equiv="refresh"and arbitrary header injections are rejected.
3. CSS Style Sanitization
@importrules inside<style>tags or inlinestyleattributes are stripped.- Risky CSS primitives such as
javascript:,vbscript:,expression(,behavior:, and-moz-bindingare removed.
4. URL Scheme Controls
- The
hrefandsrcattributes are strictly restricted tohttp,https,mailto, andtel. <img>elements additionally support embedded Base64 image payloads (data:image/*;base64,...); arbitrary data URIs are discarded.
Traceability & Operational Guidelines
- Global Trace ID Correlation: Block pages dynamically display a unique request
traceId. When users report false positives, operators can correlate the exact rule evaluation chain under Monitoring & Logs. - Information Leakage Prevention: Custom block templates should avoid revealing backend hostnames, private IPs, or internal technology stacks to external clients.
1.8 - API Security & Governance
With the widespread adoption of single-page applications and microservices, API endpoints represent a primary attack surface. CheeseWAF’s API Security module delivers automatic endpoint discovery, strict contract schema validation, stateless JWT authentication, and route-level rate limiting.
Configure settings visually in the Web console under API Security, or define them in configuration files under the apisec block.
1. Automated API Asset Discovery
When apisec.discovery.enabled: true is active, CheeseWAF samples live request streams across window intervals up to sample_limit volumes, automatically clustering URI paths into an API asset inventory:
- Static Path Filtering: Configure
ignore_prefixesto exclude static assets (such as/static,*.css, or image paths). - Asset Query Endpoint: Invoke
GET /api/apisec/endpointsto retrieve the current inventory of discovered endpoints and traffic statistics. - Contract Testing: Invoke
POST /api/apisec/validateto validate a test request against registered schemas.
2. Request Schema Validation
Schema validation enforces strict structural contracts on incoming requests, preventing unauthorized parameter injection and parameter pollution:
Supports validation of HTTP methods, path regular expressions, mandatory query/body parameters, mandatory HTTP headers, and maximum allowable body payload sizes (max_body_bytes).
3. JWT & JWKS Authentication
Enforce stateless JSON Web Token authentication at the proxy layer via apisec.auth:
- Claim Verification: Validates cryptographic signatures, token issuers (
iss), audiences (aud), timestamps (exp/nbf), and allowed signing algorithms. - Key Providers: Supports symmetric shared secrets, local PEM certificate files, inline PEM strings, local JWKS files, and remote
jwks_urlendpoints. - Automated Caching & Rotation: Remote JWKS keys are cached locally in
jwks_cache_fileand automatically refreshed according tojwks_refresh_interval.
4. Route-Level Precision Rate Limiting
Unlike global Data Plane sharded sliding-window counter limiting, API rate limiting applies strictly to specific HTTP method and path combinations (such as sensitive authentication or SMS dispatch endpoints):
5. RBAC Permission Matrix
apisec.permissions defines role-based access control mappings for the management plane:
For the mapping between permission identifiers (such as read:sites, write:protection, manage:api_tokens) and REST API endpoints, see RESTful API Reference.
1.9 - Edge Optimization: Headers, Caching & Compression
CheeseWAF provides edge acceleration capabilities at the reverse proxy layer to optimize response latency and reduce origin bandwidth consumption. Manage these settings visually under Edge in the Web console, or define them in configuration files under the edge block.
1. HTTP Response Header Rewriting
- Set Headers (
set): Appends custom tracking or security headers (e.g.,X-Content-Type-Options: nosniff). - Strip Headers (
delete): Removes sensitive internal origin response headers (such asServer,X-Powered-By, or internal debug tokens) before responses reach the public internet.
2. Static Asset Proxy Caching
- Path Targeting: Specify path prefixes in
path_prefixesstrictly for purely static assets (e.g., CSS, JS, fonts, images). - Security Caution: Never configure caching rules for authenticated dynamic API endpoints or personalized HTML pages.
3. High-Efficiency Response Compression
- Compression Algorithms: Supports Brotli (
br) and standard Gzip (gzip) algorithms. - Trigger Conditions: Responses are compressed only when payload sizes exceed
min_bytes(e.g., 1024 bytes) and match defined MIME types (text/*,application/json,application/javascript,image/svg+xml).
1.10 - TLS & Certificate Management
CheeseWAF provides comprehensive TLS/HTTPS cryptographic capabilities, covering secure transport encryption for the management plane as well as automated certificate provisioning, renewal, and HTTP/3 support for business traffic.
Manage certificates visually in the Web console under SSL, or configure settings under server.admin_tls and tls.
1. Management Plane TLS Configuration
- Container Default Behavior: The Docker deployment image enables management TLS by default, generating a self-signed certificate upon initial container launch.
- Production Requirements: If the management plane is exposed over public networks, replace self-signed certificates with a trusted CA-signed certificate.
2. Business Site TLS & HTTP/3 Configuration
- Data Plane Listeners: Configure
server.listen_tlsto enable an HTTPS ingress listener; it has no default value and remains disabled until explicitly set. Enable HTTP/3 withserver.http3.enabled: true;server.listen_http3may be set explicitly and otherwise falls back to the TLS listener (or:443when neither address is set). - TLS Version Constraints: Use
min_versionto enforce minimum protocol versions (e.g.,1.2or1.3). - HSTS Enforcement: Setting
hsts: trueautomatically injects theStrict-Transport-Securityheader into outbound responses. - HTTP/3 (QUIC) Support: Set
server.http3.enabled: trueto enable UDP-based HTTP/3 support (requires an active TLS listener).
3. ACME Automated Certificate Issuance & Renewal
CheeseWAF natively supports the ACME protocol for automated certificate management (e.g., Let’s Encrypt):
- Query DNS Providers: Call
GET /api/acme/providersto list the DNS API challenge providers that are configured and enabled in the running instance; this is not a catalog of every provider supported by the implementation. - Issue Certificates: Invoke
POST /api/sites/{id}/acme/issuefor a site to automatically perform DNS challenge verification and bind the issued certificate. - Secure Key Storage: ACME account private keys and generated certificates are persisted securely in the runtime data directory; do not commit them to Git.
1.11 - ALAP Asynchronous Review & Self-Learning
ALAP (AI Large-Language-Model Auto Pilot) serves as CheeseWAF’s out-of-band analytical brain. By decoupling LLM semantic reasoning from real-time proxying, it introduces generalized intelligence without introducing latency into the forwarding data path.
Configured under the ai block, capabilities are managed across the AI Settings and Threat Review sections of the Web Console.
1. Asynchronous Queue & Concurrency Claims
After response delivery completes, boundary samples and embedded attacks are pushed to the background review queue:
- Protocol Adapters: Background workers adapt prompts to OpenAI Chat Completions or Anthropic Messages protocols according to
ai.provider. - Decoupled Guarantee:
ai.async: trueensures real-time traffic forwarding never blocks on third-party model inference. - Concurrency Decision Claims: When multiple operators collaborate, the persistence layer uses atomic decision claims (
review_decisionslocks) to prevent race conditions and duplicate actions, while bounding queue retention.
2. Threat Triage & Operator Decisions
Security teams can audit and act upon threat findings via the console or REST API:
- Queue Inspection: Call
GET /api/reviewto fetch flagged samples and model confidence scores. - Decision Submission: Call
POST /api/review/{id}/decideto mark samples as verified threats, false positives, or promote them to persistent protection rules. - Strict Invariance: Payloads blocked under Paranoia Level 5 represent physically terminated connections and cannot be retroactively passed. An operator may still submit a separate review decision (payload/URI/IP/fingerprint) to create the selected rule.
3. Automated Rule Adoption & Fail-Closed Guardrails
When sites[].waf.semantic_policy.auto_agree: true is enabled, the system automatically translates high-confidence malicious assessments (high or critical) into a site-scoped custom payload rule. Auto-agreement itself does not create global IP denylists or client-fingerprint bans; those remain separate, explicit operator actions.
Fail-Closed Invariance: Proposed rules that fail syntax validation, lack clear site associations, or fall below confidence thresholds fail closed. The engine never injects unverified rules into the active data plane.
4. AI Copilot Tool Approvals & Replay Protection
CheeseWAF includes a streaming AI copilot (POST /api/ai/assistant using Server-Sent Events):
- Actor & Preview Binding: When the assistant generates actions affecting network bindings, site definitions, or rule tables, it requires explicit approval via
/api/ai/tools/approvals. Approval tokens are cryptographically bound to the authenticated operator (actor), the exact parameter preview fingerprint, and execution state, preventing replay attacks and privilege escalation. - RBAC Scope Separation:
use:ai: Query and interactive chat dialogs.write:ai: Modifying AI settings and triggering self-learning jobs.approve:ai: Authorizing high-risk system-level tool executions.
5. Scheduled Self-Learning Analytics
CheeseWAF includes automated periodic clustering of access logs and attack samples:
- Configuration Properties:
min_confidence: Minimum confidence score required to propose a rule (default 0.995).min_events/max_events: Sample bounds for unsupervised clustering.max_rules_per_run: Maximum rules synthesized per execution (default 3) to prevent rule bloat.dry_run: Simulation mode; generates analytical reports without modifying active rules.
- Manual Trigger: Invoke
POST /api/ai/self-learning/runto execute immediate cluster analysis over recent traffic.
1.12 - Plugins & CRP Specification
CheeseWAF defines CRP (CheeseWAF Resources Package) as its signed resource-package format and provides local offline verification and staging commands. Release policy and developer instructions are maintained in CheeseSec_Plugin and CheeseSec_Plugin_Docs.
CRP v1 Archive Layout
The CheeseWAF CRP v1 parser requires resource packages to be standard ZIP archives containing only the following three entries. Any extra files or unknown directories cause immediate admission rejection (Hard Reject):
Manifest Schema Reference
The manifest.json file uses strict schema validation and rejects unknown JSON properties:
| Field Name | Type | Description |
|---|---|---|
api_version | String | Manifest specification version (fixed to crp/v1) |
kind | String | Resource package type (detector, model, or ruleset) |
name | String | Human-readable plugin name |
plugin_id | String | Globally unique plugin identifier |
version | String | Semantic version string (e.g., 1.0.0) |
namespace | String | Plugin namespace (official, enterprise, or community) |
publisher | String | Publisher entity name |
source | String | Distribution source ID (must exist in trusted source registry) |
source_root | String | Identifier of the bound signature trust root |
release_sequence | Integer | Monotonically increasing sequence number (rollback rejected) |
digests | Object | Multi-algorithm digests of the archive (SHA-256, SHA-1, MD5) |
artifact | Object | Artifact descriptor containing name, size, and digests |
Signature Verification & Offline Admission
CRP archives require multi-party threshold signatures using Ed25519:
- Trust Roots & Source Registry: Admission verifies public key fingerprints and validity windows against
policy/trust-roots.jsonandpolicy/source-registry.json. No outbound CRL or OCSP network calls are made. - Signature Thresholds: Defined by
policy/trust-levels.json, requiring official packages to meet threshold criteria (such as 2-of-3 quorum signatures). - Air-Gapped Operation: In air-gapped environments, the daemon verifies complete cryptographic integrity locally as long as trust roots are installed.
Command-Line Operations
CheeseWAF provides dedicated subcommands for offline verification and local staging:
1. Verify Package (crp verify)
Validates archive format, digest consistency, and signatures without installing, executing, or accessing the network:
2. Stage Package (crp stage)
Persists verified packages into protected, content-addressed staging slots (restricted to owner-only read/write permissions, without activating):
3. Explicit Temporary HTTPS Probe (temporary-online probe)
For constrained environments requiring remote connectivity testing, CheeseWAF provides an explicit, single-use HTTPS probe. This command requires administrator password stdin, TLS leaf certificate pinning, and records metadata-only audit logs to <data-dir>/audit/netlease.jsonl:
Distribution Endpoints
- Catalog Service:
https://store.cheesesec.com(read-only metadata) - OTA Index Service:
https://ota.cheesesec.com(read-only release indices) - Immutable Resource Store:
https://res.cheesesec.com(read-only SHA-256 content-addressed artifacts)
Offline Analytics Boundary (DuckDB)
The DuckDB extension operates as an asynchronous, host-provided one-shot-job rather than a persistent service on the request path. The job reads redacted Parquet audit snapshots to produce structured analysis-record/v1 outputs, ensuring offline analytical queries run in an isolated sandbox without affecting real-time WAF throughput or forwarding latency.
1.13 - Observability, Logging & Threat Attack Map
CheeseWAF provides end-to-end observability, including structured JSON access logs, standard Prometheus metrics, multi-channel alerting, and an interactive real-time threat attack map.
Configured under logging and monitor, these capabilities are visualized across the Dashboard, Logs, Monitor, and Attack Map modules in the Web Console.
1. Structured Access Logs
- Rotation & Retention: Automatically rotates files based on size (
max_size) and retains a configurable number of historical backups (max_backups). - Trace ID Correlation: Every request receives a globally unique
traceIdfor end-to-end tracing across all processing stages. - Log Support Bundles: Execute
cheesewaf logs packto immediately generate a timestamped ZIP archive containing all runtime logs. - External Sinks: Asynchronously stream logs to ClickHouse, PostgreSQL, VictoriaLogs, or Elasticsearch. See Storage & Scheduler Architecture.
2. Prometheus Metrics & Remote Write
- Scrape Endpoint: When
public: false, scraping/api/metricsrequires an administrative Bearer token. Settingpublic: trueexposes/metricsdirectly at the root path. - Remote Write (Protobuf Streaming): Periodically pushes metrics directly to compatible collectors using the official Prometheus Remote Write protocol format.
3. Alerts & Notification Channels
Configure alert thresholds for anomalous drop surges (high-block-rate) or storage exhaustion (disk-usage):
- Notifiers: Deliver notifications via standard HTTP Webhooks (enterprise platforms like Slack, DingTalk, WeChat Work, and Lark connect via their incoming bot webhook URLs).
- In-App Notifications: Event alerts are mirrored to the system notification bus and retrievable via
/api/notifications.
4. Threat Attack Map (100% Offline & Compliance Ready)
Navigate to /attack-map or fullscreen /attack-map/screen to monitor inbound attack geolocations and threat distributions in real time.
The attack map is engineered for air-gapped security and compliance:
- Certified National Boundaries: Integrates officially approved China border geometries and the South China Sea ten-dash line.
- Licensed Gaode World Polygons: Uses licensed country and regional polygon datasets.
- 3D Offline Earth Canvas: Eliminates all external dependencies on public OpenStreetMap (OSM) raster tile servers. The 3D globe operates completely offline, preventing external DNS leakage and guaranteeing 100% availability in air-gapped, isolated networks.
1.14 - High Availability & Cluster Federation
For large-scale, multi-node deployments, CheeseWAF provides a cluster interconnect for mTLS node identity, health and heartbeat reporting, topology/status, and orchestration hooks. The interconnect is not a site-policy replication channel. The current runnable path is a builtin single-node coordinator; selecting etcd records the shared-cluster requirement but has no etcd-backed coordinator in this binary, so it fails closed rather than falling back from a shared deployment to heartbeat election. The commercial target is native-raft for desired-state ordering, epoch fencing, and rollback references, with PostgreSQL as durable management truth. Until that migration is complete, this page’s etcd commands describe a contract and are not evidence that native-raft is already shipped.
Cluster administration is accessible via the Cluster module in the Web Console, the cheesewaf cluster CLI commands, or REST APIs at /api/cluster/*.
1. Core Architecture & Configuration
The default standalone configuration:
The following values describe the current interconnect and admission contract; they do not turn the current binary into a production multi-node HA deployment:
- Set
deployment.mode: clusterandcluster.enabled: true, then assign a consistentcluster_id. - Assign a globally unique
node_idto each physical or virtual instance. - Configure
interconnect.advertise_addras the routable IP/port accessible by peer nodes. - Keep
mtls_required: trueand configure trustedca_file,cert_file, andkey_filepaths.
The built-in consensus provider is intentionally limited to a single node and keeps only an in-memory configuration-version log. Selecting cluster.consensus.provider: etcd with etcd_endpoints records the required shared-cluster contract, but the current binary has no etcd-backed coordinator and therefore remains in protection mode instead of pretending that heartbeat state is consensus. The staged native-raft contract is documented in Commercial Architecture; the separate command’s current startup and join limits are in Standalone Control Runtime. Neither page enables native-raft through this configuration key.
Split-Brain Protection & Majority Quorum
cluster.protection.freeze_writes_without_majority: When network partitioning prevents forming a majority quorum, configuration mutations are automatically frozen to prevent state divergence.allow_traffic_in_protection_mode: Ensures that the data plane continues forwarding and protecting traffic during read-only protection mode.
2. Cluster CLI Command Suite
CheeseWAF includes a CLI surface for local cluster initialization, token/certificate operations, and heartbeat checks. These commands expose the current compatibility contract; they do not make the unwired shared-cluster backend production-ready:
1. Controller Setup & Token Issuance
cluster init only writes configuration; the service initializes its cluster identity when cluster mode starts. Before adding remote peers, use routable values for both addresses (for example, rerun with --force --advertise-addr 10.0.0.1:9444 --listen 0.0.0.0:9444) and configure the explicit etcd contract described above. Ensure network routes, firewalls, and cluster discovery backends are reachable across all cluster nodes.
2. Worker Node Joining & Certificate Rotation
--ca-file is the CA used to verify the controller’s HTTPS management endpoint, not the cluster CA returned during enrollment. It is optional when the controller certificate chains to the system trust store; pre-provision the controller’s private CA (for example, admin-ca.crt) when needed. The join command generates the node’s local key and CSR, receives the cluster CA and signed certificate, and writes them under the configured data directory; the private key is never sent to the controller.
Certificate rotation likewise requires a configured existing node identity/certificate path and exactly one API-token source (--api-token, --api-token-file, or --api-token-env). It writes replacement files locally; follow the service’s reload/restart procedure before expecting the new certificate to be used.
3. Ansible Automated Deployment
The current POST /api/cluster/deploy/ansible exporter generates a CheeseWAF daemon bootstrap package only (inventory, variables, playbook, role, configuration template, and README). It does not include a CWEDP agent and is not a ready-to-run production bundle: before execution, provide a verified binary URL and SHA-256, service paths, and (for more than one node) the external etcd endpoints required by the generated role. The optional deploy/ansible/full.yml playbook can install a pull-only CWEDP agent only in its explicit provision_only=true hand-off mode, after all external control-plane preflight values plus the agent URL and SHA-256 are supplied; it still does not make CheeseWAF production storage runnable. Plugin CRP installation, upgrade, rollback, signing, promotion, and authenticated distribution are never performed by Ansible; those lifecycle operations belong to CWEDP.
- Playbook Generation API: Call
POST /api/cluster/deploy/ansiblewith a list of nodes, roles (waf/monitor), SSH ports, and region metadata. The response is JSON with afilesobject mapping relative filenames (for exampleinventory.ini,playbook.yml, and role files) to their text contents. Save those entries as a package, fill in the required verified binary variables and etcd settings, review the generated commands, and only then run the playbook. - Web UI Export: In the Cluster view of the Web Console, configure the target node inventory and click “Export Ansible Bundle” to download the generated bundle for review and completion; it is not a ready-to-run production package.
4. Cluster REST API Reference
| Operation | REST API Route | Description |
|---|---|---|
| Cluster Health | GET /api/cluster/status | Query overall topology, software versions, and quorum state |
| Node List | GET /api/cluster/nodes | List active nodes, IPs, and heartbeat timestamps |
| Issue Join Token | POST /api/cluster/join-tokens | Mint a temporary join token |
| Join Node | POST /api/cluster/join | Join cluster carrying an authorized token |
| Rotate Certificate | POST /api/cluster/nodes/{id}/rotate-certificate | Rotate interconnect mTLS certificates |
| Revoke Node | POST /api/cluster/nodes/{id}/revoke | Revoke node certificate and evict from cluster |
| Ansible Bundle | POST /api/cluster/deploy/ansible | Export Ansible deployment playbooks |
| Rolling Upgrade | POST /api/cluster/orchestrate/rolling-upgrade | Create a sequential node upgrade task |
| Upgrade Rollback | POST /api/cluster/orchestrate/rolling-upgrade/{id}/rollback | Create a reverse-order rollback task from backup state |
| Consensus State | GET /api/cluster/consensus | Query current cluster consensus status and coordinator details |
The default provider is builtin, which is intended for single-node deployments. Multi-node or shared-configuration environments must configure external etcd endpoints (etcd_endpoints) to coordinate distributed state and leader elections.
1.15 - Commercial Platform Architecture
This document outlines the architecture specifications for CheeseWAF commercial platforms, covering control planes, data planes, plugin security standards, and air-gapped operations.
Data Plane and Control Plane
The architecture strictly decouples traffic inspection from administrative management:
- WAF Data Plane: Dedicated to high-throughput inspection, reverse proxy forwarding, and local policy snapshot evaluation with minimal latency.
- Dedicated Control Plane (
cheesewaf-control): Orchestrates cluster topology, policy updates, and cluster-wide state convergence, exposing loopback-bound health, readiness, and proposal endpoints. See Standalone Control Runtime for runtime details. - State Storage & Clustering: Production deployments support external PostgreSQL for durable management state, native-raft for cluster consensus and topology synchronization, and Redis for distributed leases and ephemeral caching. Missing production dependencies fail closed to ensure state integrity.
Security Plugins & CRP Specification
CRP (CheeseWAF Resources Package) defines the distribution format for offline security rules:
- Trust Roots & Signatures: Supports official Vendor Roots and enterprise private roots using Ed25519 threshold signatures (such as 2-of-3 signatures).
- Verification & Staging: The CLI provides
crp verifyandcrp stagecommands to validate digests, check release sequences, and stage assets into content-addressed runtime paths. - Activation & Rollback: Production CRP workflows leverage policy snapshots, native-raft fencing, and mTLS verification to ensure zero-downtime, tamper-proof activations and atomic rollbacks.
- Release & Updates: Validates signed package indices over read-only HTTPS, preserving cryptographic verification and deterministic staging.
DuckDB serves as an offline analytics extension, executing asynchronous one-shot jobs over redacted Parquet audit snapshots to output structured analysis-record/v1 entries, operating completely out-of-band to prevent interference with real-time request processing.
Air-gapped Operations & Ephemeral Egress
In air-gapped or restricted VPC environments, offline policies deny unsolicited outbound connections while preserving data plane routing to upstreams:
- The
cheesewaf temporary-online probeutility provides an ephemeral HTTPS broker with administrator approval, IP/TLS certificate pinning, and audit logging. - Outbound access requires explicit operator confirmation and time-bounded leases.
Diagnostics & Operational Safety
- Diagnostic payloads enforce schema validation and redaction to prevent sensitive business information from leaving the cluster.
- Administrative workflows adhere to safe operational principles: explicit confirmation for high-risk actions, reduced prompts within active sessions, and re-confirmation upon environment changes.
1.16 - Storage & Scheduler Architecture
CheeseWAF uses lightweight embedded persistence alongside optional external log sinks. The current management store is SQLite; the external sinks do not replace it.
Storage and task scheduling are managed via the Operations and System views in the Web Console (storage, setup.data_dir, and scheduler).
1. Storage profiles
CheeseWAF operates under storage.profile: temporary by default. The SQLite schema stores users, admin sessions, sites, site rules, review items, notifications, promotion deadlines, TOTP replay markers, and audit records. Runtime configuration remains in the YAML file.
storage.profile: production requires an independent storage.management_postgresql.dsn, separate from storage.postgresql.dsn. If external storage is unconfigured or unreachable, the daemon enforces fail-closed safety and terminates with ErrProductionStorageUnavailable to prevent persisting production data into temporary storage.
storage.postgresql is an optional asynchronous access-log sink, not the management database.
Configuration migration
Older configurations that omit storage.profile default to temporary. When migrating to production mode, ensure the external database endpoint is verified and accessible.
Versioned Schema Migrations
CheeseWAF runs an automated transaction-safe migrator. The current supported SQLite schema is version 5:
- v1 (Initial Schema): Base tables for sites, users, credentials, and review queue items.
- v2 (Review Decision Claims): Introduces concurrency locks and operator metadata tracking for review triage.
- v3 (Legacy Rules to Site Custom Rules): Smoothly converts legacy global rule tables into standardized site-scoped custom rule collections.
- v4 (Historical Username Repair Audit): Adds the append-only
user_username_repairstable used by the explicit immutable-ID repair command; existing usernames are not rewritten. - v5 (User Credential Epochs): Adds
credential_epochtousersandadmin_sessions. Security changes advance the user epoch, and session validity requires the session epoch to match the current user epoch, so old sessions cannot remain active after a credential change.
Concurrency & Data Integrity Guarantees
- WAL Mode (Write-Ahead Logging): Configured automatically via
PRAGMA journal_mode = WAL. Readers can proceed while a writer is active, while writes remain serialized by the single SQLite connection and bounded by the configured busy timeout. - Foreign Key Constraints: Enforced by default via
PRAGMA foreign_keys = ONto protect referential integrity. - Forward-Compatibility Lock (
ErrSQLiteSchemaTooNew): If a database file was written by a newer CheeseWAF binary, an older daemon refuses to open it, preventing accidental schema degradation or corruption.
2. Redis ephemeral coordination
Redis configuration is present for planned integrations, but the current runtime does not use Redis for Bot challenges, sessions, leases, or replay state. Enabling storage.redis alone does not change the active management store.
The current challenge implementation uses the configured non-Redis backend. Native-raft and a PostgreSQL management source of truth are planned commercial architecture, not active storage paths.
3. External Log Sinks
For enterprise-scale access logs, CheeseWAF streams events asynchronously to external backends:
| Storage Sink | Use Case & Integration |
|---|---|
storage.clickhouse | High-throughput column-oriented OLAP storage for real-time aggregation across billions of records |
storage.victorialogs | Lightweight log aggregation featuring high compression ratios |
storage.postgresql | Standard relational database integration for corporate SIEM pipelines |
storage.elasticsearch | Direct indexing into Elasticsearch or OpenSearch clusters for Kibana dashboards |
storage.redis | Reserved integration; not the current Bot challenge backend |
To prevent SSRF attacks, external storage endpoints for ClickHouse, VictoriaLogs, and Elasticsearch resolving to private IP ranges require setting allow_private_endpoint: true (PostgreSQL and Redis drivers do not carry this field). Test connectivity via POST /api/system/storage/test prior to cutover.
4. Automated Task Scheduler
The built-in scheduler can run log cleanup, configuration snapshot, and security-report tasks. A configuration snapshot is not a complete database export, and the task is disabled by default in the source template:
- Task Management: Query and adjust task schedules via
GET/PUT /api/scheduler/tasks. - Execution History: Inspect execution durations and exit statuses via
GET /api/scheduler/history.
5. Backup & Space Recovery
- Backup API status:
POST /api/backup/exportandPOST /api/backup/restoreare registered routes, but the current handlers return HTTP 501 (BACKUP_EXPORT_NOT_IMPLEMENTED/BACKUP_RESTORE_NOT_IMPLEMENTED). Do not treat them as a restorable backup workflow. Use the SQLite online-backup procedure in Operations & Security Hardening, or the scheduler’s configuration snapshot task, until a verified archive/restore format is shipped. - Disk Space Defragmentation: Reclaim operations apply to the active storage profile; SQLite
VACUUMis only used by temporary mode.
6. Encrypted diagnostic queue
Diagnostic data strictly follows bounded local queueing and application-side envelope encryption with time-bounded TTL and redaction controls, ensuring sensitive business data remains private within the internal network.
1.17 - Web Management Console
CheeseWAF includes a modern single-page visual management console built with React and hosted directly by the cheesewaf process on its management listener. After completing System Setup, navigate to the configured management endpoint. Standalone deployments may use the configured HTTP/HTTPS scheme; the official Docker Compose file publishes the admin listener as HTTPS on the Docker host loopback, so use https://127.0.0.1:9443/ there (or an SSH tunnel), not a remote host URL unless you explicitly change the bind address.
The console enforces session cookie statefulness with strict double-submit CSRF defenses (dynamically adjusting Secure flags when running on unencrypted local loops and enforcing them under HTTPS), and supports enabling CAPTCHA challenges on login.
Console Routing Matrix
| Frontend Route | Module Scope & Capabilities | Documentation Reference |
|---|---|---|
/ | Dashboard: Real-time QPS, drop statistics, and security summaries | Monitoring & Logs |
/sites | Sites: Domain mappings, upstream origins, 4 load balancing algorithms, and health checks | Site Management |
/ssl | SSL Certificates: Certificate upload and automated ACME renewals | TLS & Certificates |
/rules | Rules: Site custom regex rules, YAML/JSON batch import/export, and live RE2 validation | Custom Rules |
/review | Threat Review: ALAP offline threat triage, decision claims, and rule promotion | ALAP Review |
/logs | Log Explorer: Trace ID lookups and multi-dimensional query filters | Monitoring & Logs |
/ip | IP Management: IP allow/denylists, GeoIP restrictions, and threat feeds | IP, Geo & Fingerprints |
/protection | Protection: AST semantic engine toggles and paranoia levels | Security Policies |
/bot-challenge | Bot Protection: JS challenges, slider CAPTCHAs, and waiting room policies | Bot & CAPTCHA |
/edge | Edge: Header rewriting, static caching, and Gzip/Brotli compression | Edge Features |
/ai | AI Settings: Model connectivity, self-learning jobs, and automated adoption | ALAP Review |
/monitor | Monitoring & Alerts: Prometheus metrics, Remote Write, and Webhook alerts | Monitoring & Logs |
/apisec | API Security: Endpoint discovery, schema validation, and rate limiting | API Security |
/users | User Management: Administrator accounts, role scopes, and 2FA credentials | Operations |
/ops | Operations & Cron: Automated task scheduler and log maintenance | Storage & Scheduling |
/updates | Updates: Version status, release channel information, and update checks | Operations |
/block-pages | Block Pages: Response templates, HTML sanitization, and sandboxed preview | Block Pages |
/attack-map | Threat Map: Global attack visualization with official borders and 100% offline 3D Earth | Monitoring & Logs |
/cluster | Cluster: Node health, token issuance, certificate rotation, Ansible bundle export, and orchestration task views | Cluster HA |
/system | System: Runtime configuration, NTP synchronization, and backup management | Operations |
/captcha-lab | CAPTCHA Lab: Interactive puzzle testing and asset debugging | Bot & CAPTCHA |
The console provides light, dark, and custom color accents. Visual preferences are stored locally in the browser and do not impact data plane operations.
1.18 - Standalone Control Runtime
The repository includes cheesewaf-control, a separate control-plane process. It opens the control-plane PostgreSQL adapter and the native-raft runtime, then exposes a local status server. It does not handle WAF requests, host the Web Console, or replace the main cheesewaf serve process.
This page describes the current source and runtime contract. It is not a deployment recipe for high availability. The main cheesewaf serve path still uses storage.profile: temporary with embedded SQLite and still rejects the production management profile with ErrProductionStorageUnavailable. The standalone process does not provide empty-cluster initialization, a remote join workflow, plugin installation, OTA, or CWEDP execution.
Command boundary
The process accepts flags only. Positional arguments are rejected.
| Flag | Default | Rule |
|---|---|---|
--profile | production | Only the production profile is accepted. |
--cluster-id | empty | Required. The value must not contain whitespace, control characters, or invisible format characters. |
--node-id | generated | Optional. When omitted, native-raft generates and persists the node identity under --data-dir. |
--data-dir | empty | Required. Use a persistent, private directory for native-raft state and snapshots. |
--listen | 127.0.0.1:9450 | Local management HTTP address. It must be a loopback host:port. |
--raft-listen | 127.0.0.1:9451 | Native-raft address. It must be a different loopback host:port. |
--mode | join | Must be bootstrap or join; the default does not initialize a cluster. |
--ca-file | empty | Required PEM CA bundle for the control-plane and native-raft TLS trust. Use a private, readable file. |
--cert-file | empty | Required node certificate PEM. Its identity must match the configured node identity when one is supplied. |
--key-file | empty | Required private key PEM. Keep it owner-readable (0600) and out of logs and source control. |
--postgres-dsn | empty | Required management PostgreSQL DSN. It is never placed in status JSON. |
--timeout | 15s | Positive startup timeout. Expiration stops startup. |
Both listeners are validated as loopback addresses. The current command does not expose a remote management listener. A remote deployment would need a separate design with TLS, mTLS, ACLs, audit, and rollback controls.
The --postgres-dsn value is an independent management-state connection. It is not storage.postgresql.dsn, which remains the optional asynchronous access-log sink used by cheesewaf. Loopback and Unix-socket PostgreSQL connections are allowed; a remote PostgreSQL host must use certificate-verified TLS. Redis is not opened by this process.
The CA, node certificate, and private key must be created and installed by a protected provisioning process before this command is started. The example remains fail-closed until PostgreSQL, Raft TLS, and matching durable snapshots are available; it is not a successful HA bootstrap recipe.
Startup and fail-closed behavior
cheesewaf-control does not bind the HTTP listener until the full production bootstrap succeeds:
- Open the management PostgreSQL adapter.
- Prepare and health-check PostgreSQL, including the control-plane schema migration.
- Load the PostgreSQL control-state snapshot.
- Open, prepare, and health-check native-raft.
- Load the native-raft snapshot.
- Compare both snapshots, including cluster, leader, term, epoch, revision, desired version, digest, payload, frozen state, and nonce ledger.
- Validate the snapshot and confirm it does not regress the local last-known-good state.
- Establish a fencing token bound to the same cluster, leader, epoch, revision, digest, and nonce.
- Read native-raft again. A leader, term, epoch, revision, or digest change after fencing fails startup.
- Install the equal snapshot, resume control-plane writes, and report
ready.
Any failed migration, health check, snapshot comparison, validation, or fencing step returns an error. The command reports control-plane startup failed closed and exits without starting the status server. No unverified snapshot becomes ready, and no proposal is accepted. Supervisors that deliberately use the runtime’s frozen diagnostic mode may expose liveness and the freeze reason, but that mode never claims readiness or enables writes.
An empty PostgreSQL row and an empty native-raft state are treated as an empty, frozen state. Readiness still requires a committed desired-state revision, a non-zero term and epoch, an established leader, and a matching fencing nonce. Therefore --mode bootstrap alone cannot initialize an empty production cluster or invent its first desired state.
Local status endpoints
The status server is intended for local supervisors and probes. It listens on --listen, which is loopback-only by validation.
| Method | Path | Response |
|---|---|---|
GET | /healthz | Always 200 with the current status document. A frozen process can still report liveness when a supervisor deliberately exposes frozen diagnostics. |
GET | /readyz | 200 only when both ready and write_ready are true; otherwise 503. |
GET | /status | 200 with phase, readiness, cluster/node identity, leader, term, epoch, revision, update time, and a bounded freeze reason. |
POST | /proposals | 503 before write readiness. When write-ready, the current binary returns 501 because proposal transport is not mounted. Other methods return 405. |
Status responses do not include credentials, PostgreSQL DSNs, filesystem paths, or raw backend errors. The endpoint is a local diagnostic surface, not a cluster API.
Bootstrap and join modes
bootstrap and join are native-raft startup modes, not complete cluster administration workflows.
bootstrapcalls native-raft’s one-timeBootstrapClusteroperation only when the data directory has no existing Raft state. It still needs matching PostgreSQL and native-raft snapshots and a valid committed fence before the process can become ready.joinnever callsBootstrapCluster. A fresh join node does not become leader and cannot turn an empty state into a cluster. The current CLI has no controller address, join token, or remote enrollment flag.- The native-raft package exposes a leader-side
Joinoperation that adds a voter. That operation is an internal runtime API, not an HTTP endpoint or acheesewaf-controlsubcommand. Treatjoinas a read-only registration mode until a complete, tested follower enrollment path is published.
The current standalone command therefore cannot be used to create an empty cluster, automatically add a peer, or claim production multi-node HA. Native-raft and PostgreSQL code in the repository define the consistency boundary; they do not make the existing cheesewaf serve storage path switch to PostgreSQL or native-raft.
Relationship to the main server
cheesewaf serve remains the main WAF entry point. It owns the data-plane listener and the existing management plane, and its current runnable management profile is storage.profile: temporary. Adding a PostgreSQL management DSN or selecting storage.profile: production in the main server does not migrate it to this process; the main server continues to fail closed until its complete PostgreSQL, coordinator, native-raft, approval, audit, and data-plane integration is delivered and accepted.
For the broader target architecture, see Commercial Platform Architecture. This page is the executable boundary for the separate command and should be read together with the repository’s control-plane startup contract.
1.19 - Command-Line Interface & Interactive TUI
CheeseWAF utilizes a unified single-binary (BusyBox pattern) architecture. The execution mode is determined automatically based on the invocation command name:
| Executable Name | Default Execution Behavior |
|---|---|
cheesewaf | Executes the serve command by default, launching the Data Plane reverse proxy and the same process’s Management Plane API/Web services |
waf-cli | Launches the interactive Terminal User Interface (TUI, equivalent to cli; panel is a compatibility alias) |
Global Command-Line Flags
The language resolution hierarchy is: CLI --lang flag > Environment variable CHEESEWAF_LANG > Saved setting in data directory > Host operating system locale.
Identity and Password Rules
CheeseWAF applies one username rule to the setup wizard, Web Console, REST API, CLI, storage layer, human JWT claims, and CAPTCHA receipts. A username must be 3–32 ASCII characters, start with an ASCII letter, end with an ASCII letter or digit, and contain only ASCII letters, digits, ., _, and -. Non-ASCII characters, Unicode whitespace, control characters (Cc), and format/invisible characters (Cf) are rejected. The server preserves the exact input and never trims or lowercases usernames, so admin and admin are different strings and the latter is invalid.
The role field is also exact. It must match a configured key in apisec.permissions (normally admin or readonly); empty or unknown values, */: permission expressions, and leading, trailing, or embedded Unicode whitespace, control characters (Cc), or format/invisible characters (Cf) are rejected. Roles are not trimmed or case-normalized.
New passwords must contain at least 10 characters and satisfy at least 3 of these 4 classes: uppercase letters, lowercase letters, non-repeating digits, and special characters. Common or simple patterns, including sequential or keyboard-like patterns, are rejected. A password may not equal or contain the username. Existing password hashes are not exposed by these commands.
Subcommand Reference Table
| Subcommand | Functionality & Description |
|---|---|
serve | Launches the full WAF daemon (Data Plane reverse proxy + Management Plane API and Web console) |
setup | Interactive or headless terminal initialization wizard for hardware profiling and initial credentials |
rules | Batch imports, exports, and template generation for site custom regex rules |
crp | Verifies a local CRP package and can persist it in the local staged slot; it does not promote, execute, or distribute a plugin |
temporary-online | Explicit temporary outbound network probe; requires administrator stdin password and TLS leaf pin, records metadata-only audit |
cli | Launches the interactive TUI terminal management panel (compatibility alias: panel) |
status | Checks daemon health, process PID lease, and runtime status |
healthcheck | Diagnostic probes for admin API and outbound TLS (used in Docker healthcheck probes) |
stop | Gracefully terminates the running local daemon process |
restart | Gracefully stops and restarts the local daemon |
user | Resets local admin credentials, renames users, repairs historical usernames, and manages 2FA credentials |
cluster | Cluster controller init, worker node join, certificate rotation, token management, and runtime operations |
logs | Packages service logs into a compressed ZIP support bundle (logs pack) |
lang | Displays or persistently configures the default CLI interface language (lang show / lang set) |
version | Displays software version, build Git commit, release channel, and build timestamp |
Subcommand Details & Examples
1. System Setup Wizard (setup)
Supports both interactive prompts and non-interactive scripted automation:
Key flags:
-y, --yes: Skip interactive confirmation prompts and commit directly (headless setup requires--password-stdinto ensure strong credential generation).--username/--password-stdin: Initial root administrator username and password read from standard input.--profile: Hardware profile tuning (smart,low,medium,high, orcustom; official aliasesminimal,balanced, andperformanceare fully supported).--admin-listen: Admin management API listen address (default127.0.0.1:9443; printshttp://orhttps://based onadmin_tls).--skip-probe/--skip-external: Skip hardware autodetection or skip external telemetry (GeoIP/Prometheus/VictoriaLogs) setup.
--username must satisfy the canonical username rule above. --password-stdin is the preferred automation input; the password is read from standard input and is not printed in the setup summary.
2. Custom Rules Management (rules)
Batch replaces or exports site custom_rules via YAML or JSON. On successful import, it automatically notifies the running daemon to perform a zero-downtime hot reload:
3. Local User Administration (user)
Use user rename for an account whose current username is already canonical. Both the old and new values must pass the canonical rule. The CLI updates that account and revokes all of its unrevoked sessions, but it does not create a historical-repair audit record; this path cannot select a historical non-canonical username. Only repair-username bundles the username change, session revocation, and audit insert in one transaction. Neither command silently trims or lowercases a username.
Use user repair-username only for a historical non-canonical username, and pass the immutable user ID rather than the username. The repair rejects a missing user, a canonical current username, or a target username already owned by another account; it never merges accounts. The username change, revocation of every unrevoked admin session for that user, and append-only audit record commit in one SQLite transaction. The existing user ID, password hash, role, TOTP enabled state, and TOTP secret remain unchanged. The audit records the current OS user ID, the supplied reason, the old and new usernames, the number of revoked sessions, and the timestamp.
To find the immutable ID without reading password hashes or TOTP secrets, use the SQLite CLI in read-only mode and select only the ID and a quoted username. Replace the path with the configured storage.sqlite.path or the active data directory:
quote(username) makes leading or trailing spaces visible in the result. Do not use SELECT *, and do not paste database output into tickets or logs.
The display note attached to a management API token is metadata, not an account username. It is not subject to the account username rule; do not use a token note as the user identity. Management API Tokens default to 90 days and may be set up to 365 days; expired or inactive (180 days) tokens are cleaned by a single coalesced worker and generate audit/notification attempts.
The user command manages user accounts, roles, and credentials within the local management store. For CRP plugin packages, crp verify provides local offline signature verification, and crp stage persists verified local packages into designated staged slots.
CRP local staging
The command requires explicit trust roots, source registrations, a runtime directory, and a deterministic --now. It verifies the archive and writes only local staged metadata/artifacts. It never promotes a package, starts a plugin, bypasses a confirmation requirement, or contacts a network source. --high-risk selects the high-risk signature threshold but does not grant confirmation.
The probe command executes only restricted HEAD/GET handshakes and writes a structured, read-only metadata audit record to <data-dir>/audit/netlease.jsonl. It does not start a persistent background downloader, nor does it participate in main proxy data routing.
4. Cluster Management (cluster)
--ca-file for cluster join and cert rotate verifies the controller’s 9443 HTTPS management endpoint; it is not the cluster CA returned during enrollment. Omit it only when the controller certificate chains to the system trust store; pre-provision a private admin CA when needed. Joining generates a local key/CSR and writes the returned cluster CA and certificate under the node data directory. Certificate rotation requires exactly one token source (--api-token, --api-token-file, or --api-token-env), writes files locally, and takes effect after the service reload/restart procedure.
cluster monitor-node posts heartbeats to the cluster interconnect (normally HTTPS :9444) using the local configured cluster CA/certificate/key. The fallback environment variable is CHEESEWAF_CLUSTER_CONTROLLER; a custom --controller value must likewise be an HTTPS interconnect address. --insecure-skip-verify is for isolated laboratory testing only.
5. Support Bundle Packaging (logs)
6. CLI Language Configuration (lang)
Operational Examples
On Windows systems, if you wish to run waf-cli directly by name, copy or create an alias from cheesewaf.exe to waf-cli.exe.
The TUI subcommand’s canonical spelling is cheesewaf cli; cheesewaf panel remains available as a compatibility alias.
cheesewaf user also accepts the users alias. cheesewaf healthcheck is intentionally hidden from normal --help output and is used by service/container probes.
1.20 - RESTful Management API Reference
CheeseWAF’s management API is hosted on the process’s dedicated Management Plane listener (default port 9443) under the /api route prefix, maintaining physical listener separation from business traffic on the Data Plane. This listener is not the future standalone commercial control-plane service.
Authentication & Authorization Schemes
The system supports two primary authentication models:
- Session-Based Authentication: Call
POST /api/auth/loginto authenticate; clients must include the returned Session Cookie in subsequent requests. All non-idempotent state-changing requests (POST, PUT, DELETE, PATCH) are verified by double-submit CSRF protection middleware. - Bearer Management Tokens: Enable
apisec.management_api.enabled, then invokePOST /api/system/api-tokens(requiringmanage:api_tokensprivileges) to generate a scoped API Token. Pass the token via the standard HTTP header:Authorization: Bearer <TOKEN>. The secret is returned only once in the creation response; list/read endpoints return metadata, not the secret.
Usernames and roles
Human account endpoints (POST /api/users, PUT /api/users/{id}), setup, login, storage, human JWT claims, and CAPTCHA receipts share one exact username rule: 3–32 ASCII characters, ASCII letter first, ASCII letter or digit last, and only ASCII letters, digits, ., _, and -. Non-ASCII characters, Unicode whitespace, control characters (Cc), and format/invisible characters (Cf) are rejected. The server never trims, lowercases, or otherwise normalizes the value.
When a request creates or updates a user, role must exactly match a configured key in apisec.permissions (normally admin or readonly). Empty or unknown roles, */: permission expressions, and roles containing leading, trailing, or embedded Unicode whitespace, controls (Cc), or format/invisible characters (Cf) are rejected. Invalid fields return USERNAME_INVALID or ROLE_INVALID. An existing historical non-canonical username cannot be repaired through ordinary API update; inspect its immutable ID and run the local CLI command cheesewaf user repair-username USER_ID NEW_USERNAME --reason '...'.
Public Unauthenticated Endpoints
The following read-only, login, or challenge endpoints can be accessed without a prior session or bearer token. A configured public Prometheus path is also unauthenticated when monitor.prometheus.public: true; its path is deployment-specific.
| HTTP Method | Route Path | Description & Purpose |
|---|---|---|
GET | /health, /health/live, /health/ready, /health/cluster | System and cluster health diagnostic probes |
GET | /api/auth/login-options | Retrieves login security settings (e.g., CAPTCHA/2FA requirements) |
POST | /api/auth/captcha, /api/auth/captcha/verify | Generates and verifies login CAPTCHA challenges |
POST | /api/auth/login | Administrator authentication endpoint |
GET | /api/setup/status | Reports whether first-install setup is still required; does not mutate state |
Bootstrap and Node-Authenticated Endpoints
These routes are mounted outside the normal management-token middleware, but they are not anonymous operations:
POST /api/setupandPOST /api/setup/proberequire the setup token inX-CheeseWAF-Setup-Token, and are accepted only while setup is incomplete.GET /api/setup/draftrequires the setup-session cookie issued by the probe;PATCH /api/setup/draftrequires that cookie plus the setup token.POST /api/cluster/joinrequires a one-time join token and a node CSR. The controller validates the token and enrolls the node; it is not a public membership endpoint.POST /api/cluster/nodes/{id}/heartbeatrequires a verified mTLS client certificate for an enrolled, non-revoked node (certificate identity/serial must match the registration).
First-install setup URL delivery
The service never prints the setup token or complete setup URL in its startup log. The log shows only the base setup URL (for example, http://127.0.0.1:9443/setup), the protected runtime file path (setup.url), and an opaque receipt.
The complete setup URL is stored in setup.url with mode 0600 and a 10-minute validity period. After setup completes, the setup token is revoked; expired setup.url files are cleaned up. The normal installation flow does not expose ReadURLOnce as a user-facing command.
The setup token remains required in X-CheeseWAF-Setup-Token until setup completes, when it is revoked. The browser reads the token from the URL fragment, clears the fragment from the address bar, and sends it only in that header. A token supplied through CHEESEWAF_SETUP_TOKEN before startup follows the same API validation rules and must stay out of logs and shell history.
GET /api/setup/status reports only whether setup is still needed. It never returns the setup URL or setup token.
RBAC Permission Matrix Reference
Router middleware validates token permissions against the following identifiers:
| Permission Prefix | Functional Area & Covered Capabilities |
|---|---|
read:sites / write:sites | Query, create, update, and delete site definitions; issue ACME certificates |
read:rules / write:rules | Custom regex security rule management |
read:protection / write:protection | IP access lists, ACL rules, bot challenge policies, and ALAP decisions |
read:threat_intel / write:threat_intel | Threat intelligence feed management, synchronization, and IP lookups |
read:edge / write:edge | Edge response headers, static caching rules, and compression profiles |
read:ai / write:ai / use:ai / approve:ai | AI LLM configurations, assistant conversations, and high-risk tool approvals |
read:cluster / write:cluster | Cluster node monitoring, join token issuance, and rolling upgrades |
read:system / write:system | Software version queries and NTP time synchronization; backup/restore routes are registered but currently return 501 |
manage:api_tokens | Create, query, and revoke management API tokens |
read:users / write:users | Administrator user accounts, roles, and TOTP 2FA configuration |
read:logs | Query access logs and retrieve ALAP review queue items |
read:monitor | System performance metrics, Prometheus scraping, and notification channels |
read:audit | Query operational audit logs |
read:realtime | Server-Sent Events stream (/api/realtime/events) and WebSocket feeds |
read:ops / write:ops | Built-in task scheduler and automated maintenance routines |
read:storage / write:storage | Storage status, external log sink configuration, and disk cleanup |
read:apisec | Discovered API asset inventory and OpenAPI schema definitions |
Roles assigned admin: ["*"] possess unrestricted global API access.
Management API Tokens currently support scoped permissions, notes, optional TTL/expiry, revocation, last-used metadata, and one-time secret display. The platform default lifetime is 90 days; the maximum explicit lifetime is 365 days. The service runs one coalesced cleanup worker: new tokens slide the cleanup deadline by 10 minutes, bounded by the first creation plus 60 minutes, and expired or inactive tokens (180 days without activity) are removed; audit-entry and administrator-notification attempts are made after the configuration commit.
The Web console provides a two-step confirmation workflow for non-expiring tokens. Adhering to the principle of least privilege, creating a non-expiring token requires strong identity verification (such as password and TOTP two-factor confirmation), returning API_TOKEN_CONFIRMATION_UNAVAILABLE when verification conditions are not met.
The backup routes are not a working restore workflow yet: POST /api/backup/export and POST /api/backup/restore return HTTP 501 (BACKUP_EXPORT_NOT_IMPLEMENTED / BACKUP_RESTORE_NOT_IMPLEMENTED).
Standard Error Formats
API failures return appropriate HTTP status codes accompanied by a structured JSON error response:
If a login attempt fails due to CAPTCHA validation (HTTP 401/403), request a new challenge context via /api/auth/captcha before re-submitting credentials.
1.21 - Configuration File Reference
CheeseWAF automatically generates a default cheesewaf.yaml configuration file within its runtime data directory under config/ upon first launch (default ./data/config/cheesewaf.yaml). A baseline template is maintained in the source repository at configs/cheesewaf.yaml.
configs/cheesewaf.yaml is a source template, not a runtime state file. Setup, site management, and console saves write to the runtime configuration. For source builds, copy it first to ./data/config/cheesewaf.yaml or another dedicated data directory so database paths, certificates, secrets, and site changes never modify the Git working tree.
Top-Level Configuration Index
| Top-Level Key | Functional Area & Role | Documentation Reference |
|---|---|---|
server | Network listener sockets, management endpoints, and connection timeouts | Architecture & Overview · TLS & Certificates |
tls | Data Plane TLS/HTTPS certificates and HSTS enforcement | TLS & Certificates |
setup | Initialization state tracking and runtime data directory path | System Initialization · Storage & Scheduling |
deployment / cluster | Deployment topology (standalone vs. HA cluster) and interconnects | High Availability Clustering |
console | Web console UI preferences and administrative login security | Bot & CAPTCHA · Monitoring & Logs |
sites | Reverse proxy sites, domain bindings, and upstream origin pools | Site Management |
protection | Global security baseline (AST engines, IP, Bot, rate limiting, ACL) | Security Protection Policies |
block_page | Block response templates and custom HTML branding sanitization | Block Response Pages |
storage | temporary SQLite management profile; reserved, currently rejected production profile; optional external log sinks | Storage & Scheduling |
logging | Access log verbosity, structured JSON formats, and log rotation | Monitoring & Logs |
ai | ALAP LLM provider endpoints and asynchronous review parameters | ALAP Review & Self-Learning |
update | Reserved OTA settings; updater worker is not implemented in the current runtime | System Operations |
scheduler | Automated log cleanup, configuration snapshots, and daily security reports; snapshots are not complete database exports | Storage & Scheduling |
edge | Edge response header manipulation, static caching, and Brotli compression | Edge Features |
monitor | Prometheus metrics export, Remote Write, and alert notifiers | Monitoring & Logs |
apisec | API asset discovery, request schema contracts, and RBAC matrix | API Security & Governance |
performance | Go runtime Garbage Collection (GC) adaptive tuning (memory_limit_ratio / min_gogc) | Architecture & Overview |
time_sync | NTP sources, synchronization intervals, and clock-offset consensus limits | Monitoring & Logs |
captcha_assets | Local or S3 CAPTCHA image/font assets and resource limits | Bot & CAPTCHA |
acme | ACME certificate issuance and DNS challenge provider settings | TLS & Certificates |
vulnerability | Vulnerability CVE feed subscription configurations | System Operations |
Network Timeout Controls
- Ingress Connection Timeouts:
server.read_timeout,server.write_timeout, andserver.idle_timeoutgovern the lifecycle of HTTP connections between clients and the WAF. - Reverse Proxy Timeouts:
sites[].waf.performance.proxy_timeoutdefines the maximum allowable duration when connecting and streaming responses to/from backend origin servers.
Protection Modes & Request Body Limits
- WAF Modes (
waf.mode): Supportsblock(actively drops and mitigates attacks),monitor(logs alerts without blocking), andoff(disables inspection). The legacy aliaslogis automatically recognized and normalized tomonitor. - Request Body Size Guard (
max_body_bytes): If an incoming request body exceeds the configuredmax_body_byteslimit, the data plane immediately responds with HTTP413 Request Entity Too Large, preventing memory exhaustion and partial-body evasion.
Gateway Adapter Authentication & Proxy Ingress
- Dedicated Adapter Token (
CHEESEWAF_ADAPTER_TOKEN): When integrating with external reverse proxy adapters (CheeseWAF-Adapters), callers must supply the token via the dedicatedX-CheeseWAF-Adapter-TokenHTTP header. It is not a Bearer token and must never be placed in theAuthorizationheader. - Trusted CIDR Blocks (
trusted_cidrs): By default, the trusted CIDR list is empty. When running behind an upstream proxy (such as a CDN or cloud load balancer), configuresites[].waf.access_control.trusted_cidrs(e.g.,127.0.0.1/32or::1/128) to securely parse client IP addresses fromX-Forwarded-For.
Dynamic Hot-Reload Scopes
- Atomic In-Memory Hot Reload: Modifying site definitions, custom regex rules, IP access lists, bot challenge policies, or ACL rules via the Web console or REST API takes effect immediately in memory without process restarts.
- Restart Required: Alterations to physical socket listeners (such as
server.listenorserver.admin_listen) require restarting the daemon process viacheesewaf restartor systemd.
1.22 - Operations & Security Hardening
This section outlines standard operational procedures and hardening requirements for running CheeseWAF in production. Corresponding UI modules in the Web Console include Users, System, and Updates.
CheeseWAF uses embedded SQLite by default (storage.profile: temporary) to store users, sessions, and management state. When storage.profile: production is explicitly set, the service enforces strict environment validation and fails closed with ErrProductionStorageUnavailable if external production database dependencies are not configured.
storage.postgresql is an optional asynchronous access-log sink; it is not the management database. A configured storage.redis endpoint may be connectivity-tested, but bot challenge state still uses the in-process memory backend, and protection.bot.challenge_backend: redis is rejected. cheesewaf crp verify performs bounded offline verification, while cheesewaf crp stage persists a verified local package in a staged slot. cheesewaf crp activate and cheesewaf crp rollback exist, but require protected control-plane/sidecar adapters and fail closed when those dependencies are absent. The local RuntimeStore is not connected to plugin execution, server startup, cluster distribution, promotion approvals, or OTA downloading.
The current CWEDP/NetLease packages include broker-bound HTTP/file transport, one-shot lease checks, direct-IP dialing, TLS/mTLS/NodeID/leaf pinning, Range resume, and source quarantine. These packages are not yet mounted into the main serve process, node registration, or a complete plugin installation/OTA lifecycle. The local cheesewaf temporary-online probe is a separate one-shot operator tool; it is not the production plugin egress API.
1. User Administration & CLI Credentials
- One identity rule: Setup, the Web Console, REST API, CLI, storage, human JWT claims, and login CAPTCHA receipts use the same username form. Usernames are 3–32 ASCII characters, start with an ASCII letter, end with an ASCII letter or digit, and contain only ASCII letters, digits,
.,_, and-. Non-ASCII characters, Unicode whitespace, control characters (Cc), and format/invisible characters (Cf) are rejected. The server preserves the exact input and never trims or lowercases usernames, soadminandadminare different strings and the latter is invalid. - Role input: A user
rolemust exactly match a configured key inapisec.permissions(normallyadminorreadonly). Empty or unknown roles,*/:permission expressions, and roles containing leading, trailing, or embedded Unicode whitespace, control characters (Cc), or format/invisible characters (Cf) are rejected. The server does not trim or case-normalize roles; invalid account fields returnUSERNAME_INVALIDorROLE_INVALID. - Web Console & REST API: Administer accounts programmatically via
GET/POST /api/usersandPUT /api/users/{id}. The same validation applies to Web Users, Setup, and login. - Command-Line Operations (
cheesewaf user):BASH - Use
user renamewhen the current username is already canonical. Both the old and new values must pass the canonical rule. The CLI updates that account and revokes all of its unrevoked sessions, but it does not create a historical-repair audit record; this path cannot select a historical non-canonical username. Onlyrepair-usernamebundles the username change, session revocation, and audit insert in one transaction. - Use
user repair-usernameonly for a historical non-canonical username such asadmin. It requires--reasonand an exact immutable user ID. It rejects a missing user, a canonical current username, or a target username owned by another account. It never merges accounts. The username update, revocation of every unrevoked admin session for that user, and append-only audit record commit in one SQLite transaction. The user ID, password hash, role, TOTP enabled state, and TOTP secret remain unchanged. The audit records the current OS user ID, supplied reason, old and new usernames, revoked-session count, and time. Neither path silently trims or lowercases a username. - Run the repair as the same OS account that owns the CheeseWAF data. The audit actor is derived from the current OS user ID; running the command through an unrelated account changes that evidence.
- Password policy: New passwords need at least 10 characters and at least 3 of 4 classes: uppercase, lowercase, non-repeating digits, and special characters. Common or simple patterns, including sequential or keyboard-like patterns, are rejected. A password cannot equal or contain the username. Prefer
--password-stdin; direct--passwordvalues can enter shell history or process listings. - Principle of Least Privilege: Create dedicated
readonlyaccounts for operational auditing to avoid sharing root administrative credentials. - Two-Factor Authentication (2FA/TOTP): Configure TOTP using
/api/users/{id}/2fa/setupto generate seeds and QR codes; manage state viaenable,disable, andrecover. - A management API token’s display note is metadata, not an account username. It is not validated with the account username rule and must not be used as the authenticated human identity. Management API Tokens default to 90 days and allow at most 365 days; the running service removes expired or 180-day-inactive tokens in a coalesced cleanup worker and attempts an audit entry plus administrator notification.
- The Web System page contains a second-confirmation dialog for non-expiring Tokens, but the option is disabled until the confirmation verifier is configured. The current runtime does not yet connect
ApprovalGate, current-password/TOTP verification, or the 10-second warning delay; non-expiring creation therefore returnsAPI_TOKEN_CONFIRMATION_UNAVAILABLE.
To find a user ID without reading password hashes or TOTP secrets, use the SQLite CLI in read-only mode and select only the ID and a quoted username:
quote(username) makes leading or trailing spaces visible. Do not use SELECT *, and do not paste this output into tickets or logs.
2. Back Up and Migrate the SQLite Management Store
Before a username repair or binary upgrade, resolve the active database from storage.sqlite.path and confirm that the file and its parent directory are the expected runtime paths. The usual defaults are ./data/cheesewaf.db for a local run and /var/lib/cheesewaf/cheesewaf.db for a Linux service. Do not point these commands at the tracked configs/cheesewaf.yaml template.
An active SQLite database normally uses WAL mode. Do not copy only the main .db file while CheeseWAF is running; recent commits may still be in -wal, and the copy may not be restorable. An online backup reads a consistent snapshot while the service continues to run:
The integrity check must return ok, and the final checksum command must report OK. Stop if either check fails. Keep the backup in a protected location and copy it off-host according to the retention policy. The backup contains sensitive management data; never upload it to a ticket or paste it into a chat. Check free disk space before starting, and monitor WAF health and disk latency during the backup. The single CheeseWAF binary serves both the data plane and management plane, so stopping it can interrupt protection and traffic.
If an online backup is not possible, stop only the exact CheeseWAF writer through its service manager, confirm that no CheeseWAF process is writing, and copy a consistent database set including any adjacent -wal and -shm files. Validate the copy with PRAGMA integrity_check; before restarting the service. Do not use a broad process-stop command.
The current binary applies ordered SQLite migrations when it opens the store. The current schema is version 5. Migration 3 to 4 creates the append-only user_username_repairs audit table, and migration 4 to 5 adds credential_epoch to users and admin_sessions. Security changes advance the user epoch, and active sessions must match the current epoch. These migrations do not trim, lowercase, merge, or otherwise rewrite existing accounts. A binary that supports only an older schema rejects a newer database with newer SQLite schema version.
For a downgrade, restore and validate the backup taken before the upgrade, then start the older binary only after the exact service and data paths have been checked. Do not lower PRAGMA user_version by hand. If a username repair succeeds but must be undone, restore the pre-repair backup during a planned maintenance window; repair-username intentionally refuses to turn a canonical username back into an invalid one.
3. Support Bundle Packaging & CLI Localization
- Support Bundle Archiving: When troubleshooting issues, package all runtime logs into a standardized, timestamped ZIP archive:BASH
- CLI Interface Language:BASH
4. NTP Time Synchronization
JWT signature verification, TOTP token calculations, and cluster consensus rely on synchronized clocks:
- Query Clock Sources: Call
GET /api/system/time-syncto inspect offsets and active NTP servers. - Force Resynchronization: Call
POST /api/system/time-sync/syncto trigger immediate alignment. - Reselect Lowest-Latency Peer: Call
POST /api/system/time-sync/reselectto discover and switch to the lowest-latency NTP pool.
5. OTA Capability Status
- Current runtime boundary: The configuration keys are reserved for the OTA updater, but the current binary has no updater worker. The Updates page reports
NOT_IMPLEMENTED, and enabling OTA through the system API is rejected withOTA_UPDATES_UNAVAILABLE. - Configuration safety: Keep
enabled: falseuntil an updater worker is shipped. The validator still checks the server URL, channel, interval, and signature settings when OTA is enabled. - Future behavior:
auto_update_rules,auto_update_binary, andverify_signaturedescribe the intended signed-update policy; they do not mean that rule or binary downloads run today.
6. Software Supply Chain Security & Integrity
Use only the release metadata that is actually published for the version you are deploying. The runtime does not create or verify a release signature on your behalf:
- SBOM: If the release publishes a CycloneDX or SPDX SBOM, retain it with the deployment record and compare the listed version and digest to the artifact you received.
- Container signatures: If the release publishes a Cosign signature, verify it against the exact image reference before deployment.
- Windows signatures: If a Windows package includes Authenticode metadata, verify the signer and certificate chain on the machine that will install it.
- Checksums: If the release publishes a checksum file, verify the exact artifact with
sha256sum -c checksums.txtor the platform equivalent.
1.23 - Building from Source & Developer Guide
This guide is intended for developers contributing code or building CheeseWAF directly from source. For standard production deployments, using official pre-compiled releases from GitHub Releases is strongly recommended.
1. Development Toolchain Requirements
- Go Compiler: Go 1.26 or higher
- Frontend Environment: Node.js 24.x LTS and
npmpackage manager
2. Compile Frontend Assets & Main Daemon
Console Assets Embedding Note: When compiling from source, run bash scripts/ci/build-web.sh before go build. The script uses npm ci --ignore-scripts and builds with CHEESEWAF_AGENT_EYES=0; @agent-eyes/agent-eyes is development-only and must not enter release packages or production images. Do not use a bare npm ci that triggers its monorepo postinstall.
3. Running Automated Tests & Code Quality Checks
cheesewaf-corpus runs built-in attack samples and false-positive corpora against the AST semantic analyzer, ensuring high detection rates without regression.
1.24 - Open-Source License & Ecosystem Repositories
CheeseWAF source code is open-source under the Apache License 2.0.
The CheeseSec and CheeseWAF brand names, typography, and product logos are protected trademarks and are not granted under the Apache 2.0 open-source license. When redistributing or referencing project branding, adhere to the NOTICE guidelines located in the CheeseSec_pages repository.
Ecosystem Repository Directory
| Project Repository | Functionality & Role |
|---|---|
| LaokeQwQ/CheeseWAF | Primary product source code, issue tracking, and pre-compiled release artifacts |
| LaokeQwQ/CheeseWAF-Adapters | Go-first self-hosted gateway adapters for NGINX, Envoy, and Kubernetes (adapterd) |
| LaokeQwQ/CheeseSec_Plugin | Plugin catalog, release metadata, and CRP admission policies |
| LaokeQwQ/CheeseSec_Plugin_Docs | Plugin developer handbook, CRP v1 specification, and offline extension contracts |
| LaokeQwQ/CheeseSec_Docs | Official documentation website repository and maintenance guides |
| LaokeQwQ/CheeseSec_pages | Official brand portal and marketing site |
For general issue reporting, email contacts, and vulnerability disclosure procedures, refer to Feedback & Security Reporting.
For product functional bugs, feature proposals, and security disclosures, submit an issue to the CheeseWAF Issue Tracker. For documentation errors or translation feedback, please submit an issue to the CheeseSec_Docs Issue Tracker.
1.25 - Feedback & Security Reporting
CheeseSec welcomes community contributions and operational feedback. Please use the appropriate channel below depending on the nature of your report:
General Feedback & Issue Tracking
1. GitHub Issues
For operational defects, bugs, runtime errors, documentation corrections, or feature proposals, open an issue in the corresponding GitHub repository:
| Project Scope | Repository & Issue Tracker | Intended Coverage |
|---|---|---|
| Core Engine & Server | LaokeQwQ/CheeseWAF Issues | WAF daemon, data plane proxy, AST semantic engine, CLI utilities, and Web console |
| Gateway Adapters | LaokeQwQ/CheeseWAF-Adapters Issues | NGINX auth_request, Envoy ext_authz, and the adapterd daemon |
| Plugin Ecosystem | LaokeQwQ/CheeseSec_Plugin Issues | CRP specification, package manifests, and registry admission policies |
| Technical Documentation | LaokeQwQ/CheeseSec_Docs Issues | Documentation accuracy, clarity, and bilingual synchronization |
Issue Submission Guidelines: Include your operating system, architecture, CheeseWAF version (cheesewaf version), deployment mode (systemd service or Docker), and minimal reproduction steps. Sanitize logs to ensure database credentials, API tokens, and private keys are never exposed in public issues.
2. Email Correspondence
For general questions, private deployment inquiries, or matters not suitable for a public tracker, contact the project team via email:
- Contact Email:
[email protected]
Critical Vulnerabilities & Security Disclosures
CheeseSec treats security defects with the highest priority. If you identify a security vulnerability, detection bypass, or critical stability defect in CheeseWAF or its ecosystem components, please follow Responsible Disclosure practices and do not post exploit details in public channels (such as GitHub Issues or social media).
Dedicated Security Contact
- Vulnerability Reporting Mailbox:
[email protected]
Scope of Security Reports
Reportable issues include, but are not limited to:
- Remote Code Execution (RCE) or arbitrary command injection
- Management plane authentication bypass, privilege escalation, or session forgery
- Universal detection bypasses against the AST semantic engine or baseline rulesets
- Uncontrolled resource consumption, memory leaks, or deadlocks causing high-severity Denial of Service (DoS)
- Exposure or insecure handling of sensitive configuration data, credentials, or keys
Recommended Report Contents
To accelerate verification and resolution, please include:
- Description & Severity: Vulnerability class, affected endpoints or components, and estimated impact.
- Affected Versions: Specific release versions or Git commit hashes.
- Proof of Concept (PoC): Clear, reproducible steps, including sample HTTP payloads, curl commands, or scripts.
- Prerequisites: Required user roles, configuration flags, or network topology necessary to trigger the defect.
- Remediation (Optional): Suggested patches or workarounds, if available.
Response & Handling Workflow
- Acknowledgment: The security team confirms receipt of reports sent to
[email protected]and opens an internal tracking case. - Triage & Reproduction: Engineers reproduce the PoC in an isolated environment, evaluate severity, and prioritize a patch.
- Patch & Advisory: Once a fix is implemented and verified, a security patch release and corresponding Security Advisory are published. We request that reporters maintain confidentiality until the patch is publicly available.
1.26 - Words from the Developer
Beyond standard technical specifications and operational references, this section provides an open space for the project author and core developer to share reflections, architectural motivations, and perspectives on the journey of building CheeseWAF.
1.26.1 - Words from the Developer
“Security should not be an expensive, closed black box that exhausts operations teams. It should be transparent, elegant, and dependable engineering infrastructure.”
Preface
If you are reading this document, perhaps you are preparing to deploy CheeseWAF on your servers, troubleshooting an elusive security incident, or simply exploring web security and application architecture as a fellow practitioner or enthusiast.
Whichever brings you here, I welcome you with all my heart.
Here, without cold CLI parameters or cryptic regular expression syntax, I want to use my own straightforward words to share why CheeseWAF came to life, and everything I have stood by and reflected upon throughout this journey.
Why CheeseWAF Was Created
Before committing to the project and writing the very first line of code for CheeseWAF, like many website operations and security engineers facing increasingly intricate web requests, I found myself caught in a difficult dilemma between exorbitant commercial WAF licensing quotes and the grueling rule maintenance, high false-positive, and false-negative rates of traditional open-source tools.
We often found ourselves trapped between two extremes:
- Over-reliance on traditional regex signatures: As signatures accumulate, maintenance overhead multiplies exponentially, yet a slight variation in multi-layer encoding or character nesting can bypass them;
- Blindly forcing LLMs into the synchronous request path: In the name of “intelligence,” forcing synchronous waits for remote LLM inferences within the reverse proxy pipeline turns a simple HTTP exchange into hundreds of milliseconds or even seconds of latency, ultimately crippling the entire business service.
We firmly believe that accuracy, low latency, and maintainability are the lifeline of the Data Plane, while deep semantic understanding should be entrusted to an asynchronous sidecar capable of decoupled execution and continuous self-learning. This is where CheeseWAF began: we aspire to build a truly commercial-grade, self-contained, out-of-the-box self-hosted WAF, empowering every developer and operations team to take full ownership of their application security, unconstrained by cloud vendors and expensive commercial licenses.
Architectural Convictions
Throughout the evolution of CheeseWAF, several engineering principles have been held as non-negotiable baselines:
- Self-Contained Single Binary: Consolidating complex components, the Web management console, and security engines into a single executable without wrestling with databases, middleware, or external dependencies beforehand. Written 100% in Go, CheeseWAF inherently possesses outstanding robustness and excellent portability, running directly across mainstream Linux, Windows, and macOS platforms. Furthermore, we natively support the LoongArch architecture, enabling seamless execution on hardware powered by domestic Loongson processors.
- Zero Compromise on the Request Path: An inspection pipeline capable of sub-millisecond to microsecond processing, rooted in clear Abstract Syntax Tree (AST) semantic parsing. Dynamically tuned to hardware performance profiles and refined through extensive GC tuning and hardware acceleration, it relentlessly pursues ultimate performance and concurrency.
- Defensive Authority Stays with the Operator: From gradual paranoia level progression to automated adoption of threat reviews, you can freely choose between autonomous AI remediation and manual alert approval. The ultimate control and final voice over your defense line always rest in your hands.
A Note to the Community
Building a serious Web application security product is by no means easy. It demands continuous adaptation to rapidly shifting attack vectors, modern Web protocols, and diverse production constraints.
As a newly launched, independently maintained open-source project in its formative stages, CheeseWAF continues to mature. If it helps you ward off an unexpected attack late at night, relieves your startup or small business from the heavy burden of commercial WAF licensing or cloud security costs, or simply makes your daily operations a bit easier and more dependable, that is already my greatest honor.
Anyone with ideas, feedback, or constructive critiques is warmly invited to connect via GitHub Issues or email ([email protected]).
Finally, my sincere gratitude for your trust and confidence in CheeseWAF, and my deepest respect to everyone who loves open source and security craftsmanship.
September 2026