Levelrail
Skip to content

Host firewall ​

Levelrail can manage a set of allow and deny rules for the control plane host's own ufw firewall. You declare rules as records (a port, a protocol, an optional source, an action), and a reconciler converges ufw to match them. It is the same declarative model as the rest of the platform: edit the record, and the host follows.

This is opt-in and narrow by design. If you never add a rule, nothing is changed on the host.

What it does and does not touch ​

  • Only tagged rules. Every rule the platform creates carries a ufw comment prefix derived from the brand short name (levelrail: by default, see White-labeling). Sync only adds and removes rules carrying that prefix. Rules you created yourself with ufw are never changed or deleted.
  • Never enables the firewall. The platform does not run ufw enable and does not change the default policy. If ufw is installed but inactive, rules are stored but not applied, and the reconciler reports that no rules are managed until you enable it.
  • Only ufw, only the local host. If ufw is not installed (you use firewalld, nftables, iptables or a cloud security group), nothing is applied and the reconciler reports that as informational, not a failure. Rules are stored for the control plane host. Per-node rules for remote nodes are not supported yet, and a rule pinned to a remote node would be skipped and logged.
  • Not the installer's firewall step. install.sh can allow SSH, 80 and 443 once with LEVELRAIL_CONFIGURE_UFW=1 (see Installing). That is a one-time script action. This page covers the ongoing, managed rules.

The lockout guard ​

A deny rule, or an allow rule restricted to a source CIDR, on a port the control plane itself needs is refused rather than applied. The protected ports are the ones this instance is actually configured to use:

  • the management API address (APP_HTTP_ADDR),
  • the agent gRPC address (APP_AGENT_ADDR),
  • the ingress HTTP address (APP_INGRESS_HTTP_ADDR),
  • the ingress HTTPS address (APP_INGRESS_HTTPS_ADDR).

With defaults these are 8080, 9443, 80 and 443. An unrestricted allow on a protected port is accepted. The check runs when you create the rule (the API returns a validation error) and again in the reconciler as a second line of defense. A control plane that has locked itself out cannot reopen itself, which is why this is refused unconditionally.

Add and remove rules ​

A source CIDR must parse as a valid CIDR. A source of 0.0.0.0/0 is treated the same as no source (any source).

How rules are applied ​

Creating or deleting a rule nudges the reconciler, which reads every stored rule, re-validates each against the protected ports, and syncs ufw: it adds tagged rules that are missing and removes tagged rules that no longer have a record. Each applied rule's comment is the prefix plus rule:<id>, so you can match a ufw status line back to its record.

The reconciler reports one of these outcomes as the firewall controller's status:

OutcomeMeaning
Synced N rulesEvery stored rule is in place. The message also reports how many were applied and removed on that pass.
UFWNotInstalledufw is not on the host. Nothing is managed.
UFWInactiveufw is installed but not enabled. Nothing is managed until you enable it yourself.
RuleSyncFailedOne or more ufw commands failed. The other rules are still processed, and the message lists the errors.

Released under the Apache 2.0 License.