TailStick has one workflow engine with two frontend styles:
- CLI entrypoint
- Local web UI entrypoint
Both frontends call the same state machine and the same tailscale integration logic.
- Detect environment
- Validate preset and runtime options
- Enforce elevation requirement for privileged operations
- Ensure tailscale install and stable pinning when channel is
stable - Enroll (
tailscale up) - Persist lease state and audit event
- Install lease agent for non-permanent modes
- Reconcile cleanup on timer/startup
- Retry until cleanup convergence
- Remove self when no active managed leases remain
internal/app: workflow engine, command handlers, agent routinesinternal/gui: local web launcher and APIinternal/config: config loading and validationinternal/state: local state and USB audit persistenceinternal/tailscale: tailscale CLI + control-plane delete API integrationinternal/platform: OS detection, runtime paths, command executioninternal/crypto: local secret encryption/decryption helpersinternal/logging: local structured logging
- Session lease:
- active for current boot session
- cleanup on boot mismatch
- Timed lease:
- active until
expiresAt - cleanup once expired, then retry on failure
- active until
- Permanent:
- no automatic cleanup
Lease records persist install-command snapshots and encrypted cleanup credentials so cleanup can proceed without requiring the original USB config file.
Agent actions:
tailscale downtailscale logout- Optional API
DELETE /api/v2/device/{device_id} - Uninstall tailscale for non-permanent leases
If any step fails, the record moves to cleanup_failed and retries continue in future iterations.
If no managed leases remain, the agent removes its own schedule/service registration.
The lease agent runs from a machine-local binary copy (/var/lib/tailstick/tailstick-agent on Linux, %ProgramData%\TailStick\tailstick-agent.exe on Windows) so reconciliation remains available when USB media is absent.