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.