Skip to content

Gate guest/boot SSH bring-up behind a nosshd build tag (opt-out)#86

Merged
JAORMX merged 1 commit into
mainfrom
jaosorior/guest-sshd-build-tag
May 23, 2026
Merged

Gate guest/boot SSH bring-up behind a nosshd build tag (opt-out)#86
JAORMX merged 1 commit into
mainfrom
jaosorior/guest-sshd-build-tag

Conversation

@JAORMX
Copy link
Copy Markdown
Contributor

@JAORMX JAORMX commented May 23, 2026

Summary

Splits guest/boot so the SSH-specific code lives behind a
//go:build nosshd opt-out tag. The default build keeps SSH on
(current behavior, no consumer changes required); passing
-tags=nosshd swaps in a stub that drops golang.org/x/crypto/ssh
and guest/sshd from the link-time graph.

This is the link-time follow-up to #85 (WP-3.1 vsock + runtime
WithoutSSH). That PR gave callers a runtime knob to skip the SSH
listener; this one lets opt-out callers also strip the SSH code from
the binary at build time.

Why opt-out (not opt-in)

The first revision of this PR made SSH opt-in via -tags=sshd,
which would have required brood-box to update its build before being
able to bump go-microvm. Reviewer feedback (rightly) flagged that as
gratuitously disruptive — there's no reason to flip the default for
the existing consumer. Inverted to opt-out: brood-box needs no
changes, and bbox-k8s adds -tags=nosshd to its bbox-agent build
when it wants the link-time elimination.

What's in the PR (one commit)

  • guest/boot/boot.go no longer imports golang.org/x/crypto/ssh or
    guest/sshd. The orchestrator now calls a single
    bringUpSSH(logger, cfg, envVars) provided by one of two new files.
  • guest/boot/ssh_enabled.go (//go:build linux && !nosshd) — the
    real impl. Owns ParseAuthorizedKeys, host-key load, listener start.
    This is what the default build links.
  • guest/boot/ssh_disabled.go (//go:build linux && nosshd) — stub.
    No-op when cfg.disableSSH is true; returns the new sentinel
    ErrSSHNotBuilt when it is false (loud-fail on misconfig).
  • Tests split by the same tag:
    • boot_test.go — option/config tests (default + nosshd, no SSH types).
    • ssh_enabled_test.go (!nosshd) — ParseAuthorizedKeys + the
      generateTestKey helper that depends on x/crypto/ssh.
    • ssh_disabled_test.go (nosshd) — verifies both stub paths
      (no-op vs ErrSSHNotBuilt).
  • Taskfile.yamltest, test-nocgo, and build-nocgo now run
    both the default and -tags=nosshd variants so CI exercises both
    code paths.
  • Host-side microvm.WithoutSSH doc and the guest/boot package doc
    both mention ErrSSHNotBuilt.

Verification

$ go list -deps ./guest/boot/                | grep -E "crypto/ssh|guest/sshd"
golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
github.com/stacklok/go-microvm/guest/sshd

$ go list -tags=nosshd -deps ./guest/boot/   | grep -E "crypto/ssh|guest/sshd"
(empty)

A small boot.Run-importing test binary built two ways:

Build Size crypto/ssh + guest/sshd symbols (go tool nm)
default 7.5 M 518
-tags=nosshd 4.0 M 0

Consumer impact

  • brood-box — no change required. The cmd/bbox-init build
    continues to work without any tag.
  • bbox-k8s — no source change required (cmd/bbox-agent already
    calls boot.WithoutSSH()). After bumping to the release containing
    this change, add -tags=nosshd to the bbox-agent build to actually
    strip the SSH code from the binary. Without that tag, the binary
    works correctly (WithoutSSH still suppresses the listener at
    runtime) but still links the SSH code — same as today.

Test plan

  • task fmt — clean
  • task lint — 0 issues
  • task test-nocgo — all packages pass under both default and
    -tags=nosshd
  • go list -deps confirms crypto/ssh present by default,
    absent with -tags=nosshd
  • Binary-level go tool nm: 0 SSH symbols with -tags=nosshd,
    518 in the default build
  • CI: confirms both variants pass on the runners

🤖 Generated with Claude Code

Split guest/boot/boot.go so the SSH-specific portion lives in two
build-tag-gated files:

  guest/boot/ssh_enabled.go   //go:build linux && !nosshd
  guest/boot/ssh_disabled.go  //go:build linux && nosshd

The default build keeps SSH on — current behavior is preserved and no
consumer changes are required. Pass -tags=nosshd at build time to swap
in the stub, which strips golang.org/x/crypto/ssh and guest/sshd from
the link-time graph entirely.

Semantics:
- Default build (no tag): SSH compiled in, runtime behavior identical
  to before this change.
- -tags=nosshd: SSH stripped. Callers MUST opt out at runtime via
  WithoutSSH; otherwise boot.Run returns the new sentinel
  ErrSSHNotBuilt and fails loud rather than silently boot without SSH.

The orchestrator in boot.go no longer imports golang.org/x/crypto/ssh
or guest/sshd directly. It calls a single
bringUpSSH(logger, cfg, envVars) provided by whichever of the two
gated files is compiled in. ParseAuthorizedKeys moves into
ssh_enabled.go (its return type references ssh.PublicKey).

Tests split by the same tag:
- boot_test.go (both builds): option / config tests with no SSH types.
- ssh_enabled_test.go (//go:build !nosshd): ParseAuthorizedKeys tests
  plus the generateTestKey helper that depends on x/crypto/ssh.
- ssh_disabled_test.go (//go:build nosshd): verifies the stub's two
  documented behaviors — no-op when WithoutSSH is set, ErrSSHNotBuilt
  when it is not.

Taskfile: the test, test-nocgo, and build-nocgo targets now run both
the default and -tags=nosshd variants so CI exercises both code paths.

The host-side microvm.WithoutSSH doc and the guest/boot package doc
both mention ErrSSHNotBuilt so callers know what to expect when they
forget to either drop the tag or set WithoutSSH.

Verification:
  go list -deps ./guest/boot/                  -> includes crypto/ssh
  go list -tags=nosshd -deps ./guest/boot/     -> no crypto/ssh

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX force-pushed the jaosorior/guest-sshd-build-tag branch from 910724e to c80ca7a Compare May 23, 2026 12:35
@JAORMX JAORMX changed the title Gate guest/boot SSH bring-up behind a sshd build tag Gate guest/boot SSH bring-up behind a nosshd build tag (opt-out) May 23, 2026
@JAORMX JAORMX merged commit 8109cb8 into main May 23, 2026
7 checks passed
@JAORMX JAORMX deleted the jaosorior/guest-sshd-build-tag branch May 23, 2026 12:49
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