- Fixed 4 broken markdown links (bad relative paths in See Also sections) - Corrected n8n port binding to 127.0.0.1:5678 (matches actual deployment) - Updated SnapRAID article with actual majorhome paths (/majorRAID, disk1-3) - Converted 67 Obsidian wikilinks to relative markdown links or plain text - Added YAML frontmatter to 35 articles missing it entirely - Completed frontmatter on 8 articles with missing fields Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
146 lines
5.3 KiB
Markdown
146 lines
5.3 KiB
Markdown
---
|
|
title: "Tailscale for Homelab Remote Access"
|
|
domain: selfhosting
|
|
category: dns-networking
|
|
tags: [tailscale, vpn, remote-access, wireguard, homelab]
|
|
status: published
|
|
created: 2026-03-08
|
|
updated: 2026-03-08
|
|
---
|
|
|
|
# Tailscale for Homelab Remote Access
|
|
|
|
Tailscale is how I access my home services from anywhere. It creates a private encrypted mesh network between all your devices — no port forwarding, no dynamic DNS, no exposing anything to the internet. It just works, which is what you want from networking infrastructure.
|
|
|
|
## The Short Answer
|
|
|
|
Install Tailscale on every device you want connected. Sign in with the same account. Done — all devices can reach each other by hostname.
|
|
|
|
```bash
|
|
# Install on Linux
|
|
curl -fsSL https://tailscale.com/install.sh | sh
|
|
sudo tailscale up
|
|
|
|
# Check status
|
|
tailscale status
|
|
|
|
# See your devices and IPs
|
|
tailscale status --json | jq '.Peer[] | {Name: .HostName, IP: .TailscaleIPs[0]}'
|
|
```
|
|
|
|
## How It Works
|
|
|
|
Tailscale sits on top of WireGuard — the modern, fast, audited VPN protocol. Each device gets a `100.x.x.x` address on your tailnet (private network). Traffic between devices is encrypted WireGuard tunnels, peer-to-peer when possible, routed through Tailscale's DERP relay servers when direct connection isn't possible (restrictive NAT, cellular, etc.).
|
|
|
|
The key thing: your home server's services never need to be exposed to the public internet. They stay bound to `localhost` or your LAN IP, and Tailscale makes them accessible from your other devices over the tailnet.
|
|
|
|
## MagicDNS
|
|
|
|
Enable MagicDNS in the Tailscale admin console (login.tailscale.com → DNS → Enable MagicDNS). This assigns each device a stable hostname based on its machine name.
|
|
|
|
```
|
|
# Instead of remembering 100.64.x.x
|
|
http://homelab:3000
|
|
|
|
# Or the full MagicDNS name (works from anywhere on the tailnet)
|
|
http://homelab.tail-xxxxx.ts.net:3000
|
|
```
|
|
|
|
No manual DNS configuration on any device. When Tailscale is running, hostnames resolve automatically.
|
|
|
|
## Installation by Platform
|
|
|
|
**Linux (server/desktop):**
|
|
```bash
|
|
curl -fsSL https://tailscale.com/install.sh | sh
|
|
sudo tailscale up
|
|
```
|
|
|
|
**macOS:**
|
|
Download from Mac App Store or tailscale.com/download/mac. Sign in through the menu bar app.
|
|
|
|
**iOS/iPadOS:**
|
|
App Store → Tailscale. Sign in, enable the VPN.
|
|
|
|
**Windows:**
|
|
Download installer from tailscale.com. Runs as a system service.
|
|
|
|
## Making Services Accessible Over Tailscale
|
|
|
|
By default, Docker services bind to `0.0.0.0` — they're already reachable on the Tailscale interface. Verify:
|
|
|
|
```bash
|
|
docker ps --format "table {{.Names}}\t{{.Ports}}"
|
|
```
|
|
|
|
Look for `0.0.0.0:PORT` in the output. If you see `127.0.0.1:PORT`, the service is bound to localhost only and won't be reachable. Fix it in the compose file by removing the `127.0.0.1:` prefix from the port mapping.
|
|
|
|
Ollama on Linux defaults to localhost. Override it:
|
|
|
|
```bash
|
|
# Add to /etc/systemd/system/ollama.service.d/override.conf
|
|
[Service]
|
|
Environment="OLLAMA_HOST=0.0.0.0"
|
|
```
|
|
|
|
```bash
|
|
sudo systemctl daemon-reload && sudo systemctl restart ollama
|
|
```
|
|
|
|
## Access Control
|
|
|
|
By default, all devices on your tailnet can reach all other devices. For a personal homelab this is fine. If you want to restrict access, Tailscale ACLs (in the admin console) let you define which devices can reach which others.
|
|
|
|
Simple ACL example — allow all devices to reach all others (the default):
|
|
|
|
```json
|
|
{
|
|
"acls": [
|
|
{"action": "accept", "src": ["*"], "dst": ["*:*"]}
|
|
]
|
|
}
|
|
```
|
|
|
|
More restrictive — only your laptop can reach the server:
|
|
|
|
```json
|
|
{
|
|
"acls": [
|
|
{
|
|
"action": "accept",
|
|
"src": ["tag:laptop"],
|
|
"dst": ["tag:server:*"]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Subnet Router (Optional)
|
|
|
|
If you want all your home LAN devices accessible over Tailscale (not just devices with Tailscale installed), set up a subnet router on your home server:
|
|
|
|
```bash
|
|
# Advertise your home subnet
|
|
sudo tailscale up --advertise-routes=192.168.1.0/24
|
|
|
|
# Approve the route in the admin console
|
|
# Then on client devices, enable accepting routes:
|
|
sudo tailscale up --accept-routes
|
|
```
|
|
|
|
Now any device on your home LAN is reachable from anywhere on the tailnet, even if Tailscale isn't installed on that device.
|
|
|
|
## Gotchas & Notes
|
|
|
|
- **Tailscale is not a replacement for a firewall.** It secures device-to-device communication, but your server still needs proper firewall rules for LAN access.
|
|
- **Devices need to be approved in the admin console** unless you've enabled auto-approval. If a new device can't connect, check the admin console first.
|
|
- **Mobile devices will disconnect in the background** depending on OS settings. iOS aggressively kills VPN connections. Enable background app refresh for Tailscale in iOS Settings.
|
|
- **DERP relay adds latency** when direct connections aren't possible (common on cellular). Still encrypted and functional, just slower than direct peer-to-peer.
|
|
- **Exit nodes** let you route all traffic through a specific tailnet device — useful as a simple home VPN if you want all your internet traffic going through your home IP when traveling. Set with `--advertise-exit-node` on the server and `--exit-node=hostname` on the client.
|
|
|
|
## See Also
|
|
|
|
- [self-hosting-starter-guide](../docker/self-hosting-starter-guide.md)
|
|
- [linux-server-hardening-checklist](../security/linux-server-hardening-checklist.md)
|
|
- [setting-up-caddy-reverse-proxy](../reverse-proxy/setting-up-caddy-reverse-proxy.md)
|