Wheelhouse docs

1:1 NAT#

A 1:1 mapping ties one public address to one inside host in both directions, every port, without a rule per service. Wheelhouse reads those mappings: the middle table on the NAT page lists every rule under nat static rule <n>, and clicking one opens a panel showing it. Wheelhouse does not write them on this platform build. Committing nat static through the router's HTTP API stops the API process — the CLI accepts the same lines — so the editor is disabled with that reason on the page, and the panel hands you the console commands instead.

The platform gap#

What that means in the UI:

  • + Add 1:1 is disabled for everyone, with the explanation as its tooltip.
  • The 1:1 NAT (static) panel carries the same explanation as a line of warning text above the table.
  • Clicking a row opens a read-only panel: the rule's fields, and the commands to remove it from the console.

Deleting is blocked for the same reason as adding. A delete of a nat static rule is also a nat static commit, and it takes the API down exactly as an add does — so the panel offers no delete button, only the commands.

The table#

ColumnFrom
RuleThe rule number.
Descriptiondescription.
Inboundinbound-interface. Note the shape: nat static names its interface as a plain leaf, where nat destination uses inbound-interface name. The page reads both forms.
Public addressdestination address — the address arriving on the uplink.
Inside addresstranslation address — the host behind the router.

There are no counters in this table: the statistics endpoint reads show nat destination statistics and show nat source statistics only (agent/opmode.go handleNatStats).

The read-only panel#

Clicking a row opens a side panel with the warning, a summary of the rule — inbound interface, public address, inside address, description — and a From the console block containing exactly what to type:

configure
delete nat static rule 100
commit
save

The footer button reads Editing is off for 1:1 rules and is disabled.

Writing one by hand#

From the console, a mapping of a second provider address to an inside host:

configure
set nat static rule 100 inbound-interface eth1
set nat static rule 100 destination address 203.0.113.10
set nat static rule 100 translation address 10.0.10.30
set nat static rule 100 description "mail server"
commit
save

Two conditions that are not the router's to arrange:

  • The public address must already be routed to this router — a second address from the provider, or a delegated prefix. A 1:1 rule does not make the internet send you an address you were not given.
  • The firewall still decides what gets in. A mapping translates; it does not permit. The forward chain needs accept rules for the inside host, exactly as a port forward does. Those you can write from the UI.

The rules appear in the table on the next read, and the page will show them for as long as they exist.

When it is fixed#

The block is a single constant in the page source. When a platform build commits nat static through the API without taking the API process down, the editor behind it is already written: interface, public address, inside address, description and a Log translations checkbox, staging the same commands as above. Until then this page documents a table, not an editor.

See also#

Checked against#

ui/src/pages/Nat.tsx, agent/opmode.go, agent/main.go, PLAN.md.

Updated 2026-09-02 manual nat static-nat