Metadata-Version: 2.4
Name: meshpop-wire
Version: 2.4.2
Summary: Autonomous WireGuard mesh VPN with P2P, relay fallback, and MCP server
Author-email: MeshPOP <mpop@mpop.dev>
License: MIT
Project-URL: Homepage, https://github.com/meshpop/wire
Project-URL: Repository, https://github.com/meshpop/wire
Keywords: wireguard,vpn,mesh,p2p,networking,mcp
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: System :: Networking
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Dynamic: license-file

# wire

**Self-hosted WireGuard mesh VPN — like Tailscale, but you own everything.**

```bash
pip install meshpop-wire
```

No external services. No accounts. No cloud dependency. Pure Python stdlib — installs and runs on any Linux or macOS machine.

---

## Why wire?

### The problem with existing VPN solutions

**Traditional WireGuard** is powerful but painful to manage at scale:

```bash
# Old way: manual WireGuard setup for every new node
# On each existing node — add the new peer manually:
wg set wg0 peer <NEW_PUBLIC_KEY> allowed-ips 10.0.0.5/32 endpoint NEW_IP:51820
# Repeat on EVERY other node
# When a node's IP changes — update EVERY other node again
# No central view of who's online
```

**Tailscale / ZeroTier** solve this — but you're dependent on their coordination servers. Your VPN stops working if their service goes down. Your traffic metadata goes through their infrastructure.

**wire** gives you the Tailscale experience with zero external dependencies:

| | Manual WireGuard | Tailscale / ZeroTier | wire |
|---|---|---|---|
| Setup per new node | Edit every existing node | One command | One command |
| Coordination server | You manage manually | Their cloud (required) | Your own server |
| IP changes | Re-configure everything | Auto | Auto |
| Works if vendor is down | Depends | ✗ No | ✓ Yes |
| Self-hosted | Manual config files | ✗ Enterprise only | ✓ Always |
| Dependencies | None | Account + agent | None |
| AI management (MCP) | ✗ | ✗ | ✓ |

### Before wire

```bash
# Adding a new server to existing 10-node WireGuard mesh:
# 1. Generate keys on new server
wg genkey | tee private.key | wg pubkey > public.key

# 2. On EVERY existing node — add the new peer
for host in server1 server2 server3 server4 server5 \
            server6 server7 server8 server9 server10; do
  ssh root@$host "wg set wg0 peer <PUBKEY> \
    allowed-ips 10.0.0.11/32 endpoint NEW_SERVER_IP:51820"
done

# 3. Add all existing peers to new server — one by one
# 4. When any server changes its IP — repeat

# Result: 10 servers × 10 config files = manually maintained mesh
```

### After wire

```bash
# On new server — one command, done:
sudo wire up --server http://YOUR_COORD_SERVER:8787 --name newserver

# Every existing node automatically discovers and connects to newserver
# within 30 seconds. No manual config on existing nodes.
```

---

## Architecture

```
                ┌────────────────────────────────────────┐
                │  Coordination Server  (one always-on)  │
                │  wire_server.py                        │
                │  HTTP :8787  —  peer registry          │
                │  UDP  :8788  —  STUN (NAT discovery)   │
                │                                        │
                │  Knows: who exists, their public IPs   │
                │  Does NOT carry VPN traffic            │
                └──────────┬─────────────┬──────────────┘
                           │             │
               registers / │             │ registers /
               heartbeat   │             │ heartbeat
               every 30s   │             │ every 30s
                           │             │
              ┌────────────▼──┐       ┌──▼────────────┐
              │  Node A       │◄─────►│  Node B        │
              │  wire_client  │       │  wire_client   │
              │  10.99.x.x    │       │  10.99.y.y     │
              └───────────────┘       └───────────────┘
                      direct P2P WireGuard tunnel
                      end-to-end encrypted
                      coordination server not involved
```

Three files, three roles:

| File | Role | Where it runs |
|---|---|---|
| `wire_server.py` | Coordination server + STUN | One always-on server |
| `wire_client.py` | VPN daemon + CLI | Every node |
| `wire_mcp_server.py` | MCP tools for AI agents | Machines with Claude |

