- Documents recent infrastructure cleanup (8 CTs destroyed, 35 DNS records removed, Headscale cleanup) - Adds 24 new runbooks covering Authentik, PeerTube, Meshtastic, RECON, Proxmox, Mailcow, Internet Archive, GPU routing - Adds project documentation for headscale, vaultwarden, peertube, matrix, mmud, advbbs, arr stack - Updates services.md, environment.md, caddy.md, authentik.md to match live infrastructure - Removes 4 deprecated runbook duplicates (canonical versions live in projects/) - Adds .gitignore for binary archives and editor temp files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9.3 KiB
IdahoMesh Bridge Setup
Build a one-way bridge between your tailnet and the IdahoMesh Meshtastic network. This lets your devices reach Nebra gateways through IdahoMesh, while preventing IdahoMesh from reaching back into your network.
Architecture
Your Tailnet (your Headscale/Tailscale)
↓ (one-way only)
[Bridge Machine] ← dual tailscaled, NAT + firewall
↓
IdahoMesh Tailnet (100.100.0.0/16)
↕
Nebra CM3 Gateways (Meshtastic nodes)
Security model: Your devices can reach Nebras. Nothing on IdahoMesh can initiate connections back into your network. NAT masquerades your source IPs so IdahoMesh only sees the bridge's IP.
Prerequisites
| Item | Value |
|---|---|
| IdahoMesh Headscale URL | https://vpn.idahomesh.com |
| IdahoMesh prefix | 100.100.0.0/16 |
| Your preauthkey | Provided by IdahoMesh admin |
You also need:
- A Linux machine on your network (VM, Pi, bare metal — anything running systemd)
- Root access on that machine
- Internet access (to reach vpn.idahomesh.com)
- Your own tailnet's connection details (Headscale URL, or stock Tailscale if using tailscale.com)
Step 1: Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
This installs both tailscale and tailscaled. The default service (tailscaled.service) will handle your primary tailnet.
Step 2: Set Up Dual tailscaled
You need two Tailscale daemon instances — one for your tailnet, one for IdahoMesh. The default tailscaled service handles your tailnet. Create a second service for IdahoMesh.
Create directories
mkdir -p /var/lib/tailscale-meshtastic /var/run/tailscale-meshtastic
Create the second tailscaled service
Write /etc/systemd/system/tailscaled-meshtastic.service:
[Unit]
Description=Tailscale daemon (IdahoMesh tailnet)
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/sbin/tailscaled \
--state=/var/lib/tailscale-meshtastic/tailscaled.state \
--socket=/var/run/tailscale-meshtastic/tailscaled.sock \
--port=41642 \
--tun=tailscale1
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Critical: The
--tun=tailscale1flag is required. Both instances cannot use the defaulttailscale0TUN device — the second one will fail with "TUN device tailscale0 is busy" if you omit this.
Enable and start it:
systemctl daemon-reload
systemctl enable --now tailscaled-meshtastic
Step 3: Enable IP Forwarding
cat > /etc/sysctl.d/99-bridge.conf << 'EOF'
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF
sysctl -p /etc/sysctl.d/99-bridge.conf
Step 4: Join Both Tailnets
Join your tailnet (default tailscaled)
Advertise the IdahoMesh range so your other devices can route to Meshtastic nodes through this bridge:
# If you use your own Headscale:
tailscale up \
--login-server=https://YOUR_HEADSCALE_URL \
--advertise-routes=100.100.0.0/16 \
--accept-routes
# If you use stock Tailscale (tailscale.com):
tailscale up \
--advertise-routes=100.100.0.0/16 \
--accept-routes
After joining, you need to approve the advertised route on your tailnet's admin:
- Headscale:
headscale routes listthenheadscale routes enable -r <route-id> - Stock Tailscale: Go to admin console → Machines → your bridge → approve the
100.100.0.0/16subnet route
Join IdahoMesh (second tailscaled)
tailscale --socket=/var/run/tailscale-meshtastic/tailscaled.sock up \
--login-server=https://vpn.idahomesh.com \
--authkey=YOUR_IDAHOMESH_PREAUTHKEY \
--accept-routes
Important: Do NOT advertise your tailnet's routes on IdahoMesh. The bridge is one-way — IdahoMesh should have no route back into your network.
Step 5: Configure One-Way Firewall and NAT
This is the critical security step. Your tailnet can reach IdahoMesh, but nothing on IdahoMesh can reach back into your network.
Replace YOUR_TAILNET_PREFIX below with your tailnet's IP range. Common values:
| Tailnet type | Prefix |
|---|---|
| Stock Tailscale | 100.64.0.0/10 |
| Custom Headscale | Check your config.yaml → prefixes.v4 |
Apply iptables rules
# NAT: Masquerade your source IPs when going to IdahoMesh
# Nebras see the bridge's IdahoMesh IP, not your real tailnet IPs
iptables -t nat -A POSTROUTING -s YOUR_TAILNET_PREFIX -d 100.100.0.0/16 -j MASQUERADE
# Allow your tailnet → IdahoMesh (outbound)
iptables -A FORWARD -s YOUR_TAILNET_PREFIX -d 100.100.0.0/16 -j ACCEPT
# Allow established/related return traffic only (responses to connections you initiated)
iptables -A FORWARD -s 100.100.0.0/16 -d YOUR_TAILNET_PREFIX -m state --state ESTABLISHED,RELATED -j ACCEPT
# DROP all new connections from IdahoMesh → your tailnet
iptables -A FORWARD -s 100.100.0.0/16 -d YOUR_TAILNET_PREFIX -j DROP
Persist rules across reboots
Do not use iptables-persistent — it hangs on install even with noninteractive mode. Use manual persistence instead:
# Save current rules
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4
Create /etc/systemd/system/iptables-restore.service:
[Unit]
Description=Restore iptables rules
Before=network-pre.target
Wants=network-pre.target
[Service]
Type=oneshot
ExecStart=/sbin/iptables-restore /etc/iptables/rules.v4
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Enable it:
systemctl daemon-reload
systemctl enable iptables-restore
Verify rules
iptables -L FORWARD -v -n
iptables -t nat -L POSTROUTING -v -n
You should see:
- MASQUERADE rule on POSTROUTING
- ACCEPT for your prefix → 100.100.0.0/16
- ACCEPT ESTABLISHED,RELATED for 100.100.0.0/16 → your prefix
- DROP for 100.100.0.0/16 → your prefix
Step 6: Enable Routes on Your Other Devices
Any device on your tailnet that wants to reach IdahoMesh Nebras through the bridge needs to accept subnet routes:
# On each device that needs access
tailscale set --accept-routes
Without this, traffic to 100.100.0.x goes to the default gateway instead of through the Tailscale tunnel.
Step 7: Verify
Check both tailscaled instances
# Your tailnet
tailscale status
# IdahoMesh
tailscale --socket=/var/run/tailscale-meshtastic/tailscaled.sock status
Both should show "online" with peers listed.
Ping a Nebra gateway
# From the bridge itself, via IdahoMesh socket
tailscale --socket=/var/run/tailscale-meshtastic/tailscaled.sock ping burley-butte
Ping from another device on your tailnet
# From any device on your tailnet (with --accept-routes enabled)
# Use the Nebra's IdahoMesh IP
ping 100.100.0.3 # Burley Butte
Verify isolation
From an IdahoMesh device or ask the admin to test — pinging your tailnet IPs from IdahoMesh should time out / be unreachable.
Troubleshooting
Second tailscaled won't start
- Check
journalctl -u tailscaled-meshtastic -f - Most common: forgot
--tun=tailscale1— both instances fighting overtailscale0 - Verify the port isn't in conflict: default uses 41641, second uses 41642
Can't reach Nebras from other devices on your tailnet
- Verify the bridge advertises
100.100.0.0/16:tailscale statusshould show it as a subnet router - Approve the route on your tailnet admin (Headscale or Tailscale admin console)
- Enable
--accept-routeson the client device trying to reach Nebras
IdahoMesh preauthkey expired
- Contact the IdahoMesh admin for a new key
- Re-join:
tailscale --socket=/var/run/tailscale-meshtastic/tailscaled.sock up --login-server=https://vpn.idahomesh.com --authkey=NEW_KEY --accept-routes
After reboot, only one tailscaled reconnects
- Check both services:
systemctl status tailscaledandsystemctl status tailscaled-meshtastic - Verify iptables rules survived:
iptables -L FORWARD -v -n - If the second instance lost state, re-join IdahoMesh with a new preauthkey
Default tailscaled pointed at wrong server after force-reauth
- If you run
tailscale up --force-reauthwithout specifying--login-server, it may reconnect to the wrong Headscale - Always specify
--login-serverexplicitly when re-authing:- Default instance:
tailscale up --login-server=https://YOUR_HEADSCALE_URL --force-reauth - IdahoMesh instance:
tailscale --socket=/var/run/tailscale-meshtastic/tailscaled.sock up --login-server=https://vpn.idahomesh.com --force-reauth
- Default instance:
Quick Reference
| Item | Value |
|---|---|
| IdahoMesh URL | https://vpn.idahomesh.com |
| IdahoMesh prefix | 100.100.0.0/16 |
| IdahoMesh socket | /var/run/tailscale-meshtastic/tailscaled.sock |
| IdahoMesh TUN device | tailscale1 |
| IdahoMesh port | 41642 |
| Default Tailscale socket | /var/run/tailscale/tailscaled.sock |
| Default TUN device | tailscale0 |
| Default port | 41641 |
Useful commands
# IdahoMesh status
tailscale --socket=/var/run/tailscale-meshtastic/tailscaled.sock status
# IdahoMesh ping
tailscale --socket=/var/run/tailscale-meshtastic/tailscaled.sock ping <hostname>
# Check firewall rules
iptables -L FORWARD -v -n
iptables -t nat -L POSTROUTING -v -n
# Restart services
systemctl restart tailscaled # Your tailnet
systemctl restart tailscaled-meshtastic # IdahoMesh
Last updated: 2026-02-11