# Tailscale Funnel Reference

## What It Does

Tailscale Funnel exposes a local HTTP/HTTPS service to the public internet through Tailscale's infrastructure. It provides:
- Automatic HTTPS certificates (Let's Encrypt via Tailscale)
- No port forwarding or public IP required
- Authentication via Tailscale identity (optional: restrict to specific users)
- DDoS protection at the Tailscale edge

## Prerequisites

1. Tailscale installed and running on the machine
2. Funnel enabled in the Tailscale admin console (one-time per tailnet)
   - URL: `https://login.tailscale.com/f/funnel?node=<NODE_ID>`
   - Enable for the tailnet owner
3. Operator permission granted: `sudo tailscale set --operator=$USER`

## Basic Usage

```bash
# Expose port 8080 (background)
tailscale funnel --bg 8080

# Check status
tailscale serve status
# Output:
# # Funnel on:
# https://<hostname>.tail<id>.ts.net (Funnel on)
# |-- / proxy http://127.0.0.1:8080

# Stop funnel
tailscale funnel --https=443 off
# Or reset all serve config
tailscale serve reset
```

## Common Issues

### "Funnel is not enabled on your tailnet"
- Visit the admin console URL shown in the error message
- The tailnet owner must enable Funnel in the Tailscale admin panel

### "serve config denied" / "Use 'sudo tailscale funnel 8080'"
- Run `sudo tailscale set --operator=$USER` to grant non-root access
- Then re-run the funnel command without sudo

### "foreground listener already exists for port 443"
- A previous `tailscale serve` or `funnel` is still running
- Kill it: `pkill -f "tailscale (serve|funnel)"`
- Reset config: `tailscale serve reset`
- Then restart

### Funnel stops after terminal closes
- Use `--bg` flag: `tailscale funnel --bg 8080`
- Or create a systemd user service for persistence (see below)

### Local curl fails with connection closed
- Check if `http_proxy` env vars are set — they can interfere with localhost connections
- Unset: `unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY`

## Systemd User Service for Persistence

Create `~/.config/systemd/user/tailscale-funnel.service`:

```ini
[Unit]
Description=Tailscale Funnel
After=network-online.target tailscaled.service

[Service]
Type=simple
ExecStart=/usr/bin/tailscale funnel 8080
Restart=on-failure
RestartSec=10

[Install]
WantedBy=default.target
```

Enable and start:
```bash
systemctl --user daemon-reload
systemctl --user enable --now tailscale-funnel.service
systemctl --user status tailscale-funnel.service
```

## Limitations

- **HTTP/HTTPS only** — cannot expose SSH, databases, or arbitrary TCP/UDP
- Single port per funnel instance (use a reverse proxy like nginx for multiple paths)
- Requires Tailscale running on the machine
- Funnel must stay running — if the process exits, the service goes down

## Security Notes

- By default, anyone on the internet can reach the funnel URL
- Optionally restrict access via Tailscale ACLs in the admin console
- The HTTPS certificate is managed by Tailscale — no manual certbot needed
