VirtuaMesh Documentation

A zero-trust identity-based networking platform built on the WireGuard protocol. Replace legacy VPNs and securely connect remote teams, multi-cloud environments, and IoT devices.

What is VirtuaMesh? It pulls devices "located around the world, behind NAT firewalls" into a virtual LAN, letting them reach each other as if they were under the same router — with WireGuard end-to-end encryption the entire way.

What problems does it solve? ① Remote access to your home NAS / cameras / smart home; ② Building an intranet across branch offices in different regions; ③ Remote work access to corporate internal systems; ④ Bridging IoT devices across network segments; ⑤ Building secure tunnels between servers.

Who is it for? From home users who know nothing about networking to senior developers who need API, ACL, subnet routing, and Kubernetes integration — this page has dedicated sections for each.

📍 Current display mode: All content

🌱 5-Minute Beginner Tutorial

This tutorial is for: Anyone who has never touched VPN / servers / the command line. The whole process only requires a browser — no commands to type.

What you'll be able to do
Put your home PC, work PC, and phone app all inside one secure "virtual LAN," where they can reach each other as if they were under the same router.

What exactly is it?

Imagine: your phone is on 4G, your home PC is on residential broadband, and your work PC is on the corporate network. These three devices normally can't see each other — but through VirtuaMesh, they get "pulled" into a virtual internal network. You can access your home NAS from your work PC, or connect to your home smart camera from your phone.

You don't need to understand public IPs, port forwarding, or firewalls. VirtuaMesh handles all of it automatically.

What do you need to prepare?

  • One internet-connected computer (Windows / Mac / Linux all work) for logging into the admin console
  • Two or more devices that need to reach each other (phones, computers, NAS all fine)
  • One server with public internet access (a cloud VPS or your home NAS) to host the server and DERP relay — all services are self-hosted and depend on no public relays

3 steps to get it done

Step 1: Log in to the admin console (2 minutes)

Open https://your-server-address/manager/ in a browser and sign in with the admin account. After the first deployment, the default admin account is admin@virtuamesh.com; see the deployment docs for the password.

What is the "admin console"?
It's just a web page. Here you can "create users, invite devices, and see who's online," all with mouse clicks.

Step 2: Add each device to the network (1 minute per device)

In the admin console, click "Add Device" and the system will generate a 6-digit invite code. Then:

📱 Phone / Tablet
  1. Search for VirtuaMesh in the app store and install
  2. Open the app and enter the invite code
  3. Allow adding the VPN configuration
  4. Wait for admin approval (new nodes default to "Pending" state)
  5. Once approved, the app shows "Connected"
💻 Computer (Win/Mac/Linux)
  1. Download the client from the admin console
  2. Double-click to install (Windows / Mac)
  3. Launch it and enter the invite code
  4. Wait for admin approval (client shows "Connecting...")
  5. Once approved, the tray icon turns green = connected
About node approval
For security, VirtuaMesh enables node admission approval by default: after a new device registers with an invite code, its status is Pending and it cannot access any internal resources yet. An admin must manually approve (Approved) it in the "Node Management" section of the web console before the node can officially join the network. Admins can disable or remove nodes at any time, ensuring every device joining the network is controlled.

Step 3: Test the connection

All joined devices are now on the same virtual network. You can:

  • View all online devices in the admin console; each has a name (e.g. "My Phone", "Home NAS")
  • See other devices' shared folders directly from your computer's "Network"
  • Connect to your NAS with an SSH tool: ssh admin@my-nas.virtuamesh.com
  • Access the NAS web UI at http://my-nas.virtuamesh.com:5000 in a browser
What if it fails?
99% of issues are one of these three:
1. Device isn't online → open a browser and try a normal website
2. Invite code is wrong → regenerate one in the admin console
3. Firewall is blocking → temporarily disable antivirus and system firewall and try again
Still not working? Check the FAQ or run virtuamesh test-connection to test connectivity.

What to learn next?

You've completed basic networking! Below are advanced use cases — learn as needed:

📖 Concept Cheat Sheet (must-read for beginners)

Run into a term you don't understand? Look it up here. Every concept comes with a real-life analogy.

Mesh Network Mesh Network
A "peer-to-peer" network of multiple devices where any two can communicate directly, without depending on a central server.
Like a group chat — anyone in the group can post a message and everyone else receives it directly, no "central post office" needed.
P2P Direct Peer-to-Peer
A network connection established directly between two devices. Fast speed, low latency.
Two friends talking face to face — faster than a phone call.
Relay Server DERP Relay
When P2P direct connection fails, automatically switch to a relay server to forward encrypted data. Slightly slower but guarantees connectivity.
Two people separated by a wall can't hear each other clearly, so a friend stands in the middle as a "message relay."
Virtual IP Virtual IP
Each device's "internal address" in the virtual network, e.g. 100.64.0.5. Fixed — doesn't change when you switch Wi-Fi.
Like your home landline number — whether you use a desk phone or mobile, anyone dialing that number reaches you.
Node Node / Peer
Every device that joins a VirtuaMesh network is called a "node."
Like "classmates" in a class — each classmate is a node, and classmates can message each other.
Control Plane Control Plane
The server's brain — it only does "scheduling": telling nodes where other nodes are and who can access whom. It cannot see encrypted data content.
A hotel front desk — knows every room number and guest, but never enters your room to look at your stuff.
Data Plane Data Plane
The channel where nodes actually transfer business data, fully end-to-end encrypted.
The hallway between guest rooms — end-to-end encrypted, even the front desk can't enter.
MagicDNS Magic DNS
VirtuaMesh's built-in domain name resolution service, letting you access devices by name (e.g. my-nas) instead of IP.
Your phone contacts — you just remember "Mom," the system dials Mom's number automatically.
NAT Traversal NAT Traversal
Automatically handles "port restrictions" on home routers so two devices on different Wi-Fi networks can communicate directly.
Two rooms separated by a locked door — VirtuaMesh automatically finds the key and opens it, no manual router config needed.
Exit Node Exit Node
Let another device access the public internet on your behalf, so your traffic "appears" to come from that device.
When traveling abroad, have a local friend buy things for you — items ship from abroad, bypassing domestic restrictions.
Subnet Router Subnet Router
Lets other devices in the virtual network access this device's local network (e.g. the office printer).
Let everyone on the VirtuaMesh network use that old printer in your office.
Zero Trust Zero Trust
Trust no device by default; every access must verify identity and permissions.
Corporate access control — even as a veteran employee, you must badge in at every door; being "in the group" doesn't get you a pass.

🧩 Architecture Deep Dive

Understanding how VirtuaMesh works internally is essential for troubleshooting.

Overall Architecture

Control Plane API · MySQL · Redis · Admin Console DERP Relay Server STUN + Relay MagicDNS Auto domain registration Node A Home PC Node B Work PC Node C Phone Node D NAS Register / Heartbeat / Config P2P fails → use DERP DNS resolution Control channel (plaintext) P2P data (encrypted) DERP relay (encrypted) MagicDNS (auto register)

Connection Establishment Flow (5 steps)

  1. Node registration

    After startup, the node registers with the control plane, submitting its public key and authentication info.

  2. Get peer list

    The control plane returns information about all peer nodes this node can access (public key, virtual IP, endpoint).

  3. NAT traversal attempt

    Nodes pair up and attempt to establish P2P direct connections via STUN hole-punching. 80% of home networks succeed.

  4. P2P established or DERP fallback

    If P2P succeeds, they communicate directly; if it fails, they automatically fall back to DERP relay for encrypted data — the connection still works.

  5. Continuous keepalive

    Nodes send heartbeats to the control plane via a long-lived gRPC stream (server default suggestion: 30s, adjustable in client config.yaml), keeping NAT mappings alive. The server marks a node offline if no heartbeat arrives within HeartbeatTimeout (30s).

Key Design Principles

PrincipleMeaningBenefit
End-to-end encryptionWireGuard ChaCha20; nodes encrypt/decrypt directlyServer can't see business data — zero knowledge
No central data pathData flow doesn't pass through the control planeControl plane cannot become a bottleneck
Auto traversalSTUN + candidate path negotiationZero config, zero port forwarding
Keys never persistedNode private keys live only on the local machineServer compromise doesn't affect communication security

Multi-Transport Protocol

VirtuaMesh supports multiple transport protocols with automatic fallback when UDP is rate-limited or NAT traversal fails:

  • WireGuard UDP (default) — Standard WireGuard UDP transport, lowest latency, preferred
  • WireGuard over TCP — Automatically enabled when UDP is QoS-throttled or with symmetric NAT
  • WebSocket Transport — Tunnel WireGuard packets over WebSocket for strict firewalls/proxies
  • KCP over UDP — Reliable UDP transport for high packet loss networks
  • DERP Relay — Fallback relay with self-hosted DERP server support
  • TURN Relay — Standard TURN relay support

Transports auto-switch by priority: UDP → TCP → WebSocket → DERP → TURN, no manual configuration needed.

Data Compression

Built-in packet compression (Deflate algorithm) automatically compresses IP packets larger than 256 bytes before encryption, reducing bandwidth usage by 30-70%. Transparent to users, no configuration required.

Self-hosted DERP Server

Add custom DERP servers in the configuration file to prioritize over official DERP servers:

"natTraversal": {
    "customDerpServers": [
        {
            "host": "derp.example.com",
            "port": 443,
            "verifyTls": true,
            "regionName": "Self-hosted US-East",
            "enabled": true,
            "stunPort": 3478
        }
    ]
}

🏠 Full Walkthrough: Remote Access to a Home NAS

Scenario: You're on a business trip in a hotel and want to access photos and files on your home NAS. The home NAS is Synology/QNAP; your computer is on the company or hotel Wi-Fi.

What you need

  • One always-on device as the server (the home NAS itself, a Raspberry Pi, or an old PC all work)
  • Services on the NAS you want to use (e.g. Synology Photos, Jellyfin, SMB file sharing)

Step-by-step

🖥️ Phase 1: Server deployment (10 minutes)
1
Log in to your home NAS and enable SSH (Synology: Control Panel → Terminal & SNMP → Enable SSH)
2
SSH into the NAS and deploy the server with one Docker Compose command:
# Download docker-compose.prod.yml and config
mkdir -p ~/virtuamesh && cd ~/virtuamesh
# See the Server Deployment section for the config file
docker compose -f docker-compose.prod.yml up -d
3
Set the admin account password as prompted and wait 2-3 minutes for installation. Note the "Admin Console URL" printed to the console — usually https://your-domain or http://NAS-LAN-IP:58080
📱 Phase 2: Join the network (5 minutes)
4
Open the admin console in a browser and sign in with the admin account
5
Click "Node List" → "Add Node" → name it home-nas → copy the generated invite code
6
In the NAS terminal run:
virtuamesh register --server https://your-domain --network-code your-invite-code
7
Back in the admin console, the home-nas status in "Node List" changes to "Online" ✓
💼 Phase 3: Add travel devices (3 minutes each)
8
In the admin console, generate an invite code for each travel device (e.g. "Work PC", "Phone")
9
On the work PC:
virtuamesh register --server https://your-public-domain --network-code invite-code
(Note: external clients need the NAS public address or domain)
10
On the phone: install VirtuaMesh from the App Store, enter the invite code to join
🎉 Phase 4: Enjoy
11
Now in the hotel, on your laptop, you can:
• Open http://home-nas.virtuamesh.com:5000 in a browser for the Synology web UI
• Type \\home-nas.virtuamesh.com in File Explorer's address bar to see shared folders
• Copy files directly over SMB — speed depends on your upload bandwidth
12
On the phone:
• In Synology Photos / DS File, "Add NAS" with server address home-nas.virtuamesh.com
• Works on 4G / Wi-Fi, instant LAN-like experience
Speed optimization tips
Speed depends on your home upload bandwidth. Telecom/Unicom broadband usually offers 30-50 Mbps upload — fine for photos, but for movies you want ≥ 80 Mbps. You can enable P2P mode so the home NAS maintains a long-lived connection to the server, avoiding the overhead of re-establishing connections each time. See the Performance Tuning section.

⚡ 5-Minute Developer Track

Already comfortable with Docker, Linux, and the command line? Here's the 5-minute fast track, all via CLI.

Step 1: One-click server deployment

# Get the deployment script and config (see the Server Deployment section)
mkdir -p ~/virtuamesh && cd ~/virtuamesh
# Edit .env to fill in domain and keys
docker compose -f docker-compose.prod.yml up -d

Step 2: Install the client

# macOS
curl -fsSL https://control.virtuamesh.com/install/macos.sh | sh

# Linux
curl -fsSL https://control.virtuamesh.com/install/linux.sh | sh

# Windows (PowerShell)
iwr -useb https://control.virtuamesh.com/install/windows.ps1 | iex

Step 3: Join the network

virtuamesh init
virtuamesh register --server https://your-server.com --network-code <invite-code>
virtuamesh up
virtuamesh status
virtuamesh test-connection --target-ip <peer-virtual-ip>

Step 4: Access via MagicDNS

curl http://api-service.virtuamesh.com/health
ssh deploy@build-runner.virtuamesh.com

Step 5: Advanced config (optional)

# Enable subnet routing (expose the office network to the virtual network)
virtuamesh subnet advertise 192.168.1.0/24

# Enable exit node (route all traffic through this node)
virtuamesh exit-node enable
CI/CD integration
Use the virtuamesh client as a build node in GitHub Actions / GitLab CI, letting build machines directly access internal services. Steps: register with a service-account token via virtuamesh register, see the Quick Reference section for register command details.

🔌 API Reference

The VirtuaMesh control plane provides a complete RESTful API. All APIs use JWT Bearer Token auth; base URL is https://your-server.com/api/v1.

Authentication

curl -H "Authorization: Bearer <JWT_TOKEN>" https://your-server.com/api/v1/nodes

How to obtain a JWT:

# 1. Log in with email/password to get a short-lived access_token + long-lived refresh_token
curl -X POST https://your-server.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"your-password"}'

# 2. Exchange refresh_token for a new access_token
curl -X POST https://your-server.com/api/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token":"..."}'

Node Management

GET /api/v1/nodes List all nodes
GET /api/v1/nodes/:id Get node details
POST /api/v1/nodes Register a new node (requires admin)
DELETE /api/v1/nodes/:id Deregister a node
PATCH /api/v1/nodes/:id Update node metadata (tags, ACL, etc.)

Users & Permissions

GET /api/v1/users User list (admin)
POST /api/v1/users Create a user (admin)
GET /api/v1/traffic-rules List ACL/traffic rules
POST /api/v1/traffic-rules Create an ACL/traffic rule

DNS Management

GET /api/v1/dns/networks/{networkId}/records List DNS records in a network
POST /api/v1/dns/{networkId}/nodes/{nodeId}/register Register a DNS hostname for a node
DELETE /api/v1/dns/{networkId}/nodes/{nodeId} Unregister a node's DNS record

Request & Response Example

POST /api/v1/nodes
Content-Type: application/json
Authorization: Bearer eyJhbGc...

{
  "name": "build-runner-1",
  "tags": ["ci", "linux"],
  "acl_groups": ["developers", "ci-agents"]
}

# 201 Created
{
  "id": "node_a1b2c3d4",
  "name": "build-runner-1",
  "hostname": "build-runner-1",
  "virtual_ip": "100.64.0.42",
  "auth_key": "tskey-auth-k7PqLm3vR9wX2zE8nF4hJ6tY1uA0oI5sD3cVbN9xMqW",
  "created_at": "2026-06-07T08:23:11Z",
  "tags": ["ci", "linux"],
  "acl_groups": ["developers", "ci-agents"]
}
Rate limiting
API defaults to 1000 requests/minute per client IP, sufficient for normal heartbeat and polling. Auth endpoints (login/register/refresh/forgot-password) are tightened to 10/minute to prevent brute-force. 429 responses include Retry-After and X-RateLimit-Remaining headers. Override via RateLimiting:ClientLimitPerMinute.

DERP WebSocket Bidirectional Channel

Bidirectional WebSocket channel between the client and the DERP relay server (for relaying WireGuard packets when NAT traversal fails), carried by the WireGuard-over-WebSocket protocol. There is no JSON event subscription on the business layer:

// Client connects to DERP relay via WireGuard over WebSocket
// (handled internally by the virtuamesh client process, no business code needed)
const ws = new WebSocket('wss://your-server.com/derp');

🚀 Performance Tuning

VirtuaMesh's default config handles most scenarios, but if you're chasing peak performance or hitting bandwidth issues, refer to the tuning options below.

1. MTU tuning

Default MTU 1420 fits most networks. If your network path has no PPPoE/VPN nesting, you can bump it to 1500 for higher throughput:

network:
  mtu: 1500  # Only when the link has no nested VPN

If you traverse multiple NAT levels or complex networks, drop to 1280 instead:

network:
  mtu: 1280  # Extreme network conditions

2. Enable kernel mode

On Linux, kernel mode gives a 2-5x throughput boost:

sudo apt install wireguard-tools
# Config file
network:
  wireguard_mode: "kernel"

3. Deploy multi-region DERP

Latency between nodes and DERP should stay under 50ms. Globally distributed teams should deploy one DERP per major region:

# derp-asia.yaml
{
  "DerpServer": {
    "Enabled": true,
    "Port": 443,
    "Hostname": "derp-asia.your-domain.com",
    "Region": "ap-east"
  }
}

# derp-eu.yaml
{
  "DerpServer": {
    "Enabled": true,
    "Port": 443,
    "Hostname": "derp-eu.your-domain.com",
    "Region": "eu-west"
  }
}

Then list all DERP domains in the client config — VirtuaMesh will auto-pick the closest:

derp:
  servers:
    - url: "https://derp-asia.your-domain.com"
      region: "ap-east"
    - url: "https://derp-eu.your-domain.com"
      region: "eu-west"
    - url: "https://derp-na.your-domain.com"
      region: "us-east"

4. Persistent connection keepalive

Maintain long-lived connections between nodes to avoid re-hole-punching on every request:

network:
  keepalive: 25  # Send a keepalive packet every 25 seconds (seconds)

Shorter intervals mean faster connection setup but more traffic. 25s is fine for home networks; 15s is better behind enterprise NAT.

5. Enable multi-core processing

The server uses a single core for encryption by default. Servers with more CPUs can enable multi-core:

# docker-compose.prod.yml
services:
  api:
    environment:
      - ASPNETCORE_THREADPOOL_MINTHREADS=Environment.ProcessorCount
      - ASPNETCORE_THREADPOOL_MAXTHREADS=512

Performance monitoring

View real-time performance data:

# Node performance
virtuamesh status --verbose

# Traffic stats
virtuamesh traffic
virtuamesh top

# DERP relay load
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
  https://your-server.com/api/v1/derp-servers/healthy
Performance benchmark reference
Typical scenario reference values:
  • 2 nodes P2P same city: 800-950 Mbps (limited by WireGuard encryption performance)
  • Cross-province P2P: 200-500 Mbps
  • Cross-ocean DERP relay: 80-150 Mbps (depends on DERP egress bandwidth)
  • Single CPU core handles ~1 Gbps encrypt/decrypt (with AES-NI acceleration)

🔐 Security Best Practices

5 things everyone should do

  1. Enable strong passwords / 2FA

    Admin console accounts must enable two-factor authentication. Setting path: Account Settings → Security → Enable TOTP 2FA.

  2. Use sub-accounts, don't share accounts

    Give each family or team member their own account; you can revoke permissions individually if issues arise.

  3. Rotate Auth Keys regularly

    In the admin console → Node Management, regenerate the invite code, then use virtuamesh register --force to re-register the node and rotate credentials.

  4. Enable audit logs

    Audit logs are enabled by default; view them in Admin Console → Audit Logs.

  5. Restrict admin console IP access

    Use an Nginx reverse proxy to allow only corporate IP ranges to access the /manager/ path:

    location /manager/ {
      allow 203.0.113.0/24;   # Corporate IP range
      deny all;
    }

ACL: Fine-grained access control

ACL (Access Control List) decides which nodes can access which, and on which ports.

Basic syntax

acls:
  - action: accept
    src:
      - "group:developers"
    dst:
      - "group:production:*"
    ports:
      - "443"
      - "22"

  - action: deny
    src:
      - "group:guests"
    dst:
      - "group:production"

Common rule examples

👥 User group management
Group nodes by "dev/test/prod"; cross-group access requires authorization
🚪 Port whitelist
Only expose 80/443 to guests; 22 limited to ops
⏰ Time windows
Allow dev → prod access only on weekdays 9-18
📍 Device fingerprint
Restrict access to core nodes to "company-registered MAC addresses" only

View and validate ACL rules

# List all rules (with hit stats)
virtuamesh acl list

# View a single rule's details
virtuamesh acl show <rule-id>

Advanced security topics

Key rotation strategy

# Auto-rotation: server config
key_rotation:
  enabled: true
  interval: 7d           # Rotate every 7 days
  grace_period: 24h      # Old key grace period
  notify_before: 1h      # Notify 1 hour in advance

WireGuard cipher selection

The default ChaCha20-Poly1305 is secure enough. If you have hardware acceleration, you can pick AES-256-GCM:

network:
  crypto:
    algorithm: "chacha20-poly1305"  # or "aes-256-gcm" (requires AES-NI support)

Audit log format

# Default JSON Lines format, can feed into ELK / Loki
{
  "timestamp": "2026-06-07T10:23:45Z",
  "event": "node.online",
  "node_id": "node_a1b2c3",
  "src_ip": "100.64.0.42",
  "user_agent": "virtuamesh/1.2.3"
}

Compliance & data residency

Enterprise edition supports:

  • Designated DERP regions (data stays in-country)
  • Private deployment of the server
  • SOC 2 / ISO 27001 audit logs
  • SSO integration (SAML / OIDC)

🚀 Command Quick Reference

One-page quick reference. Ctrl+F to search as needed.

Client lifecycle

virtuamesh init                                # Initialize local config
virtuamesh register --server <url> --network-code <code>  # Join network
virtuamesh up                                  # Start connection
virtuamesh down                                # Disconnect
virtuamesh status                              # Show status
virtuamesh service install                     # Install system service (auto-start on boot)
virtuamesh service start                       # Start background service
virtuamesh service stop                        # Stop background service
virtuamesh service restart                     # Restart service

Diagnostics

virtuamesh status --verbose                    # Verbose status
virtuamesh test-connection --target-ip <ip>    # Test connectivity
virtuamesh test-connection --all               # Test all peers
virtuamesh top                                 # Real-time network monitor
virtuamesh logs follow                         # Live logs
virtuamesh logs show --level debug             # Debug logs

Network & ACL

virtuamesh peers                               # All peers
virtuamesh subnet advertise 192.168.1.0/24     # Expose subnet
virtuamesh subnet list                         # List subnets
virtuamesh subnet unadvertise 192.168.1.0/24   # Unexpose subnet
virtuamesh exit-node enable                    # Enable exit node
virtuamesh exit-node disable
virtuamesh acl list                            # List ACL rules
virtuamesh acl show <rule-id>                  # View rule details

DNS

virtuamesh dns resolve <name>                 # Resolve
virtuamesh dns resolve --verbose <name>       # Verbose resolve
virtuamesh dns stats                           # DNS stats
virtuamesh dns cache clear                     # Clear cache
virtuamesh dns register --hostname X --network-id <guid> --node-id <guid>
virtuamesh dns list --network-id <guid>
virtuamesh dns unregister --network-id <guid> --node-id <guid>

