Skip to content

fix(setup): non-root + tailscale provisioning on fresh Debian 13 - #54

Merged
im-tyler merged 2 commits into
mainfrom
fix/nonroot-upload-and-hostkey-algos
Oct 26, 2026
Merged

im-tyler merged 2 commits into
mainfrom
fix/nonroot-upload-and-hostkey-algos

Conversation

@im-tyler

Copy link
Copy Markdown
Contributor

Provisioning a fresh OVH Debian 13 VPS as debian with --network tailscale exposed a chain of bugs. They never showed up before because the other fleet boxes are root or were only set up once. Each fix was reproduced and verified live on that box (deploy-ovh2).

Fixes

  • Host-key algorithms: teploy now offers only the algorithms known_hosts holds for the host. Before, a box first trusted by stock ssh (ed25519) failed with a mismatch when Go negotiated ecdsa. Confirmed live: the old binary fails and the new one connects.
  • Upload mode ordering: chmod now runs after cat. A 0440 target such as the sudoers audit drop-in could not be written by a non-root user, which aborted hardening.
  • sbin probes via sudo: ufw, auditctl, visudo and ufw status are in /usr/sbin, which isn't on a non-root user's PATH. ufw and auditd were reinstalled on every run, the firewall stage reported "No active firewall", and visudo was not found.
  • Tailscale auth key: joins now use --auth-key=file:<staged path>. tailscale 1.104 ignores TS_AUTHKEY and fell back to an interactive login URL, verified live. The key still never appears in argv, and the staged file is removed when the CLI exits.
  • BackendState check: the status JSON is now parsed. The compact "BackendState":"Running" substring never matched the pretty-printed output.
  • Re-run safety: re-running setup no longer wipes /var/lib/tailscale on an already-joined node. The wipe plus a re-up with the spent one-time key logged the server out. Verified live: a re-run with a fake key leaves the node joined.
  • Join errors: a failed join now shows the provider's output on timeout.
  • cron: setup installs it and doctor checks for it. Debian 13 cloud images have none, and backups and autodeploy need it.
  • DNS check: the first-deploy check now also accepts the server's interface addresses (hostname -I). A server registered by its Tailscale IP refused every public domain.

Verified live on deploy-ovh2

  • go vet ./... and go test ./... pass.
  • A full setup run as debian with --network tailscale.
  • An idempotent re-run.
  • doctor: 15 ok, 0 warn, 0 fail.
  • Static deploy, redeploy, rollback and remove, with a Let's Encrypt cert issued.
  • Container deploy (traefik/whoami): health check, HTTPS, remove.

Not live-verified: the join-output-on-timeout message. It would have meant logging the node out again.

🤖 Generated with Claude Code

im-tyler and others added 2 commits October 25, 2026 18:49
Found provisioning a fresh OVH Debian 13 VPS as `debian` with
--network tailscale. Each fix was reproduced and verified live there.

- ssh: offer only host-key algorithms known_hosts holds for the host
- ssh: Upload applies the mode after writing (0440 was unwritable off-root)
- harden/setup: sbin probes (ufw, auditctl, visudo, ufw status) via sudo
- network: tailscale/headscale join via --auth-key=file: (CLI ignores
  TS_AUTHKEY); parse status JSON instead of a compact substring
- setup: leave an already-joined tailnet node alone on re-run (the
  unconditional state wipe logged servers out); surface join output on
  timeout
- setup/doctor: install and check cron
- deploy/validate: DNS check accepts the server's interface addresses
  when it is reached over a mesh IP

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he redirect

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@im-tyler
im-tyler merged commit 511cb85 into main Oct 26, 2026
1 check passed
@im-tyler
im-tyler deleted the fix/nonroot-upload-and-hostkey-algos branch October 26, 2026 02:01
@im-tyler im-tyler mentioned this pull request Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant