8c13ad55ce
- update-vendor.sh now creates webui/vendor symlinks (htm.js) - install.sh calls update-vendor.sh after package install - Add vendor/.empty and webui/vendor/.empty as directory placeholders in git
150 lines
9.8 KiB
Markdown
150 lines
9.8 KiB
Markdown
# Vacuum Wall
|
|
|
|
## What is Vacuum Wall?
|
|
|
|
Vacuum Wall is a zone-based firewall appliance with a built-in SSL reverse proxy, providing a unified platform for network security and traffic management. It combines firewalld policy control, DHCP/DNS services, systemd-networkd for static IP management, WireGuard VPN tunnels, and automated certificate provisioning into a single device. A single web UI controls everything, making enterprise-grade network infrastructure manageable from one place.
|
|
|
|
## Architecture Overview
|
|
|
|
Vacuum Wall is built around five integrated subsystems managed through a two-layer architecture: a non-privileged Flask web UI and a privileged background daemon (`vacuum-walld`). The web UI communicates with the daemon via a Unix socket. The daemon handles all privileged operations (sudo) for the subsystems: the traffic plane uses firewalld with its nftables backend (zone-based policies, source NAT, destination NAT); the DNS/DHCP plane serves private subnets via dnsmasq; the network plane uses systemd-networkd for static IP management; the proxy plane runs nginx with automatic ACME certificates through acme.sh; and the VPN plane uses WireGuard (wg-quick) for encrypted tunnel management. All subsystems are configured and monitored through the Flask web UI, which is itself proxied through nginx with basic HTTP authentication.
|
|
|
|
## Subsystems
|
|
|
|
### Firewall
|
|
|
|
The firewall uses firewalld's zone model for traffic control. Network interfaces are assigned to zones such as external, internal, VPN, and trusted. Rules and services define which traffic is allowed between zones. Source NAT (masquerade) enables RFC 1918 networks to reach the internet through the external interface. Destination NAT rules provide port forwarding, exposing internal services to external networks on configurable ports.
|
|
|
|
### DHCP/DNS
|
|
|
|
dnsmasq serves as both the DHCP server and local DNS resolver. It is configured to serve address pools on specified LAN interfaces, with support for dynamic allocation ranges and static MAC-based reservations. Custom DNS records can be defined for local name resolution, and upstream DNS forwarding passes external queries to configurable resolvers.
|
|
|
|
### SSL Proxy
|
|
|
|
The nginx reverse proxy handles HTTPS termination for user-defined domains, with certificates automatically provisioned and renewed via acme.sh and an ACME provider (Let's Encrypt by default). Each proxy domain is configured with an HTTP-to-HTTPS redirect, modern TLS settings, and a configurable backend target. New proxy domains are added through the web UI, and the configuration is applied without manual intervention.
|
|
|
|
### Network (systemd-networkd)
|
|
|
|
The networkd subsystem manages static IP configuration for network interfaces via systemd-networkd. It renders declarative JSON configuration into per-interface `.network` INI files (`50-<name>.network`), supporting static addresses, routes, DNS, DHCP clients, link settings, and all `[Address]`, `[Route]`, `[DHCPv4]`, `[DHCPv6]`, and `[Link]` section keys. When the full apply runs, public DNS servers from networkd configs are auto-synced to dnsmasq's upstream resolvers. Helper endpoints can infer candidate DHCP ranges from static IPs and suggest firewalld zone assignments based on interface role.
|
|
|
|
### WireGuard
|
|
|
|
WireGuard support provides server-side VPN tunnel management. Peers are added through the web UI, with the system generating client configuration files that can be downloaded and applied on remote devices. The dashboard displays active connections and transfer statistics for each peer, allowing operators to monitor tunnel health and usage.
|
|
|
|
## Tech Stack
|
|
|
|
- Debian 13 (trixie) target platform
|
|
- Python 3.13+, Flask 3.x for web management
|
|
- firewalld (nftables backend)
|
|
- systemd-networkd (ip-lladdr, networkctl)
|
|
- nginx 1.26+
|
|
- dnsmasq
|
|
- WireGuard tools (wireguard-tools)
|
|
- acme.sh for ACME certificate management (Let's Encrypt by default)
|
|
|
|
## Quick Start
|
|
|
|
To install Vacuum Wall on a Debian 13 system, run `install.sh` as root with required settings (CLI flags or environment variables):
|
|
|
|
```bash
|
|
# Production
|
|
./install.sh --mgmt-pass yourpassword
|
|
|
|
# Development (auto-detects your user)
|
|
./install.sh --dev --mgmt-pass yourpassword
|
|
```
|
|
|
|
After installation, access the management interface at `https://<hostname>.local` using the credentials you configured. The `install.sh` script auto-detects the system hostname, network interfaces, and provisions nginx, authentication, an initial self-signed certificate, and all services. Run `./install.sh --help` for all options.
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
├── install.sh # Deployment script (renders Jinja2 templates)
|
|
├── pyproject.toml # Project metadata + dependencies
|
|
├── .venv/ # Python virtual environment
|
|
├── config/ # Declarative JSON configuration (source of truth)
|
|
│ ├── dnsmasq/ # DHCP/DNS config
|
|
│ ├── network/ # systemd-networkd per-interface config
|
|
│ ├── firewall/ # Firewall zone & rule config
|
|
│ ├── nginx/ # Proxy domain & SSL config
|
|
│ ├── wireguard/ # VPN interface & peer config
|
|
│ └── acme/ # ACME account settings (email, CA provider)
|
|
├── data/ # Runtime artifacts & generated files
|
|
│ ├── nginx/sites-enabled/ # Generated server blocks
|
|
│ ├── dnsmasq/fragments/ # User config fragments
|
|
│ ├── acme/ # ACME certificates
|
|
│ ├── firewall/ # Firewall rule backup
|
|
│ ├── logs/ # Application logs
|
|
│ ├── networkd/ # Generated 50-<name>.network files
|
|
│ └── wireguard/ # Generated WireGuard configs
|
|
├── daemon/ # Privileged background daemon
|
|
│ ├── server.py # aiohttp server, cache, batch routing, handler registry
|
|
│ ├── client.py # Sync HTTP client over Unix socket
|
|
│ ├── handlers/ # Privileged operation handlers (all sudo calls)
|
|
│ │ └── network.py # networkd handler (generate + apply)
|
|
├── system/ # System file templates (all Jinja2)
|
|
│ ├── systemd/ # Service and timer unit files
|
|
│ │ ├── vacuum-wall.service # Web UI service (rendered at install)
|
|
│ │ ├── vacuum-wall-acme.service # Certificate renewal (rendered at install)
|
|
│ │ └── vacuum-wall-acme.timer # Renewal schedule
|
|
│ ├── sudoers.d/ # Sudo whitelist (rendered at install)
|
|
│ ├── nginx/ # Nginx config templates (rendered at runtime)
|
|
│ ├── dnsmasq.conf # Dnsmasq template (rendered at runtime)
|
|
│ └── wireguard*.conf # WireGuard templates (rendered at runtime)
|
|
├── lib/ # Subsystem abstraction layer
|
|
│ ├── common.py # Shared utilities (run, run_proc, load_json, save_json, deep_merge, ensure_dirs)
|
|
│ ├── logging.py # Logging setup
|
|
│ ├── firewall.py # firewalld bindings
|
|
│ ├── network.py # systemd-networkd rendering & parsing
|
|
│ ├── dnsmasq.py # DHCP/DNS configuration
|
|
│ ├── nginx.py # Reverse proxy configuration
|
|
│ ├── state.py # State collector (uses lib.network.parse_networkctl_status)
|
|
│ ├── acme.py # Certificate management (ACME helpers)
|
|
│ └── wireguard.py # VPN tunnel and peer management
|
|
├── webui/ # Flask web application
|
|
│ ├── server.py # Application entry point
|
|
│ ├── api/ # REST API route modules (blueprints)
|
|
│ │ ├── common.py # Shared API response helpers (_ok, _error)
|
|
│ │ ├── firewall.py # Firewall API
|
|
│ │ ├── dhcp.py # DHCP/DNS API
|
|
│ │ ├── proxy.py # Nginx proxy API
|
|
│ │ ├── certs.py # Certificate API
|
|
│ │ ├── wireguard.py # WireGuard API
|
|
│ │ ├── network.py # Networkd API
|
|
│ │ └── logs.py # Logs API
|
|
│ └── static/ # SPA (index.html, app.js, style.css)
|
|
│ ├── hoover/ # Hoover SPA framework (VDOM, reactivity, router, components)
|
|
│ │ ├── index.js # Barrel export of all public APIs
|
|
│ │ ├── reactivity.js
|
|
│ │ ├── vdom.js
|
|
│ │ ├── render.js
|
|
│ │ ├── component.js
|
|
│ │ ├── router.js
|
|
│ │ ├── websocket.js
|
|
│ │ ├── api.js
|
|
│ │ ├── helpers.js
|
|
│ │ └── components/ # Layout, data display, modal, toast
|
|
│ └── pages/ # Page modules (each defines a route via definePage)
|
|
├── vendor/ # Vendored scripts and JS libraries
|
|
│ ├── acme.sh # ACME certificate client
|
|
│ └── htm.js # JS tagged-template HTML adapter
|
|
├── docs/ # Documentation
|
|
│ ├── overview.md # This file
|
|
│ ├── deployment.md
|
|
│ ├── api.md
|
|
│ ├── security.md
|
|
│ ├── architecture.md
|
|
│ ├── config.md
|
|
│ └── hoover.md # Hoover SPA framework
|
|
└── scripts/ # Utility scripts
|
|
└── update-vendor.sh # Download vendored libraries (acme.sh, htm)
|
|
```
|
|
|
|
## Documentation
|
|
|
|
- [Deployment Guide](deployment.md) - Full installation and configuration
|
|
- [API Reference](api.md) - REST API endpoints
|
|
- [Security Model](security.md) - Privilege model and sudo whitelist
|
|
- [Architecture](architecture.md) - Detailed subsystem design
|
|
- [Configuration](config.md) - Config file formats and locations
|
|
- [Hoover Framework](hoover.md) - Frontend SPA framework reference
|