[Unit] Description=Tailscale VPN Client for Headscale (saltylab-orin) Documentation=https://tailscale.com/kb/1207/headscale Documentation=https://gitea.vayrette.com/seb/saltylab-firmware After=network-online.target systemd-resolved.service Wants=network-online.target Requires=network-online.target [Service] Type=notify RuntimeDirectory=tailscale StateDirectory=tailscale CacheDirectory=tailscale EnvironmentFile=/etc/tailscale/tailscale-env # Restart policy for WiFi resilience Restart=always RestartSec=5s StartLimitInterval=60s StartLimitBurst=10 # Timeouts TimeoutStartSec=30s TimeoutStopSec=10s # User and permissions User=root Group=root # Working directory WorkingDirectory=/var/lib/tailscale # Pre-start: ensure directories exist and auth key is readable ExecStartPre=/bin/mkdir -p /var/lib/tailscale /var/cache/tailscale ExecStartPre=/bin/chmod 700 /var/lib/tailscale /var/cache/tailscale # Main service: start tailscale daemon ExecStart=/usr/sbin/tailscaled \ --state=/var/lib/tailscale/state \ --socket=/var/run/tailscale/tailscaled.sock # Post-start: authenticate with Headscale server if auth key exists ExecStartPost=-/bin/bash -c ' \ if [ -f ${AUTH_KEY_FILE} ]; then \ /usr/bin/tailscale up \ --login-server=${HEADSCALE_SERVER} \ --authkey=$(cat ${AUTH_KEY_FILE}) \ --hostname=${DEVICE_NAME} \ --accept-dns=false \ --accept-routes=true \ 2>&1 | logger -t tailscale; \ fi \ ' # Enable accept-routes for receiving advertised routes from Headscale ExecStartPost=/bin/bash -c ' \ sleep 2; \ /usr/bin/tailscale set --accept-routes=true >/dev/null 2>&1 || true \ ' # Stop service ExecStop=/usr/sbin/tailscaled --cleanup # Logging to systemd journal StandardOutput=journal StandardError=journal SyslogIdentifier=tailscale-vpn # Security settings NoNewPrivileges=false PrivateTmp=no ProtectSystem=no ProtectHome=no RemoveIPC=no [Install] WantedBy=multi-user.target