Use Tailscale for Private Raspberry Pi Administration
Use Tailscale for the Pi’s private administration plane, not for publishing the website. In this design Starlink’s default IPv4 CGNAT remains in place; the Netgate 2100 routes an isolated LAN4 DMZ (192.168.60.0/24), the Raspberry Pi 5 is 192.168.60.10, Nginx serves loopback 127.0.0.1:8080, and cloudflared handles the public web path. Tailscale lets approved administrator devices reach the Pi without a WAN port forward.
Choose the smallest Tailscale role
Install Tailscale directly on the Pi when administrators need the Pi only. Do not advertise the whole DMZ as a subnet route merely to reach one host. A subnet router is a separate gateway role and should be used only for devices that cannot run Tailscale. An exit node is for routing general internet traffic and is not needed for Pi administration.
| Path | Intended audience | Boundary to verify |
|---|---|---|
| Tailscale on Pi | Named administrators to Pi services | Host firewall and Tailscale policy expose only required ports. |
| Subnet router | Named administrators to a small non-Tailscale subnet | Advertise and approve only the necessary prefix and destinations. |
| Cloudflare Tunnel | Public web or an Access-protected browser application | It is not a private SSH overlay or a replacement for host authorization. |
Enroll the Pi and administrator devices
- Protect the tailnet identity account with MFA and review its administrator roles.
- Install Tailscale from the official repository or application source on the patched Pi and on a patched administrator device.
- Use a device name that identifies the role without revealing a secret. Check the Pi’s owner, key expiry, approval state, and last-seen time in the admin console.
- Prefer an interactive, one-off enrollment. If an auth key is necessary for automation, scope it, expire it, protect it as a secret, and revoke it after use.
- Remove lost, replaced, and test devices. Do not approve an unknown device simply because its name looks familiar.
Tailscale’s coordination service helps peers find one another; traffic may use a direct encrypted WireGuard path or an encrypted DERP relay. Either way, tailnet membership and endpoint policy are trust decisions, not evidence that the Pi itself is hardened.
Use host and tailnet least privilege
Write a policy that names the administrator group, the Pi (or a narrowly scoped tag), and only the required services. A browser administration port might be TCP 443 or a documented local port; SSH is TCP 22 only for the named administrators. Do not use an everyone-to-everything default as a substitute for a policy review. If using a subnet router, name the exact DMZ destination and port rather than granting access to the whole 192.168.60.0/24 network.
On the Pi, keep sshd key-only, disable password login and root login as appropriate for the distribution, and restrict its listen addresses or host firewall to the Tailscale interface and a local recovery network. Keep the local console or a trusted-LAN recovery host documented and tested: from that host, verify that SSH to 192.168.60.10:22 works when Tailscale is deliberately stopped, while every other trusted-LAN source remains denied. This recovery exception is not a reason to trust the whole tailscale0 interface or the whole LAN. Tailscale SSH is optional; enabling Tailscale does not require replacing ordinary SSH policy.
If using nftables, put the state rule first and add this narrow input rule in the Pi’s existing inet input chain (preserving its loopback, ICMP, and established-service rules):
ct state established,related accept
iifname "tailscale0" tcp dport 22 accept
The second rule permits only new TCP/22 packets arriving through tailscale0; it does not accept all protocols or all traffic from that interface. Keep Tailscale’s identity policy and SSH key authorization in force, and add no broad iifname "tailscale0" accept rule. If the distribution uses another firewall frontend, express the same source-interface and destination-port constraint there and inspect the rendered rules.
Direct peer transport is optional. If the Pi’s LAN4-facing interface really is eth0, an operator may add this separate host-input rule after the established/related rule and after the SSH rule:
iifname "eth0" udp dport 41641 accept
UDP/41641 carries Tailscale’s WireGuard transport, whose packets are authenticated and encrypted by the enrolled peer keys; this rule does not make arbitrary UDP payloads trusted. It does, however, expose a host UDP socket to unsolicited internet traffic, so it can increase scan, resource-exhaustion, and logging noise. Use it only when the host and the LAN4 firewall policy have accepted that trade-off, keep SSH restricted to tailscale0, and do not add a WAN pass rule or port forward. Starlink CGNAT may prevent a direct inbound path regardless of this rule; Tailscale can use an encrypted DERP relay over TCP 443 instead.
Tailscale normally needs outbound HTTPS to its control plane and DERP relays on TCP 443, UDP 3478 for STUN/NAT discovery, and UDP 41641 for direct WireGuard peer paths. A direct path may fail over to an encrypted DERP relay over TCP 443; these are stateful outbound flows, not inbound port forwards. Permit the documented outbound behavior from the Pi/DMZ as the site policy requires, do not allow unsolicited WAN traffic, and re-check the current Tailscale firewall-port documentation when versions or egress rules change.
# Verify listeners and routes; adapt commands to the Pi distribution.
ss -lntp
tailscale status
tailscale ip
Do not paste an auth key, private key, or machine-state file into a command transcript. Rotate credentials if they appear in a log or terminal capture.
Understand Cloudflare Access versus Tailscale
| Question | Tailscale | Cloudflare Access |
|---|---|---|
| Who can reach the Pi’s private services? | Tailnet identity, grants or ACLs, and host firewall | Usually an identity check at a web hostname |
| Does it publish a public website? | No, unless a separate public feature is enabled | Cloudflare Tunnel can publish a hostname; Access can restrict it |
| Does it authorize SSH? | It can carry an explicitly permitted SSH connection | Web Access does not transparently authorize ordinary SSH |
Do not enable Tailscale Funnel because a website uses Cloudflare Tunnel, and do not treat a Cloudflare Access-protected dashboard as permission to administer the operating system. Keep these audiences, policies, logs, and recovery paths separate.
Test and maintain private administration
- From an administrator device on cellular or another outside network, bring Tailscale up and confirm the Pi is reachable by its tailnet address.
- Confirm the allowed SSH or administration service works, then verify that Nginx’s origin port, Netgate WebGUI, unrelated DMZ hosts, and unlisted ports do not.
- Use
tailscale netcheckandtailscale pingdiagnostics to record whether the path is direct or relayed. When the optionaleth0UDP/41641 rule is enabled, compare a direct result with a controlled firewall-blocked result that falls back to DERP, and inspect counters for both the UDP transport and narrowtailscale0TCP/22 rules. Do not weaken policy just because a relay adds latency. - Test an unauthorized tailnet identity and a device with Tailscale stopped. Both should be denied over the overlay. With Tailscale stopped, use the documented trusted-LAN recovery host to verify SSH works, then verify that another LAN host and every public source remain denied.
- Review device inventory, users, tags, routes, grants, key expiry, administrative events, and outbound control/relay transport at each maintenance cycle.
Continue with Restrict Netgate 2100 DMZ Egress before treating the Pi as a finished service host.
Sequence navigation
Previous: Publish Nginx through Cloudflare DNS · Next: Restrict Netgate 2100 DMZ Egress
dispelled