Show all missing env vars with usage when install.sh is run without required variables
This commit is contained in:
@@ -0,0 +1,123 @@
|
|||||||
|
# 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 Let's Encrypt
|
||||||
|
- HTMX + Jinja2 templates
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
MGMT_DOMAIN=wall.example.com \
|
||||||
|
MGMT_PASS="strongpassword" \
|
||||||
|
MGMT_USER="admin" \
|
||||||
|
ACME_EMAIL="admin@example.com" \
|
||||||
|
bash install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
| Variable | Required | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `MGMT_DOMAIN` | Yes | Public domain for the management WebUI |
|
||||||
|
| `MGMT_PASS` | Yes | HTTP basic auth password for the WebUI |
|
||||||
|
| `MGMT_USER` | No | WebUI username (defaults to `admin`) |
|
||||||
|
| `ACME_EMAIL` | Yes | Let's Encrypt registration email |
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
1. **Assign interfaces** to zones from the Interfaces tab
|
||||||
|
2. **Configure DHCP** ranges for your LAN
|
||||||
|
3. **Add proxy domains** with Let's Encrypt 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 <repo-url> && cd vacuum-wall
|
||||||
|
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/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
.venv/bin/python -m pytest tests/ -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Tests mock all subprocess calls (firewalld, acme.sh, WireGuard, nginx, dnsmasq) — no system services required.
|
||||||
|
|
||||||
|
### 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 (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](docs/architecture.md) for detailed request flow and zone model.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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
|
||||||
|
- [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
|
||||||
Regular → Executable
+20
-3
@@ -15,10 +15,27 @@ err() { echo -e "${RED}[!!]${NC} $*"; exit 1; }
|
|||||||
PROJECT_DIR="/home/wall/vacuum-wall"
|
PROJECT_DIR="/home/wall/vacuum-wall"
|
||||||
USER_NAME="vacuum-wall"
|
USER_NAME="vacuum-wall"
|
||||||
USER_HOME="/home/$USER_NAME"
|
USER_HOME="/home/$USER_NAME"
|
||||||
DOMAIN="${MGMT_DOMAIN:?ERROR: Set MGMT_DOMAIN env var (e.g., wall.lan)}"
|
# --- Validate required env vars ---
|
||||||
|
missing=()
|
||||||
|
[[ -z "${MGMT_DOMAIN:-}" ]] && missing+=(MGMT_DOMAIN)
|
||||||
|
[[ -z "${MGMT_PASS:-}" ]] && missing+=(MGMT_PASS)
|
||||||
|
[[ -z "${ACME_EMAIL:-}" ]] && missing+=(ACME_EMAIL)
|
||||||
|
|
||||||
|
if (( ${#missing[@]} )); then
|
||||||
|
echo -e "${RED}[!!]${NC} Missing required environment variables:"
|
||||||
|
for v in "${missing[@]}"; do
|
||||||
|
case "$v" in
|
||||||
|
MGMT_DOMAIN) echo ' export MGMT_DOMAIN="wall.lan" # Management UI hostname';;
|
||||||
|
MGMT_PASS) echo ' export MGMT_PASS="your-password" # WebUI basic auth password';;
|
||||||
|
ACME_EMAIL) echo " export ACME_EMAIL=\"you@example.com\" # Let's Encrypt email";;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
printf '\nTo run: MGMT_DOMAIN=wall.lan MGMT_PASS=pass ACME_EMAIL=you@example.com ./install.sh\n'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOMAIN="$MGMT_DOMAIN"
|
||||||
MGMT_USER="${MGMT_USER:-admin}"
|
MGMT_USER="${MGMT_USER:-admin}"
|
||||||
MGMT_PASS="${MGMT_PASS:?ERROR: Set MGMT_PASS env var for WebUI basic auth}"
|
|
||||||
ACME_EMAIL="${ACME_EMAIL:?ERROR: Set ACME_EMAIL env var for Let's Encrypt}"
|
|
||||||
|
|
||||||
# --- Pre-flight checks ---
|
# --- Pre-flight checks ---
|
||||||
[[ $EUID -eq 0 ]] || err "This script must be run as root."
|
[[ $EUID -eq 0 ]] || err "This script must be run as root."
|
||||||
|
|||||||
Reference in New Issue
Block a user