Building¶
Prerequisites¶
- Go 1.23+
wireguard-tools(for testing)podmanordocker(for container images)
Build Binaries¶
Or build individual components:
Cross-Compilation¶
The agent uses Linux-specific netlink APIs. When building on macOS, always
cross-compile:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -ldflags="-s -w" -o bin/agent-linux-amd64 ./cmd/agent/
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 \
go build -ldflags="-s -w" -o bin/agent-linux-arm64 ./cmd/agent/
CGO_ENABLED=0 produces a fully static binary with no external dependencies.
Build Container Image¶
Multi-Architecture (Recommended)¶
Or manually:
podman build --platform linux/amd64,linux/arm64 \
--manifest inerplat/wirekube:latest .
podman manifest push inerplat/wirekube:latest \
docker://docker.io/inerplat/wirekube:latest
Single Architecture¶
CI/CD¶
Tag builds run formatting, vet, lint, unit tests, and the TCP/WSS disposable-cluster E2E matrix before publishing anything. After those gates pass, the workflow publishes the multi-architecture image, builds four standalone wirekubectl binaries, injects the version, commit, build date, and immutable image digest, and creates a GitHub Release with SHA256 checksums.
Cutting a release¶
The manifests under config/ and the chart's appVersion pin a release tag, and the image for that tag does not exist until the tag is pushed. So the pin lands first and is verified afterwards:
- Update
config/**image tags,charts/wirekube/Chart.yamlappVersion, and theVERSION=example indocs/getting-started/installation.mdto the tag you are about to cut. Commit tomain. - Push the tag.
release.ymlpublishes the image, then itsverify-pinsjob re-checks every pin withverifyflags -strict.
CI's manifest-images job runs the same check on main without -strict, so an as-yet-unpublished tag reports PENDING rather than failing. Anything else it reports is real: REJECT means the pinned binary does not define a flag the manifest passes, which is a CrashLoopBackOff on install.
The E2E suite overrides the image with the one it just built, so it cannot catch a stale pin. This check is the only thing that does.
Homebrew tap¶
The public formula lives in
inerplat/homebrew-tap as
Formula/wirekube.rb. After publishing a WireKube release, update the formula's
version, four platform URLs, and four SHA-256 values from
wirekubectl-checksums.txt, then verify it on a clean tap checkout:
brew style inerplat/tap/wirekube
brew audit --strict inerplat/tap/wirekube
brew install inerplat/tap/wirekube
brew test inerplat/tap/wirekube
wirekubectl version
Do not point the formula at latest, a mutable container tag, or an unverified
binary. The released CLI embeds the matching immutable WireKube container image
digest used by wirekubectl install and wirekubectl upgrade.
Dockerfile¶
The multi-stage Dockerfile:
- Builder stage: Go 1.23 Alpine, builds agent, relay, operator, and wirekubectl
- Runtime stage: Alpine 3.21 with
wireguard-tools,iptables,iproute2
Run Tests¶
make test # go test ./... -v
make vet # go vet ./...
make fmt # go fmt ./...
go test -v ./pkg/agent/... # specific package
go test -v -run TestEndpointDiscovery ./pkg/agent/... # specific test
Code Generation¶
After modifying types in pkg/api/v1alpha1/ (especially +kubebuilder: markers):
Generated files in config/crd/ must be committed alongside type changes.
Project Structure¶
wirekube/
├── cmd/
│ ├── agent/ # Agent entrypoint
│ ├── admin-web/ # External-peer management web UI
│ ├── relay/ # Relay server entrypoint
│ ├── stun-server/ # Development STUN server
│ └── wirekubectl/ # CLI entrypoint
├── pkg/
│ ├── agent/ # Agent logic (endpoint discovery, peer sync)
│ │ ├── nat/ # STUN and UPnP endpoint discovery
│ │ └── relay/ # Relay client, Bind delivery fallback proxy, relay pool
│ │ ├── client.go # TCP client with auto-reconnect
│ │ ├── proxy.go # Legacy/fallback per-peer UDP proxy
│ │ └── pool.go # Multi-instance relay pool
│ ├── api/v1alpha1/ # Mesh, peer, gateway, and external-peer CRD types
│ ├── controller/ # Embedded external-peer reconciler and stub legacy reconcilers
│ ├── relay/ # Relay server and wire protocol
│ └── wireguard/ # WireGuard interface, routing, xfrm bypass
├── config/
│ ├── agent/ # Separate RBAC, DaemonSet, and ServiceMonitor manifests
│ ├── crd/ # CustomResourceDefinition YAMLs (generated)
│ ├── relay/ # Relay deployment + service examples
│ └── examples/ # WireKubeMesh and EKS Hybrid Node examples
├── charts/wirekube/ # Helm chart (appVersion tracks the latest release tag)
├── docs/ # Documentation (MkDocs Material)
├── hack/
│ └── verifyflags/ # Checks pinned images accept their manifest args
├── .github/workflows/ # CI (tag-triggered build + test)
├── Dockerfile
├── Makefile
├── mkdocs.yml
└── go.mod