---

## Installation

### No external dependencies

wire is pure Python standard library. No pip packages, no system packages beyond Python 3.8+.

```bash
pip install meshpop-wire
```

This installs:
- `wire` — CLI command
- `wire-mcp` — MCP server for AI integration

### WireGuard kernel module (every node)

wire uses the WireGuard Linux kernel module for the actual VPN tunnels. Install the userspace tools:

```bash
# Debian / Ubuntu
apt install wireguard wireguard-tools

# RHEL / Fedora / CentOS
dnf install wireguard-tools

# Alpine
apk add wireguard-tools

# macOS
brew install wireguard-tools wireguard-go
```

Run `wire install` to check your platform and see the right command.

### Step 1 — Start the coordination server (once, on one always-on machine)

```bash
# Copy to your server and run
scp wire_server.py user@COORD_SERVER:/opt/wire/
ssh user@COORD_SERVER "python3 /opt/wire/wire_server.py"
```

As a systemd service:

```bash
# /etc/systemd/system/wire-server.service
[Unit]
Description=wire coordination server
After=network.target

[Service]
ExecStart=/usr/bin/python3 /opt/wire/wire_server.py
Restart=always

[Install]
WantedBy=multi-user.target
```

```bash
systemctl enable --now wire-server
```

### Step 2 — Join every node to the mesh

```bash
# First time on each node (saves config for future starts):
sudo wire up --server http://COORD_SERVER:8787 --name myserver

# After first run — just:
sudo wire up
```

That's it. The node generates its own WireGuard key pair, discovers its NAT-mapped port via the built-in STUN server, registers with the coordination server, and starts syncing peers every 30 seconds.

---

## How It Works

### VPN IP assignment — no DHCP, no conflicts

Each node's VPN IP is derived deterministically from its own identity:

```python
node_id = sha256(hostname + mac_address)
vpn_ip  = f"10.99.{node_id[0]}.{node_id[1]}"   # e.g. 10.99.23.187
```

Same machine → same VPN IP every time. No central IP allocation. No conflicts.

### NAT traversal — works behind home routers

wire has its own STUN server built in (no Google STUN or external service). Before starting WireGuard, each node probes the coordination server's UDP port to discover what IP and port its NAT router is using:

```
Node UDP :51820  →  COORD_SERVER UDP :8788
Server sees: EXTERNAL_IP:MAPPED_PORT
Server replies: {"ip": "EXTERNAL_IP", "port": MAPPED_PORT}
```

Two nodes behind different NAT routers use WireGuard's `PersistentKeepalive=25` to punch holes in both NATs simultaneously — tunnels work without any port forwarding.

### Peer sync — automatic, every 30 seconds

The client daemon queries `/peers` from the coordination server every 30 seconds and updates WireGuard with any new or changed peers. When you add a new node, all existing nodes discover it within 30 seconds without any manual action.

---

## CLI Reference

### `wire up` — join the network

```bash
# First time (saves config):
sudo wire up --server http://COORD_SERVER:8787 --name NODENAME

# After first run:
sudo wire up
```

| Flag | Description |
|---|---|
| `--server` / `-s` | Coordination server URL |
| `--name` / `-n` | This node's name (default: hostname) |
| `--port` / `-p` | WireGuard listen port (default: 51820) |

---

### `wire status` — view the whole mesh

```bash
wire status
```

```
wire status  http://COORD_SERVER:8787
  4 online / 1 offline / 5 total

  ● web1        10.99.23.187     203.0.113.10       5s ago
  ● web2        10.99.45.22      198.51.100.20      12s ago  (this node)
  ● db1         10.99.87.3       192.0.2.30         8s ago
  ● storage1    10.99.200.5      203.0.113.40       3s ago
  ○ backup1     10.99.100.1      198.51.100.30      14m ago  OFFLINE
```

```bash
wire status --json   # machine-readable
```

---

### `wire peers` — list all registered nodes

```bash
wire peers
```

---

### `wire ping` — ping a node by name

```bash
wire ping web1
wire ping 10.99.23.187
```

Resolves names via the coordination server, then pings over the VPN.

---

### `wire down` — leave the network

