Overview
Tailscale provides automatic HTTPS certificates for devices on your tailnet. This solves a common problem: you have a local service (like a web app on your home server) that you want to access securely, but getting TLS certificates for private IPs or local hostnames is normally impossible.
How It Works
The Problem
Normally, to get an HTTPS certificate you need:
- A public domain name (like
example.com) - Proof that you own that domain (DNS or HTTP challenge)
- A Certificate Authority to issue the cert (Let's Encrypt, etc.)
This doesn't work for private services because:
- Private IPs (192.168.x.x, 10.x.x.x) can't get certificates
- Local hostnames aren't globally unique
- Your home server isn't reachable from the internet for validation
Tailscale's Solution
Tailscale gives every device on your tailnet a unique DNS name under *.ts.net:
your-machine.your-tailnet.ts.net
Since Tailscale controls the ts.net domain, they can issue valid certificates
for your devices through Let's Encrypt.
amd-miniserver
amd-miniserver.tail0489.ts.net
Valid HTTPS for your domain
Tailscale Serve
tailscale serve is a built-in reverse proxy that:
- Automatically provisions HTTPS certificates
- Handles TLS termination
- Proxies requests to your local HTTP service
- Only accessible from your tailnet (private by default)
Basic Usage
# Serve a local HTTP app over HTTPS sudo tailscale serve --bg https / http://localhost:3004 # Now accessible at: # https://your-machine.your-tailnet.ts.net/
What Happens
The --bg Flag
The --bg flag runs the serve configuration in the background and persists
it across reboots. Without it, the serve would stop when you close the terminal.
Common Commands
| Command | Description |
|---|---|
tailscale serve status |
Show current serve configuration |
tailscale serve --bg https / http://localhost:PORT |
Serve local app over HTTPS |
tailscale serve reset |
Remove all serve configurations |
tailscale cert DOMAIN |
Manually download certificate files |
tailscale status |
Show your tailnet devices and IPs |
Multiple Apps
If you have multiple apps on the same machine, you have several options:
Option 1: Path-based Routing
sudo tailscale serve --bg --https=443 /biodex http://localhost:3004 sudo tailscale serve --bg --https=443 /calories http://localhost:3000 # Access at: # https://machine.tailnet.ts.net/biodex # https://machine.tailnet.ts.net/calories
base configuration.
Option 2: Different Ports
sudo tailscale serve --bg --https=443 / http://localhost:3004 sudo tailscale serve --bg --https=8443 / http://localhost:3000 # Access at: # https://machine.tailnet.ts.net/ (port 443) # https://machine.tailnet.ts.net:8443/
Option 3: Caddy Reverse Proxy
For more complex setups, use Caddy with Tailscale certificate integration:
# /etc/caddy/Caddyfile
machine.tailnet.ts.net {
handle /biodex/* {
uri strip_prefix /biodex
reverse_proxy localhost:3004
}
handle /calories/* {
uri strip_prefix /calories
reverse_proxy localhost:3000
}
tls {
get_certificate tailscale
}
}
Serve vs Funnel
Tailscale has two ways to expose services:
| Feature | tailscale serve | tailscale funnel |
|---|---|---|
| Accessibility | Tailnet only (private) | Public internet |
| Who can access | Only your devices | Anyone with the URL |
| Use case | Personal apps, dev servers | Webhooks, sharing with others |
| Security | Protected by Tailscale auth | Exposed to internet |
tailscale serve. Your services stay
private and are only accessible from devices signed into your Tailscale account.
Certificate Details
Automatic Management
When using tailscale serve, certificates are managed automatically:
- Provisioned on first request
- Renewed automatically (Let's Encrypt certs are valid 90 days; Tailscale renews ~30 days before expiry)
- Stored securely by Tailscale daemon
Manual Certificates
If you need the actual certificate files (for custom server configuration):
sudo tailscale cert your-machine.tailnet.ts.net # Creates: # your-machine.tailnet.ts.net.crt (certificate) # your-machine.tailnet.ts.net.key (private key)
You can then configure your web server (nginx, Node.js, etc.) to use these files.
Why HTTPS Matters for Web Apps
Modern browsers restrict powerful APIs to "secure contexts" (HTTPS or localhost):
| Feature | Requires HTTPS? |
|---|---|
| WebAuthn / Passkeys | Yes |
| Geolocation API | Yes |
| Camera / Microphone | Yes |
| Push Notifications | Yes |
| Service Workers (PWA) | Yes |
| Clipboard API | Yes |
| Web Bluetooth | Yes |
This is why accessing http://amd-miniserver:3004 over plain HTTP breaks
features like passkey authentication - the browser refuses to expose the WebAuthn API.
Troubleshooting
Certificate not working
# Check serve status tailscale serve status # Reset and try again sudo tailscale serve reset sudo tailscale serve --bg https / http://localhost:3004
Can't access from other device
- Make sure both devices are on your tailnet
- Check
tailscale statusshows both devices - Verify MagicDNS is enabled in Tailscale admin console
App works on localhost but not via Tailscale
- Verify the port number in your serve command matches the port your app is listening on
tailscale serveconnects locally, so your app only needs to listen on127.0.0.1- Check firewall allows the port if you also need direct LAN access