Skip to content

fix(test): assert guest egress over TCP, not ICMP, for VM-boot CI#13

Merged
pilat merged 1 commit into
mainfrom
fix/linux-egress-and-brew-trust-docs
Jun 13, 2026
Merged

fix(test): assert guest egress over TCP, not ICMP, for VM-boot CI#13
pilat merged 1 commit into
mainfrom
fix/linux-egress-and-brew-trust-docs

Conversation

@pilat

@pilat pilat commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Two things, both surfaced right after v0.4.0 shipped.

The bigger one: the VM-boot CI on main went red. With the v0.4.0 unification it now boots the full suite and, for the first time, asserts that a guest can reach the public internet — which failed immediately. Chasing it took a couple of wrong turns, but the cause is the test environment, not the backend. GitHub-hosted runners drop outbound ICMP entirely (the runner host itself can't ping 1.1.1.1, while TCP works), so the conformance test's ping-based egress check was a false negative. On top of that the runners run Docker, which sets the iptables FORWARD policy to DROP — the same conflict that breaks libvirt and LXD on Docker hosts — so forwarded guest traffic is dropped before it's masqueraded. The fix asserts egress with a TCP connect to 1.1.1.1:443 instead of ping (a better egress proof anyway) and opens the VM subnet through DOCKER-USER on the runner so the forward survives Docker's policy. fleetbox itself still does not touch the host firewall — that is a deliberate ADR-0025 decision — so the Docker-host egress ceiling is now spelled out as a limitation for real users, with the one-line DOCKER-USER allow they can add if they want egress on such a host.

The smaller one: Homebrew 6.0 made third-party tap trust mandatory, so installing the cask now needs a one-time brew trust first. The install docs carry that step.

Checklist

  • Changed the public API, package list, CLI surface, on-disk layout, or dependencies → ARCHITECTURE.md updated in this PR
  • Made a new, hard-to-reverse design decision → added an ADR under docs/adr/ (next sequential number)
  • Breaking change (! in the title) → the description spells out what callers must change

Summary by CodeRabbit

  • Documentation

    • Added macOS Homebrew trust step.
    • Documented Docker host networking note and DOCKER-USER allow-rule for the VM subnet to restore VM internet egress.
    • Updated CI/hosted-runner guidance to prefer TCP checks (e.g., 1.1.1.1:443) since ICMP may be blocked.
  • Bug Fixes

    • Made VM egress verification use a TCP connectivity check instead of ping for more reliable results.

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a02e2f35-b989-4f8d-80ee-2335dfd8d798

📥 Commits

Reviewing files that changed from the base of the PR and between 93cdf99 and df50641.

📒 Files selected for processing (4)
  • .github/workflows/vm-linux.yml
  • README.md
  • docs/adr/0025-linux-netlink-nftables.md
  • fleetboxtest/conformance_vm_test.go
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/vm-linux.yml
  • fleetboxtest/conformance_vm_test.go

📝 Walkthrough

Walkthrough

This PR resolves a Docker networking issue where the host's FORWARD chain policy inadvertently blocks VM internet egress. Changes include iptables rules in CI, a test update from ping to TCP egress verification, and documentation of the limitation and workaround across README and ADR.

Changes

Docker FORWARD Fix and Egress Verification

Layer / File(s) Summary
Docker FORWARD limitation and iptables workaround documentation
README.md, docs/adr/0025-linux-netlink-nftables.md
README and ADR now document that Docker/ufw FORWARD=DROP blocks guest egress, explain the DOCKER-USER chain allow-rule workaround for the fleetbox subnet (192.168.0.0/16), and note that GitHub-hosted runners drop ICMP, requiring TCP connectivity checks (1.1.1.1:443) instead of ping.
CI workflow iptables rules for Docker-USER chain
.github/workflows/vm-linux.yml
GitHub Actions step conditionally inserts ACCEPT rules into DOCKER-USER chain for the VM subnet in both source and destination directions, bypassing Docker's default DROP policy and allowing VM internet egress in CI environments.
Egress test update from ICMP ping to TCP connectivity
fleetboxtest/conformance_vm_test.go
Guest egress verification switches from ICMP ping checks to outbound TCP connection attempts to 1.1.1.1:443 via /dev/tcp, reflecting GitHub-hosted runner ICMP drop behavior and enabling tests to pass in Docker-host CI environments.
macOS Homebrew cask trust step
README.md
Installation instructions add brew trust --cask pilat/fleetbox/fleetbox for macOS cask setup.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • pilat/fleetbox#12: Both PRs modify fleetboxtest/conformance_vm_test.go to adjust VM egress reachability verification; this PR switches from ICMP ping to TCP, which may relate to or depend upon parallel work in that PR.

Poem

A Docker wall stood in the way,
FORWARD DROP blocked our VM's day.
With DOCKER-USER rules we write,
And TCP checks to set things right,
Now guest egress sees the light. 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: shifting VM egress testing from ICMP (ping) to TCP and updating CI configuration for Docker host constraints.
Description check ✅ Passed The PR description thoroughly explains the problem, root causes, and solutions for both the VM-boot CI egress issue and Homebrew installation update, with clear reasoning for design decisions and limitations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/linux-egress-and-brew-trust-docs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
README.md (1)

309-315: ⚡ Quick win

Clarify the destination rule command.

Line 315's phrasing "add the matching -d 192.168.0.0/16 rule" doesn't show the complete command. Consider making it explicit:

  yourself: `sudo iptables -I DOCKER-USER -s 192.168.0.0/16 -j ACCEPT` and
  `sudo iptables -I DOCKER-USER -d 192.168.0.0/16 -j ACCEPT` for the return path.

The workflow file at lines 59-60 shows both rules in full; matching that clarity here would help operators.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 309 - 315, Update the README paragraph so the
return-path rule is shown as a complete iptables command instead of just
mentioning "-d 192.168.0.0/16"; replace the trailing sentence to explicitly show
both commands: "sudo iptables -I DOCKER-USER -s 192.168.0.0/16 -j ACCEPT" and
"sudo iptables -I DOCKER-USER -d 192.168.0.0/16 -j ACCEPT" (mirroring the full
rules used in the workflow).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/adr/0025-linux-netlink-nftables.md`:
- Around line 129-131: The sentence calling it "the one-line `DOCKER-USER`
allow" is inaccurate because the README documents a two-rule workaround (an `-s`
rule for egress and a corresponding `-d` return-path rule); update the phrasing
to reflect that (for example, "the two-rule `DOCKER-USER` workaround" or "the
`DOCKER-USER` allow rules") so the ADR matches the README guidance.

---

Nitpick comments:
In `@README.md`:
- Around line 309-315: Update the README paragraph so the return-path rule is
shown as a complete iptables command instead of just mentioning "-d
192.168.0.0/16"; replace the trailing sentence to explicitly show both commands:
"sudo iptables -I DOCKER-USER -s 192.168.0.0/16 -j ACCEPT" and "sudo iptables -I
DOCKER-USER -d 192.168.0.0/16 -j ACCEPT" (mirroring the full rules used in the
workflow).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 637a2910-2672-409a-9060-b981a07798fb

📥 Commits

Reviewing files that changed from the base of the PR and between 6dfaa98 and 93cdf99.

📒 Files selected for processing (4)
  • .github/workflows/vm-linux.yml
  • README.md
  • docs/adr/0025-linux-netlink-nftables.md
  • fleetboxtest/conformance_vm_test.go

Comment thread docs/adr/0025-linux-netlink-nftables.md Outdated
@pilat pilat force-pushed the fix/linux-egress-and-brew-trust-docs branch from 93cdf99 to df50641 Compare June 13, 2026 15:31
@pilat pilat merged commit 6345840 into main Jun 13, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant