Skip to content

ci: FlowAccount release pipeline — signed macOS pkg + Linux rpm/deb - #1

Open
wickstargazer wants to merge 1 commit into
mainfrom
feat/macos-signed-pkg-release
Open

ci: FlowAccount release pipeline — signed macOS pkg + Linux rpm/deb#1
wickstargazer wants to merge 1 commit into
mainfrom
feat/macos-signed-pkg-release

Conversation

@wickstargazer

Copy link
Copy Markdown
Member

Adds a release pipeline so the fork can actually produce deployable artifacts.

Why

The fork inherits .goreleaser.yaml and release_files/ but no release automation — upstream builds its published packages outside this repository. A fork with no workflow produces nothing to deploy.

What it produces

netbird_<v>_linux_{amd64,arm64}.rpm     ← ryzen, RHEL deployment terminals
netbird_<v>_linux_{amd64,arm64}.deb
netbird_<v>_darwin_universal.pkg        ← signed + notarized, headless

Linux is nearly free — goreleaser already builds deb and rpm via nfpms using upstream's own post_install.sh and pre_remove.sh. Only the macOS installer is new.

Headless vs GUI packaging

release_files/darwin_pkg_headless/ is a variant, not a replacement. Upstream's darwin_pkg/ scripts install /Applications/NetBird.app and quit/relaunch the UI around the install — correct for a laptop, meaningless on mm-1/2/3 and ryzen where there is no console user.

The headless package installs the binary and registers the launchd service using the client's own service install subcommand, rather than hand-rolling a plist that would drift from upstream.

It deliberately does not bring the peer up

Joining the mesh needs a setup key. Baking one into a package makes it a reusable bearer credential shipped to every machine — anything that can read the package can join the network. Enrolment stays a per-host step with a one-off key.

Blocked on

An Apple Developer Program membership for Developer ID certificates. Apple requires MDM-deployed packages to be signed with a Developer ID Installer cert; unsigned ones fail to install, and there is no user present to click through a warning. Our own Santa policy and System Extensions profile also key on signing identity.

The macOS job fails loudly when secrets are absent rather than producing an uninstallable package — a build that "succeeds" and yields a .pkg nobody can install wastes more time than a red X.

Secrets required are documented in the workflow header. Setup brief for whoever holds Apple Developer access is in incident-2026-08/handoff/apple-signing-brief.md.

Version pinning

Client must match the management server. flowaccount.infrastructure pins netbirdio/netbird-server:0.76.3. A client ahead of its server is unsupported and fails quietly — the peer connects, looks healthy, does not route correctly.

Worth a reviewer's judgement

release_files/darwin_pkg_headless/README.md records that having the fork and building from it are separate decisions. The fork is insurance against an upstream licence change. Building from it means owning NetBird security patches on the component that gates all network access — which ADR-010 in flowaccount.infrastructure explicitly declined for that reason.

If the fleet ships from these artifacts, someone needs to own tracking upstream security releases. That ownership should be named before the first machine is deployed from here.

🤖 Generated with Claude Code

The fork inherits .goreleaser.yaml and release_files/ but no release
automation, because upstream builds its published packages outside this
repository. A fork with no workflow produces no artifacts, so there is
nothing to deploy from it.

goreleaser already covers most of it — universal darwin binaries, plus deb
and rpm through nfpms with the existing postinstall and preremove scripts.
Only the macOS installer is new: pkgbuild, Developer ID signing and
notarization.

Adds release_files/darwin_pkg_headless/ as a variant rather than a
replacement. Upstream's darwin_pkg/ scripts install /Applications/NetBird.app
and quit and relaunch the UI around the install, which is right for a laptop
and meaningless on mm-1/2/3 and ryzen where there is no console user. The
headless package installs the binary and registers the launchd service using
the client's own "service install" subcommand — rather than hand-rolling a
plist that would drift from upstream — and stops there.

It deliberately does NOT bring the peer up. Joining the mesh needs a setup
key, and baking one into a package makes it a reusable bearer credential
shipped to every machine: anything that can read the package can join the
network. Enrolment stays a per-host step with a one-off key.

The macOS job fails loudly when signing secrets are absent rather than
producing an uninstallable package. An unsigned or un-notarized pkg is
blocked by Gatekeeper and would also be refused by the fleet's Santa rules
and System Extensions profile, so shipping one wastes more time than the
failed build.

Blocked on an Apple Developer Program membership, which also unblocks signing
the CrewOps daemon and Tray for ADR-009. One purchase, two blockers.
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