# Wire — Self-Hosted WireGuard Mesh VPN

**No Tailscale dependency** — run your own mesh VPN with full control.

## Overview

Wire is a self-hosted WireGuard mesh VPN that automatically connects all your servers into a single private network (`10.99.x.x/16`). It handles peer discovery, NAT traversal, relay failover, and interface management — all with zero manual WireGuard configuration.

## Features

- **Zero config**: Point to coordinator server, get connected automatically
- **Auto mesh**: Nodes discover each other via coordinator API
- **Relay failover**: Multi-relay support with automatic fallback
- **NAT traversal**: UDP hole punching with relay fallback for NAT clients
- **Cross-platform**: Linux, macOS, Synology NAS (DSM 7)
- **MCP support**: AI-driven VPN management via MCP server
- **Interface: `wire0`**: Standardized interface name across all nodes

## Quick Start

### Coordinator + Relay Server (VPS with public IP)
```bash
python3 server.py 8786
```

### Client Node
```bash
sudo python3 client.py --server http://YOUR_VPS:8786
```

Done. All clients automatically discover each other and form a mesh.

## Architecture

```
┌─────────────────────────────────────────────────────────┐
│                   Wire Mesh Network                      │
│                   10.99.x.x/16                           │
├─────────────────────────────────────────────────────────┤
│                                                          │
│    ┌──────────────────────────────────────────┐         │
│    │          Relay Nodes (Public IP)          │         │
│    │  v1 (Primary)  v2 (Secondary)  v3 (Tertiary) │    │
│    │  AllowedIPs: per-peer /32 routing         │         │
│    └──────────┬───────────────────┬────────────┘         │
│               │                   │                      │
│    ┌──────────┴───────────────────┴────────────┐         │
│    │          Client Nodes (Behind NAT)         │         │
│    │  g1-g4 (GPU)   d1-d2 (Bare Metal)         │         │
│    │  m1 (macOS)    s1-s2 (Synology NAS)       │         │
│    │  AllowedIPs: 10.99.x.x/16 via relay       │         │
│    └───────────────────────────────────────────┘         │
│                                                          │
└─────────────────────────────────────────────────────────┘
```

### Routing Model

- **Relay nodes** (v1, v2, v3): Have `/32` routes to every peer; forward traffic between NAT clients
- **Client nodes**: Route all VPN traffic (`10.99.x.x/16`) via the primary relay (v1); direct `/32` peers added for VPS nodes with known endpoints
- **Hub node** (v1): Primary relay and coordinator; all nodes set `AllowedIPs: 10.99.x.x/16` for v1

## Installation

### One-liner (Linux)
```bash
curl -sSL http://YOUR_VPS:8786/install.sh | sudo bash
```

This installs WireGuard, downloads `client.py`, registers as a systemd service, and enables IP forwarding.

### macOS
```bash
brew install wireguard-tools wireguard-go
sudo python3 client.py --server http://YOUR_VPS:8786
```

### Synology NAS (DSM 7)
```bash
# Requires WireGuard package from SynoCommunity
# Config: /etc/wireguard/wire0.conf
# WireGuard binary: /volume1/@appstore/WireGuard/wireguard/wg-quick

# Boot script: /usr/local/etc/rc.d/wire0.sh
cat > /usr/local/etc/rc.d/wire0.sh << 'EOF'
#!/bin/bash
case "$1" in
  start) /volume1/@appstore/WireGuard/wireguard/wg-quick up wire0 ;;
  stop)  /volume1/@appstore/WireGuard/wireguard/wg-quick down wire0 ;;
esac
EOF
chmod +x /usr/local/etc/rc.d/wire0.sh
```

## Configuration

### wire0.conf (Example — Client Node)
```ini
[Interface]
PrivateKey = <generated-private-key>
ListenPort = 51820
Address = 10.99.x.x/16

[Peer]
PublicKey = <relay-public-key>
Endpoint = <relay-public-ip>:51838
AllowedIPs = 10.99.x.x/16
PersistentKeepalive = 25
```

