xeiaso-net-ygnwtd.txt (23659B)
1 [1] Xe 2 [2] Blog 3 [3] Contact 4 [4] Resume 5 [5] Talks 6 [6] VODs 7 [7] Signalboost 8 9 gokrazy is really cool 10 11 Published on 09/20/2023, 3515 words, 13 minutes to read 12 13 An image of undefined - Nikon D3300, 35mm f/1.8 DX, a red formula one style car 14 speeds along a racetrack with visible tire skidmarks. Photo by Xe Iaso I worked 15 for Tailscale at the time of writing this article. I wrote this on my own time 16 out of my own volition. 17 18 When you deal with Linux, you end up hearing about "distributions" as different 19 "flavors" of Linux combined with a bunch of other tools. This is mostly true, 20 but it's slightly missing the forest for the trees. 21 22 Consider this famous and often misunderstood quote by Richard Stallman: 23 24 I'd just like to interject for a moment. What you're referring to as Linux 25 is in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus 26 Linux.Linux is not an operating system unto itself, but rather another free 27 component of a fully functioning GNU system made useful by the GNU 28 corelibs, shell utilities and vital system components comprising a full OS 29 as defined by POSIX. 30 31 Many pages of ink have been spilled over analyzing this quote, and a lot of 32 them fall short of really getting at the heart of the matter. What this 33 actually means is something like this: 34 35 By itself, Linux is useless. It does boot the system, it does interface with 36 hardware, but without a bunch of other tools, it's not very useful. It's like a 37 car without a steering wheel, or a boat without a rudder. It does something, 38 but it's not very useful. The real value of things like the GNU project, 39 systemd, openrc and other tools in that vein is that they make Linux useful. 40 They make it into a complete system that you can use to do things. They are the 41 proverbial steering wheel and rudder in the metaphor. 42 43 Mara is hacker 44 <[8]Mara> Fun fact, if you try to boot a Linux kernel without an init process, 45 it'll just panic and crash! 46 47 Most Linux systems on the face of the planet are built with GNU tools and 48 utilities. In order to compile the Linux kernel, you need to use [9]GCC. In 49 order to run ls to list files in the current directory, you need to use [10]GNU 50 coreutils. Every dynamically linked program uses [11]glibc for performing basic 51 system interactions like writing to files or opening network sockets. 52 Everything is built on top of the GNU toolset. This is why Stallman is so 53 adamant about calling it GNU/Linux. It's not that he's trying to take credit 54 for Linux, it's that he's trying to give credit to the GNU project for making 55 Linux useful. 56 57 However, there's a lot of room for nuance here. For example, [12]Alpine Linux 58 is a Linux distribution that uses [13]musl libc instead of [14]glibc and [15] 59 busybox instead of GNU coreutils. It's still a Linux distribution, but it 60 doesn't use the GNU toolset. It's still a Linux distribution, but it's not GNU/ 61 Linux. 62 63 Mara is hacker 64 <[16]Mara> Also, for the record you can build the Linux kernel with clang, but 65 that's a whole other can of worms. For one, GCC supports many more targets than 66 clang likely ever will, but in general there are some compromises you need to 67 make until clang implements some GCC-specific compiler extensions a bit better. 68 Google, Facebook, and a few other companies do run LLVM compiled kernels in 69 production though, so it's probably closer to viable than you think. Especially 70 if you use ChromeOS or Android. 71 72 So, what is a Linux distribution? It's a collection of tools that make Linux 73 useful. It's a collection of tools that make Linux into a complete system. It's 74 not a "flavor" of Linux (though this conceptually can exist with alternative 75 kernels like the Zen kernel patchset), it's a system that just so happens to 76 make Linux useful. 77 78 As a counter-argument, consider the reason why Linux runs on more devices 79 worldwide than there are people: [17]Android. Android does use the Linux 80 kernel, but it doesn't use any GNU tools in the stack at all. You can't take 81 programs that are compiled against other Linux distributions and run them on 82 Android. You can't take programs that are compiled against Android and run them 83 on other Linux distributions. 84 85 Aoi is wut 86 <[18]Aoi> Wait, so does this mean Android's not a Linux distribution? What is 87 it then? 88 89 I'm going to argue that Android is not a Linux distribution unto itself. 90 Android is a Linux implementation. It uses the Linux kernel, but that's where 91 the similarities with the rest of the ecosystem end. Android is its own little 92 world where there's just enough system tools to get the system running, but 93 once you get into the UI, it's a completely different world. It's a completely 94 different ecosystem. It's a completely different operating system. 95 96 Aoi is wut 97 <[19]Aoi> So what's the difference between a Linux distribution and a Linux 98 implementation? 99 Cadey is enby 100 <[20]Cadey> It's a bit of a fuzzy line, but I'd say that a Linux distribution 101 is a collection of discrete tools that make Linux useful, and a Linux 102 implementation is a cohesive collection of bespoke tools that make Linux into a 103 complete system. Really, you could argue that if it has /bin/sh, it's a Linux 104 distribution. 105 106 gokrazy 107 108 [21]gokrazy is a Linux implementation that I've used off and on for a few years 109 now. It's a very interesting project because everything on the system is 110 written in Go save the kernel. The init process is in Go (and even listens over 111 HTTP to handle updates!), every userland process is written in Go, and even the 112 core system services are written in Go. 113 114 Out of the box a gokrazy install comes with these basic tools: 115 116 • The init process that is mandated to be the parent of all userland 117 processes by the Linux kernel. 118 • A [22]DHCP client that automatically configures the network interface. 119 • A [23]NTP client that automatically sets the system clock. 120 • A little tool to save randomness from the kernel to a file so that it can 121 be used to seed the random number generator on boot (because the Raspberry 122 Pi doesn't have a robust hardware random number generator) 123 124 That's it. Everything else from the web UI to A/B update logic is written in 125 Go. It boots in literal seconds, uses an insanely small amount of RAM out of 126 the box, and runs with nearly zero overhead. When you configure your gokrazy 127 install to run additional software, you do so by adding the Go command path to 128 a configuration file and then updating to trigger a reboot into the new 129 version. 130 131 Here's an example of what my gokrazy virtual machine's file tree looks like: 132 133 / # tree etc gokrazy user 134 etc 135 ├── breakglass.authorized_keys 136 ├── gokr-pw.txt 137 ├── gokrazy 138 │ └── sbom.json 139 ├── hostname 140 ├── hosts 141 ├── http-port.txt 142 ├── https-port.txt 143 ├── localtime 144 ├── machine-id 145 ├── resolv.conf -> /tmp/resolv.conf 146 └── ssl 147 └── ca-bundle.pem 148 149 gokrazy 150 ├── dhcp 151 ├── heartbeat 152 ├── init 153 ├── ntp 154 └── randomd 155 156 user 157 ├── breakglass 158 ├── fbstatus 159 ├── qemu-guest-kragent 160 ├── serial-busybox 161 ├── tailscale 162 ├── tailscaled 163 └── waifud-gok-agent 164 165 That is the entire system. It's all stripped down to these few programs, 166 configuration files, and one symlink for DNS resolution. This is a very minimal 167 system, and it's all you need to run statically linked Go programs. It's very 168 easy to deploy your own services to it too. It's probably the easiest platform 169 I know of that lets you just deploy a Go binary and have it run as a service, 170 automatically restarting when it crashes. 171 172 The tooling 173 174 When I used gokrazy back in the day, you had to use a command line called 175 gokr-packer that you passed a bunch of command line flags to with information 176 about all the Go programs you wanted to run on the machine, configuration for 177 those programs, and any other meta-information like where the update tool 178 should push the image to. It was a bit of a pain to use, but it worked. 179 Recently the [24]gok tool was added to the project, and this has been 180 revolutionary when it comes to using and administrating gokrazy installs. 181 182 Essentially, gok is a wrapper around the existing gokr-packer logic with a JSON 183 file to store your configuration details. It's a lot easier to use, understand, 184 and automate. You don't have to remember command line flags or maintain 185 unwieldy scripts. You just edit a JSON file and push updates with gok update. 186 It's amazingly simple. 187 188 Setting up a gokrazy machine 189 190 As an example, I'm going to show you how to install a bunch of tailnet addons 191 to a gokrazy machine. I'm also going to assume that you don't have a gokrazy 192 install set up yet, so we'll need to install it. To do this, we'll need to do a 193 few simple things: 194 195 • Install the gok tool. 196 • Create your gok configuration. 197 • Install Tailscale on the machine. 198 • Create your "seed" image with gok overwrite. 199 • Boot it on your Raspberry Pi or VM. 200 • Push any updates to the image to the machine with gok update. 201 202 First, let's install the gok tool. In order to do this, you need to have the 203 [25]Go toolchain installed. Once you have that, you can run go install to 204 install the gok tool: 205 206 go install github.com/gokrazy/tools/cmd/gok@main 207 208 Mara is hacker 209 <[26]Mara> You may want to ensure that ~/go/bin is in your $PATH variable so 210 that you can run it by the name gok instead of ~/go/bin/gok. 211 212 Next, create a new gokrazy configuration with gok new: 213 214 gok new -i casa 215 216 This will create a configuration named casa (cf: Spanish for "house") in ~/ 217 gokrazy/casa. This is where all of your configuration files will live. You can 218 edit the configuration file with gok edit: 219 220 gok edit -i casa 221 222 If you are making a virtual machine 223 224 If you are making a virtual machine, you will need to override the kernel and 225 firmware packages. You can do this by adding the following to your 226 configuration file: 227 228 { 229 // ... 230 "KernelPackage": "github.com/rtr7/kernel", 231 "FirmwarePackage": "github.com/rtr7/kernel", 232 // ... 233 } 234 235 You will need to prefix the gok overwrite and gok update commands with GOARCH= 236 amd64 to ensure that Go builds x86_64 binaries instead of ARM binaries: 237 238 GOARCH=amd64 gok update -i casa 239 240 If you don't do this, you will get arm64 binaries being built. This may require 241 manual recovery of your virtual machine. 242 243 Let's make our lives easier by installing [27]Tailscale on the machine. By 244 default, gokrazy will announce its hostname over DHCP, which usually makes most 245 consumer routers pick it up and then lets you ping it by name. When you have 246 [28]MagicDNS enabled, Tailscale can take over this logic and prevent you from 247 accessing the machine by name. 248 249 However, Tailscale is written in Go and doesn't require any of the services 250 that most Linux distributions provide in order to function. It's a perfect fit 251 for gokrazy. You can install it with gok add: 252 253 gok add tailscale.com/cmd/tailscaled 254 gok add tailscale.com/cmd/tailscale 255 256 And be sure to add the mkfs service to create a persistent partition on /perm: 257 258 gok add github.com/gokrazy/mkfs 259 260 Next, fetch an [29]auth key from [30]the admin console and make sure you check 261 that it's reusable. Then, add the following to your configuration file under 262 the PackageConfig block: 263 264 { 265 // ... 266 "PackageConfig": { 267 // ... 268 "tailscale.com/cmd/tailscale": { 269 "CommandLineFlags": [ 270 "up", 271 // paste your key here! 272 "--authkey=tskey-auth-hunter2-hunter2hunter2hunter2" 273 ] 274 }, 275 // ... 276 } 277 // ... 278 } 279 280 Mara is hacker 281 <[31]Mara> You can pass any other [32]tailscale up flags you want here, such as 282 --advertise-exit-node if you want to use your gokrazy machine as an [33]exit 283 node. 284 285 This will make your machine automatically connect to Tailscale on boot. 286 287 Next, we need to create our "seed" image with gok overwrite. First, figure out 288 what the device node for your SD card is. On Linux, you can do this with lsblk: 289 290 lsblk 291 292 And then look for the one that has the same size as your SD card. In my case, 293 it's /dev/sdd. Once you have that, you can run gok overwrite: 294 295 gok overwrite --full /dev/sdd 296 297 However if you want to write the image to a file (such as if you are doing mass 298 distribution or making a VM image), you need to use gok overwrite with a file 299 instead of a device node. This will create a 16 GB image: 300 301 gok overwrite -i casa --full gokrazy.img --target_storage_bytes 17179869184 302 303 Once you have your image, you can write it to your SD card with dd (or [34] 304 balenaEtcher) or import it into your virtual machine hypervisor of choice. 305 306 Once you have your image written to your SD card, you can boot it on your 307 Raspberry Pi or VM. 308 309 Aoi is wut 310 <[35]Aoi> Wait, so how do I log in with a shell? 311 Cadey is enby 312 <[36]Cadey> You don't. gokrazy doesn't have a login prompt. It's a single-user 313 system. There is [37]breakglass as a tool of last resort to modify things, but 314 you only have a very minimal subset of busybox to work with, so it should be 315 avoided if at all possible. 316 317 Once you have your machine booted and it responds to pings over Tailscale, you 318 can open its HTTP interface in your browser. If you called your machine casa, 319 you can open it at [38]http://casa. It will prompt you for a username and 320 password. Your username is gokrazy, and the password is near the top of your 321 config.json file. When you log in, you'll see a screen like this: 322 323 [39][gokrazy-ui] 324 325 This is the gokrazy web UI. It lets you see the status of your machine and any 326 logs that are being generated by your applications. You can also start, stop, 327 and restart any of your applications from here. It's a very simple UI, but it's 328 fantastic for debugging and monitoring. 329 330 Tailnet addons 331 332 Now that we have a Gokrazy system up and running, let's add some programs to 333 it! I'm going to list a couple tailnet addons that give your tailnet 334 superpowers. These are all written in Go, so they're a perfect fit for gokrazy. 335 336 Today I'm going to show you how to install these tools into your tailnet: 337 338 • [40]golink - a URL shortener at http://go 339 • [41]tmemes - an internal meme generator you can host at http://memegen 340 • [42]tclip - a pastebin you can host at http://paste 341 342 These tools help you augment your tailnet by giving you tools that will make 343 you and your team's life a lot easier. A URL shortener helps you link to 344 complicated Google Docs URLs. A meme generator gives you a new innovative way 345 to let off steam. A pastebin lets you share text with your team without having 346 to worry about the service you're using going offline due to no fault of your 347 own. 348 349 golink 350 351 To install golink, we need to add the golink binary to the configuration. You 352 can do this with gok add: 353 354 gok add github.com/tailscale/golink/cmd/golink 355 356 Then configure it with gok edit: 357 358 { 359 // ... 360 "PackageConfig": { 361 // ... 362 "github.com/tailscale/golink/cmd/golink": { 363 "CommandLineFlags": [ 364 "--sqlitedb=/perm/home/golink/data.db" 365 ], 366 "Environment": [ 367 // the same one from before 368 "TS_AUTHKEY=tskey-auth-hunter2-hunter2hunter2hunter2" 369 ], 370 // don't start the service until NTP catches up 371 "WaitForClock": true 372 }, 373 // ... 374 } 375 // ... 376 } 377 378 And finally push it with gok update: 379 380 gok update -i casa 381 382 It'll build the image, push it out over Tailscale, trigger a reboot, and be 383 back up in the span of a minute. Once it's back up, you can open the web UI 384 again and see the status of your golink instance at [43]http://casa/status?path 385 =%2fuser%2fgolink: 386 387 [44][golink] 388 389 And then you can start using short URLs at [45]http://go: 390 391 [46][golink-ui] 392 393 And that's it! You now have a super minimal VM running small programs that let 394 you do useful things to you. You can add more programs to your configuration 395 file and push them with gok update to add more functionality to your machine. 396 You can even add your own programs to the configuration file and push them to 397 your machine. It's a very simple system, but it's very powerful. 398 399 tmemes 400 401 Google is infamous for having an internal service named [47]memegen. This 402 allows Googlers to make internal-facing memes about the slings and arrows that 403 impact them as highly paid programmers. This is an internal service inside 404 Google that has a lot of serious investment of time and energy to make it the 405 best possible experience it can be. It's to the point that reportedly people 406 can keep up with how an all-hands meeting is going by the tone of the sarcastic 407 memes that are being posted to memegen. 408 409 The main reason this is run inside Google is to avoid information leaking via 410 memes. Yes, this is an actual threat model. 411 412 Thanks to the magic of Tailscale, you can make your own private memegen using 413 [48]tmemes. tmemes is a tailnet addon that lets you post image macro templates 414 and layer wisdom over it in the form of text. 415 416 Here's an example meme: 417 418 [49][society-if] 419 420 To add tmemes to your gokrazy machine, you can use gok add: 421 422 gok add github.com/tailscale/tmemes/tmemes 423 424 Then open your config with gok edit and add the following to your PackageConfig 425 block: 426 427 { 428 // ... 429 "PackageConfig": { 430 // ... 431 "github.com/tailscale/tmemes/tmemes": { 432 "Environment": [ 433 "TS_AUTHKEY=tskey-auth-hunter2-hunter2hunter2hunter2" 434 ], 435 "CommandLineFlags": [ 436 // change this to your desired hostname 437 "--hostname=memegen", 438 // change this to your username on Tailscale 439 "--admin=Xe@github", 440 "--store=/perm/home/tmemes" 441 ], 442 "WaitForClock": true 443 }, 444 // ... 445 }, 446 // ... 447 } 448 449 And then push it with gok update: 450 451 gok update -i casa 452 453 Then you can head to [50]http://memegen and upload a template to make your own 454 dank memes. 455 456 If you want to integrate your own tools with tmemes, you can check out the [51] 457 API documentation. This should help you do whatever it is you want with a meme 458 generator as a service. 459 460 tclip 461 462 Sometimes you just need a place to paste text and get a URL pointing to it. 463 [52]tclip is a tool that you can add to your tailnet and get exactly that. It's 464 a very simple tool, but it's very useful. It's also written in Go, so it's a 465 perfect fit for gokrazy. [53]Their recent update to remove Cgo dependencies 466 makes it possible to run your tclip node on a gokrazy machine. 467 468 To add tclip to your gokrazy machine, you can use gok add: 469 470 gok add github.com/tailscale-dev/tclip/cmd/tclipd 471 472 Then open your config with gok edit and add the following to your PackageConfig 473 block: 474 475 { 476 // ... 477 "PackageConfig": { 478 // ... 479 "github.com/tailscale-dev/tclip/cmd/tclipd": { 480 "CommandLineFlags": [ 481 "--data-location=/perm/home/tclip/" 482 ], 483 "WaitForClock": true, 484 "Environment": [ 485 "TS_AUTHKEY=tskey-auth-hunter2-hunter2hunter2hunter2", 486 "USE_FUNNEL=true" // Remove this if you don't want to use Funnel 487 ] 488 }, 489 // ... 490 } 491 } 492 493 And then push it with gok update: 494 495 gok update -i casa 496 497 And then you can start using it by heading to [54]http://paste. Install the 498 command-line tool on your development workstation with go install: 499 500 go install github.com/tailscale-dev/tclip/cmd/tclip@latest 501 502 Here's an example tclip link if you want to see what it looks like in practice: 503 [55]interjection.c. It's a very simple tool, but it's very useful. 504 505 Conclusion 506 507 gokrazy is insanely cool. It's the easiest way to deploy Go services to your 508 homelab. It integrates seamlessly with Tailscale, and is something that I'm 509 very excited to see grow and mature. I'm very excited to see what the future 510 holds for gokrazy, and I'm very excited to see what people do with it. 511 512 I've seen signs that they're going to be adding an automatic update process, 513 and that has me very excited. I'm also excited to see what other services 514 people add to the gokrazy ecosystem. I'm hoping to add a few of my own in the 515 future, and I'm hoping to see what other people do with it. 516 517 Mara is hacker 518 <[56]Mara> Spoiler alert: [57]waifud support is coming soon to a homelab near 519 you. 520 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 521 Share 522 523 Facts and circumstances may have changed since publication. Please contact me 524 before jumping to conclusions if something seems wrong or unclear. 525 526 Tags: go, gokrazy, linux 527 528 Copyright 2012-2024 Xe Iaso (Christine Dodrill). Any and all opinions listed 529 here are my own and not representative of any of my employers, past, future, 530 and/or present. 531 532 Like what you see? Donate on [59]Patreon like [60]these awesome people! 533 534 Served by xesite v4 (/nix/store/ 535 5pbrsn0khhga62ipyl043c9z22dlah4w-xesite_v4-20231122/bin/xesite) with site 536 version [61]71d942d2 , source code available [62]here. 537 538 539 References: 540 541 [1] https://xeiaso.net/ 542 [2] https://xeiaso.net/blog 543 [3] https://xeiaso.net/contact 544 [4] https://xeiaso.net/resume 545 [5] https://xeiaso.net/talks 546 [6] https://xeiaso.net/vods 547 [7] https://xeiaso.net/signalboost 548 [8] https://xeiaso.net/characters#mara 549 [9] https://gcc.gnu.org/ 550 [10] https://www.gnu.org/software/coreutils/coreutils.html 551 [11] https://www.gnu.org/software/libc/ 552 [12] https://alpinelinux.org/ 553 [13] https://musl.libc.org/ 554 [14] https://www.gnu.org/software/libc/ 555 [15] https://en.wikipedia.org/wiki/BusyBox 556 [16] https://xeiaso.net/characters#mara 557 [17] https://en.wikipedia.org/wiki/Android_(operating_system) 558 [18] https://xeiaso.net/characters#aoi 559 [19] https://xeiaso.net/characters#aoi 560 [20] https://xeiaso.net/characters#cadey 561 [21] https://gokrazy.org/ 562 [22] https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol 563 [23] https://en.wikipedia.org/wiki/Network_Time_Protocol 564 [24] https://gokrazy.org/quickstart/ 565 [25] https://golang.org/doc/install 566 [26] https://xeiaso.net/characters#mara 567 [27] https://tailscale.com/ 568 [28] https://tailscale.com/kb/1081/magicdns/ 569 [29] https://tailscale.com/kb/1085/auth-keys/ 570 [30] https://login.tailscale.com/admin/settings/keys 571 [31] https://xeiaso.net/characters#mara 572 [32] https://tailscale.com/kb/1080/cli/#up 573 [33] https://tailscale.com/kb/1103/exit-nodes/?q=exit%20node 574 [34] https://etcher.balena.io/ 575 [35] https://xeiaso.net/characters#aoi 576 [36] https://xeiaso.net/characters#cadey 577 [37] https://github.com/gokrazy/breakglass 578 [38] http://casa/ 579 [39] https://cdn.xeiaso.net/file/christine-static/blog/2023/gokrazy/gokrazy-ui.jpg 580 [40] https://github.com/tailscale/golink 581 [41] https://github.com/tailscale/tmemes 582 [42] https://github.com/tailscale-dev/tclip 583 [43] http://casa/status?path=%2fuser%2fgolink 584 [44] https://cdn.xeiaso.net/file/christine-static/blog/2023/gokrazy/golink.jpg 585 [45] http://go/ 586 [46] https://cdn.xeiaso.net/file/christine-static/blog/2023/gokrazy/golink-ui.jpg 587 [47] https://www.buzzfeednews.com/article/reyhan/inside-googles-internal-meme-generator 588 [48] https://github.com/tailscale/tmemes 589 [49] https://cdn.xeiaso.net/file/christine-static/blog/2023/gokrazy/society-if-gokrazy.jpg 590 [50] http://memegen/ 591 [51] https://github.com/tailscale/tmemes/blob/main/docs/api.md 592 [52] https://tailscale.dev/blog/tclip 593 [53] https://tailscale.dev/blog/tclip-updates-092023 594 [54] http://paste/ 595 [55] https://paste.shark-harmonic.ts.net/paste/696b9b02-90ac-4adc-a33d-d749bb6f460f 596 [56] https://xeiaso.net/characters#mara 597 [57] https://github.com/Xe/waifud-gok-agent 598 [59] https://patreon.com/cadey 599 [60] https://xeiaso.net/patrons 600 [61] https://github.com/Xe/site/commit/71d942d2664615d081d14037ad9930848f6a72b4 601 [62] https://github.com/Xe/site