Setting up Tailscale on pfSense gave me a secure, no-inbound-ports VPN in under an hour. This post documents my process, key configurations, and lessons learned.
Before we get started, a huge thanks to these two guides which made my setup painless:
If you’re new to Tailscale, you can find their install docs here.
Why Tailscale?
I chose Tailscale for a few key reasons:
- No inbound firewall rules required — it works entirely with outbound connections.
- Centralized authentication via my GitHub account to control access to my tailnet.
- Cross-platform support and quick deployment.
While it’s arguably less “hands-on” than rolling WireGuard manually, the speed and safety tradeoff was worth it for this stage of my homelab.
Steps to Install & Configure
1. Register & Authenticate
I created a free Tailscale account using my GitHub user. This lets me manage access to my tailnet centrally and securely.
2. Install the pfSense Package
In System → Package Manager, I installed the Tailscale package. After installation, it appears under VPN → Tailscale in the web UI.
3. Authorize pfSense with a Pre-Auth Key
From the Tailscale Admin Console → Settings → Keys, I generated a pre-authentication key. I pasted this into pfSense → VPN → Tailscale → Authentication under Pre-authentication key. Once saved, the device appeared in the Tailscale admin console, ready for approval. Since it serves as an exit node and subnet router, I disabled key expiry.
4. Core pfSense Tailscale Settings
Settings
- Enable: ✔
- Listen port: default
- State directory: default
- Keep configuration: ✔ (persists through reboots)
DNS
- Accept DNS: ✔
Routing
- Advertise exit node: ✔ (lets me route traffic through pfSense — useful for whitelisted-IP scenarios)
- Accept subnet routes: ✔
- Advertised routes: my internal LAN subnet
In the Tailscale admin console, I approved both the exit node and the subnet route.
5. Add Remote Devices
I installed Tailscale on my laptop and iPhone, then ran on my laptop:
sudo tailscale up --accept-routes
sudo tailscale set --exit-node={TAILNET_IP_OF_PFSENSE} --exit-node-allow-lan-access=true
Because all connections are outbound, no new fireall rules were needed
Gotchas and Lessons Learned
- An initial subnet typo blocked LAN access until fixed
- I didn’t need any NAT or packet filters for this minimal, initial setup
- I’ve seen reports of pfSense/Tailscale quicks, but with the settings listed it’s been stable.