# Running Tailscale with Docker
Tailscale provides a simple and secure way to connect servers and services using a **mesh VPN**, without exposing ports or managing complex firewall rules.
In this post, I’ll walk through running **Tailscale as a Docker container** using the **host network**, allowing the server itself to join the Tailscale network with minimal configuration.
The focus is on a setup that is:
- Simple and reproducible
- Restart-safe
- Suitable for production environments
The full script is provided at the end.
---
## What are we trying to achieve?
The goal of this setup is to:
- Join a server to a Tailscale network
- Avoid manual Tailscale installation on the host
- Keep the setup containerized and easy to manage
- Allow Tailscale to operate at the **host network level**
This is especially useful for servers, VMs, or bare-metal machines.
---
## General approach
In this setup:
- The official `tailscale/tailscale` Docker image is used
- The container runs on the **host network**
- Required Linux capabilities are explicitly granted
- Authentication is handled via a **Tailscale auth key**
- No configuration files are required
This keeps the container **stateless** and easy to recreate.
---
## Prerequisites
Before starting, make sure that:
- Docker is installed on the server
- You have a Tailscale account
- You have generated a valid **Auth Key** from the Tailscale admin panel
> Auth keys can be created under **Tailscale Admin → Keys**.
---
## Step 1: Running Bash in safe mode
The script starts by enabling strict Bash settings:
- Exit immediately on errors
- Fail on undefined variables
- Catch errors in pipelines
This prevents silent failures and is considered a best practice for production scripts.
---
## Step 2: Defining base variables
The script defines the following core variables:
| Variable | Description |
|-----------------|-----------------------------------------------------------|
| `CONTAINER` | Container name, used for easier management and debugging |
| `IMAGE` | Docker image pinned to a specific version for reproducibility |
| `AUTH_KEY` | Authentication key used to join the Tailscale network |
> In real environments, the auth key should be stored as a secret
> (e.g. `.env`, Docker secrets, CI/CD secrets).
---
## Step 3: Using the host network
The container is started with `--network host`.
This allows:
- Tailscale to use the host’s network stack directly
- VPN interfaces to be created at the host level
- No additional port mapping or routing configuration
This mode is ideal for VPN-style workloads like Tailscale.
---
## Step 4: Granting required Linux capabilities
Tailscale requires specific capabilities to function correctly:
- `NET_ADMIN` – to manage network interfaces and routing
- `SYS_MODULE` – to interact with kernel modules when needed
Without these, the Tailscale daemon will not be able to establish connectivity.
---
## Full Bash script (copy & paste)
Below is the complete script containing all the steps described above:
```bash
#!/usr/bin/env bash
set -euo pipefail
# ============================================================
# Tailscale setup script (bash)
#
# This script:
# - starts a Tailscale container using the host network
# - joins the server to a Tailscale network
# ============================================================
# ------------------------------------------------------------
# 0) Base variables
# ------------------------------------------------------------
CONTAINER="tailscale"
IMAGE="tailscale/tailscale:v1.90.9"
TS_AUTHKEY="tskey-XXXX" # replace with your real auth key
# ------------------------------------------------------------
# 1) Start Tailscale container
# ------------------------------------------------------------
docker run -d \
--name "$CONTAINER" \
--network host \
--cap-add NET_ADMIN \
--cap-add SYS_MODULE \
-e TS_AUTHKEY="$TS_AUTHKEY" \
"$IMAGE"