Installation¶
Install with Homebrew¶
The public tap installs wirekubectl on macOS or Linux, on ARM64 or AMD64:
The formula installs only the client. It does not modify a Kubernetes cluster. Run a dry run to see the cluster-wide CRDs, privileged agent, and relay topology:
wirekubectl install --dry-run \
--kubeconfig ~/.kube/config \
--context my-cluster
wirekubectl install \
--kubeconfig ~/.kube/config \
--context my-cluster
Upgrade the CLI independently from the installed cluster resources, then run the explicit WireKube upgrade command:
brew upgrade inerplat/tap/wirekube
wirekubectl upgrade --kubeconfig ~/.kube/config --context my-cluster
Install from a GitHub Release¶
Release assets contain standalone wirekubectl binaries for macOS and Linux on AMD64 and ARM64. Download the binary and checksum file for the version you want from the GitHub Releases page, verify the checksum, and place the binary on your PATH. Each release also includes wirekube-release.json with the immutable container image digest embedded in that CLI.
VERSION=v0.0.20
curl -fLO "https://github.com/inerplat/wirekube/releases/download/${VERSION}/wirekubectl-linux-amd64"
curl -fLO "https://github.com/inerplat/wirekube/releases/download/${VERSION}/wirekubectl-checksums.txt"
sha256sum --check --ignore-missing wirekubectl-checksums.txt
chmod +x wirekubectl-linux-amd64
sudo install wirekubectl-linux-amd64 /usr/local/bin/wirekubectl
The released CLI contains the matching immutable container image digest. Installation inspects the target cluster and prints the complete resource and infrastructure plan, then applies it:
install prints the plan and applies it in the same run; nothing prompts for confirmation, so --dry-run is the way to inspect a plan first. An unset --relay defaults to load-balancer, which creates public LoadBalancer Services, so state the topology explicitly rather than inheriting it:
wirekubectl install --kubeconfig ~/.kube/config --context my-cluster --relay load-balancer --mesh-cidr 100.96.0.0/11 --node-addresses internal-ip --output json
Use --dry-run to inspect the same plan without creating the Namespace, CRDs, or any workloads. Automatic mesh CIDR selection is best effort because the CLI cannot inspect every VPC, corporate, or node route; add known routes with --exclude-cidr, review the selected candidate with --dry-run, and provide an explicit --mesh-cidr in automation. Use wirekubectl manifest to render the exact resources selected by the plan.
--relay load-balancer creates separate TCP and UDP LoadBalancer Services by default so raw TCP relay clients and external WireGuard peers both have a usable entry point without relying on mixed-protocol LoadBalancer support. Use --relay-udp=false only when the installation must remain TCP-only. With --relay node-port --relay-transport tcp, agents use TCP NodePort 30478 while optional external WireGuard traffic uses UDP NodePort 30479; supply the reachable node address as --relay-endpoint HOST:30478 and enable the UDP Service with --relay-udp.
Use --relay-transport wss when agents must enter through an HTTPS-aware load balancer, Gateway, or Ingress. The installer deploys the authenticated wirekube-relay-ws HTTP backend and configures agents to use the supplied public WSS URL; it does not create the hostname, certificate, Gateway, Ingress, or HTTPRoute. Pre-create the selected namespace if necessary, then create the TLS route to Service wirekube-relay-ws port 8081 before installation so the readiness wait can complete; wirekubectl preserves an existing Namespace.
wirekubectl install --relay load-balancer --relay-transport wss --relay-endpoint wss://relay.example.com/relay --mesh-cidr 100.96.0.0/11
In WSS load-balancer mode, the installer creates the UDP LoadBalancer by default and keeps the WebSocket backend as ClusterIP for the existing TLS Gateway or Ingress; it does not create an unused raw TCP LoadBalancer. In WSS NodePort mode, Service wirekube-relay-ws exposes plain HTTP/WebSocket on NodePort 30478 for an upstream TLS terminator. If external WireGuard peers also need the UDP NodePort, add --relay-udp --relay-udp-endpoint HOST:30479 because the WSS hostname and the reachable UDP node address may differ.
For --relay external, use --relay-endpoint HOST:PORT with TCP or --relay-endpoint wss://HOST/PATH --relay-transport wss with WSS. --relay-udp-endpoint HOST:PORT remains an independent raw WireGuard endpoint for external peer invites and is optional; without it, external peer invites remain Pending.
WireKube is a cluster-wide singleton because its CRDs, mesh, and RBAC are cluster-scoped. --namespace chooses where workloads and inventory run; it does not permit a second installation in another namespace. Every managed resource is stamped with the inventory installation ID, and upgrade or uninstall refuses resources owned by a different installation.
Lifecycle commands¶
wirekubectl upgrade keeps the stored topology unless flags override it and uses the immutable image digest embedded in the new released CLI. Upgrade snapshots existing objects and inventory before mutation; readiness, inventory, or stale-resource deletion failures restore the previous objects and inventory. Resources removed from the selected topology, such as a disabled UDP relay Service, are deleted only when their inventory ownership is still valid.
uninstall --dry-run prints the resources that would be deleted and those that would be kept, without deleting anything. Default uninstall removes resources recorded in the installation inventory while preserving CRDs and WireKube custom resources. Destructive removal requires both --purge and --confirm-purge; --purge alone never authorizes data deletion.
Container Image¶
The official multi-architecture container image supports linux/amd64 and linux/arm64. Released wirekubectl binaries default to the digest embedded in the matching release. --image also accepts mutable tag references: the plan warns about them, tagged workloads pull on every Pod start, and a re-pushed tag reaches running Pods only after the next rollout. Pin IMAGE@sha256:DIGEST for deterministic rollouts.
Install with Helm¶
The wirekube chart installs the CRDs, agent DaemonSet, relay, and a WireKubeMesh from a source checkout:
helm install wirekube ./charts/wirekube \
--namespace wirekube-system --create-namespace \
--set mesh.meshCIDR=100.96.0.0/11
mesh.meshCIDR has no default: pick a private range that does not overlap your VPC, Pod, or Service CIDRs. The chart mirrors the installer's topology options (relay.service.type, relayWs.enabled, mesh.relay.transport); invalid value combinations fail at template time. Helm installs the CRDs on first install but never upgrades them, so apply charts/wirekube/crds/ manually when upgrading across CRD changes. See the chart README for the full value reference.
Unlike wirekubectl install, Helm does not inspect the cluster for CIDR conflicts, does not embed a pinned image digest, and does not manage the installation inventory used by wirekubectl upgrade/uninstall. Pick one installation method per cluster and stay with it.
Install from repository manifests¶
The repository manifests remain available for development and manual inspection. They are not the primary release installation contract because they may contain environment-specific examples and require a source checkout.
1. CRDs¶
Create the namespace used by the bundled manifests:
2. WireKubeMesh Resource¶
Create a mesh configuration. See Configuration for all options.
3. Agent DaemonSet¶
RBAC and the DaemonSet are separate manifests:
The DaemonSet runs with hostNetwork: true, dnsPolicy: Default, privileged: true, and appArmorProfile: Unconfined. It does not include an initContainer; the agent leaves the interface, routes, and routing rules in place across restarts and reconciles them during startup and periodic sync. Set WIREKUBE_CLEAN_STATE=true on the container to rebuild a node's state once at the next start, or run the cleanup Job when decommissioning a node.
4. (Optional) Relay¶
For managed relay:
The bundled relay Deployment has an EKS-specific eks.amazonaws.com/nodegroup: relay-ng node selector. Remove or replace it for other clusters.
See Relay Architecture for external relay, managed relay, and scaling options.
Build from Source¶
Requirements¶
- Go 1.23+
wireguard-tools(forwgCLI, testing)- Linux kernel 5.6+ (or WireGuard backport module)
podmanordocker(for container images)
Build Binaries¶
Or individually:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -ldflags="-s -w" -o bin/wirekube-agent ./cmd/agent/
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -ldflags="-s -w" -o bin/wirekube-relay ./cmd/relay/
Cross-Compilation
The agent uses Linux-specific netlink APIs. When building on macOS, always
set GOOS=linux to avoid undefined symbol errors.
Build Container Image (Multi-Arch)¶
Or manually with podman:
podman build --platform linux/amd64,linux/arm64 \
--manifest inerplat/wirekube:latest .
podman manifest push inerplat/wirekube:latest \
docker://docker.io/inerplat/wirekube:latest
Relay Server Deployment¶
Option A: In-Cluster (Managed)¶
Deploy as a Kubernetes Deployment + Service:
Managed agents connect to the cluster-local wirekube-relay-control Service. Use an external provider endpoint when an agent must enter through the public LoadBalancer, NodePort, or an HTTP CONNECT proxy. See Relay Entry Points.
Option B: External (Standalone)¶
On a server with a public IP:
Or as a systemd service:
[Unit]
Description=WireKube Relay Server
After=network.target
[Service]
ExecStart=/usr/local/bin/wirekube-relay --addr :3478
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Configure in WireKubeMesh:
spec:
relay:
provider: external
external:
controlEndpoint: "relay.example.com:3478"
endpoint: "relay.example.com:51820"
transport: tcp
Manual manifest uninstall¶
kubectl delete -f config/agent/ --ignore-not-found
kubectl delete -f config/relay/ --ignore-not-found
kubectl delete wirekubemesh --all
kubectl delete wirekubepeers --all
kubectl delete -f config/crd/ --ignore-not-found
CRD Deletion
Deleting CRDs removes all WireKubeMesh and WireKubePeer resources permanently.