Move 150+ scripts from root and scripts/ into client/project directories: - clients/dataforth/scripts/ (110 files: AD2, sync, SSH, DB, DOS scripts) - clients/bg-builders/scripts/ (14 files: Lesley mgmt, Exchange, termination) - clients/internal-infrastructure/scripts/ (10 files: GDAP, Gitea, backups) - projects/msp-tools/scripts/ (9 files: CIPP, MSP onboarding, Datto) - projects/gururmm-agent/scripts/ (3 files: API test, JWT, record counts) - clients/glaztech/scripts/ (1 file: CentraStage removal) Also reorganized: - VPN scripts → infrastructure/vpn-configs/ - Retrieved API/JS files → api/ - Forum posts → projects/community-forum/forum-posts/ - SSH docs → clients/internal-infrastructure/docs/ - NWTOC/CTONW docs → projects/wrightstown-smarthome/docs/ - ACG website files → projects/internal/acg-website-2025/ - Dataforth docs → clients/dataforth/docs/ - schema-retrieved.sql → docs/database/ Deleted 24 tmp_*.ps1 one-off debug scripts (preserved in git history). Root reduced from 220+ files to 62 items (docs + directories only). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.5 KiB
Fix: Remote VLAN Not Reachable via Tailscale - Missing Subnet Route
Environment
- Tailscale: 1.94.2
- Remote site: Dataforth (192.168.0.0/24 main LAN, 192.168.100.0/24 VLAN100 for phones)
- Tailscale exit nodes advertising routes: pfSense-2 (172.16.0.0/22), D2TESTNAS (192.168.0.0/24)
- Target: FreePBX PBX at 192.168.100.2 on VLAN100
Problem
A FreePBX phone system at 192.168.100.2 (VLAN100) was unreachable via Tailscale from a remote workstation, even though other devices on the same site's main LAN (192.168.0.0/24) were reachable.
ping 192.168.0.6 # Works - on main LAN, routed via D2TESTNAS
ping 192.168.100.2 # Fails - 100% packet loss
Diagnosis
Check what subnet routes Tailscale peers are advertising:
tailscale status --json | python3 -c "
import json,sys
d=json.load(sys.stdin)
for k,v in d.get('Peer',{}).items():
routes = v.get('PrimaryRoutes', [])
if routes:
print(f\"{v['HostName']}: {routes}\")
"
Output:
pfSense-2: ['172.16.0.0/22']
D2TESTNAS: ['192.168.0.0/24']
192.168.100.0/24 (VLAN100) is not being advertised by any Tailscale node. The PBX is on a separate VLAN that no Tailscale peer is routing.
Also verify the local machine is accepting routes:
# Check if --accept-routes is enabled
tailscale status
# Look for health warning: "Some peers are advertising routes but --accept-routes is false"
# If present, enable it:
sudo tailscale set --accept-routes
Check local routing table:
ip route | grep 192.168.100
# Empty - no route exists
Fix
The VLAN subnet needs to be advertised by a Tailscale node that has a leg on that network. Two options:
Option A: Add Route to Existing Tailscale Node (Recommended)
On the pfSense or gateway that bridges VLAN100, update the Tailscale advertised routes to include the phone VLAN:
# On pfSense-2 (or whichever node routes VLAN100):
tailscale set --advertise-routes=172.16.0.0/22,192.168.100.0/24
Then approve the new route in the Tailscale admin console (if using ACLs) or it auto-approves if --advertise-routes auto-approval is enabled.
Option B: Add Route to D2TESTNAS (if it has VLAN access)
If the NAS has a trunk port or tagged VLAN interface for VLAN100:
# On D2TESTNAS:
tailscale set --advertise-routes=192.168.0.0/24,192.168.100.0/24
Option C: Connect Directly to Site WiFi (Workaround)
If you're physically at the site, connect to the local WiFi network that has routing to VLAN100. This bypasses the need for Tailscale routing entirely.
# After connecting to Dataforth WiFi:
ping 192.168.100.2
# Works - local routing handles the VLAN
Verification
After adding the route:
# Check the route appears
tailscale status --json | python3 -c "
import json,sys
d=json.load(sys.stdin)
for k,v in d.get('Peer',{}).items():
routes = v.get('PrimaryRoutes', [])
if routes:
print(f\"{v['HostName']}: {routes}\")
"
# Should now show: pfSense-2: ['172.16.0.0/22', '192.168.100.0/24']
# Test connectivity
ping 192.168.100.2
# Should respond
Why This Happens
Tailscale subnet routing is explicit — each subnet that should be reachable via the mesh must be advertised by a node on that network. VLANs are separate broadcast domains, so even though 192.168.0.0/24 and 192.168.100.0/24 are at the same physical site, they require separate route advertisements.
This is easy to miss when a site has multiple VLANs — the main LAN works fine via Tailscale, but phone VLANs, management VLANs, IoT VLANs, etc. are silently unreachable until explicitly advertised.