Skip to content

fix: fail fast on container runners lacking NET_ADMIN (OSS-123)#84

Open
alexprivalov wants to merge 2 commits into
mainfrom
fix/oss-123-container-runner-preflight
Open

fix: fail fast on container runners lacking NET_ADMIN (OSS-123)#84
alexprivalov wants to merge 2 commits into
mainfrom
fix/oss-123-container-runner-preflight

Conversation

@alexprivalov

Copy link
Copy Markdown

Problem

The action fails on ubuntu-slim and other minimal/unprivileged container runners (e.g. blacksmith-4vcpu-ubuntu-2404), reported in #76 / OSS-123. The client installs fine, but twingate start loops on status: 'not-running' for ~75s and then exits 1 with a generic "Twingate service failed to connect."

Root cause

Twingate is a VPN — it must create and configure a TUN interface, which requires the CAP_NET_ADMIN capability. These runners execute the job in an unprivileged container that drops NET_ADMIN from its capability set.

  • /dev/net/tun does exist on these runners, so the client's existing device-node check passes (which is why the "docker run must be run with --cap-add NET_ADMIN" hint never appears).
  • With no systemd in the container, the client forks the daemon directly and returns success ("Twingate has been started").
  • Inside the forked daemon, ioctl(tun_fd, TUNSETIFF) fails without CAP_NET_ADMIN, so the interface is never created and the tunnel never comes online.
  • The daemon's error goes to /var/log/twingated.log, but the action's debug branch runs journalctl -u twingate, which is empty without systemd — so the failure is invisible.

Changes

  • scripts/linux-helpers.sh — new check_network_capabilities(): verifies /dev/net/tun and CAP_NET_ADMIN (parsed from the CapBnd bounding set in /proc/self/status, bit 12). Prints actionable guidance when missing. Skips the cap check if CapBnd is unreadable (no false failures).
  • action.yml — calls it right after setup, before the retry loop, to fail fast with guidance instead of retrying silently. Also dumps /var/log/twingated.log in debug mode when systemd is absent.

What this does / doesn't fix

  • Container jobs the user controls: the error now tells them to add container.options: --cap-add NET_ADMIN --device /dev/net/tun.
  • GitHub-hosted ubuntu-slim: no way to add capabilities, so Twingate still cannot run there — but the action now fails immediately with a clear reason instead of a 75s silent timeout.

Testing

Capability bit extraction verified against known cap sets:

CapBnd NET_ADMIN (bit 12)
000001ffffffffff (full) ✅ present
0000003fffffffff (VM runner) ✅ present
00000000a80425fb (Docker default) ❌ dropped → flagged

🤖 Generated with Claude Code

Twingate must create a TUN interface, which requires CAP_NET_ADMIN.
Unprivileged container runners (ubuntu-slim, container jobs without
extra options) drop that capability, so the daemon starts but the
tunnel never comes online — surfacing only as an endless
"status: not-running" retry loop with no diagnostics.

- Add check_network_capabilities() to linux-helpers.sh: verifies
  /dev/net/tun and CAP_NET_ADMIN (bounding set, bit 12) and prints
  actionable guidance (container.options: --cap-add NET_ADMIN
  --device /dev/net/tun) when missing.
- Call it right after setup, before the retry loop, to fail fast
  instead of retrying silently for ~75s.
- In debug mode, dump /var/log/twingated.log when systemd is absent
  (journalctl is empty on container runners).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jul 13, 2026

Copy link
Copy Markdown

OSS-123

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the Linux start path for the action on container-based/minimal runners by detecting when the environment cannot support a VPN (missing /dev/net/tun and/or CAP_NET_ADMIN) and failing early with actionable guidance, instead of waiting through the retry loop; it also improves debug output when systemd/journald aren’t available.

Changes:

  • Add check_network_capabilities() in scripts/linux-helpers.sh to validate /dev/net/tun and CAP_NET_ADMIN via CapBnd.
  • Call the new check immediately after twingate setup in the Linux step to fail fast.
  • In debug mode, dump /var/log/twingated.log when systemd is absent instead of relying on journalctl.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
scripts/linux-helpers.sh Adds a preflight check for TUN + CAP_NET_ADMIN to detect unsupported runners early.
action.yml Invokes the preflight check before retrying and improves debug logs in non-systemd environments.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/linux-helpers.sh Outdated
Comment thread scripts/linux-helpers.sh Outdated
- Guard the CapBnd awk with `|| true` so an unreadable /proc/self/status
  yields "" instead of tripping `set -e` in the calling step.
- Clarify the comment: TUN node often exists while CAP_NET_ADMIN is dropped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alexprivalov alexprivalov marked this pull request as ready for review July 14, 2026 07:37
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.

2 participants