```bash
sudo wire down
```

Removes the WireGuard interface and stops the background daemon. The node appears offline on `wire status` within 5 minutes.

---

### `wire install` — check WireGuard installation

```bash
wire install
```

Checks if WireGuard is installed and shows platform-specific instructions if not.

---

## AI Management via MCP

wire ships with an MCP server that lets AI agents (Claude, etc.) manage your VPN mesh through natural language — from initial setup through ongoing monitoring.

### Setup

```bash
pip install meshpop-wire   # installs wire-mcp automatically
```

Add to Claude config (`~/.claude/settings.json`):

```json
{
  "mcpServers": {
    "wire": { "command": "wire-mcp" }
  }
}
```

### What the AI can do

Once connected, you can ask Claude in plain language:

> "Set up wire on this server and connect it to the mesh"
> "Which nodes are currently offline?"
> "Why can't web1 reach db1?"
> "Ping all nodes and tell me which have high latency"
> "Is the WireGuard module installed on this machine?"

The AI handles the commands, interprets the output, and explains what's happening.

### MCP Tools Reference

| Tool | Description |
|---|---|
| `wire_status` | Full mesh view — all nodes, online/offline, VPN IPs, last seen |
| `wire_up` | Bring up the VPN tunnel on this machine |
| `wire_down` | Tear down the VPN tunnel |
| `wire_peers` | List all registered peers |
| `wire_ping` | Ping a peer by name or VPN IP |
| `wire_install` | Check WireGuard installation status |
| `wire_diagnose` | Full diagnostic: module loaded? interface up? server reachable? peers synced? |
| `wire_watchdog` | Check peer handshake ages, stale connections, service health |

---

## Configuration

Config is written automatically by `wire up`. Locations:

| Context | Path |
|---|---|
| Root / system daemon | `/etc/wire/config.json` |
| Regular user | `~/.wire/config.json` |

Example:

```json
{
  "server_url":   "http://COORD_SERVER:8787",
  "node_name":    "web1",
  "node_id":      "a1b2c3d4...",
  "vpn_ip":       "10.99.23.187",
  "listen_port":  51820,
  "nat_port":     54321
}
```

Server-side environment variables:

| Variable | Default | Description |
|---|---|---|
| `WIRE_PORT` | `8787` | HTTP port (UDP STUN = this + 1) |
| `WIRE_VPN_SUBNET` | `10.99` | VPN IP prefix |
| `WIRE_STATE_FILE` | `/etc/wire/state.json` | Peer state file |

---

## File Reference

```
wire/
├── wire_server.py      Coordination server + UDP STUN
│                       Run on ONE always-on server
├── wire_client.py      VPN daemon + CLI
│                       Run on EVERY node in the mesh
└── wire_mcp_server.py  MCP server for AI integration

/etc/wire/  (root) or  ~/.wire/  (user)
├── config.json         Node config — written by wire up
├── private.key         WireGuard private key (chmod 600)
├── public.key          WireGuard public key
└── state.json          Server peer state (coordination server only)
```

---

## Stack Position

wire is **Layer 1** of the MeshPOP infrastructure stack:

```
Layer 3  mpop    Fleet orchestration — monitor, manage, automate
Layer 2  vssh    Fast authenticated transport — remote exec, file transfer
Layer 1  wire    Encrypted mesh VPN — connects all nodes
```

Each layer is independently installable. wire works without vssh or mpop. vssh works with any VPN or direct network. mpop works with any transport.

---

## Design Principles

**No external services.** The coordination server you run provides everything including STUN for NAT discovery. Nothing phones home.

**No central traffic bottleneck.** The coordination server handles only small JSON heartbeats. All VPN traffic flows directly between nodes, peer to peer.

**No manual peer management.** Add a node once. Every other node discovers it automatically within 30 seconds.

**Deterministic IPs.** Each machine's VPN IP is derived from its own hardware identity. No DHCP, no allocation table, no conflicts.

**Offline tolerance.** Nodes keep their WireGuard peers configured when the coordination server is unreachable. Established tunnels survive coordination server restarts.

---

## License

MIT — [MeshPOP](https://github.com/meshpop)
