tailscale/gokrazy
Brad Fitzpatrick 0fb8226708 gokrazy, tstest, cmd/vnet: switch amd64 kernel to gokrazy/kernel.amd64
The tailscale/gokrazy-kernel module was a fork of rtr7/kernel that
stalled at Linux 6.8.9 (July 2024). All of the kernel config options we
had added in that fork (ENA, Xen for EC2, virtio-mmio for qemu microvm,
virtio RNG, IPv6 policy routing, netlink diag, etc) are now present in
the gokrazy project's own gokrazy/kernel.amd64 module, which tracks
current kernel.org releases (Linux 7.1.3 as of this change) and is the
gokrazy project's supported kernel for x86_64 PCs and VMs.

Switch the tsapp and natlabapp images, the natlab VM tests, and the
CI workflow to gokrazy/kernel.amd64, drop the tailscale/gokrazy-kernel
dependency, and update gokrazy/kernel.arm64 to latest while here.

Verified with TestEasyEasy, TestJustIPv6, and TestTailscaleSSH in
tstest/natlab/vmtest with --run-vm-tests.

Updates #1866

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I90c3765a4e18f5609b4d77b51ac38d17c8e3688a
2026-07-15 11:45:02 -04:00
..
build gokrazy/build: expose AMI pipeline as composable steps 2026-07-15 15:15:17 +02:00
gafpush cmd/tailscale: add 'configure pve-appliance' to make Proxmox VM of appliance 2026-07-07 13:12:13 -07:00
mkfs all: apply go fix 2026-07-10 17:39:16 -07:00
natlabapp gokrazy, tstest, cmd/vnet: switch amd64 kernel to gokrazy/kernel.amd64 2026-07-15 11:45:02 -04:00
natlabapp.arm64 go.mod, gokrazy: bump to fork of gokrazy/gokrazy init process for syslog change 2026-04-29 11:27:41 -07:00
tsapp gokrazy, tstest, cmd/vnet: switch amd64 kernel to gokrazy/kernel.amd64 2026-07-15 11:45:02 -04:00
tsapp-pi.arm64 cmd/fbstatus: add framebuffer status display for the Tailscale appliance 2026-07-02 09:24:01 -07:00
tsapp-vm.arm64 gokrazy: read config from EC2 user-data on the appliance 2026-07-14 10:29:19 +02:00
.gitignore gokrazy,tstest/integration/nat: add Gokrazy appliance just for natlab 2024-08-13 15:26:12 -07:00
build.go gokrazy/build: expose AMI pipeline as composable steps 2026-07-15 15:15:17 +02:00
gokrazy_test.go gokrazy, tstest, cmd/vnet: switch amd64 kernel to gokrazy/kernel.amd64 2026-07-15 11:45:02 -04:00
Makefile gokrazy, clientupdate: add start of Gokrazy auto-updates, tests 2026-06-04 11:20:14 -07:00
monogok gokrazy: use monorepo for gokrazy appliance builds (monogok) 2026-02-13 16:19:14 -08:00
README.md gokrazy/build: use AWS SDK instead of shelling out to aws CLI 2026-07-15 15:15:17 +02:00
tidy-deps.go gokrazy: use monorepo for gokrazy appliance builds (monogok) 2026-02-13 16:19:14 -08:00
UTM.md gokrazy: add prototype Tailscale appliance, build tooling, docs 2024-06-03 15:01:19 -07:00

Tailscale Appliance Gokrazy Image

This is (as of 2024-06-02) a WORK IN PROGRESS (pre-alpha) experiment to package Tailscale as a Gokrazy appliance image for use on both VMs (AWS, GCP, Azure, Proxmox, ...) and Rasperry Pis.

See https://github.com/tailscale/tailscale/issues/1866

Overview

It makes a ~70MB image (about the same size as tailscale-setup-full-1.66.4.exe and smaller than the combined Tailscale Android APK) that combines the Linux kernel and Tailscale and that's it. Nothing written in C. (except optional busybox for debugging) So no operating system to maintain. Gokrazy has three partitions: two read-only ones (one active at a time, the other for updates for the next boot) and one optional stateful, writable partition that survives upgrades (/perm/)

Initial bootstrap configuration of this appliance will be over either serial or configuration files (auth keys, subnet routes, etc) baked into the image (for Raspberry Pis) or in cloud-init/user-data (for AWS, etc). As of 2024-06-02, AWS user-data config files work.

Quick start

Install dependencies:

$ brew install qemu e2fsprogs

Build + launch:

$ make qemu

That puts serial on stdio. To exit the serial console and escape to the qemu monitor, type Ctrl-a c. Then type quit in the monitor to quit.

Building

make image to build just the image (tsapp.img), without uploading it.

UTM

You can also use UTM, but the qemu path above is easier. For UTM, see the UTM instructions.

AWS

Build an AMI

go run build.go --bucket=your-S3-temp-bucket to build an AMI.

Credentials come from the AWS SDK's default chain, so authenticate any way it recognizes: aws sso login, aws configure, an AWS_PROFILE, AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY env vars, or aws-vault exec <profile> -- go run build.go --bucket=... (aws-vault injects temporary credentials as env vars). If no credentials are found the build stops with a message telling you how to log in.

Creating an instance

When creating an instance, you need a Nitro machine type to get a virtual serial console. Notably, that means the t2.* instance types that AWS pushes as a free option are not new enough. Use t3.* at least.

As of 2024-06-02 this builder tool only supports x86_64 (arm64 should be trivial and will come soon), so don't use a Graviton machine type.

To connect to the serial console, you can either use the web console, or use the CLI like:

$ aws ec2-instance-connect send-serial-console-ssh-public-key --instance-id i-0b4a0eabc43629f13 --serial-port 0 --ssh-public-key file:///your/home/.ssh/id_ed25519.pub --region us-west-2
{
    "RequestId": "a93b0ea3-9ff9-45d5-b8ed-b1e70ccc0410",
    "Success": true
}
$ ssh i-0b4a0eabc43629f13.port0@serial-console.ec2-instance-connect.us-west-2.aws 

Configuring the appliance

The appliance's tailscaled runs with -config=optional:vm:user-data, so a single AMI supports two ways of joining a tailnet:

  • Declarative (user-data): put a Tailscale config (the alpha0 HuJSON format) in the instance's user-data and the node configures itself on first boot. The minimal config is just an auth key:

    {
      "Version": "alpha0",
      "AuthKey": "tskey-auth-..."
    }
    

    A config present in user-data locks the CLI (tailscale set/up are rejected) unless it sets "Locked": false. Add "RemoteConfig": true to hand full remote management of the node to the tailnet admin (see Prefs.RemoteConfig) — appropriate for admin-owned fleet devices.

  • Interactive (serial console): launch the AMI with no user-data. The optional: prefix means the missing config is not an error, so tailscaled boots unconfigured and you can enroll it over the serial console (connect as above, then run tailscale up and open the printed login URL).

To require config instead (fail to boot if none is present), build an image whose tailscaled uses -config=vm:user-data without the optional: prefix.