Skip to content

jcbasso/wireguard-manager

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Autonomous WireGuard Manager Agent

This repository contains the Go source code for a fully autonomous agent that creates and maintains a self-healing WireGuard mesh network. It is designed to run in a Docker container and uses a private Git repository as its single source of truth, following GitOps principles.

The agent removes the need for manual peer configuration. Each node in the network runs this agent, which allows it to automatically register itself, discover other peers, and heal the network by updating its public IP address as it changes.

Core Features

  • Zero-Touch Peer Provisioning: A new server, once launched, automatically generates its keys and registers itself in the central Git repository.
  • Automatic IP Healing: The agent periodically checks its public IP address and pushes updates to Git, ensuring all peers can always find it.
  • Dynamic Peer Discovery: Each agent regularly syncs with the Git repository, automatically adding, updating, and removing peers from its configuration.
  • GitOps-Driven Configuration: The Git repository provides a version-controlled, auditable history of your entire network's state.
  • Intelligent Endpoint Selection: The agent is smart enough to determine the best way to connect to a peer, whether it's on the public internet, on the same local network, or even in another container on the same test machine.

Prerequisites & Setup

Before deploying the agent, you need two GitHub repositories and two sets of credentials.

Step 1: Create the backbone-config Repository

This is the private repository that will store your network's state.

  1. Create a new private GitHub repository (e.g., backbone-config).
  2. Initialize it with a README.md.
  3. In the repository, create an empty directory named peer_data with a .gitkeep file inside it. The agents will populate this directory.

Step 2: Create and Add the Deploy Key

The agent needs an SSH key to be able to write to the backbone-config repository. A Deploy Key is the best practice as its permissions are limited to a single repository.

  1. Generate a new SSH key pair on your local machine. This key will be shared by all your agents.

    # Use ed25519 for modern security and shorter keys
    # The -f flag prevents overwriting your default key
    ssh-keygen -t ed25519 -C "server1-wg-manager" -f ./server1-wg-manager

    When prompted for a passphrase, press Enter twice to leave it empty. This is required for automation. This will create two files: server1-wg-manager (private) and server1-wg-manager.pub (public).

  2. Add the Public Key to GitHub:

    • Go to your backbone-config repository on GitHub.
    • Navigate to Settings > Deploy Keys.
    • Click "Add deploy key".
    • Title: Give it a clear name, like Server1 Wireguard Agent.
    • Key: Copy the contents of your public key file and paste it here.
      # On your Mac/Linux
      cat ./server1-wg-manager.pub

    [!IMPORTANT] Check the box for "Allow write access". The agent needs this permission to register itself and update its IP address.

    • Click "Add key".
  3. Secure the Private Key: The server1-wg-manager (the private key) is the file you will securely place on your servers. Treat this file like a password.


Building & Publishing the Agent Image

This repository includes a Makefile to simplify building the agent and publishing it to the GitHub Container Registry (GHCR).

Step 1: Create a Personal Access Token (PAT)

To log in and push to GHCR, you need a Personal Access Token with the correct permissions.

  1. On GitHub, go to your Settings > Developer settings > Personal access tokens > Tokens (classic).
  2. Click "Generate new token (classic)".
  3. Note: Give your token a descriptive name (e.g., "GHCR Publish Token").
  4. Expiration: Set an expiration date as a security best practice.
  5. Scopes: CRITICAL: Check the box for write:packages. This permission is required to upload container images.
  6. Click "Generate token" and copy the token immediately. You will not see it again.

Step 2: Using the Makefile

Place the provided Makefile in the root of this wireguard-manager repository.

  1. Set Environment Variables: Before running make, you must export your GitHub username and the PAT you just created (can add to your shell profile for convenience).

    # Replace with your actual GitHub username and token
    export CR_USERNAME="jcbasso"
    export CR_PAT="ghp_..."
  2. Run the Commands:

    • make help: Shows a list of all available commands.
    • make login: Tests your credentials by logging into GHCR.
    • make build: Builds the Docker image locally.
    • make push: Pushes the locally built image to GHCR.
    • make publish: The all-in-one command. It will log in, build, and push the image.

