Skip to content

Change the firewall safely

In this guide a superuser changes the host firewall (ufw) from the panel. Every change is applied with a snapshot of the old rules and a rollback timer, so a change that cuts you off undoes itself.

  • A superuser account.
  • ufw on the host (GET /firewall/ reports available).
Terminal window
PANEL=https://panel.example.com
H='Authorization: Bearer gsl_xxxxxxxxxxxxxxxx'
J='Content-Type: application/json'
  1. The API records the change and returns it (201). Only one change can be in progress at a time, so another request gets 409.
  2. The worker applies it through gisila-agent firewall. The agent refuses anything that would cut off SSH or the panel:
    • blocking the host’s SSH ports (22 and any Port in sshd_config), 80, 443, or the port your request came in on;
    • blocking a source that contains your IP;
    • removing the last allow rule for one of those ports;
    • turning the firewall on while a rule blocks you. Turning it on first adds allow rules for SSH, 80 and 443.
  3. The agent saves the old rules and starts a transient systemd timer outside the panel. The change moves to awaiting_confirmation.
  4. Confirm within the window (5 minutes by default, FIREWALL_CONFIRM_MINUTES, 1 to 10). In the browser, any panel page confirms it automatically: if that request gets through, the panel is still reachable. If nobody confirms, the old rules come back.

Change statuses: queued, applying, awaiting_confirmation, confirm_requested, revert_requested, applied, rolled_back, failed (refused, with the reason in error).

Terminal window
curl -s $PANEL/firewall/ -H "$H" | jq '{available, active, defaultIncoming, sshPorts, rules, open}'

Each rule has an origin: panel (added here, removable here), base, web or other. Rules from apps, databases or the shell are read-only here.

Terminal window
CHANGE=$(curl -sX POST $PANEL/firewall/rules -H "$H" -H "$J" -d '{
"action": "allow",
"proto": "tcp",
"port": "8000:8100",
"from": "198.51.100.0/24",
"note": "office"
}' | jq .id)
Field Values
action allow, deny, reject, limit
proto tcp, udp, any
port "22", a range "8000:8100", or empty for every port
from any, an IP or a CIDR
note Up to 60 characters

From a script, poll until the change is applied, then confirm. Only the person who made the change can confirm it, before its confirmBy time.

Terminal window
until [ "$(curl -s $PANEL/firewall/changes/$CHANGE -H "$H" | jq -r .status)" = awaiting_confirmation ]; do
sleep 2
done
curl -sX POST $PANEL/firewall/changes/$CHANGE/confirm -H "$H"

To undo it right away instead: POST /firewall/changes/{id}/revert.

Send the same fields as the rule to remove. Only origin: panel rules match.

Terminal window
curl -sX POST $PANEL/firewall/rules/remove -H "$H" -H "$J" \
-d '{"action": "allow", "proto": "tcp", "port": "8000:8100", "from": "198.51.100.0/24"}'

Confirm it the same way.

Terminal window
curl -sX POST $PANEL/firewall/enable -H "$H"
curl -sX POST $PANEL/firewall/disable -H "$H"

When every site is proxied through Cloudflare:

Terminal window
curl -sX POST $PANEL/firewall/web-sources -H "$H" -H "$J" -d '{"preset": "cloudflare"}'
# or your own list:
curl -sX POST $PANEL/firewall/web-sources -H "$H" -H "$J" \
-d '{"sources": "203.0.113.0/24, 2001:db8::/32"}'
# open them to everyone again:
curl -sX POST $PANEL/firewall/web-sources -H "$H" -H "$J" -d '{"sources": "any"}'

The panel swaps its allow-from-anywhere rules for 80 and 443 for gisila-web rules. It refuses when your own address isn’t among the sources, or when another rule still lets everyone in on 80 or 443.

Terminal window
curl -s $PANEL/firewall/pending -H "$H" # {"open": null} when nothing is in progress
sudo ufw status numbered # on the host

The panel re-reads ufw every minute. POST /firewall/refresh forces it.