network:rules service¶
Compiles a module's declared firewall surface into OPNsense rules — who may reach it, what it may reach, and the named aliases those rules are built from. The whole rule set for the module is re-derived on every pass, so a rule the operator removed from the declaration is removed from the firewall.
The module's firewall surface. Every change is a live OPNsense API call; established connections may reset, but nothing reboots.
Why reconcile¶
A rule set is reconciled by adding, changing and removing rules against OPNsense's own model. Removing a rule the operator deleted from ingress cannot be expressed as a scalar diff — a generic differ would see "the value changed" and have nothing to apply. update-service.sh re-derives the whole rule set for this module on every pass and deletes what is no longer declared.
Fields¶
network:rules owns 6 declared field(s). Each table below carries the field's full definition and, where the service applies it, its ADR-020 change semantics.
ingress¶
Inbound traffic permitted to this module's ports. Each entry is compiled into an OPNsense pass rule and validated against the destination zone's pinhole-allowed-from policy at compile time.
| Attribute | Value |
|---|---|
| Type | array |
| Default | (none) |
| Example | [{"from": "srvWork", "ports": [4000], "description": "Intra-zone consumers read the API"}, {"from": "dmz", "ports": [4000], "description": "Caddy reverse proxy forwards the public hostname"}] |
| Required by | (none) |
| Used by | network:rules |
| Change class | in-place |
| Apply mode | reconcile |
About the field. Module peer (from = another module name): compiler ensures an OPNsense host alias 'tappaas_module_
Why this change class. Who may reach this module. A rule swap on OPNsense takes effect immediately; no guest is touched, so there is no downtime to authorize.
egress¶
Outbound traffic exceptions beyond what the source zone's access-to already permits. Compiled into OPNsense pass rules on the source-zone interface.
| Attribute | Value |
|---|---|
| Type | array |
| Default | (none) |
| Example | [{"to": "alias:llm_cloud_providers", "ports": [443], "description": "Upstream LLM providers"}, {"to": "vllm-amd", "ports": [11434], "description": "Local inference fallback"}] |
| Required by | (none) |
| Used by | network:rules |
| Change class | in-place |
| Apply mode | reconcile |
About the field. Module peer (to = another module name): compiler creates a host alias 'tappaas_module_
Why this change class. What this module may reach (consumer egress, ADR-COM-0002). Same cost as ingress.
ports¶
Network ports this module exposes for inbound traffic. Source of truth for ingress validation.
| Attribute | Value |
|---|---|
| Type | array |
| Default | (none) |
| Example | [{"port": 4000, "protocol": "TCP", "description": "Service API"}] |
| Required by | (none) |
| Used by | network:rules |
| Change class | in-place |
| Apply mode | reconcile |
About the field. Ingress entries must reference ports declared here. Activated when network:rules is in dependsOn.
Why this change class. The module's declared service surface, from which the default ingress rules are derived.
aliases¶
Module-local OPNsense aliases that this module's ingress/egress rules reference via 'alias:
| Attribute | Value |
|---|---|
| Type | object |
| Default | |
| Example | {"llm_cloud_providers": {"type": "host", "addresses": ["api.anthropic.com", "api.openai.com"], "description": "Curated whitelist of approved upstream model providers"}} |
| Required by | (none) |
| Used by | network:rules |
| Change class | in-place |
| Apply mode | reconcile |
About the field. Aliases are created in OPNsense before referencing rules are applied, and removed on remove-rules unless still referenced by other modules.
Why this change class. Named address/port groups the module's rules refer to. Changing one re-points every rule that uses it — still a live firewall change, still no downtime.
aliasType¶
OPNsense alias type for the module's firewall alias (tappaas_module_
| Attribute | Value |
|---|---|
| Type | string |
| Default | host |
| Allowed values | host — Host alias → network — Network alias → zone0 subnet CIDR from zones.json (multi-device modules) |
| Example | network |
| Required by | (none) |
| Used by | network:rules |
| Change class | in-place |
| Apply mode | reconcile |
About the field. When 'network', the alias content is derived from the zone0 subnet — no separate field is needed. The module's zone0 must define an 'ip' (subnet) in zones.json. Owned by network:rules (#704): rules_manager.py builds and validates the alias, and network:proxy never reads this field at all — the old attribution made every device module that declares network:rules and not network:proxy warn as an orphan on each conversion.
Why this change class. How the module is addressed in the generated firewall alias (host vs network).
firewallType¶
Type of firewall in use. Set to 'NONE' when the TAPPaaS OPNsense firewall is not deployed (e.g. using pfSense, UniFi, Cisco, or no firewall).
| Attribute | Value |
|---|---|
| Type | string |
| Default | opnsense |
| Allowed values | opnsense — TAPPaaS-managed OPNsense firewall (default)NONE — No TAPPaaS firewall — manual reverse proxy and firewall rule configuration required |
| Example | NONE |
| Required by | (none) |
| Used by | network:rules |
| Change class | in-place |
| Apply mode | reconcile |
About the field. When set to 'NONE', network:proxy prints manual configuration instructions instead of calling caddy-manager. Owned by network:rules (#704), which is the only service that reads it from a MODULE's config. network:proxy's delete-service.sh reads a firewallType too, but from the estate's config/firewall.json — a different value in a different place, so it is not a usedBy of the module field.
Why this change class. Which firewall implementation serves this estate. 'NONE' makes the service print manual instructions instead of calling a controller; that branch is the non-field logic update-service.sh keeps.