# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Production deployment of **Headscale** - a self-hosted WireGuard control plane providing Tailscale-compatible networking with complete infrastructure control. This setup enables secure device-to-device connectivity for personal and server environments. **Server Endpoint**: https://headscale.lotimmy.com **Network Range**: 100.64.0.0/10 (IPv4), fd7a:115c:a1e0::/48 (IPv6) ## Essential Commands ### Service Management - `make up` - Start all services in background - `make up-fg` - Start services in foreground (debugging) - `make down` - Stop and remove containers - `make restart` - Restart all services - `make logs` - View service logs (last 100 lines) - `make ps` - Show container status - `make exec` - Enter container shell - `./run.sh` - Quick service start - `./restart.sh` - Quick service restart - `./stop.sh` - Quick service stop ### Headscale Operations - `headscale nodes list` - List all connected devices - `headscale nodes register --user --key ` - Register new node - `headscale nodes tag --identifier --tags tag:server/mobile` - Apply tags - `headscale nodes approve-routes --identifier --routes ` - Approve routes - `headscale users list` - List user namespaces - `headscale preauthkeys list --user ` - List pre-auth keys - `headscale apikeys list` - List API keys - `headscale apikeys revoke ` - Revoke API key ### Node On Workflow 1. Create pre-auth key: `headscale preauthkeys create --user 1 --reusable --ephemeral=false --expiration 87600h` 2. Client connects: `tailscale up --login-server https://headscale.lotimmy.com --auth-key ` 3. Register node: `headscale nodes register --user --key ` ### Backup and Recovery - `./headscale_backup_and_restore.sh` - Automated backup with remote verification - Manual backup: `docker compose down && tar czvf backup_$(date +%Y%m%d).tar.gz . && docker compose up -d` ### Health Monitoring - `./api_user_request.sh` - API health check (returns 200 if healthy) - `curl -s http://localhost:9090/metrics` - Prometheus metrics - `make logs` - Service logs monitoring ## Architecture ### Core Components - **Headscale Service**: Docker container (`headscale/headscale:latest`) - **Configuration**: `/config/config.yaml` with extensive Chinese comments - **Data Storage**: `/data` directory containing SQLite database, keys, and certificates - **Networking**: Three ports exposed (8080 HTTP API, 9090 metrics, 50443 gRPC) - **External Network**: Requires `shared-net` Docker network ### Configuration Architecture The `config.yaml` file contains: - **Server Settings**: HTTPS endpoint (https://headscale.lotimmy.com) with multi-port binding - **WireGuard Networking**: Tailscale-compatible IP ranges (100.64.0.0/10, fd7a:115c:a1e0::/48) - **DNS Management**: Multi-provider setup with NextDNS primary, Cloudflare/Google fallback - **Authentication**: API key and pre-authentication key system - **Database**: SQLite with WAL mode for performance ### Data Persistence Structure ``` /data/ ├── db.sqlite # SQLite database (with -shm, -wal files) ├── noise_private.key # WireGuard encryption key └── [certificates/] # TLS certificates (if using ACME) ``` ### Management Scripts - **Device Management**: `list_headscale_nodes.sh`, create/revoke API keys - **Backup System**: `headscale_backup_and_restore.sh` with MD5 verification - **Health Check**: `api_user_request.sh` verifies API availability - **Onboarding**: `create_headscale_preauthkey.sh` creates 10-year device keys ### Network Architecture - **Public Endpoint**: https://headscale.lotimmy.com (managed reverse proxy) - **Internal Range**: 100.64.0.0/10 for IPv4, fd7a:115c:a1e0::/48 for IPv6 - **Exit Nodes**: Support for full internet routing through designated nodes - **Custom Routes**: Advertisement of local subnets (e.g., 192.168.42.0/24) ## Operational Patterns ### Service Architecture - Single-container deployment using `headscale/headscale:latest` - External Docker network (`shared-net`) for connectivity - Three critical ports: 8080 (HTTP API), 9090 (metrics), 50443 (gRPC) - Watchtower integration for automatic image updates > ⚠️ Because the image is pinned to `:latest` **and** auto-updated by Watchtower, a breaking change in a new Headscale release can crash-loop the container (a removed config key triggers a startup FATAL, taking every node offline). Removed keys seen so far: `randomize_client_port` (FATAL), `ephemeral_node_inactivity_timeout` (renamed to `node.ephemeral.inactivity_timeout`). Prefer pinning a specific version tag, or review the CHANGELOG BREAKING section before upgrading. See OPERATIONS.md → 故障排除. ### Security Model - Bearer token authentication for API access (hardcoded in scripts) - Pre-authentication keys for device enrollment - Tag-based node classification (server/mobile) for ACL policies - Random WireGuard ports to avoid firewall conflicts - TLS encryption required for all external communications ### Data Management - SQLite database with WAL mode for performance - Persistent volumes for config (`/config`) and data (`/data`) - Automatic key generation for WireGuard encryption - MD5 checksum verification for backups ### Critical Scripts - **Device Onboarding**: `create_headscale_preauthkey.sh` creates 10-year reusable keys - **API Management**: Automated key creation/revocation with JSON parsing - **Backup System**: `headscale_backup_and_restore.sh` with remote verification - **Health Monitoring**: `api_user_request.sh` verifies API endpoint availability ## Critical Setup Requirements ### Network Prerequisites - Must create `shared-net` Docker network before deployment - Public endpoint https://headscale.lotimmy.com requires reverse proxy - All scripts execute from project root directory ### Configuration Details - Chinese comments throughout config.yaml explain each parameter - SQLite database with WAL mode enabled automatically - Multi-provider DNS: NextDNS (primary) with Cloudflare/Google fallback - MagicDNS enabled with base_domain: internal.lotimmy.com ### Operational Constraints - All scripts interact via `docker exec -it headscale` - Backup script stops service during backup process - API scripts use hardcoded authentication tokens - Container name fixed as "headscale" across all operations