Initial commit: SSL proxy / firewall appliance
Flask WebUI behind nginx reverse proxy with zone-based firewall, DHCP, WireGuard, and ACME certificate management.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# Vacuum Wall — Agent Instructions
|
||||
|
||||
## What This Is
|
||||
|
||||
SSL proxy / firewall appliance. Python 3 Flask WebUI behind nginx reverse proxy.
|
||||
Deploys on Debian 13 (trixie). Target system: `/home/wall/vacuum-wall`.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Client ──→ nginx (SSL + basic auth) ──→ Flask (127.0.0.1:9090)
|
||||
Flask ──→ lib/*.py ──→ sudo <cmd> ──→ system service
|
||||
```
|
||||
|
||||
- `webui/server.py` — Flask app entry point. **Only** file that creates the `app`.
|
||||
- `webui/api/*.py` — Flask blueprints, one per subsystem. Routes prefix `/api/<subsystem>/`.
|
||||
- `lib/*.py` — Backend modules. Wrap system commands via `subprocess.run(["sudo", ...])`.
|
||||
- `data/` — Declarative JSON configs (source of truth). Generated `.conf` in `data/nginx/sites-enabled/`.
|
||||
- `system/` — System file templates. `systemd/` (service units installed to `/etc/systemd/system/`), `sudoers.d/`, `nginx/`.
|
||||
|
||||
Project uses `.venv`. Install deps with `pip install -e .` (from `pyproject.toml`). `__init__.py` files in `webui/` and `lib/` are intentionally empty — no `sys.path` boilerplate needed.
|
||||
|
||||
## Fixed Path
|
||||
|
||||
Every module hardcodes `/home/wall/vacuum-wall`. Changing it requires updating `lib/*.py`, `system/systemd/*.service`, `install.sh`, and `system/sudoers.d/vacuum-wall`.
|
||||
|
||||
## Local Dev
|
||||
|
||||
```bash
|
||||
.venv/bin/python webui/server.py # binds 127.0.0.1:9090
|
||||
```
|
||||
|
||||
In production the systemd unit runs as the `vacuum-wall` system user (`NoNewPrivileges`, `ProtectSystem=strict`, loopback-only networking).
|
||||
|
||||
## Blueprint ↔ lib Mapping (Naming Is Not 1:1)
|
||||
|
||||
| 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` |
|
||||
|
||||
## Privileged Operations
|
||||
|
||||
`lib/` modules call `sudo` for everything that touches system services. Whitelist is `system/sudoers.d/vacuum-wall`.
|
||||
|
||||
Pattern for mutations: write JSON → render native config → `sudo <cmd>` to apply.
|
||||
Adding a new privileged command requires a sudoers entry **and** the `lib/` code.
|
||||
|
||||
## API Response Contract
|
||||
|
||||
- Success: `{"ok": true, "data": <value>}` — helper `_ok(data)`
|
||||
- Error: `{"ok": false, "error": "msg"}` — helper `_error(msg, code=400)`
|
||||
- HTTP codes: `400` bad request, `404` not found, `500` internal failure
|
||||
- Full spec: `docs/api.md`
|
||||
|
||||
## Page Routes vs API
|
||||
|
||||
`server.py` serves HTML pages with Jinja templates. All data is wrapped in `_safely(fn, default)` so page routes never 500 — they render with fallback values instead.
|
||||
|
||||
## Deploy
|
||||
|
||||
`install.sh` is the single deploy script. Run as root, requires `MGMT_DOMAIN`, `MGMT_PASS`, `ACME_EMAIL` env vars.
|
||||
|
||||
## Lint and Tests
|
||||
|
||||
**Linter / formatter:** Ruff (`ruff check` + `ruff format`). Config in `pyproject.toml` under `[tool.ruff]`.
|
||||
|
||||
**Tests:** pytest in `tests/`. Run with `python -m pytest`. Tests mock out subprocess calls (firewalld, acme.sh, WireGuard, nginx, dnsmasq) — no system services required.
|
||||
|
||||
```bash
|
||||
.venv/bin/ruff check lib/ webui/ tests/ # lint
|
||||
.venv/bin/ruff format lib/ webui/ tests/ # format
|
||||
.venv/bin/python -m pytest tests/ -v # test (149 tests)
|
||||
```
|
||||
|
||||
Install dev tooling with `pip install -e ".[dev]"`.
|
||||
|
||||
## Docs
|
||||
|
||||
`docs/` contains the authoritative reference. `docs/architecture.md` covers request flow, zone model, and data directory layout in detail.
|
||||
Reference in New Issue
Block a user