# ez-headscale **Repository Path**: b166er/ez-headscale ## Basic Information - **Project Name**: ez-headscale - **Description**: ez-headscale:一个简化Headscale部署与管理的开源项目,提供易用的界面和强大的功能,助力开发者快速搭建安全可靠的Tailscale网络环境。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-17 - **Last Updated**: 2026-03-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Headscale + DERP Docker Compose Deployment Automated deployment solution for Headscale server and DERP relay with subnet routing capabilities. ## Features - ✅ Single docker-compose.yml with profile-based deployment - ✅ Server profile: Headscale + DERP relay - ✅ Client profile: Tailscale subnet router - ✅ Automated configuration generation - ✅ ACL policy support - ✅ Subnet routing for LAN access ## Prerequisites - Docker Engine 20.10+ - Docker Compose v2.0+ - VPS with public IP (for server deployment) - A machine on your LAN (for client/subnet router deployment) ## Quick Start ### Server Deployment (VPS) ```bash # 1. Clone/copy project files git clone cd punch-through # 2. Configure environment cp .env.template .env nano .env # Edit SERVER_HOST and other variables # 3. Generate configuration files ./scripts/setup.sh # 4. Deploy server docker compose --profile server up -d # 5. Verify server is running docker compose logs headscale # 6. Create admin user docker exec headscale headscale users create admin@example.com # 7. Get user ID docker exec headscale headscale users list -o json # 8. Generate auth key (use user ID from step 7) docker exec headscale headscale preauthkeys create --user 1 --expiration 24h --reusable ``` ### Client Deployment (LAN Router) ```bash # 1. Clone/copy project files on LAN machine git clone cd punch-through # 2. Configure environment cp .env.template .env nano .env # Edit SERVER_HOST, SUBNET_CIDR, and AUTH_KEY # 3. Generate configuration files ./scripts/setup.sh # 4. Deploy client docker compose --profile client up -d ``` ### Enable Subnet Routing After the client connects, approve the subnet route on the server: ```bash # List nodes and routes docker exec headscale headscale nodes list docker exec headscale headscale nodes list-routes # Approve route (use node ID from list command) docker exec headscale headscale nodes approve-routes -i -r # Or use the helper script ./scripts/enable-route.sh ``` ## Tailscale Client Setup (Native) Connect native Tailscale clients to your Headscale server. ### Generate Auth Key First, create a pre-auth key on the server: ```bash # Create a reusable auth key (valid for 24h) docker exec headscale headscale preauthkeys create --user 1 --expiration 24h --reusable ``` ### Linux ```bash # Use --login-server flag with your configured SERVER_PORT sudo tailscale up --login-server http://: --authkey # Verify connection tailscale status ``` ### macOS ```bash # Set the login server sudo tailscale up --login-server http://: --authkey # If using App Store version, you may need: /Applications/Tailscale.app/Contents/MacOS/Tailscale up --login-server http://: --authkey ``` ### Windows ```powershell # Run in PowerShell as Administrator tailscale up --login-server http://: --authkey ``` ### iOS / Android Mobile clients require a custom coordination server URL: 1. **iOS**: Open Settings → Tailscale → Custom Coordination Server 2. **Android**: Open Settings → Custom control plane URL Enter your server URL: `http://:` Then sign in with the auth key when prompted. ### Verify Connection ```bash # Check node status on the server docker exec headscale headscale nodes list # On the client tailscale status tailscale ping ``` ## Configuration ### Environment Variables (.env) | Variable | Description | Required | |----------|-------------|----------| | `SERVER_HOST` | VPS IP or domain | Yes | | `SERVER_PORT` | Headscale API port (default: 8080) | Yes | | `DERP_PORT` | DERP/STUN port (default: 3478) | Yes | | `SUBNET_CIDR` | LAN subnet CIDR to advertise | Yes | | `ADMIN_EMAIL` | Admin email for ACL | Yes | | `HEADSCALE_DATA_DIR` | Headscale data path (default: ./data/headscale) | Yes | | `HEADSCALE_CONFIG_DIR` | Config path (default: ./config) | Yes | | `TAILSCALE_STATE_DIR` | Tailscale state path (default: ./data/tailscale) | Yes | | `AUTH_KEY` | Pre-auth key from server | Client only | ### Directory Structure ``` punch-through/ ├── docker-compose.yml # Main compose file ├── .env.template # Configuration template ├── config/ │ ├── config.yaml.template # Headscale config template │ ├── derp.yaml.template # DERP map template │ ├── acls.json.template # ACL policy template │ ├── config.yaml # Generated (gitignored) │ ├── derp.yaml # Generated (gitignored) │ └── acls.json # Generated (gitignored) ├── scripts/ │ ├── setup.sh # Config generation │ └── enable-route.sh # Route management └── data/ # Persistent data (gitignored) ``` ## Common Commands ```bash # View logs docker compose logs -f headscale # View service status docker compose ps # Stop services docker compose down # Restart services docker compose restart # Access headscale CLI docker exec headscale headscale help # Health check curl http://localhost:8080/health ``` ## Security Notes - The Tailscale client container runs with privileged mode for subnet routing (Linux) - For macOS testing only, set `TS_USERSPACE=true` (no subnet routing support) - Consider running the client on a dedicated, isolated machine - Server containers do not require privileged mode - For production, use HTTPS with a reverse proxy (nginx, caddy, traefik) ## Troubleshooting ### Container keeps restarting 1. Check logs: `docker compose logs headscale` 2. Verify config was generated: `ls -la config/` 3. Ensure config.yaml exists (not headscale.yaml) ### Client won't connect - Verify AUTH_KEY is valid and not expired - Check SERVER_HOST is accessible from the client machine - Check firewall allows outbound connections to SERVER_PORT and DERP_PORT ### Subnet route not working - Ensure that the route is approved on the server: `docker exec headscale headscale nodes list-routes` - Verify that the client has access to the LAN subnet - Check that the client is advertising the correct subnet ### Configuration generation fails - Ensure that all required variables are set in .env - Validate CIDR format (e.g., 192.168.1.0/24) - Check that the template files exist in the config/ directory ## Version Compatibility This project is tested with: - Headscale v0.28.0 - Tailscale client v1.74+ > ⚠️ **Important**: Headscale configuration format changed significantly in v0.23+. If you're using an older version, you may need to adjust the config templates. ## License MIT