The token refresh callback in websocket.js ignored its ok parameter, causing an infinite reconnect loop when the server rejected the refresh attempt. On failure, redirect to login instead of reconnecting with a cleared token. clearAuthTokens() now also removes vw:permissions from sessionStorage to prevent stale permissions from persisting across logout/login cycles. Also removed duplicate vw:user removeItem call.
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 (ZeroSSL)
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)
MGMT_DOMAIN=wall.example.com \
MGMT_PASS="strongpassword" \
MGMT_USER="admin" \
ACME_EMAIL="admin@example.com" \
bash scripts/install.sh
Install (Development)
./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 | HTTP basic auth password for the WebUI |
--mgmt-user |
MGMT_USER |
No | WebUI username (defaults to admin) |
--acme-email |
ACME_EMAIL |
Yes | ACME registration email (ZeroSSL by default) |
--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://<MGMT_DOMAIN>. The initial certificate is self-signed — use the Certs tab to issue a real one once DNS is propagating.
Next Steps
- Assign interfaces to zones from the Interfaces tab
- Configure DHCP ranges for your LAN
- Add proxy domains with ACME certificates
- Set up WireGuard (optional)
See docs/deployment.md for the full guide, including troubleshooting.
For Developers
Local Development
git clone <repo-url> && 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):
.venv/bin/python webui/server.py
Lint and Format
.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
.venv/bin/python -m pytest tests/ -v
Tests mock all subprocess calls (firewalld, acme.sh, WireGuard, nginx, dnsmasq) — no system services required. 192 tests across 5 test modules.
Documentation MCP Server
This project uses docs-mcp-server for grounded, real-time documentation lookups during development.
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 (SSL + basic auth) ──→ Flask (127.0.0.1:9090)
Flask ──→ lib/*.py ──→ sudo <cmd> ──→ system service
| Blueprint | URL prefix | Backend module |
|---|---|---|
webui/api/firewall |
/api/firewall/ |
lib.firewall |
webui/api/dhcp |
/api/dhcp/ |
lib.dnsmasq |
webui/api/proxy |
/api/proxy/ |
lib.nginx |
webui/api/certs |
/api/certs/ |
lib.acme |
webui/api/wireguard |
/api/wireguard/ |
lib.wireguard |
See docs/architecture.md for detailed request flow, zone model, and shared utility patterns.
Documentation
- Overview — Feature summary and tech stack
- Deployment Guide — Full installation and post-install configuration
- Architecture — Request flow, subsystems, zone model, shared utilities
- API Reference — REST API endpoints
- Security Model — Privilege model and sudo whitelist
- Configuration — Declarative config file formats and locations