feat: bases deployment — tsnet integration and Basefile #1

Closed
arne wants to merge 0 commits from feat/bases-deployment into main
Owner

Summary

  • Embeds Tailscale via tsnet so the SSH/TUI server listens on a Tailscale-only net.Listener — no SSH port exposed on the container's local interface
  • Adds a `/tailscale` HTTP route that shows the Tailscale auth URL (NeedsLogin), connected status, or error — allows bootstrapping and re-authenticating Tailscale from the browser
  • Changes all default paths from XDG (`~/.local/share/keys/`) to `/var/lib/keys/` so the binary works without any env var configuration in a container
  • Adds a `Basefile` so `bases install keys` deploys the service with zero manual configuration

Post-install flow

  1. `bases install keys` — container created, binary built, SSH host key generated, service starts
  2. Visit `https://keys./tailscale` — click the Tailscale auth link
  3. `ssh keys` — connects to the wish SSH server via Tailscale, TUI opens

Test Plan

  • `go test ./...` passes
  • `go build ./...` produces a clean binary
  • Deploy to a bases instance and verify post-install flow above
## Summary - Embeds Tailscale via `tsnet` so the SSH/TUI server listens on a Tailscale-only `net.Listener` — no SSH port exposed on the container's local interface - Adds a \`/tailscale\` HTTP route that shows the Tailscale auth URL (NeedsLogin), connected status, or error — allows bootstrapping and re-authenticating Tailscale from the browser - Changes all default paths from XDG (\`~/.local/share/keys/\`) to \`/var/lib/keys/\` so the binary works without any env var configuration in a container - Adds a \`Basefile\` so \`bases install keys\` deploys the service with zero manual configuration ## Post-install flow 1. \`bases install keys\` — container created, binary built, SSH host key generated, service starts 2. Visit \`https://keys.<domain>/tailscale\` — click the Tailscale auth link 3. \`ssh keys\` — connects to the wish SSH server via Tailscale, TUI opens ## Test Plan - [ ] \`go test ./...\` passes - [ ] \`go build ./...\` produces a clean binary - [ ] Deploy to a bases instance and verify post-install flow above
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- tsnet: remove watchAuthURL goroutine — use st.AuthURL from StatusWithoutPeers directly
- tsnet: use ipn.Running.String() instead of magic string "Running"
- main: handle SIGTERM/SIGINT to close tsnet node cleanly
- server_test: replace nil store with testutil.NewStore(t) in Tailscale route tests
- server_test: add t.Parallel() to TestHTTP_* tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Install binary to /usr/local/bin via GOBIN
- Set up OpenRC init script (stdout+stderr → /var/log/keys.log)
- Register service to start on boot
- start task uses rc-service instead of direct binary exec

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
arne closed this pull request 2026-03-27 14:26:57 +01:00

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
arne/keys!1
No description provided.