A command-line tool for managing WireGuard virtual networks with automatic IP allocation, configuration generation, and version history tracking.
- 🌐 Virtual Network Management - Create and manage isolated WireGuard virtual networks with CIDR notation
- 🖥️ Server & Node Management - Configure servers and nodes (peer/route types) with automatic IP assignment
- 🔄 IP Pool Management - Automatic IP allocation from network CIDR with recycling on entity deletion
- ⚙️ Config Generation - Generate WireGuard configurations with proper peer relationships
- 📚 Version History - Track configuration changes with hash-based versioning
- 💾 Persistent Storage - Embedded BoltDB database (no external dependencies)
- 🗑️ Cascade Deletion - Remove networks with automatic cleanup of servers, nodes, and configs
- Go 1.21 or later
- WireGuard installed on target systems (for running generated configs)
# Clone the repository
git clone <repository-url>
cd wedevctl
# Build the binary
go build -o wedevctl main.go
# (Optional) Install to system path
sudo mv wedevctl /usr/local/bin/wedevctl --helpHere's a complete example to create a WireGuard network with a server and two peer nodes:
# 1. Create a virtual network
wedevctl vn add mynetwork 10.0.0.0/24
# 2. Add a server (will get IP 10.0.0.1)
wedevctl vn mynetwork server add server1 vpn.example.com 51820
# 3. Add peer nodes (will get IPs 10.0.0.2, 10.0.0.3, etc.)
wedevctl vn mynetwork node add laptop laptop.local 51821 peer
wedevctl vn mynetwork node add phone phone.local 51822 peer
# 4. Generate WireGuard configuration files
wedevctl vn mynetwork config generate --output-dir ./configs
# 5. View generated configs
ls -l ./configs/
# server1.conf laptop.conf phone.confVirtual networks define an isolated WireGuard network with its own CIDR block.
# Create a network with CIDR notation
wedevctl vn add <network-name> <cidr>
# Example
wedevctl vn add production 10.10.0.0/24
wedevctl vn add development 192.168.100.0/24
# List all networks
wedevctl vn listNaming Rules:
- Must start with a letter
- Can contain letters, numbers, and hyphens
- No special characters except hyphens
Each virtual network requires exactly one server. The server always receives the first IP from the CIDR range.
# Add a server
wedevctl vn <network> server add <server-name> <endpoint> <listen-port>
# Example - server gets 10.10.0.1
wedevctl vn production server add server1 vpn.mycompany.com 51820
# View server information
wedevctl vn production server infoServer Configuration:
- Automatically gets first IP (e.g., 10.10.0.1 from 10.10.0.0/24)
- Default port: 51820
- Endpoint can be a hostname or IP address
- Server configs include IP forwarding (PostUp/PostDown rules)
Nodes are clients that connect to the network. There are two types:
Peer nodes can communicate with both the server and other peer nodes.
# Add a peer node (type defaults to "peer")
wedevctl vn <network> node add <node-name> <endpoint> <listen-port> peer
# Examples
wedevctl vn production node add laptop1 laptop1.local 51821 peer
wedevctl vn production node add desktop1 desktop1.local 51822 peer
wedevctl vn production node add phone1 phone1.local 51823 peerRoute nodes only communicate with the server (not with other nodes).
# Add a route node
wedevctl vn production node add iot-device iot.local 51824 routeIP Assignment:
- Nodes automatically receive sequential IPs (10.10.0.2, 10.10.0.3, etc.)
- IPs are recycled when nodes are deleted
List all nodes:
wedevctl vn production node listGenerate configuration files for all entities in a network:
# Generate configs to current directory
wedevctl vn <network> config generate
# Generate to specific directory
wedevctl vn production config generate --output-dir /etc/wireguard
# Force overwrite existing files
wedevctl vn production config generate --output-dir ./configs --forceGenerated Files:
- One
.conffile per server/node - Named after the entity (e.g.,
server1.conf,laptop1.conf) - Ready to use with WireGuard
Configuration Features:
- Server config: Includes IP forwarding rules (PostUp/PostDown)
- Peer node config: Includes peers for server + all other peer nodes
- Route node config: Only includes peer for the server
Version Tracking: Configurations are automatically versioned when generated. Each unique configuration gets a new version number with content hash tracking.
# View all configuration versions for a network
wedevctl vn production config history
# Output shows:
# Version | Created At | Content Hash
# 1 | 2026-01-18 10:30:00 | a1b2c3d4...
# 2 | 2026-01-18 11:45:00 | e5f6g7h8...# View latest configuration info
wedevctl vn production config info
# View specific version
wedevctl vn production config info 1# Edit server endpoint
wedevctl vn production server edit --endpoint new.vpn.example.com
# Edit server listen port
wedevctl vn production server edit --listen-port 51821
# Edit both
wedevctl vn production server edit --endpoint new.vpn.example.com --listen-port 51821# Edit node endpoint
wedevctl vn production node edit laptop1 --endpoint new-laptop.local
# Edit node listen port
wedevctl vn production node edit laptop1 --listen-port 51830
# Edit both
wedevctl vn production node edit laptop1 --endpoint new-laptop.local --listen-port 51830After Editing: Regenerate configurations to apply changes:
wedevctl vn production config generate --output-dir /etc/wireguard --force# Delete a node (IP is returned to pool)
wedevctl vn production node delete laptop1# Delete the server (also removes all nodes)
wedevctl vn production server delete# Delete entire network (removes server, nodes, and all configs)
wedevctl vn delete productionCascade Deletion:
- Deleting a network removes all servers, nodes, and configurations
- Deleting a server removes all nodes
- All IPs are returned to the pool for reuse
After generating configuration files, set up WireGuard on each machine:
# 1. Copy the config file to WireGuard directory
sudo cp server1.conf /etc/wireguard/wg0.conf
# 2. Start WireGuard interface
sudo wg-quick up wg0
# 3. Enable on boot (optional)
sudo systemctl enable wg-quick@wg0
# 4. Check status
sudo wg show
# 5. Stop interface
sudo wg-quick down wg0# Using Homebrew
brew install wireguard-tools
# Copy config
sudo mkdir -p /usr/local/etc/wireguard
sudo cp server1.conf /usr/local/etc/wireguard/wg0.conf
# Start interface
sudo wg-quick up wg0
# Check status
sudo wg show# Check if interface is up
ip link show wg0
# View WireGuard logs
sudo journalctl -u wg-quick@wg0
# Test connectivity
ping 10.0.0.1 # Ping server from node
# Check peer handshake
sudo wg show wg0 latest-handshakesvn add <name> <cidr> # Create virtual network
vn list # List all networks
vn delete <name> # Delete network (cascade)vn <network> server add <name> <endpoint> <port> # Add server
vn <network> server info # Show server info
vn <network> server edit [--endpoint] [--listen-port] # Edit server
vn <network> server delete # Delete servervn <network> node add <name> <endpoint> <port> [type] # Add node (type: peer|route)
vn <network> node list # List all nodes
vn <network> node edit <name> [--endpoint] [--listen-port] # Edit node
vn <network> node delete <name> # Delete nodevn <network> config generate [--output-dir dir] [--force] # Generate configs
vn <network> config history # View config history
vn <network> config info [version] # View config infowedevctl/
├── main.go # Entry point
├── cmd/
│ ├── root.go # CLI commands (Cobra)
│ └── root_test.go # CLI tests
├── wedev/
│ ├── manager.go # Business logic
│ ├── manager_test.go # Manager tests
│ ├── storage.go # BoltDB persistence
│ └── storage_test.go # Storage tests
├── util/
│ ├── util.go # Utilities & IP pool
│ └── util_test.go # Utility tests
└── go.mod # Dependencies
- spf13/cobra v1.7.0 - CLI framework
- go.etcd.io/bbolt v1.3.8 - Embedded database
- github.com/google/uuid v1.5.0 - UUID generation
# Build
go build -o wedevctl main.go
# Build with optimizations
go build -ldflags="-s -w" -o wedevctl main.goThe project uses GitHub Actions for continuous integration. All pull requests to the main branch must pass the following checks before merging:
-
Static Analysis
- Go formatting check (
gofmt) - Static analysis (
go vet) - Comprehensive linting (
golangci-lint) - Dependency verification
- Go formatting check (
-
Secret Scanning
- Gitleaks scan for exposed secrets
- Prevents accidental credential commits
-
Test Suite
- All unit tests with race detection
- Code coverage verification (≥70% required)
- Coverage reporting
-
Build Verification
- Binary compilation check
- Executable verification
-
Security Scanning
- Gosec security analysis
- Vulnerability detection
# Triggered on: Pull requests to main branch
# Required checks: All must pass (static-analysis, secret-scan, test, build, security-scan)
# Merge policy: Only allowed after all checks succeedTo ensure your PR passes all checks locally:
# Format code
go fmt ./...
# Run static analysis
go vet ./...
# Run tests with coverage
go test -v -race -coverprofile=coverage.out ./...
# Check coverage
go tool cover -func=coverage.out
# Build
go build -o wedevctl main.goThe project includes comprehensive test coverage (~70% overall):
# Run all tests
go test ./...
# Run with verbose output
go test ./... -v
# Run with coverage
go test ./... -cover# Utility tests (28 tests, 89.0% coverage)
go test ./util -v
# Storage tests (16 tests)
go test ./wedev -v
# CLI tests (14 tests)
go test ./cmd -v- Validation Tests: Network name, CIDR, endpoint, port validation
- IP Pool Tests: Allocation, recycling, persistence
- Network Management Tests: CRUD operations, cascade deletion
- Configuration Tests: Generation, versioning, history
- Storage Tests: BoltDB operations, transaction consistency
wedevctl stores data in an embedded BoltDB database:
- Default Location:
~/.wedevctl/wedevctl.db - Format: BoltDB key-value store
- No External Dependencies: Database file is portable
# Create network for office (10.20.0.0/24)
wedevctl vn add office 10.20.0.0/24
# Add office VPN server
wedevctl vn office server add vpn-server vpn.company.com 51820
# Add employee devices
wedevctl vn office node add ceo-laptop ceo-laptop.local 51821 peer
wedevctl vn office node add cto-desktop cto-desktop.local 51822 peer
wedevctl vn office node add sales-laptop sales-laptop.local 51823 peer
# Generate configs
wedevctl vn office config generate --output-dir ~/wireguard-configs
# Check history
wedevctl vn office config history# Create IoT network
wedevctl vn add iot 192.168.50.0/24
# Add IoT gateway server
wedevctl vn iot server add iot-gateway gateway.iot.local 51820
# Add IoT devices as route nodes (only talk to gateway)
wedevctl vn iot node add camera1 camera1.iot.local 51821 route
wedevctl vn iot node add sensor1 sensor1.iot.local 51822 route
wedevctl vn iot node add thermostat thermostat.iot.local 51823 route
# Add admin laptop as peer (can access all devices)
wedevctl vn iot node add admin-laptop admin.local 51824 peer
# Generate configs
wedevctl vn iot config generate --output-dir /etc/wireguard --force# Development environment
wedevctl vn add dev 10.100.0.0/24
wedevctl vn dev server add dev-server dev.example.com 51820
wedevctl vn dev node add dev-laptop1 dev1.local 51821 peer
# Staging environment
wedevctl vn add staging 10.101.0.0/24
wedevctl vn staging server add staging-server staging.example.com 51820
wedevctl vn staging node add staging-laptop1 staging1.local 51821 peer
# Production environment
wedevctl vn add production 10.102.0.0/24
wedevctl vn production server add prod-server prod.example.com 51820
wedevctl vn production node add prod-laptop1 prod1.local 51821 peer
# List all networks
wedevctl vn listCopyright 2026
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Contributions are welcome! Please ensure:
- All tests pass:
go test ./... - Code follows Go conventions:
go fmt ./... - Add tests for new features
- Update documentation as needed
For issues, questions, or contributions, please refer to the project repository.
Built with: