A Dockerised FastAPI web app for toggling firewall rules on a Ubiquiti EdgeRouter X from a mobile browser. The router is the single source of truth — rule state is read live over SSH on every page load.
# clone and enter the repo
git clone <repo-url> edgewall && cd edgewall
# copy the example env file and fill in real credentials
cp .env.example .env
$EDITOR .env
# build and start
docker compose up -d --build
# check it's running
curl http://localhost:6000/healthThen open http://<host-ip>:6000 in a browser.
Set these in docker-compose.yaml or override them in Dockge.
| Variable | Description | Default |
|---|---|---|
ROUTER_HOST |
EdgeRouter LAN IP | 192.168.1.1 |
ROUTER_PORT |
Router SSH port | 22 |
ROUTER_USER |
SSH username | — |
ROUTER_PASS |
SSH password | — |
WEB_USER |
Web UI login username | — |
WEB_PASS |
Web UI login password | — |
FIREWALL_RULESET |
EdgeOS allow-chain ruleset name | TIMED_ACCESS |
TOGGLABLE_RULES |
Comma-separated rule numbers the UI can toggle | 40,50,60,70 |
HIDDEN_RULES |
Comma-separated rule numbers hidden from the UI | 10,100,101,10000 |
CHILD_RULESET |
EdgeOS per-child block ruleset name | PER_CHILD |
CHILD_TOGGLES |
Comma-separated child-block rule numbers | 1,2,3,6 |
HIDDEN_RULES suppresses specific fixed rules from the "Currently on" list (e.g. the default-action rule that is always enabled and not useful to display).
- Page load — app SSHes to the router, runs
show firewall name {RULESET} statistics(allow chain) andshow firewall name {CHILD_RULESET} statistics(block chain), parses both outputs, and renders the page server-side with Jinja2. - Toggle — tapping a card POSTs to
/api/rules/{num}/toggle. The app SSHes to the router, reads current state, then issuesbegin / set-or-delete disable / commit / save / endas a single chained command. The card updates in-place viafetch()— no page reload. - Per Child Block rules — non-togglable rules that are currently enabled appear as a plain text list below the toggle cards. Disabled fixed rules and
HIDDEN_RULESare never shown. Per-child block rules use red styling when disabled (enabled=false), white/neutral when enabled.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | / |
Yes | Render UI with live rule state |
| GET | /api/rules |
Yes | JSON list of rules |
| POST | /api/rules/{rule_num}/toggle |
Yes | Toggle one rule; returns new state |
| GET | /api/block-rules |
Yes | JSON list of per-child block rules |
| POST | /api/block-rules/{rule_num}/toggle |
Yes | Toggle one block rule; returns new state |
| GET | /health |
No | Liveness probe |
Auth is HTTP Basic (browser prompts automatically). All routes except /health require credentials.
Toggle response:
{ "rule_num": 40, "enabled": true }Returns 403 if rule_num is not in TOGGLABLE_RULES. Returns 502 if SSH fails.
- Paste
docker-compose.yamlinto a new Dockge stack. - Override
ROUTER_PASS,WEB_USER, andWEB_PASSin the Dockge env editor. - Deploy. The container exposes port
6000.
docker logs -f edgewall-firewall-manager-1SSH connection attempts, command output, and toggle operations are all logged. Paramiko's low-level kex negotiation is suppressed — only warnings and errors from the transport layer appear.
- EdgeOS v3.x / Vyatta
- Password-based auth (
ROUTER_USER/ROUTER_PASS) - The SSH user needs permission to run:
/opt/vyatta/bin/vyatta-op-cmd-wrapper— read firewall statistics/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper— modify firewall config
Upgrade path: SSH key auth can replace password auth by changing
paramikofromconnect(password=...)toconnect(key_filename=...). Generate a key on the Docker host and add the public key to the EdgeRouter's authorised keys.
- LAN-only. Do not expose port
6000to the WAN. - Credentials live in
docker-compose.yamlenv block or a.envfile — never in source code. .envis in.gitignore.- Only rules listed in
TOGGLABLE_RULEScan be changed — enforced in the API before any SSH call. - HTTP Basic Auth is stateless (no sessions, no cookies). Adequate for LAN use.
edgewall/
├── app/
│ ├── main.py — FastAPI app, routes, logging setup
│ ├── router_ssh.py — all SSH / EdgeOS logic
│ ├── auth.py — HTTP Basic Auth dependency
│ ├── models.py — Pydantic models (Rule, ToggleResponse)
│ ├── templates/
│ │ └── index.html — Jinja2 template
│ └── static/
│ └── style.css — all CSS
├── docs/
│ └── spec.md — full project specification
├── Dockerfile
├── docker-compose.yaml
├── requirements.txt
├── .env.example
└── .gitignore