(Fire)fox + Tail(scale) = Foxtail
A Firefox browser that lives on your Tailscale network — accessible from any device on your tailnet, directly in a browser tab.
Foxtail runs Firefox inside Docker and joins it to your tailnet as a named node. From any device on your tailnet you open a tab, and you're in. No port forwarding. No public exposure. No VPN client on the remote device.
Some things this is good for:
- Browse the web through your home or office network from anywhere
- Reach internal services on your tailnet (dashboards, dev servers, NAS) without exposing them
- Give a teammate a shared browser pointed at your internal resources
- Test how a site behaves from a specific network's perspective
Userspace networking — Tailscale runs entirely in userspace inside the container. No /dev/net/tun, no host networking, no special kernel modules. It works anywhere Docker runs.
MagicDNS — the browser resolves .ts.net hostnames out of the box. Internal services are reachable by name, not IP.
Auth keys + 1Password — the auth key is fetched at runtime from 1Password CLI and injected as an environment variable. It never touches disk or a config file.
Ephemeral nodes — use an ephemeral auth key and the device disappears from your tailnet automatically when the container stops. No stale devices to clean up.
- Docker Desktop installed and running
- Task installed:
brew install go-task
- 1Password CLI installed and configured:
brew install --cask 1password-cli op signin
- Tailscale account with an auth key stored in 1Password
Generate a key at https://login.tailscale.com/admin/settings/keys, then save it in 1Password:
- Vault:
Private(or setOP_VAULT) - Item name:
Foxtail(or setOP_ITEM_NAME) - Field name:
auth_key
Key options to consider:
- Reusable — lets you recreate the container without generating a new key each time
- Ephemeral — the tailnet device is removed automatically when the container stops
cp .env.example .env
# Edit .env and set VNC_PW and VNC_VIEW_ONLY_PWtask starthttps://localhost:6901
- Username:
kasm_user - Password: (your
VNC_PWfrom.env, default:foxtail)
Run task with no arguments to see all available commands.
| Command | Description |
|---|---|
task start |
Fetch auth key from 1Password and start |
task stop |
Stop and remove the container |
task restart |
Stop and restart |
task build |
Rebuild the Docker image from scratch |
task logs |
Stream container logs |
task status |
Check running container processes |
task debug |
Start with verbose logging |
task test-auth |
Validate 1Password CLI and auth key |
task tailscale-status |
Show Tailscale connection inside the container |
TAILSCALE_HOSTNAME=my-browser task startOP_VAULT="Personal" OP_ITEM_NAME="Tailscale Keys" task startTAILSCALE_TAGS="tag:browser,tag:docker" task start┌─────────────────────────────────────┐
│ Docker Container │
│ │
│ ┌──────────────────────────────┐ │
│ │ Tailscale (userspace mode) │ │
│ │ - No /dev/net/tun required │ │
│ │ - Connected to your tailnet │ │
│ └──────────────────────────────┘ │
│ │
│ ┌──────────────────────────────┐ │
│ │ Xvfb (Virtual Display) │ │
│ └──────────────────────────────┘ │
│ │
│ ┌──────────────────────────────┐ │
│ │ Firefox │ │
│ └──────────────────────────────┘ │
│ │
│ ┌──────────────────────────────┐ │
│ │ x11vnc → noVNC │ │
│ │ (Web-based VNC interface) │ │
│ └──────────────────────────────┘ │
│ │
└─────────────────────────────────────┘
│
│ Port 6901
▼
Your Web Browser
(https://localhost:6901)
Built on kasmweb/firefox. Supervisor manages all four processes inside the container. The entrypoint starts Tailscale as root, connects to your tailnet, then drops to an unprivileged user before handing off to Kasm.
task test-auth
# Or check manually
op whoami
op read "op://Private/Foxtail/auth_key"task logs
task tailscale-status- Verify the container is running:
docker-compose ps - Check port 6901 isn't in use:
lsof -i :6901 - Check noVNC logs:
task logsand search fornovnc
- The Tailscale auth key is fetched at runtime from 1Password — never stored in a file or image layer
- VNC credentials are set via
.envwhich is gitignored - The container requires
NET_ADMINandNET_RAWcapabilities for Tailscale userspace networking - Tailscale state persists in a Docker volume — delete it with
docker volume rm foxtail_tailscale-stateto force re-authentication
MIT