Files
vacuum-wall/docs/deployment.md
T
mteehan e2f56b8cc8 Initial commit: SSL proxy / firewall appliance
Flask WebUI behind nginx reverse proxy with zone-based firewall, DHCP,
WireGuard, and ACME certificate management.
2026-05-07 22:24:24 +00:00

11 KiB

Vacuum Wall Deployment Guide

This guide walks through deploying Vacuum Wall on a real appliance or server. Vacuum Wall is an SSL proxy firewall appliance that combines edge proxying, firewall management, DHCP, DNS, and WireGuard in a single device.


Prerequisites

  • OS: Clean Debian 13 (Trixie) system. Also works on Debian 12 with backports for firewalld.
  • git: Required for cloning the repository.
  • Access: Root access to the machine.
  • Networking:
    • One public-facing network interface (external/edge). This receives inbound traffic and serves the management UI.
    • At least one LAN network interface (internal). This connects to your downstream network and will serve DHCP/DNS.
  • DNS: A DNS record pointing to the appliance's public IP for the management domain (e.g., wall.example.com).
  • Minimum hardware: 1 CPU, 512 MB RAM, 4 GB disk.

Installation

Download the Vacuum Wall repository onto the target machine, then run the installer with the required environment variables:

MGMT_DOMAIN=wall.example.com \
MGMT_PASS="strongpassword" \
MGMT_USER="admin" \
ACME_EMAIL="admin@example.com" \
bash install.sh

Environment Variables

Variable Required Description
MGMT_DOMAIN Yes The public-facing domain for the management WebUI. A DNS A record must point to the appliance's IP.
MGMT_PASS Yes The password for HTTP basic auth protecting the WebUI. Use a strong, randomly generated password.
MGMT_USER No The username for WebUI access. Defaults to admin.
ACME_EMAIL Yes The email address registered with Let's Encrypt for certificate issuance and expiry notifications.

What install.sh Does

The installer performs the following steps automatically:

  • Package installation: Installs firewalld, nginx, dnsmasq, wireguard-tools, python3, Flask, pip, jq, curl, iptables, nftables, and apache2-utils.
  • acme.sh installation: Downloads and installs the acme.sh client to the project user's home directory for Let's Encrypt certificate management.
  • Flask installation: Ensures the Flask Python package is available via pip for the WebUI backend.
  • System user creation: Creates a dedicated vacuum-wall system user (nologin shell) that owns the project data and runs the WebUI service.
  • Directory setup: Creates data directories under /home/wall/vacuum-wall/data/ for nginx sites, dnsmasq config, firewall rules, and WireGuard config. Sets ownership to the vacuum-wall user.
  • Sudoers whitelist: Installs a restrictive sudoers file at /etc/sudoers.d/vacuum-wall allowing the vacuum-wall user to run only the specific privileged commands needed for firewall, nginx, and dnsmasq management. Validates syntax with visudo -cf.
  • IP forwarding: Enables net.ipv4.ip_forward=1 in sysctl.conf and applies it at runtime, required for routing traffic between zones.
  • Firewalld initialization: Starts and enables firewalld. Opens HTTP, HTTPS, and SSH services on the public zone for management access.
  • Dnsmasq initialization: Starts and enables dnsmasq for future DHCP/DNS serving on internal interfaces.
  • Self-signed certificate: Generates a temporary self-signed X.509 certificate for the management domain with the correct CN and SAN, placed where acme.sh would store a real cert.
  • Management proxy configuration: Configures nginx as a reverse proxy that forward-proxies to the WebUI at 127.0.0.1:9090, with HTTP-to-HTTPS redirect, basic auth, and WebSocket upgrade support.
  • Credentials: Generates an htpasswd file using apache2-utils (with a Python fallback) for the management proxy's basic auth.
  • Systemd units: Installs three units:
    • vacuum-wall.service — the Flask WebUI backend.
    • vacuum-wall-acme.service — the certificate renewal oneshot.
    • vacuum-wall-acme.timer — periodic timer that triggers cert renewals.
  • Firewalld zones: Creates initial zones:
    • internal — trusted LAN zone with DHCP, DNS, and NTP services allowed.
    • vpn — WireGuard tunnel zone.
  • Service startup: Enables and starts nginx, the vacuum-wall WebUI, and the ACME renewal timer.
  • ACME registration: Registers the Let's Encrypt account with the provided email via acme.sh.

Post-Installation

Verify Services

After the installer completes, confirm all services are running:

systemctl status vacuum-wall nginx firewalld dnsmasq

Each should be active (running). The vacuum-wall-acme.timer should also be active (waiting).

Access the WebUI

Open a browser and navigate to:

https://wall.example.com

Log in with the username and password you provided during installation.

Certificate Note

The initial certificate is self-signed and generated during installation. Your browser will show a security warning. This is expected. Once DNS is pointing to the appliance and port 80 is accessible from the internet, use the Certs tab in the WebUI to issue a real Let's Encrypt certificate for the management domain. After issuance, go to the Proxy tab and click Apply to reload nginx with the new cert.


Configuring Your First Network

After installation, the appliance has no interfaces assigned to zones and no DHCP ranges configured. Use the WebUI to set up your LAN.

1. Assign a LAN Interface to the Internal Zone

  1. Navigate to the Interfaces tab.
  2. From the interface list, select your LAN interface (e.g., eth1).
  3. Assign it to the internal zone.
  4. Click Apply to update the firewall configuration.

