diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 6e7b25550..bb0c99d80 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -3220,6 +3220,10 @@ func (b *LocalBackend) TailscaleVarRoot() string { switch runtime.GOOS { case "ios", "android", "darwin": return paths.AppSharedDir.Load() + case "linux": + if distro.Get() == distro.Gokrazy { + return "/perm/tailscaled" + } } return "" } diff --git a/ssh/tailssh/incubator.go b/ssh/tailssh/incubator.go index c6810172d..67efa78ec 100644 --- a/ssh/tailssh/incubator.go +++ b/ssh/tailssh/incubator.go @@ -691,6 +691,9 @@ func (ss *sshSession) startWithStdPipes() (err error) { func loginShell(u *user.User) string { switch runtime.GOOS { case "linux": + if distro.Get() == distro.Gokrazy { + return "/tmp/serial-busybox/ash" + } out, _ := exec.Command("getent", "passwd", u.Uid).Output() // out is "root:x:0:0:root:/root:/bin/bash" f := strings.SplitN(string(out), ":", 10) diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 33770b396..d97c042b1 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -42,6 +42,7 @@ "tailscale.com/types/netmap" "tailscale.com/util/clientmetric" "tailscale.com/util/mak" + "tailscale.com/version/distro" ) var ( @@ -388,6 +389,15 @@ func (c *conn) doPolicyAuth(ctx ssh.Context, pubKey ssh.PublicKey) error { if a.Accept { c.finalAction = a } + if runtime.GOOS == "linux" && distro.Get() == distro.Gokrazy { + // Gokrazy is a single-user appliance with ~no userspace. + // There aren't users to look up (no /etc/passwd, etc) + // so rather than fail below, just hardcode root. + // TODO(bradfitz): fix os/user upstream instead? + c.userGroupIDs = []string{"0"} + c.localUser = &user.User{Uid: "0", Gid: "0", Username: "root"} + return nil + } lu, err := user.Lookup(localUser) if err != nil { c.logf("failed to look up %v: %v", localUser, err) @@ -396,6 +406,7 @@ func (c *conn) doPolicyAuth(ctx ssh.Context, pubKey ssh.PublicKey) error { } gids, err := lu.GroupIds() if err != nil { + c.logf("failed to look up local user's group IDs: %v", err) return err } c.userGroupIDs = gids