# Vacuum Wall A zone-based firewall appliance with a built-in SSL reverse proxy. Combines firewalld policy control, DHCP/DNS, WireGuard VPN, and automated certificate provisioning into a single device managed through one web UI. ## Tech Stack - Debian 13 (trixie) target platform - Python 3.13+, Flask 3.x web UI - firewalld (nftables backend), dnsmasq, nginx, WireGuard - acme.sh for ACME certificates (CA is config-driven; code default Let's Encrypt) --- ## For Operators ### Prerequisites - Clean Debian 13 system with root access - git installed - One public-facing NIC (external) and at least one LAN NIC (internal) - A DNS A record pointing to the appliance's public IP for the management domain - Minimum hardware: 1 CPU, 512 MB RAM, 4 GB disk ### Install (Production) ```bash MGMT_DOMAIN=wall.example.com \ MGMT_PASS="strongpassword" \ MGMT_USER="admin" \ ACME_EMAIL="admin@example.com" \ bash scripts/install.sh ``` ### Install (Development) ```bash ./scripts/install.sh --dev --mgmt-pass strongpassword --acme-email "admin@example.com" ``` `--dev` auto-detects the repo's file owner as the service user, skips the safety warning about running as a regular user, and keeps file ownership dev-friendly. | Flag | Env Var | Required | Description | |---|---|---|---| | -- | `MGMT_DOMAIN` | No | Public domain for the management WebUI (auto-detected as `hostname.local`) | | `--mgmt-pass` | `MGMT_PASS` | Yes | SQLite DB password for the initial `admin` user (full `rw` on all subsystems) — not an nginx htpasswd | | `--mgmt-user` | `MGMT_USER` | No | WebUI username (defaults to `admin`) | | `--acme-email` | `ACME_EMAIL` | Yes | ACME registration email (CA is config-driven; code default Let's Encrypt) | | `--user, -u` | `USER_NAME` | No | System user for service (default: `vacuum-wall`) | | `--path, -p` | `INSTALL_DIR` | No | Install directory (default: repo root) | | `--dev` | -- | No | Auto-detect repo owner as service user, skip safety warning | | `--mgmt-domain` | `MGMT_DOMAIN` | No | (alias for env var) | | `--wan-iface` | `WAN_IFACE` | No | WAN interface (auto-detected) | | `--lan-ifaces` | `LAN_IFACES` | No | LAN interfaces, comma-separated (auto-detected) | CLI flags take precedence over environment variables. Run `./scripts/install.sh --help` for full usage. After installation, access the WebUI at `https://`. The initial certificate is self-signed — use the Certs tab to issue a real one once DNS is propagating. ### Next Steps 1. **Assign interfaces** to zones from the Interfaces tab 2. **Configure DHCP** ranges for your LAN 3. **Add proxy domains** with ACME certificates 4. **Set up WireGuard** (optional) See [docs/deployment.md](docs/deployment.md) for the full guide, including troubleshooting. --- ## For Developers ### Local Development ```bash git clone && cd vacuum-wall bash scripts/update-vendor.sh python3 -m venv .venv && . .venv/bin/activate pip install -e ".[dev]" ``` Start the WebUI locally (binds to 127.0.0.1:9090): ```bash .venv/bin/python webui/server.py ``` ### Lint and Format ```bash .venv/bin/ruff check lib/ webui/ tests/ .venv/bin/ruff format lib/ webui/ tests/ ``` All `lib/` modules share `lib.common` utilities (`run`, `run_proc`, `load_json`, `save_json`, `deep_merge`, `ensure_dirs`) and have full type hints and `__all__` exports. API blueprints share `_ok`/`_error` from `webui.api.common`. ### Tests ```bash .venv/bin/python -m pytest tests/ -v ``` Tests mock all subprocess calls (firewalld, acme.sh, WireGuard, nginx, dnsmasq) — no system services required. 28 Python test files (pytest) + 9 JS test files (jsdom/node harness). ### Documentation MCP Server This project uses `docs-mcp-server` for grounded, real-time documentation lookups during development. ```bash pipx install docs-mcp-server docs-mcp init ``` Then run with Claude Code or Opencode to activate it. It automatically checks live docs before answering technical questions — no manual doc search needed. ### Architecture ``` Client ──→ nginx (TLS; basic auth on basic-authed proxy domains only) ──→ Flask (127.0.0.1:9090) Flask ──→ daemon/client.py (Unix socket) ──→ vacuum-walld ──→ handlers ──→ sudo ``` Blueprints are thin proxies — privileged handlers live in `daemon/handlers/*.py`. | Blueprint | URL prefix | Handler | lib module | |---|---|---|---| | `webui/api/firewall` | `/api/firewall/` | `daemon/handlers/firewall` | `lib.firewall` | | `webui/api/dhcp` | `/api/dhcp/` | `daemon/handlers/dnsmasq` | `lib.dnsmasq` | | `webui/api/proxy` | `/api/proxy/` | `daemon/handlers/nginx` | `lib.nginx` | | `webui/api/certs` | `/api/certs/` | `daemon/handlers/acme` | `lib.acme` | | `webui/api/wireguard` | `/api/wireguard/` | `daemon/handlers/wireguard` | `lib.wireguard` | | `webui/api/network` | `/api/network/` | `daemon/handlers/network` | `lib.network` | | `webui/api/logs` | `/api/logs/` | `daemon/handlers/logs` | — | | `webui/api/status` | `/api/status/` | `daemon/handlers/status` | — | | `webui/api/auth` | `/api/auth/` | `daemon/handlers/auth` | `lib.auth` / `lib.auth_users` | See [docs/architecture.md](docs/architecture.md) for detailed request flow, zone model, and shared utility patterns. --- ## Documentation - [Overview](docs/overview.md) — Feature summary and tech stack - [Deployment Guide](docs/deployment.md) — Full installation and post-install configuration - [Architecture](docs/architecture.md) — Request flow, subsystems, zone model, shared utilities - [API Reference](docs/api.md) — REST API endpoints - [Security Model](docs/security.md) — Privilege model and sudo whitelist - [Configuration](docs/config.md) — Declarative config file formats and locations - [State Model](docs/state-model.md) — Per-subsystem state schema and real-time push mechanics - [Frontend (hoover)](docs/hoover.md) — Custom reactive SPA framework API reference