This is the multi-page printable view of this section. .

Return to the regular view of this page.

Deployment & Installation

Comprehensive deployment guides and installation options for CheeseWAF across Linux, Docker, Windows, and macOS.

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:

Choose a shared application root or the standard FHS layout, then configure systemd and a dedicated unprivileged system user.

Deploy with Docker Compose featuring a read-only root filesystem and unprivileged non-root execution.

Run via single-file CLI, portable Zip archive, or GUI NSIS installer with a local helper controller.

Install as a desktop DMG application or run via portable tar.gz command-line archive.

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 PackageTarget Platform & Architecture
cheesewaf-amd64-linux-*.tar.gzLinux x86_64 architecture
cheesewaf-arm64-linux-*.tar.gzLinux ARM64 architecture
cheesewaf-loong64-linux-*.tar.gzLinux LoongArch architecture
cheesewaf-amd64-darwin-*.tar.gz / .dmgmacOS Intel architecture
cheesewaf-arm64-darwin-*.tar.gz / .dmgmacOS Apple Silicon architecture
cheesewaf-amd64-windows-*.exeWindows x86_64 standalone executable
cheesewaf-arm64-windows-*.exeWindows ARM64 standalone executable
cheesewaf-amd64-windows-*.zipWindows x86_64 portable ZIP archive
cheesewaf-arm64-windows-*.zipWindows ARM64 portable ZIP archive
cheesewaf-amd64-windows-*-setup.exeWindows x86_64 NSIS graphical installer
cheesewaf-arm64-windows-*-setup.exeWindows ARM64 NSIS graphical installer

Following installation, proceed to Quick Start to complete system initialization and onboard your first reverse proxy site.

1 - Linux Deployment (systemd)

Install CheeseWAF with the one-line installer or an offline release archive, then configure a public HTTPS management entry and one-time setup token.

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:

BASH
curl -fsSL https://github.com/LaokeQwQ/CheeseWAF/releases/latest/download/install-linux.sh | sudo bash

When already running as root, omit sudo:

BASH
curl -fsSL https://github.com/LaokeQwQ/CheeseWAF/releases/latest/download/install-linux.sh | bash

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):

BASH
curl -fsSL https://github.com/LaokeQwQ/CheeseWAF/releases/latest/download/install-linux.sh \
  | sudo env CHEESEWAF_RELEASE=v0.4.2-beta bash

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:

BASH
curl -fsSL https://github.com/LaokeQwQ/CheeseWAF/releases/latest/download/install-linux.sh \
  | sudo env CHEESEWAF_INSTALL_DIR=/opt/cheesewaf bash

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:

  1. Ask for 中文 or English and check Linux, architecture, disk space, curl, tar, sha256sum, awk, and od prerequisites.
  2. Download the selected server archive from GitHub Releases and verify its single matching SHA256SUMS entry. A failed verification stops before installation or service startup.
  3. Install the binary, Web Console, runtime configuration, and systemd unit, then create the non-login cheesewaf service account.
  4. 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.
  5. Start the service when systemd is 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. Without systemd, 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:

TEXT
https://PUBLIC_IP:9443/setup#setup_token=ONE_TIME_TOKEN

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:

BASH
sudo -u cheesewaf cheesewaf setup token reset

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

BASH
systemctl status cheesewaf --no-pager
ss -ltnp | grep ':9443'
sudo journalctl -u cheesewaf -n 100 --no-pager

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:

PathPurpose
/usr/local/bin/cheesewafMain binary
/usr/local/bin/waf-cliCLI symlink
/usr/share/cheesewaf/webWeb Console assets
/etc/cheesewaf/cheesewaf.yamlRuntime configuration copy
/var/lib/cheesewafData, certificates, and bootstrap state
/var/log/cheesewafAccess 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:

BASH
sha256sum --check SHA256SUMS --ignore-missing
tar -xzf cheesewaf-*-linux-*.tar.gz
cd cheesewaf-*-linux-*
sudo ./install-linux.sh

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.

2 - Docker Compose Deployment

Deploy CheeseWAF with Docker Compose supporting read-only root filesystems and unprivileged container security.

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:

YAML
services:
  cheesewaf:
    image: cheesewaf:dev
    build:
      context: ../..
      dockerfile: deploy/docker/Dockerfile
    user: "10001:10001"
    restart: unless-stopped
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp:size=32m,mode=1777,noexec,nosuid,nodev
    ports:
      - "8080:8080"
      - "127.0.0.1:9443:9443"
    volumes:
      - cheesewaf-data:/var/lib/cheesewaf
      - cheesewaf-logs:/var/log/cheesewaf
    healthcheck:
      test: ["CMD", "/usr/local/bin/cheesewaf-entrypoint", "healthcheck"]
      interval: 30s
      timeout: 5s
      retries: 3

volumes:
  cheesewaf-data:
  cheesewaf-logs:

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:

BASH
docker compose -f deploy/docker/docker-compose.yml up -d
docker compose -f deploy/docker/docker-compose.yml logs -f cheesewaf

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.

BASH
docker compose -f deploy/docker/docker-compose.yml exec -it cheesewaf \
  cheesewaf --config /var/lib/cheesewaf/config/cheesewaf.yaml \
  --data-dir /var/lib/cheesewaf setup

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.

3 - Windows Deployment

Three Windows deployment modes: Single-file CLI, Portable Zip archive, and NSIS graphical installer, plus native Windows Service integration and a loopback-only local controller.

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:

POWERSHELL
# Start WAF forwarder and management plane interactively
.\cheesewaf.exe serve --config .\data\config\cheesewaf.yaml --data-dir .\data

# Query running daemon status and PID lease
.\cheesewaf.exe status

# Gracefully terminate the running daemon
.\cheesewaf.exe stop

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 Stop and Shutdown signals 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:

  1. Extract cheesewaf-amd64-windows-*.zip to your target directory (e.g., D:\CheeseWAF).
  2. Run terminal setup and start the server:
POWERSHELL
# Run the interactive setup wizard on first launch
.\cheesewaf.exe setup

# Launch the WAF daemon
.\cheesewaf.exe serve --config .\data\config\cheesewaf.yaml --data-dir .\data

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:

  1. Run the cheesewaf-amd64-windows-*-setup.exe installer (use the arm64 variant on Windows ARM64).
  2. Follow the wizard prompts. The installer registers the CheeseWAF Windows service in manual (start= demand) mode; start or stop it explicitly from the Service Control Manager or with sc.exe.
  3. 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 serve process when requested; it is not a second management backend.
POWERSHELL
.\cheesewaf-gui.exe --config .\data\config\cheesewaf.yaml --data-dir .\data

Once started, open http://127.0.0.1:17943/ in your browser to view the local desktop controller dashboard.

4 - macOS Deployment

Install CheeseWAF on macOS via graphical DMG package or lightweight tar.gz command-line archive.

CheeseWAF supports two primary deployment mechanisms on macOS:

1. DMG Graphical Installer

Ideal for local testing, development, and desktop workstations:

  1. Download the DMG matching your CPU architecture: cheesewaf-arm64-darwin-*.dmg for Apple Silicon (M-series), or cheesewaf-amd64-darwin-*.dmg for Intel Macs.
  2. Open the DMG image and drag CheeseWAF into your Applications folder.
  3. 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:

BASH
# Extract the archive
tar -xzf cheesewaf-arm64-darwin-*.tar.gz
cd cheesewaf-*

# Run terminal setup wizard
./cheesewaf setup

# Launch the WAF daemon
./cheesewaf serve --config ./data/config/cheesewaf.yaml --data-dir ./data

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.