Intelligent Endpoint Selection Logic

The agent determines the best network path to connect to each peer by following these rules in order:

  1. Different Public IPs? (WAN Scenario)

    • If a peer's public_ip is different from the agent's own public IP, it will always use the peer's public_ip for the endpoint.
  2. Same Public IP? (LAN / Local Test Scenario)

    • If a peer's public_ip is the same, the agent then checks the SERVER_IDENTIFIER.
    • Are the SERVER_IDENTIFIERs the same?
      • This means both agents are running on the same host machine.
      • If the DOCKER_CONTAINER variable is set, it will use the peer's Docker container name as the endpoint (e.g., wireguard-jc2). This is for local testing.
    • Are the SERVER_IDENTIFIERs different?
      • This means the peers are on different host machines but on the same LAN.
      • The agent will use the peer's public_ip. This requires the router to have correct port forwarding rules and NAT Hairpinning/Loopback support.

Configuration

The agent is configured entirely through environment variables.

Variable Required? Example Description
PEER_NAME Yes wireguard-server-1 A unique name for this node. For local testing, this should match the container name.
BACKBONE_IP Yes 10.100.0.1 The private IP address this node will use within the WireGuard backbone network.
WIREGUARD_PORT Yes 51820 The public-facing UDP port that this node will listen on.
GIT_REPO_URL Yes git@github.com:user/backbone-config.git The SSH URL of your private Git repository.
GIT_SSH_KEY_PATH Yes /run/secrets/server1-wg-manager The path inside the container to the mounted private SSH deploy key.
SERVER_IDENTIFIER Yes my-macbook-pro or aws-us-east-1a A manually set, unique identifier for the host machine this agent is running on.
DOCKER_CONTAINER Optional wireguard-jc1 The Docker container name. Used only for same-host endpoint logic.

Deployment Example

This example shows how to deploy a backbone node on a production server using the secure file-based secret method.

1. Server Preparation

On your server, create the following structure:

/opt/backbone-node/
├── docker-compose.yml
├── .env
└── secrets/
    └── server1-wg-manager  # Your private SSH deploy key file

Place your private key file inside the secrets directory.

[!CRITICAL] Set strict permissions on the key file: bash sudo chown root:root /opt/backbone-node/secrets/server1-wg-manager sudo chmod 600 /opt/backbone-node/secrets/server1-wg-manager

2. Configuration Files

docker-compose.yml File

services:
  wireguard:
    image:  ghcr.io/jcbasso/wireguard-manager:latest
    container_name: wireguard
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    volumes:
      - ./wireguard-config:/etc/wireguard
      - ./secrets:/run/secrets:ro
    ports:
      - "${WIREGUARD_PORT}:${WIREGUARD_PORT}/udp"
    environment:
      - PEER_NAME
      - BACKBONE_IP
      - GIT_REPO_URL
      - GIT_SSH_KEY_PATH
      - WIREGUARD_PORT
      - SERVER_IDENTIFIER
      # DOCKER_CONTAINER is omitted in production

  postgres:
    image: postgres:15-alpine
    container_name: postgres
    restart: unless-stopped
    network_mode: "service:wireguard"
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB
    depends_on:
      - wireguard

.env File

# --- WireGuard Agent Configuration ---
PEER_NAME=aws-node-1
BACKBONE_IP=10.100.0.1
WIREGUARD_PORT=51820

# A unique name for the physical/virtual server
SERVER_IDENTIFIER=my-macbook-pro

# --- Git Configuration ---
GIT_REPO_URL=git@github.com:jcbasso/backbone-config.git
GIT_SSH_KEY_PATH=/run/secrets/server1-wg-manager

# --- PostgreSQL Configuration ---
POSTGRES_USER=myuser
POSTGRES_PASSWORD=my-secure-password
POSTGRES_DB=mydb

Launch Command:

docker compose up -d

About

This is a Go-based agent for the self-healing WireGuard backbone. It runs on each peer, reports its public IP to a central Git repository, and configures its local WireGuard interface based on the state of all other peers.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors