Cloud-Native WireGuard Network Orchestration
Wireflow simplifies the construction of encrypted overlay networks across multi-cloud, cross-datacenter, and edge environments — without touching firewalls or exposing public IPs.
Wireflow is a WireGuard management platform built for Kubernetes. It automates the full lifecycle of secure peer-to-peer tunnels:
- Control Plane — Kubernetes Operator that declaratively manages network topology via CRDs. Acts as the single source of truth for keys, IP allocation, and peer relationships.
- Data Plane — Lightweight agent deployed on each device. Establishes encrypted WireGuard tunnels with automatic NAT traversal (ICE/STUN/TURN), even across symmetric NATs.
- Relay Plane — Built-in WRRP relay server as fallback when direct P2P is not possible.
| Feature | Status |
|---|---|
| WireGuard tunnel automation (key distribution, rotation) | ✅ |
| Automatic NAT traversal (ICE / STUN / TURN) | ✅ |
| Built-in IPAM — conflict-free IP allocation per workspace | ✅ |
| CRD-based declarative network topology | ✅ |
| Network policy engine (allow/deny, ingress/egress, port-level) | ✅ |
| Multi-workspace & RBAC | ✅ |
| Web Dashboard | ✅ |
| All-in-One deployment (embedded NATS + SQLite, no external deps) | ✅ |
| Telemetry export (VictoriaMetrics push) | ✅ |
| Multi-region / multi-cloud bridging | 🔜 |
| Smart DNS (internal service naming) | 🔜 |
Wireflow's control plane runs on Kubernetes. The quickstart script handles cluster creation and deployment automatically.
curl -sSL https://raw.githubusercontent.com/wireflowio/wireflow/master/hack/quickstart.sh | bashThe script will:
- Verify Docker, k3d, and kubectl are present (installing missing tools automatically).
- Check that ports 8080 (Dashboard / API) and 4222 (NATS signaling) are free.
- Create a local k3d cluster and apply CRDs, RBAC, and Deployments.
- Wait for the pod to become healthy.
- Print a ready-to-use
wireflow upcommand with the NATS address and initial token.
Existing cluster (kustomize):
kubectl apply -k https://github.com/wireflowio/wireflow/config/wireflow/overlays/all-in-oneAll management commands below use --signaling-url to reach the embedded NATS server (default port 4222).
wireflow workspace add dev \
--display-name "Development" \
--signaling-url nats://localhost:4222# List all workspaces (shows namespace values used in subsequent commands)
wireflow workspace list --signaling-url nats://localhost:4222wireflow token create dev-team \
-n <namespace> \
--limit 10 \
--expiry 168h \
--signaling-url nats://localhost:4222| Flag | Description |
|---|---|
-n / --namespace |
Workspace namespace (from workspace list) |
--limit |
Max agent connections (0 = unlimited) |
--expiry |
Token lifetime (e.g. 24h, 168h, omit = never) |
wireflow up --signaling-url nats://localhost:4222 --token <token>Run as a container:
docker run -d \
--name wf-agent \
--restart unless-stopped \
--privileged \
--network host \
ghcr.io/wireflowio/wireflow:latest \
up --signaling-url nats://localhost:4222 --token <token>Wireflow enforces a default-deny policy — agents can establish tunnels but cannot exchange traffic until a policy explicitly permits it. This prevents accidental exposure in multi-tenant environments.
CLI — allow all traffic in a workspace (development / single-tenant):
wireflow policy allow-all \
-n <namespace> \
--signaling-url nats://localhost:4222CLI — fine-grained policy:
wireflow policy add my-policy \
-n <namespace> \
--action ALLOW \
--desc "allow all peer traffic" \
--signaling-url nats://localhost:4222Dashboard — visual policy editor:
Navigate to http://localhost:8080 → Policies → Create Policy.
You can define rules scoped to specific peers (by label), ports, and direction (ingress / egress).
kubectl — apply a policy CRD directly:
apiVersion: wireflowcontroller.wireflow.run/v1alpha1
kind: WireflowPolicy
metadata:
name: allow-all
namespace: default
labels:
action: ALLOW
annotations:
description: "Full mesh — allow all peer traffic"
policyTypes: "Ingress,Egress"
spec:
action: ALLOW
peerSelector: {} # matches all peers in the namespace
ingress: [] # empty = no port restriction
egress: []kubectl apply -f policy-allow-all.yamlCheck the local agent status and peer list:
wireflow statusExample output:
Interface : wg0
Address : 10.100.0.1/24
Public Key: abc123...=
Port : 51820
Peers: 2 total, 2 connected
Peer : xyz456...=
Address : 10.100.0.2/32
Endpoint : 203.0.113.5:51820
Handshake : 8 seconds ago
Traffic : ↑ 1.2 MB ↓ 3.4 MB
Status : connected
Peer : def789...=
Address : 10.100.0.3/32
Endpoint : 198.51.100.7:51820
Handshake : 22 seconds ago
Traffic : ↑ 0.5 MB ↓ 2.1 MB
Status : connected
Ping between nodes to confirm the tunnel is working:
On Node A (address 10.100.0.1), ping Node B:
ping 10.100.0.2Expected output when the tunnel is up:
PING 10.100.0.2 (10.100.0.2): 56 data bytes
64 bytes from 10.100.0.2: icmp_seq=0 ttl=64 time=4.3 ms
64 bytes from 10.100.0.2: icmp_seq=1 ttl=64 time=3.8 ms
If ping times out, the tunnel has not been established. Common causes:
- The policy is still default-deny — run
wireflow policy allow-all -n <namespace>to permit traffic. - The peer has not yet completed a WireGuard handshake — check
wireflow statuson both nodes and wait a few seconds. - A firewall is blocking UDP on port 51820 — Wireflow will attempt TURN relay fallback automatically.
Remove a specific agent from the workspace:
wireflow token delete <token>Delete a workspace and all its peers:
wireflow workspace remove <namespace> --signaling-url nats://localhost:4222Remove a policy:
wireflow policy remove <name> -n <namespace> --signaling-url nats://localhost:4222Uninstall the control plane from Kubernetes:
kubectl delete -k https://github.com/wireflowio/wireflow/config/wireflow/overlays/all-in-oneAll commands accept --signaling-url nats://<host>:4222 to target the control plane.
wireflow up --token <token> --signaling-url <url>
wireflow statuswireflow workspace add <slug> [--display-name <name>] [-n <namespace>]
wireflow workspace list
wireflow workspace remove <namespace>wireflow token create <name> [-n <namespace>] [--limit <n>] [--expiry <duration>]
wireflow token list [-n <namespace>]
wireflow token delete <token>wireflow policy allow-all -n <namespace>
wireflow policy add <name> -n <namespace> [--action ALLOW|DENY] [--desc <text>]
wireflow policy list -n <namespace>
wireflow policy remove <name> -n <namespace>The control plane is configured via a YAML file (default: /etc/wireflow/wireflow.yaml):
app:
listen: :8080
name: "WireFlow"
env: "production"
init_admins:
- username: "admin"
password: "changeme" # ⚠ Change before deploying
jwt:
secret: "replace-with-random-secret" # ⚠ Use a 32-byte random value
expire_hours: 24
signaling-url: "nats://localhost:4222" # Embedded NATS in all-in-one mode
database:
dsn: "data/wireflow.db" # SQLite (all-in-one)
# dsn: "root:pass@tcp(mariadb:3306)/wireflow?charset=utf8mb4&parseTime=True" # MariaDB- Go 1.24+
- Docker 20.10+
- k3d 5.x+ (for local cluster)
- kubectl 1.20+
git clone https://github.com/wireflowio/wireflow.git
cd wireflow
make build-allContributions are welcome. Please read CONTRIBUTING.md before submitting a pull request.
This tool is intended for legitimate technical research, enterprise private networking, and compliant remote access scenarios only. Users are responsible for ensuring their use complies with all applicable local laws and regulations. The authors assume no liability for any misuse of this software.
