Skip to content

Kubernetes lifecycle automation for Tailscale/Headscale nodes. Handles automatic cleanup of stale nodes and DNS records on pod restart, and creates new DNS records after VPN registration. Includes kubectl and Python dependencies pre-installed for fast startup.

Notifications You must be signed in to change notification settings

vegcom/tailscale-lifecycle-automation

Repository files navigation

Tailscale Lifecycle Automation

Kubernetes lifecycle automation for Tailscale/Headscale nodes. Handles automatic cleanup of stale nodes and DNS records on pod restart, and creates new DNS records after VPN registration.

Features

  • Cleanup: Removes old Headscale nodes and DNS records before pod startup
  • DNS Creation: Automatically creates DNS A records after Tailscale registers with Headscale
  • Pre-built Dependencies: Includes kubectl and Python requests library for fast startup
  • Idempotent: Safe to run multiple times, handles "already exists" errors gracefully

Usage

As Init Container (Cleanup)

initContainers:
  - name: lifecycle-cleanup
    image: registry.core.svc.cluster.local:5000/tailscale-lifecycle:latest
    command: ["/usr/local/bin/python3"]
    args:
      - "/scripts/lifecycle_cleanup.py"
      - "--hostname"
      - "my-service.example.com"
      - "--record-name"
      - "my-service"
    env:
      - name: HEADSCALE_NAMESPACE
        value: "core"
      - name: CLOUDFLARE_API_TOKEN
        value: "your-token"
      - name: CLOUDFLARE_ZONE_ID
        value: "your-zone-id"
      - name: DOMAIN_NAME
        value: "example.com"

As Sidecar Container (DNS Creation)

containers:
  - name: lifecycle-dns-create
    image: registry.core.svc.cluster.local:5000/tailscale-lifecycle:latest
    command: ["/usr/local/bin/python3"]
    args:
      - "/scripts/lifecycle_dns_create.py"
      - "--hostname"
      - "my-service.example.com"
      - "--record-name"
      - "my-service"
    env:
      - name: HEADSCALE_NAMESPACE
        value: "core"
      - name: CLOUDFLARE_API_TOKEN
        value: "your-token"
      - name: CLOUDFLARE_ZONE_ID
        value: "your-zone-id"
      - name: DOMAIN_NAME
        value: "example.com"
      - name: MAX_RETRIES
        value: "30"
      - name: RETRY_INTERVAL
        value: "10"

Building

Option 1: Alpine-based (Recommended for Production)

Smallest image size (~76MB), fastest startup:

docker build -t registry.core.svc.cluster.local:5000/tailscale-lifecycle:latest .
docker push registry.core.svc.cluster.local:5000/tailscale-lifecycle:latest

Option 2: Conda-based (Better for Development)

Uses Miniforge and environment.yaml (~200MB), better Python ecosystem:

docker build -f Dockerfile.conda -t registry.core.svc.cluster.local:5000/tailscale-lifecycle:conda .
docker push registry.core.svc.cluster.local:5000/tailscale-lifecycle:conda

Using the build script

./build-and-push.sh          # Builds Alpine version with :latest tag
./build-and-push.sh conda    # Builds Conda version with :conda tag

Environment Variables

Required

  • HEADSCALE_NAMESPACE: Kubernetes namespace where Headscale is running (default: core)
  • CLOUDFLARE_API_TOKEN: Cloudflare API token for DNS management
  • CLOUDFLARE_ZONE_ID: Cloudflare zone ID for the domain
  • DOMAIN_NAME: Base domain name (default: example.com)

Optional (DNS Creation only)

  • MAX_RETRIES: Maximum attempts to wait for Headscale registration (default: 30)
  • RETRY_INTERVAL: Seconds between retry attempts (default: 10)

Scripts

lifecycle_cleanup.py

Runs before pod startup to clean up old resources:

  • Deletes all Headscale nodes matching the hostname (online or offline)
  • Deletes all DNS A records matching the record name
  • Always exits with code 0 (cleanup failures don't block pod startup)

lifecycle_dns_create.py

Runs as sidecar to create DNS records:

  • Waits for Headscale node to register and come online
  • Extracts the assigned VPN IP address
  • Creates DNS A record pointing to the VPN IP
  • Handles "record already exists" errors gracefully
  • Exits after successful creation (or failure after max retries)

License

MIT

About

Kubernetes lifecycle automation for Tailscale/Headscale nodes. Handles automatic cleanup of stale nodes and DNS records on pod restart, and creates new DNS records after VPN registration. Includes kubectl and Python dependencies pre-installed for fast startup.

Resources

Stars

Watchers

Forks