2. Enable NAT/Masquerade

  1. Go to the NAT tab.
  2. Enable masquerade on the internal zone. This allows devices on your LAN to reach the internet through the appliance's external interface.
  3. Click Apply.

3. Configure DHCP

  1. Go to the DHCP tab.
  2. Click Add Range.
  3. Specify:
    • Address range: e.g., 192.168.2.100-192.168.2.200
    • Lease time: e.g., 12h
    • Interface: eth1 (or whichever interface you assigned to internal)
  4. Click Apply. This writes the dnsmasq configuration and reloads the service.

DNS resolution will also be provided on this interface by dnsmasq, which forwards queries upstream.


Adding a Proxy Domain

Vacuum Wall's primary function is proxying incoming HTTPS traffic to internal backend services.

1. Add the Domain

  1. Navigate to the Proxy tab.
  2. Click Add Domain.
  3. Fill in:
    • Domain: The public domain name (e.g., app.example.com).
    • Backend Host: The internal IP address of the service (e.g., 192.168.2.50).
    • Backend Port: The port the service listens on (e.g., 8080).

2. Issue a Certificate

  1. Go to the Certs tab.
  2. Click Issue Certificate and enter the domain name.
  3. ACME validation requires that port 80 on the appliance is reachable from the internet and that the domain's DNS A record points to the appliance's public IP.

3. Reload Nginx

  1. Return to the Proxy tab.
  2. Click Apply to write the nginx configuration and reload the service.

The proxied domain is now accessible via HTTPS at the configured domain name.


Setting up WireGuard

Vacuum Wall includes integrated WireGuard server support for VPN access.

1. Initialize the Server

  1. Navigate to the WireGuard tab.
  2. Click Initialize. This generates the server's private and public keys and creates the wg0 interface configuration.

2. Add a Peer

  1. Click Add Peer.
  2. Enter a peer name (e.g., alice).
  3. Optionally set a specific AllowedIPs range for this peer (defaults to 0.0.0.0/0).
  4. Optionally set an Endpoint if you know the peer's static public IP (restricts incoming connections to that IP).
  5. Click Add. The peer's public key and preshared key are generated automatically.

3. Activate the Tunnel

  1. Click Apply to write the WireGuard configuration and bring up the wg0 interface.

4. Download Client Configuration

  1. In the peer list, use the peer actions menu to download the client configuration file for the peer.
  2. Install this configuration on the client device.

5. Assign WireGuard to a Firewall Zone

  1. Navigate to the Interfaces tab.
  2. Assign wg0 to the vpn zone.
  3. The vpn zone allows all traffic by default (target ACCEPT). Adjust firewall rules as needed to restrict VPN access to specific services.

6. Configure Firewall Rules for VPN Traffic

  1. Go to the Firewall tab or use the NAT tab.
  2. Add rules as needed to control what VPN peers can access. For example, you can restrict VPN peers to only reach specific internal services rather than the entire LAN.
  3. Optionally enable masquerade on the vpn zone to allow VPN clients to reach the internet through the appliance.

Troubleshooting

Services Won't Start

Check service logs and configuration:

journalctl -u vacuum-wall --no-pager -n 50
journalctl -u nginx --no-pager -n 50
nginx -t

Common causes include port conflicts (another service on port 80/443), missing dependencies, or file permission issues on /home/wall/vacuum-wall/data/.

Firewall Rules Not Applying

Verify that firewalld is running:

firewall-cmd --state
systemctl status firewalld

If firewalld is not running, start it with systemctl start firewalld. Check that the sudoers whitelist is valid:

visudo -cf /etc/sudoers.d/vacuum-wall

Certificate Issuance Fails

Let's Encrypt ACME validation requires:

  • The domain's DNS A record points to the appliance's public IP.
  • Port 80 (HTTP-01 challenge) is accessible from the internet on the external interface.
  • The ACME email was registered correctly. Check with:
su -s /bin/bash vacuum-wall -c "~/.acme.sh/acme.sh --list"

If port 80 is blocked or the DNS record hasn't propagated yet, wait and retry. The ACME timer will also attempt renewal automatically.

DHCP Not Working

Verify that:

  • The LAN interface is assigned to a firewalld zone (check the Interfaces tab or firewall-cmd --get-active-zones).
  • Dnsmasq is running: systemctl status dnsmasq.
  • A DHCP range is configured for the correct interface. Check dnsmasq config at /home/wall/vacuum-wall/data/dnsmasq/.
  • The firewall allows DHCP traffic on the internal zone: firewall-cmd --zone=internal --list-services should include dhcp and dns.

WebUI Not Accessible

  1. Verify nginx is running: systemctl status nginx.
  2. Test nginx configuration: nginx -t.
  3. Check the management proxy configuration at /etc/nginx/conf.d/vacuum-wall-mgmt.conf.
  4. Ensure the vacuum-wall WebUI service is listening on port 9090: ss -tlnp | grep 9090.
  5. If using the self-signed cert, confirm your browser trusts it or use the WebUI to issue a real Let's Encrypt certificate.

Reference

Component Service Config Location
WebUI backend vacuum-wall.service /home/wall/vacuum-wall/webui/
Reverse proxy nginx /etc/nginx/conf.d/vacuum-wall-mgmt.conf
Firewall firewalld Managed via WebUI and firewall-cmd
DHCP/DNS dnsmasq /home/wall/vacuum-wall/data/dnsmasq/
VPN wireguard-tools /home/wall/vacuum-wall/data/wireguard/
Certificates vacuum-wall-acme.timer /home/vacuum-wall/.acme.sh/
Sudoers /etc/sudoers.d/vacuum-wall