What is VirtuaMesh

VirtuaMesh is a zero-trust identity-based networking platform built on the WireGuard protocol. It establishes a secure virtual mesh network between devices via encrypted peer-to-peer connections. All traffic is encrypted with WireGuard's ChaCha20-Poly1305, ensuring only devices in the same network can communicate with each other.

VirtuaMesh creates a peer-to-peer mesh network rather than the traditional centralized VPN architecture. This means devices communicate directly whenever possible (P2P), avoiding the latency and single-point-of-failure issues of a central gateway in legacy VPNs. When P2P isn't available, DERP relay servers automatically take over to keep connections always available.

Core Advantages

End-to-end encryption
WireGuard protocol encryption; the control plane cannot decrypt user data — zero-knowledge architecture
Zero-config connectivity
Auto-traverses NAT and firewalls; no port forwarding or complex network configuration needed
MagicDNS
Auto DNS resolution, split DNS, DoH encryption, custom records — connect everything by name
Zero-trust access
Identity-based access control, RBAC permission management, fine-grained traffic rules
Cross-platform
Supports Windows, macOS, Linux — CLI and graphical UI
Observability
Real-time traffic monitoring, network topology visualization, alert rules — full visibility into network state

Differences from legacy VPN

FeatureLegacy VPNVirtuaMesh
Network architectureCentralized gatewayDistributed P2P mesh
EncryptionTunnel encryption (gateway can decrypt)End-to-end encryption (zero knowledge)
Connection modeAll traffic through the centerDirect device-to-device + DERP fallback
NAT traversalRequires port forwardingAutomatic traversal
Single point of failureGateway down = whole network downNo central node, highly available
Access controlNetwork-layer basedIdentity-based (zero trust)

Quick Start

Set up a VirtuaMesh virtual network in just a few simple steps. No deep networking knowledge required — done in minutes.

  1. Deploy the control plane

    One-click server start with Docker Compose, including the API server, MySQL database, Redis cache, and DERP relay.

    cd /path/to/VirtuaMesh/Server
    docker-compose -f docker-compose.prod.yml up -d
  2. Install the client

    Install the VirtuaMesh client on each device that needs to join the network.

    # Windows
    iwr -useb https://control.virtuamesh.com/install/windows.ps1 | iex
    
    # macOS
    curl -fsSL https://control.virtuamesh.com/install/macos.sh | sh
    
    # Linux
    curl -fsSL https://control.virtuamesh.com/install/linux.sh | sh
  3. Register the node

    Register the client with the control plane to get node credentials and a virtual IP.

    virtuamesh register --server https://your-server.com --network-code <CODE>
  4. Start the connection

    Start the WireGuard tunnel and connect to the virtual network.

    virtuamesh up
  5. Verify the connection

    Check node status and connectivity.

    virtuamesh status
    virtuamesh test-connection --target-ip <peer-virtual-ip>

Server Deployment

Requirements

ItemMinimumRecommended
OSUbuntu 20.04+ / Debian 11+Ubuntu 22.04 LTS
CPU2 cores4 cores+
Memory4 GB8 GB+
Disk20 GB SSD50 GB+ SSD
Docker20.10+Latest stable
Docker Compose2.0+Latest stable

Deployment Steps

  1. Install Docker
    curl -fsSL https://get.docker.com | sh
    sudo usermod -aG docker $USER
  2. Configure environment variables

    Copy .env.example to .env and fill in the required config:

    MYSQL_ROOT_PASSWORD=your_strong_root_password
    MYSQL_PASSWORD=your_strong_mysql_password
    REDIS_PASSWORD=your_strong_redis_password
    JWT_KEY=YourSuperSecretKeyHereMakeItLongEnough32Chars!
    DOMAIN_NAME=your-domain.com
  3. Configure the firewall
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw allow 3478/udp
    sudo ufw enable
  4. Start the services
    docker-compose -f docker-compose.prod.yml up -d
Production recommendations
We recommend using an Nginx reverse proxy with an SSL certificate to expose both the API service and the web admin UI on port 443. See the config/nginx/ directory in the project for example configs.

Method 2: systemd + Self-Contained Publish (No Docker)