### Coordinator API

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/register` | POST | Register node (node_id, wg_public_key, port, lan_ip) |
| `/peers` | GET | List all registered peers |
| `/punch` | POST | Request NAT hole-punching (relay fallback on failure) |
| `/health` | GET | Coordinator health check |

## MCP Integration

Wire includes a dedicated MCP server (`wire-mcp-server.py`) for AI-assisted VPN management.

```json
{
  "mcpServers": {
    "wire": {
      "command": "python3",
      "args": ["/path/to/wire-mcp-server.py"]
    }
  }
}
```

### MCP Tools

| Tool | Description |
|------|-------------|
| `wire_status` | Check VPN interface and peer status |
| `wire_peers` | List all connected peers with handshake info |
| `wire_install` | Generate installation commands for new nodes |
| `wire_diagnose` | Diagnose connectivity issues |
| `wire_connect` | Generate connect commands |
| `wire_add_node` | Add a new node to the mesh |
| `wire_remove_node` | Remove a node from the mesh |
| `wire_watchdog` | Monitor VPN health |

## Cluster Status (14 Nodes)

| Server | Role | VPN IP | Platform | Interface |
|--------|------|--------|----------|-----------|
| v1 | Relay + Coordinator | 10.99.x.x | Linux | wire0 |
| v2 | Relay | 10.99.x.x | Linux | wire0 |
| v3 | Relay | 10.99.x.x | Linux | wire0 |
| n1 | Client | 10.99.x.x | Linux | wire0 |
| g1 | Client | 10.99.x.x | Linux | wire0 |
| g2 | Client | 10.99.x.x | Linux | wire0 |
| g3 | Client | 10.99.x.x | Linux | wire0 |
| g4 | Client | 10.99.x.x | Linux | wire0 |
| d1 | Client | 10.99.x.x | Linux | wire0 |
| d2 | Client | 10.99.x.x | Linux | wire0 |
| m1 | Client | 10.99.x.x | macOS | wire0 |
| s1 | Client | 10.99.x.x | DSM 7 | wire0 |
| s2 | Client | 10.99.x.x | DSM 7 | wire0 |

> **Note**: All nodes migrated from legacy `awlite0` interface to `wire0` as of 2026-03-14. The `awlite0` interface and all related configurations have been fully removed from every server.

## Troubleshooting

### No handshake with peer
```bash
# Check interface status
wg show wire0

# Verify endpoint is reachable
ping <relay-public-ip>

# Manually set endpoint
wg set wire0 peer <pubkey> endpoint <ip>:<port>
```

### Check if traffic routes through relay
```bash
ping 10.99.x.x
wg show wire0   # Check "endpoint" column — relay IP means relayed
```

### Restart service
```bash
# Linux
systemctl restart wire

# Synology NAS
/usr/local/etc/rc.d/wire0.sh stop && /usr/local/etc/rc.d/wire0.sh start
```

### Tailscale Fallback
If Wire VPN is unreachable, all nodes also have Tailscale installed as backup access:
```bash
# Example: access s1 via Tailscale
ssh user@100.x.x.x
```

## Requirements

- Python 3.8+
- WireGuard: `apt install wireguard` (Linux), `brew install wireguard-tools wireguard-go` (macOS)
- IP forwarding enabled on relay nodes

## File Locations

| File | Path | Description |
|------|------|-------------|
| server.py | `MeshPOP/wire/server.py` | Coordinator + relay server |
| client.py | `MeshPOP/wire/client.py` | Auto-mesh client agent |
| wire-mcp-server.py | `MeshPOP/wire/wire-mcp-server.py` | MCP server for AI integration |
| wire0.conf | `/etc/wireguard/wire0.conf` | WireGuard interface config |
| install.sh | Served via coordinator | One-liner install script |

## Migration History

| Date | Change |
|------|--------|
| 2026-03-14 | `awlite0` → `wire0` migration on s1, s2 (Synology NAS); awlite0 remnants removed from all 14 servers |
| 2026-02-26 | Mesh routing fix — v1 hub model with /16 routing; NAT clients route via relay |
| 2026-02-20 | Initial Wire deployment replacing Tailscale dependency |

## License

MIT
