nftables reload-after-tailscale systemd fix #181

Closed
opened 2026-03-26 23:12:37 +00:00 by forgejo_admin · 2 comments

Type

Bug

Lineage

standalone — discovered during Mac agent setup (#174)

Repo

forgejo_admin/pal-e-platform

What Broke

nftables resolves interface names (e.g. iif "tailscale0") to numeric ifindex at load time. If Tailscale restarts and gets a new interface index, the firewall rule silently stops matching — Tailscale traffic gets dropped by the default policy. Discovered when Mac Salt minion couldn't reach the master.

Repro Steps

  1. Reboot archbox (or restart Tailscale)
  2. sudo nft list ruleset | grep iif — shows iif 5 (stale numeric index) instead of iif "tailscale0"
  3. Tailscale traffic (100.x.x.x) is silently dropped

Expected Behavior

After reboot, nftables rules should reference the current Tailscale interface, not a stale index. Firewall should reload automatically after Tailscale starts.

Environment

  • Host: archbox (Arch Linux)
  • nftables managed by Salt (salt/states/firewall/)
  • Tailscale interface: tailscale0 (index varies across restarts)

Acceptance Criteria

  • After reboot, nft list ruleset | grep iif shows iif "tailscale0" (not a number)
  • Systemd dependency or timer ensures nftables reloads after tailscaled starts

Notes

Scope clarification: Is this about boot ordering (nftables loads before tailscaled starts) or mid-uptime restart (tailscaled restarts while system is running)? Fix may differ.

Existing salt state at salt/states/firewall/init.sls lines 31-45 already manages nftables rules — verify before duplicating.

  • feedback_ci_pipeline_lessons — similar nftables boot ordering issue fixed before (PR #81)
  • pal-e-platform #174 — discovered during Mac agent setup
### Type Bug ### Lineage standalone — discovered during Mac agent setup (#174) ### Repo `forgejo_admin/pal-e-platform` ### What Broke nftables resolves interface names (e.g. `iif "tailscale0"`) to numeric ifindex at load time. If Tailscale restarts and gets a new interface index, the firewall rule silently stops matching — Tailscale traffic gets dropped by the default policy. Discovered when Mac Salt minion couldn't reach the master. ### Repro Steps 1. Reboot archbox (or restart Tailscale) 2. `sudo nft list ruleset | grep iif` — shows `iif 5` (stale numeric index) instead of `iif "tailscale0"` 3. Tailscale traffic (100.x.x.x) is silently dropped ### Expected Behavior After reboot, nftables rules should reference the current Tailscale interface, not a stale index. Firewall should reload automatically after Tailscale starts. ### Environment - Host: archbox (Arch Linux) - nftables managed by Salt (`salt/states/firewall/`) - Tailscale interface: `tailscale0` (index varies across restarts) ### Acceptance Criteria - [ ] After reboot, `nft list ruleset | grep iif` shows `iif "tailscale0"` (not a number) - [ ] Systemd dependency or timer ensures nftables reloads after tailscaled starts ### Notes > **Scope clarification:** Is this about boot ordering (nftables loads before tailscaled starts) or mid-uptime restart (tailscaled restarts while system is running)? Fix may differ. > > Existing salt state at `salt/states/firewall/init.sls` lines 31-45 already manages nftables rules — verify before duplicating. ### Related - `feedback_ci_pipeline_lessons` — similar nftables boot ordering issue fixed before (PR #81) - pal-e-platform #174 — discovered during Mac agent setup
Author
Owner

Scope Review: NEEDS_REFINEMENT

Review note: review-400-2026-03-27

Critical finding: The codebase already has a partial fix. salt/states/firewall/init.sls (lines 31-45) creates a systemd drop-in with After=tailscaled.service + Wants=tailscaled.service, ensuring nftables loads after tailscaled at boot. Acceptance criterion #3 ("Salt state manages the systemd drop-in") is already done.

Issues to resolve before moving to next_up:

  • Clarify the failure scenario: Is this about boot ordering (possibly already fixed) or mid-uptime systemctl restart tailscaled (not fixed by After=)? The After= directive only controls startup ordering -- it does NOT trigger nftables reload when tailscaled restarts.
  • Update acceptance criteria: Remove criterion #3 (already implemented). Add explicit criterion for the actual delta, e.g.: "After systemctl restart tailscaled, nft list ruleset | grep iif still shows tailscale0."
  • Specify the fix mechanism: If mid-uptime restart is the scenario, the fix is likely adding PartOf=tailscaled.service to the existing drop-in (causes nftables to restart when tailscaled restarts).
  • Verify boot scenario first: Reboot archbox and check nft list ruleset | grep iif to confirm whether criterion 1 already passes with existing code.
## Scope Review: NEEDS_REFINEMENT Review note: `review-400-2026-03-27` **Critical finding:** The codebase already has a partial fix. `salt/states/firewall/init.sls` (lines 31-45) creates a systemd drop-in with `After=tailscaled.service` + `Wants=tailscaled.service`, ensuring nftables loads after tailscaled at boot. Acceptance criterion #3 ("Salt state manages the systemd drop-in") is already done. **Issues to resolve before moving to next_up:** - **Clarify the failure scenario**: Is this about boot ordering (possibly already fixed) or mid-uptime `systemctl restart tailscaled` (not fixed by `After=`)? The `After=` directive only controls startup ordering -- it does NOT trigger nftables reload when tailscaled restarts. - **Update acceptance criteria**: Remove criterion #3 (already implemented). Add explicit criterion for the actual delta, e.g.: "After `systemctl restart tailscaled`, `nft list ruleset | grep iif` still shows `tailscale0`." - **Specify the fix mechanism**: If mid-uptime restart is the scenario, the fix is likely adding `PartOf=tailscaled.service` to the existing drop-in (causes nftables to restart when tailscaled restarts). - **Verify boot scenario first**: Reboot archbox and check `nft list ruleset | grep iif` to confirm whether criterion 1 already passes with existing code.
Author
Owner

Issue body updated per scope review corrections.

Issue body updated per scope review corrections.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/pal-e-platform#181
No description provided.