Use this when you want to run VirtuaMesh as a native system service to avoid container overhead, or when the deployment environment doesn't support Docker. Underlying dependencies: .NET 10 runtime + SQLite. No MySQL/Redis required (you can still point to an external Redis for distributed cache if needed):

  1. Prepare Linux environment

    You need the .NET 10 SDK on the build machine (only for building; the published artifact is a self-contained executable so the target server does NOT need .NET installed):

    # Ubuntu 22.04: install .NET 10 SDK
    wget https://dot.net/v1/dotnet-install.sh -O /tmp/dotnet-install.sh
    chmod +x /tmp/dotnet-install.sh
    sudo /tmp/dotnet-install.sh --channel 10.0 --install-dir /usr/share/dotnet
    sudo ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet
    dotnet --version   # should print 10.x.x
  2. Build a self-contained Linux publish
    git clone https://github.com/virtuamesh/virtuamesh.git
    cd virtuamesh/Server
    dotnet publish src/VirtuaMesh.Api -c Release \
      -r linux-x64 --self-contained true \
      -o ./publish/linux-x64
  3. Upload to the server and extract
    REMOTE_DIR=/data/virtuamesh/server
    ssh user@server "sudo mkdir -p $REMOTE_DIR && sudo chown \$USER:\$USER $REMOTE_DIR"
    scp -r ./publish/linux-x64/* user@server:$REMOTE_DIR/
    ssh user@server "chmod +x $REMOTE_DIR/VirtuaMesh.Api"
  4. Generate the secrets file

    The project uses /etc/virtuamesh/secrets.env to inject the JWT and DERP registration secrets (avoiding hardcoding in config files). Run the project's bundled key-rotation script:

    sudo mkdir -p /etc/virtuamesh
    sudo bash scripts/rotate-secrets.sh    # generates VIRTUAMESH_JWT_KEY, etc.
    sudo chmod 600 /etc/virtuamesh/secrets.env
  5. Place the production config
    sudo cp scripts/appsettings.Production.example.json $REMOTE_DIR/appsettings.Production.json
    sudo vim $REMOTE_DIR/appsettings.Production.json   # adjust Database/StunServer/P2P nodes
  6. Initialize the SQLite database

    SQLite is recommended for single-node deployments (zero dependencies, zero ops). For MySQL cluster mode see docker-compose.prod.yml for the connection-string format:

    scp scripts/database-init-sqlite.sql user@server:/tmp/
    ssh user@server "cd $REMOTE_DIR && sqlite3 virtuamesh.db < /tmp/database-init-sqlite.sql"
  7. Install the systemd unit
    sudo cp scripts/virtuamesh-api.service /etc/systemd/system/
    sudo systemctl daemon-reload
    sudo systemctl enable virtuamesh-api
    sudo systemctl start virtuamesh-api
    sudo systemctl status virtuamesh-api     # should show active (running)
  8. Configure firewall and log rotation
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw allow 53478/udp    # STUN (differs from Docker deploy: default 53478)
    # journald retains logs by default; for long-term archival see scripts/ logrotate configs
Comparison of the two deployment methods
DimensionDocker deploysystemd deploy
Startup speedMedium (image pull + container orchestration)Fast (direct process)
Resource overhead+1 container abstraction layer (~100MB RAM)Minimal
Upgrade / rollbackSwitch image tagManual file replace + service restart
Default ports443 / 347858443(HTTPS) / 53478(STUN)
DatabaseMySQL + Redis (containers)SQLite (local file, external Redis optional)
Best forBeginners, "one-click" experience seekersOps veterans, internal production environments

Method 3: Kubernetes Deployment (Production-Grade HA)

Use this for multi-replica HA, cross-node failover, and auto-scaling (HPA). The project ships a complete Server/k8s/ Kustomize-managed YAML manifest set including API / DERP / Redis / Ingress / HPA / NetworkPolicy:

  1. Prerequisites
    • Kubernetes 1.24+ cluster (any distribution: EKS / AKS / GKE / self-hosted)
    • kubectl + kustomize installed
    • A StorageClass configured (for Redis persistence)
    • Nginx Ingress Controller (or equivalent) deployed
  2. Build and push images
    # Build and push
    docker build -t registry.example.com/virtuamesh/api:1.0.0 -f src/VirtuaMesh.Api/Dockerfile .
    docker build -t registry.example.com/virtuamesh/derp:1.0.0 -f src/VirtuaMesh.DerpServer/Dockerfile .
    docker push registry.example.com/virtuamesh/api:1.0.0
    docker push registry.example.com/virtuamesh/derp:1.0.0
  3. Configure secrets and domain
    # 1) Edit secret.yaml to fill in VIRTUAMESH_JWT_KEY etc.
    #    (recommend sealed-secrets or external-secrets for production)
    vim k8s/secret.yaml
    
    # 2) Edit ingress.yaml and change the host to your domain
    vim k8s/ingress.yaml
    
    # 3) If you need a different image tag, edit kustomization.yaml
    sed -i 's|latest|1.0.0|g' k8s/kustomization.yaml
  4. One-shot deploy
    kubectl apply -k k8s/
    
    # Verify
    kubectl -n virtuamesh get pods
    kubectl -n virtuamesh get svc
    kubectl -n virtuamesh get ingress
  5. Check auto-scaling status
    kubectl -n virtuamesh get hpa
    # NAME              REFERENCE                 TARGETS   MINPODS  MAXPODS  REPLICAS
    # virtuamesh-api    Deployment/virtuamesh-api  45%/70%   2        10       3
Key K8s deployment details
  • Zero-downtime rolling updates: maxUnavailable: 0 + maxSurge: 1 with readinessProbe for smooth releases
  • NetworkPolicy: by default only allows Ingress Controller → API and API → Redis traffic; all other cross-pod traffic is DROP (open up as needed)
  • HPA strategy: CPU threshold 70%, min 2 / max 10 replicas — load-test before tuning in production
  • Multi control plane: for cross-cluster DR, set MULTI_REGISTRY_ENABLED=true so this cluster's DERP registers with both primary and backup control planes

Method 4: Windows MSI Installer (GUI Deploy)

Use this for Windows Server users who want a zero-config install (includes EULA + VC++ runtime + automatic Windows service registration). The project uses the WiX 3.14 toolchain:

  1. Download the MSI

    From GitHub Releases or https://control.virtuamesh.com/download/, download virtuamesh-server-windows-x64.msi (self-contained .NET 10 runtime, ~80MB).

  2. Double-click to install

    Fill in the wizard:

    • Install path (default C:\Program Files\VirtuaMesh\Server)
    • Data directory (default C:\ProgramData\VirtuaMesh)
    • HTTPS certificate (.pfx path + password)
    • Listen port (default 58443)
  3. Service auto-starts

    The MSI automatically registers a Windows service named VirtuaMesh.Api and configures restart-on-failure after 3 attempts (via sc failure).

    # Verify service status
    sc query VirtuaMesh.Api
    # View logs
    Get-EventLog -LogName Application -Source VirtuaMesh.Api -Newest 50

DERP Relay Configuration

DERP (Detoured Encrypted Relay Protocol) is VirtuaMesh's relay server protocol. When two nodes can't establish a P2P direct connection (e.g. both are behind symmetric NAT), the DERP server relays encrypted traffic to keep the connection available.

Deployment tips
We recommend deploying DERP servers in different geographic regions to reduce latency. Each region's DERP server should also provide STUN service (UDP 3478) to assist with NAT traversal.

Port reference

PortProtocolUse
443TCPDERP relay server (HTTPS)
3478UDPSTUN server (NAT traversal probe)

Configuration Example

{
  "DerpServer": {
    "Enabled": true,
    "Port": 443,
    "StunPort": 3478,
    "Hostname": "derp.your-region.com",
    "UseHttps": true,
    "MaxConnections": 1000,
    "Region": "ap-east"
  }
}

Standalone DERP Relay Deployment (Cross-Region Latency)

DERP relay is a stateless service (no database / JWT / STUN config needed) and can be deployed independently in different geographic regions, registering with the primary control plane via MultiRegistry. The project ships a virtuamesh-derp.service systemd unit + virtuamesh-derp-deploy.sh deploy script:

  1. Build and package
    dotnet publish src/VirtuaMesh.DerpServer -c Release \
      -r linux-x64 --self-contained true \
      -o ./publish/derp-linux-x64
    cd ./publish/derp-linux-x64
    zip -r /tmp/VirtuaMesh-DerpServer-Linux.zip .
  2. Upload to the target region's server
    scp /tmp/VirtuaMesh-DerpServer-Linux.zip user@derp-ap-east:/tmp/
    scp scripts/virtuamesh-derp.service user@derp-ap-east:/tmp/
    scp scripts/derp-appsettings.Production.json user@derp-ap-east:/tmp/
  3. Deploy on the target server
    mkdir -p /data/virtuamesh/derp
    cd /data/virtuamesh/derp
    unzip /tmp/VirtuaMesh-DerpServer-Linux.zip
    cp /tmp/derp-appsettings.Production.json ./appsettings.Production.json
    # Edit ControlPlaneUrl to point to your primary control plane
    vim appsettings.Production.json
    chmod +x VirtuaMesh.DerpServer
    
    sudo cp /tmp/virtuamesh-derp.service /etc/systemd/system/
    sudo systemctl daemon-reload
    sudo systemctl enable --now virtuamesh-derp
    sudo systemctl status virtuamesh-derp
  4. Verify registration

    Once deployed, DERP auto-registers with the primary control plane via POST /api/derp-servers. You should see the new node in Admin Console → DERP Relays, status Healthy.

Co-located DERP vs main API on the same host

If DERP and the main API are on the same machine and share the certificate directory, add After=virtuamesh-api.service to the DERP systemd unit to avoid a race condition where DERP starts before the main API and can't find the cert. For production, prefer separate deployments (different machines / AZs) for cleaner failure-domain isolation.

Client Usage

Commands must run in strict order: init → register → up

These three commands have a strict serial dependency and must run in this exact order. Skipping or reordering any of them will fail:

  1. init — generate the local config file and WireGuard key pair (must run first; running register without init fails because the config file doesn't exist)
  2. register — register the node with the control plane using the invite code, receive a virtual IP and tunnel config (must run after init)
  3. up — bring up the WireGuard interface and establish the connection (must run after register, otherwise you'll see "Control plane server URL not configured" or "Virtual IP not found")

Common error scenarios:

$ virtuamesh register --server https://control.virtuamesh.com --network-code ABC123
Error: Configuration file does not exist. Please run `virtuamesh init` first.

$ virtuamesh up
Error: Control plane server URL not configured. Please run the register command first.

Re-initialization: use init --force to wipe old config; use register --force to force re-registration (e.g. when rotating keys).

Install the client

PlatformInstall command
Windowsiwr -useb https://control.virtuamesh.com/install/windows.ps1 | iex
macOScurl -fsSL https://control.virtuamesh.com/install/macos.sh | sh
Linuxcurl -fsSL https://control.virtuamesh.com/install/linux.sh | sh

Basic Usage Flow

  1. Initialize config

    Generate the default config file and WireGuard key pair.

    virtuamesh init
  2. Register with the control plane

    Register the node using the token provided by the admin.

    virtuamesh register --server https://your-server.com --network-code <CODE>
  3. Start the network connection

    Establish the WireGuard encrypted tunnel and connect to the virtual network.

    virtuamesh up
  4. View connection status

    Show current node info and the peer list.

    virtuamesh status
    virtuamesh peers
Background service mode
Use virtuamesh service install to install a system service for auto-start on boot, virtuamesh service start to start the background service, and virtuamesh service stop to stop the background service.

MagicDNS

MagicDNS is VirtuaMesh's built-in DNS service that automatically assigns readable domain names to every device in the virtual network, letting you access any node without memorizing IP addresses. It builds on the core design of Tailscale MagicDNS and adds capabilities like automatic domain registration, custom records (A/AAAA/CNAME/TXT), and reverse resolution.

How it works

When a node joins a VirtuaMesh network, the control plane automatically registers a DNS record mapping the node's hostname to its virtual IP address. The client configures a local DNS search domain so devices within the virtual network can reach each other directly using short hostnames.

# Full domain format
my-server.virtuamesh.com    → 100.64.0.3

# Short-name access (within the same network)
my-server                   → 100.64.0.3

# Multi-level subdomain
api.production.virtuamesh.com → 100.64.1.10
DNS caching
MagicDNS caches DNS records locally on the client with a default TTL of 600 seconds. When a node goes offline or its IP changes, the control plane pushes an update notification and the client automatically refreshes the cache, ensuring DNS resolution stays accurate.

Enable & Configure

MagicDNS is enabled by default. You can control its behavior in the client config file:

network:
  magic_dns:
    enabled: true
    suffix: "virtuamesh.com"
ParameterDefaultDescription
enabledtrueWhether MagicDNS is enabled
suffixvirtuamesh.comDNS suffix; every node's domain ends with this

Custom DNS records

Besides auto-registered node records, you can add custom DNS records to map dedicated domains for internal services. Supports A, AAAA, CNAME, and TXT record types.

# Register a hostname for a node via CLI (node must have joined the network first)
virtuamesh dns register --hostname "grafana" --network-id <guid> --node-id <guid>

# View all DNS records for a given network
virtuamesh dns list --network-id <guid>

# Unregister a node's hostname
virtuamesh dns unregister --network-id <guid> --node-id <guid>
Record typeDescriptionExample
AIPv4 address mappinggrafana.internal → 100.64.0.5
AAAAIPv6 address mappinggateway.internal → fd7a:115c:a1e0::1
CNAMEDomain aliasdocs.internal → web-server.virtuamesh.com
TXTText record_service.internal → "version=2.1.0"

DNS diagnostic commands

VirtuaMesh provides a set of DNS diagnostic commands to help troubleshoot DNS resolution issues:

# Resolve a given domain
virtuamesh dns resolve my-server

# View DNS stats
virtuamesh dns stats

# Clear the local DNS cache
virtuamesh dns cache clear

Common use cases

Scenario 1: Microservice internal communication

In a microservice architecture, services reach each other via MagicDNS domains — no need to hardcode IP addresses. When services migrate or scale, DNS records update automatically; no config changes required.

# Service-to-service calls
curl http://api-gateway:8080/v1/users
curl http://redis-cache:6379
curl http://kafka-broker:9092

Scenario 2: Internal service domain mapping

For internal services like Grafana, Redis, and Kafka, use virtuamesh dns register to register hostnames for nodes and map stable internal domains, avoiding hardcoded IPs.

# Register hostnames for a node (requires the owning network ID and node ID)
virtuamesh dns register --hostname "grafana" --network-id <guid> --node-id <guid>
virtuamesh dns register --hostname "docs" --network-id <guid> --node-id <guid>

Troubleshooting

DNS resolution failure

# View DNS stats
virtuamesh dns stats

# Clear the DNS cache
virtuamesh dns cache clear

# View the detailed resolution process
virtuamesh dns resolve --verbose my-server

Short name cannot be resolved

If a short name (e.g. my-server) cannot be resolved, check:

  • Whether MagicDNS is enabled: virtuamesh dns stats to view stats
  • Whether the DNS search domain is configured correctly
  • Whether the target node is online and has a registered DNS record

Split DNS not taking effect

Confirm that the domain suffix in the Split DNS config matches the domain actually being queried. Use virtuamesh dns check-availability --hostname <name> to check whether a hostname is available for registration.

🌐 Exit Node

Exit Node lets all internet traffic from a device in the network be forwarded out through another designated node. It's like wrapping the device in a "secure proxy" — all outbound access originates from the exit node's network.

Typical uses: Safe browsing over the corporate network while traveling / cross-border access to domestic systems / bypassing public Wi-Fi snooping / unifying egress IPs to meet compliance audit requirements.

How it works

After you enable an exit node on the client, the device's all non-LAN traffic is sent through the WireGuard tunnel to the exit node, which accesses the internet on your behalf and returns the result along the same path. The whole path is end-to-end encrypted; intermediate nodes (including DERP relays) cannot decrypt the traffic.

Before you begin
  • The exit node needs a stable internet connection and sufficient bandwidth
  • Enabling an exit node adds latency (one extra forwarding hop); pick a node with good network quality
  • All outbound traffic rules of the exit node's network apply to you (e.g. firewalls, content filtering)
  • Exit Node functionality is limited in kernel mode; userspace WireGuard mode is recommended

How to configure an Exit Node

  • Choose a device to act as the exit node

    This device will handle forwarding traffic. Pick a device with a stable network and ample bandwidth (e.g. an office desktop, a cloud server, a NAS).

  • Enable the exit node feature on that device

    Turn on "Allow as exit node" in the client settings, or use the command:

    virtuamesh exit-node enable
  • On devices that need to use the exit, specify the exit node

    Select the exit node to use in the client settings, or use the command:

    virtuamesh exit-node use <node-id>
  • Verify it works

    Visit https://ifconfig.me or a similar site and confirm the displayed IP is the exit node's IP, not your local network's IP.

  • Common commands

    virtuamesh exit-node enable     # Enable exit node (allow this machine to act as exit)
    virtuamesh exit-node disable    # Disable exit node
    virtuamesh exit-node status     # Show exit node status
    
    virtuamesh exit-node use server-01   # Use the specified exit node
    virtuamesh exit-node off             # Don't use an exit node (direct)

    Use cases

    🏢 Scenario 1: Secure remote work while traveling
    1
    Enable the exit node on a computer in the corporate office
    2
    Traveling employees connect to VirtuaMesh on hotel public Wi-Fi and specify the corporate exit node
    3
    All browsing traffic goes out through the corporate exit, avoiding public Wi-Fi snooping and data leaks
    🌏 Scenario 2: Cross-border access to domestic systems
    1
    Deploy the VirtuaMesh client on a domestic cloud server and enable the exit node
    2
    Overseas employees specify that node as exit to access domestic-restricted business systems
    3
    Access speed and stability are far better than ordinary proxies, and the path is fully encrypted

    Differs from a regular proxy (VPN)

    ComparisonLegacy VPN proxyVirtuaMesh Exit Node
    DeploymentNeed to buy/rent a VPN serviceUse your own device as exit, zero cost
    Data sovereigntyTraffic passes through a third-party providerForwarded entirely between nodes you control
    Simultaneous networkingCan only browse, no internal meshBoth egress browsing and internal device access
    Encryption strengthDepends on the providerWireGuard end-to-end encryption, self-controlled
    Switching exitNeed to disconnect and reconnectReal-time switch, internal connections not interrupted

    WireGuard Mode

    VirtuaMesh supports two WireGuard implementation modes, selectable based on platform and performance needs.

    ModeConfig valueDescription
    Userspace userspace WireGuard.NET cross-platform userspace implementation (default); no extra dependencies, best compatibility
    Kernel kernel Linux kernel module mode (Linux only); requires wireguard-tools, better performance
    Auto fallback
    When kernel mode is selected but the system doesn't support it, VirtuaMesh automatically falls back to userspace mode to keep the service running.
    Kernel mode limitations
    ExitNode functionality is limited when running in kernel mode. Userspace packet injection/interception is unavailable; the kernel will handle packet forwarding natively.

    Configuration example

    network:
      interface_name: "virtuamesh0"
      virtual_ip: ""
      mtu: 1280
      wireguard_mode: "userspace"  # "userspace" or "kernel"

    Install kernel mode dependencies

    # Ubuntu/Debian
    sudo apt-get install wireguard-tools
    
    # CentOS/RHEL
    sudo yum install wireguard-tools

    CLI Command Reference

    Node management

    CommandDescriptionExample
    initInitialize local configvirtuamesh init
    registerRegister with the control planevirtuamesh register --server <url> --network-code <CODE>

    Network connection

    CommandDescriptionExample
    upStart and connect to the networkvirtuamesh up
    downDisconnect and stopvirtuamesh down
    service installInstall as a system service (auto-start on boot)virtuamesh service install
    service startStart the background servicevirtuamesh service start
    service stopStop the background servicevirtuamesh service stop
    service restartRestart the background servicevirtuamesh service restart

    Status queries

    CommandDescriptionExample
    statusShow connection statusvirtuamesh status
    peersShow the peer listvirtuamesh peers
    nodesList network nodesvirtuamesh nodes
    topReal-time network monitorvirtuamesh top
    trafficView traffic statsvirtuamesh traffic

    Network diagnostics

    CommandDescriptionExample
    test-connectionTest connectivity to a peervirtuamesh test-connection --target-ip <ip>
    test-connection --allTest all peersvirtuamesh test-connection --all
    logsView logsvirtuamesh logs follow

    Utility commands

    CommandDescriptionExample
    versionShow versionvirtuamesh version
    gen-keyGenerate a WireGuard private keyvirtuamesh gen-key
    pub-keyDerive a public key from a private keyvirtuamesh pub-key --private-key <key>
    completionGenerate a shell completion scriptvirtuamesh completion
    interactiveStart an interactive shellvirtuamesh interactive

    DNS commands

    CommandDescriptionExample
    dns resolveResolve a domainvirtuamesh dns resolve my-server
    dns statsView DNS statsvirtuamesh dns stats
    dns cache clearClear the DNS cachevirtuamesh dns cache clear
    dns cache statusView DNS cache statusvirtuamesh dns cache status
    dns registerRegister a hostname for a nodevirtuamesh dns register --hostname "app" --network-id <guid> --node-id <guid>
    dns unregisterUnregister a node hostnamevirtuamesh dns unregister --network-id <guid> --node-id <guid>
    dns listList a network's DNS recordsvirtuamesh dns list --network-id <guid>
    dns check-availabilityCheck if a hostname is available for registrationvirtuamesh dns check-availability --hostname "app"
    dns searchSearch DNS recordsvirtuamesh dns search <query>
    dns reverseReverse resolutionvirtuamesh dns reverse <ip>

    Ports & Protocols

    Server ports

    PortProtocolServiceDescription
    80TCPHTTPAPI reverse proxy (redirects to HTTPS)
    443TCPHTTPSAPI + gRPC + DERP + Web admin UI
    3478UDPSTUNNAT traversal probe
    3306TCPMySQLDatabase (internal access only)
    6379TCPRedisCache (internal access only)

    Client ports

    PortProtocolDescription
    51820UDPWireGuard default listen port
    Firewall configuration
    Make sure the server's 443/TCP and 3478/UDP ports are open in the firewall. The client's 51820/UDP port does not need to be opened in the firewall — VirtuaMesh handles NAT traversal automatically.

    Configuration Reference

    The client config file uses YAML format; default path is ~/.virtuamesh/config.yaml.

    version: "1.0"
    
    node:
      id: ""
      hostname: ""
    
    control:
      server_url: "https://control.virtuamesh.com"
      node_token: ""
    
    network:
      interface_name: "virtuamesh0"
      virtual_ip: ""
      mtu: 1420
      wireguard_mode: "userspace"
      magic_dns:
        enabled: true
        suffix: "virtuamesh.com"
    
      exit_node:
        enabled: false
      subnet_router:
        enabled: false
    
    derp:
      servers: []
    
    nat_traversal:
      stun_servers:
        - "stun.l.google.com:19302"
        - "stun.cloudflare.com:3478"
      turn_servers: []
    
    logging:
      level: info
      retained_days: 30
      max_file_size_mb: 10
      max_file_count: 7
      console_output: true

    ✅ Pre-deployment Checklist

    Before you start deploying, go through each item below. Checking them off one by one helps you avoid 90% of common pitfalls.

    🖥️ Server environment

    🔐 Accounts & keys

    🌐 Network connectivity

    💡 Choose a deployment mode

    Different scenarios call for different deployment styles — pick the one that fits:

    Your situationRecommended deploymentNotes
    Personal / home use, < 10 devices Single-host Docker Compose A 2-core 4GB cloud VPS is enough; costs around $5-8/month
    Small team / studio, 10-50 devices Single server + multi-region DERP Primary control + 1-2 DERP relays (Hong Kong / Tokyo recommended)
    Company / 50+ devices Kubernetes cluster deployment Stateless control plane scales horizontally; DERP multi-region
    Compliance required (data stays in-country) Private deployment + private DERP Full stack deployed on-prem; only essential outbound ports opened
    What if I don't have a public IP?
    Three options: ① Use a cloud VPS (simplest); ② Use IPv6 (home broadband usually provides public IPv6 by default); ③ Use an intranet-penetration tool like FRP / Tailscale Funnel to reverse-proxy port 443 from a home computer.

    ⚖️ Comparison with Similar Products

    Choosing is hard — here's a horizontal comparison of mainstream networking solutions to help you decide in 5 minutes.

    FeatureVirtuaMeshTailscaleZeroTierNebulaWireGuard native
    Self-hosted control plane✅ Yes (data sovereignty)❌ Uses official cloud⚠️ Self-hostable (planet/moon)✅ Yes (lighthouse)✅ DIY
    End-to-end encryption✅ WireGuard✅ WireGuard✅ Self-developed protocol✅ Self-developed protocol✅ WireGuard
    NAT traversal✅ Automatic✅ Automatic✅ Automatic✅ Automatic❌ Manual port forwarding
    Relay fallback✅ DERP multi-region✅ DERP✅ Planet✅ Lighthouse❌ None
    MagicDNS (auto domains)✅ Auto-registration + custom records✅ Included❌ None❌ None❌ Self-configured
    ACL access control✅ Tags + ports + time✅ ACL rules⚠️ Basic rules⚠️ Basic❌ None
    Web admin console✅ Full UI✅ Full UI⚠️ Third-party❌ None❌ None
    REST API✅ Complete✅ Complete⚠️ Partial❌ None❌ None
    Open-source licenseApache 2.0Partially openGPL v2MITGPL v2
    Free for commercial use✅ Completely free⚠️ Free for personal, paid for enterprise✅ Free✅ Free✅ Free
    Learning curve⭐⭐ Low (5-min onboarding)⭐⭐ Low⭐⭐⭐ Medium⭐⭐⭐⭐ High⭐⭐⭐⭐⭐ Very high
    ✅ Choose VirtuaMesh if
    • You want data sovereignty — no third-party cloud in the path
    • You need a full toolchain: web UI, ACL, API
    • Your team has hybrid cloud / IoT onboarding needs
    • You want to avoid Tailscale Business device-count limits
    ❌ Pick something else if
    • Pure personal, < 3 devices, can't be bothered to operate: pick Tailscale
    • Only need to bridge two LANs: pick ZeroTier / Nebula
    • Chasing extreme performance / embedded: use WireGuard directly
    • Already have an OpenVPN stack: stick with OpenVPN for now

    🩺 Troubleshooting Flowchart

    Don't panic when something goes wrong — follow the flow below step by step. 99% of issues are resolved in the first 3 steps.

    One-click diagnostics

    Run this command first — it automatically tests connectivity to all peers:

    virtuamesh test-connection --all

    The output shows latency and packet loss to each node, helping you quickly locate the problematic node.

    Decision flowchart

    Start troubleshooting virtuamesh up Does it start? No Check token / config Permissions, network, invite code Yes status Shows online? No Check server + firewall Open ports 443/3478 Yes ping <peer> Works? No Check ACL / MagicDNS Port blocked by ACL? Yes Network is up! Troubleshoot app layer

    Common symptom quick reference

    Symptom90% causeFix
    up shows offline Server port 443 blocked by firewall Open in both cloud provider security group and server ufw
    Status online but ping fails ACL rule not allowing virtuamesh acl list to view rules
    Short name my-nas won't resolve MagicDNS not enabled or cache expired virtuamesh dns cache clear to refresh cache
    P2P keeps falling back to DERP Both sides behind symmetric NAT Deploy a closer DERP or use IPv6
    Speed far below expected MTU too small or multiple relays Adjust MTU to 1420; enable kernel mode
    Client keeps reconnecting Server time out of sync sudo ntpdate time.google.com
    Works on phone, not on PC PC firewall / antivirus Temporarily disable and retry; allow 51820/UDP
    Windows says insufficient permissions Not running as administrator Right-click → Run as administrator

    Viewing logs

    # Client live logs
    virtuamesh logs follow
    
    # Client debug logs (more detail)
    virtuamesh logs show --level debug
    
    # Server logs (Docker deployment)
    docker logs -f virtuamesh-api
    docker logs -f virtuamesh-derp
    
    # Server logs (systemd deployment)
    journalctl -u virtuamesh-api.service -f
    
    # Filter client logs by keyword
    virtuamesh logs show --level error
    Still not resolved?
    Attach the full output of virtuamesh status --verbose and virtuamesh test-connection --all and email it to support@virtuamesh.com — the author usually replies within 24 hours.

    FAQ

    How do I view node connection status?

    virtuamesh status

    This command shows the current node's virtual IP, connection status, number of online peers, and more.

    What if P2P connection fails?

    VirtuaMesh automatically falls back to a DERP relay server to keep the connection available. If latency is high, consider deploying a DERP server in a closer region. Use virtuamesh test-connection --all to test connectivity to all peers.

    How do I view logs?

    # Server logs (Docker deployment)
    docker-compose -f docker-compose.prod.yml logs -f api
    
    # Server logs (systemd deployment)
    journalctl -u virtuamesh-api.service -f
    
    # Server log files
    tail -f /data/virtuamesh/server/logs/virtuamesh-*.log
    
    # Client logs
    virtuamesh logs follow
    virtuamesh logs show --level error

    How do I update the client?

    The client has a built-in auto-update feature that checks the server's /api/v1/updates/latest endpoint on startup and downloads the new version automatically. You can also trigger an update for a specific node from the admin console → Node Management.

    What dependencies does Linux kernel mode need?

    The kernel WireGuard mode requires wireguard-tools:

    # Ubuntu/Debian
    sudo apt-get install wireguard-tools
    
    # CentOS/RHEL
    sudo yum install wireguard-tools

    How do I configure an Exit Node?

    Enable exit_node.enabled: true in the client config, then designate that node as an exit node. All traffic from other nodes will be routed through it. Note: Exit Node functionality is limited in kernel mode.

    How do I configure a Subnet Router?

    Enable subnet_router.enabled: true in the client config to expose the local subnet to the VirtuaMesh network so other nodes can reach devices in the local subnet.

    What if MagicDNS short names can't be resolved?

    First use virtuamesh dns stats to view DNS stats, then use virtuamesh dns resolve --verbose <name> to see the detailed resolution process. Common causes: MagicDNS not enabled, target node offline, or DNS cache expired (use virtuamesh dns cache clear to clear the cache).

    How do I configure a custom domain for an internal service?

    Use the virtuamesh dns register command to register a hostname for a node. For example: virtuamesh dns register --hostname "grafana" --network-id <guid> --node-id <guid>. After registration you can access the node via grafana.virtuamesh.com.

    🎉 What to do next after deployment?

    Reaching this section means your network is up and running. Below is a follow-up roadmap for both beginners and developers, ordered from shallow to deep — each step tells you what specific problem it solves.

    You've finished the hardest part. What follows isn't mandatory — pick the steps you need based on what you're doing with VirtuaMesh.

    Click any path title below to expand its content. The open/closed state is remembered automatically and persists across visits.

    1

    Pure home user

    Just want to use it, no fuss

    🏠
    1. Give each device a memorable name: In Admin Console → Node List → Edit Device, rename "my-macbook-pro" to "My Laptop" or "Pixel-7" to "Wife's Phone." Then ping My-Laptop finds it.
    2. Enable MagicDNS: In Admin Console → Network Settings, enable MagicDNS so clients can access devices by name instead of IP.
    3. Expose the NAS to all devices: On the NAS, configure the VirtuaMesh client as a "subnet router" (see Remote NAS walkthrough); all home devices can then reach the NAS across networks.
    4. Bind a fixed domain (optional): At your domain registrar, point an A record at your server's public IP so you can access home services from outside via the domain.
    5. Check the admin console regularly: The dashboard shows online devices, recent traffic, and alerts. If you see an unfamiliar login or stranger node, disable it and change the password immediately.
    2

    SMB / team

    Need stability and security

    🏢
    1. Configure ACL access control: By default, devices in the same network can reach each other; use acls/rules to enforce "finance PCs can only reach finance systems" or "frontend servers can't connect to databases." See Security Best Practices.
    2. Deploy DERP relays: Deploy 1-2 more DERP nodes on your intranet / same region (see DERP Configuration); avoid routing cross-region access through foreign public relays and cut latency by over 50%.
    3. Review audit logs: Audit logs are enabled by default; all user logins, node joins, and ACL changes are recorded automatically. View them in Admin Console → Audit Logs for compliance.
    4. Set up automatic backups: Back up the entire /data/virtuamesh/server/ directory (including the SQLite database and config) to object storage (S3 / OSS / COS) daily. Disaster recovery time drops from 24 hours to 1 hour.
    5. Integrate SSO (optional): The server supports OIDC integration with WeCom, Lark, Azure AD, and Okta — employees sign in with one click using their corporate account, and permissions are auto-revoked on departure.
    3

    Developer / ops

    Need automation and integration

    ⚙️
    1. Use the API instead of the web console: All admin operations (create nodes, revoke devices, edit ACLs) have a RESTful API; managing them with scripts/programs is far faster than clicking through the console 1000 times.
    2. Write a client install script: Wrap virtuamesh register --network-code xxx && virtuamesh up in an Ansible/Shell script so new machines auto-join the network within 5 minutes of boot. Example:
      #!/bin/bash
      curl -fsSL https://control.virtuamesh.com/install/linux.sh | sh
      virtuamesh register --server https://control.virtuamesh.com --network-code $1
      virtuamesh up --accept-routes
    3. Bring CI/CD build machines into the network: Install the VirtuaMesh client on GitHub Actions runners / Jenkins agents so pipelines can reach internal test servers for deployment. Pair with virtuamesh exit-node use to route pipeline traffic through the corporate exit.
    4. Monitor with Prometheus: The server exposes a /metrics endpoint (see the API section); feed node online rate, traffic peaks, and handshake failures into Grafana. Set alert thresholds so you get notified within 1 minute of a service issue.
    5. Use MagicDNS + Service Discovery: Have all microservices use service-name.namespace MagicDNS domains — no need to maintain hosts files, and scaling in/out requires no config changes when IPs change.
    6. Enable WireGuard kernel mode: On Linux servers set wireguard.mode: kernel to boost throughput from 500 Mbps to 5 Gbps and cut CPU usage by 80% (see Performance Tuning).

    🛠 Routine maintenance checklist (recommended monthly)

    🌍 Want more?

    📖 Full API docs
    All endpoints, parameters, sample code, and error codes are in the API Reference section.
    🏗 Architecture
    Want to understand NAT traversal, key exchange, and DERP relay internals? See the flowchart in the walkthrough section.
    🚀 Performance tuning
    MTU, buffers, connection pools, kernel mode... every switch that makes the network faster is in Performance Tuning.
    🩺 Trouble
    99% of common issues are answered in Troubleshooting and FAQ.
    💬
    Didn't find an answer? Feel free to ask in GitHub Issues (attach the virtuamesh status --json output and the steps you took); the community and official team will help you look into it.