A Week With Plan 9
Tales From The Dork Web #26
I spent the first week of 2021 learning an OS called Plan 9 from Bell Labs. This is a fringe Operating System, long abandoned by it’s original authors. It's also responsible for a great deal of inspiration elsewhere. If you’ve used the Go language, /proc, UTF-8 or Docker, you’ve used Plan 9-designed features. This issue dives into Operating System internals and some moderately hard computer science topics. If that sort of thing isn’t your bag you might want to skip ahead. Normal service will resume shortly.
The best way to read Tales From The Dork Web is via email. Sign up below to try it.
This week’s music comes from Jefferson Airplane. Press Play and read on. Screenshots come from various Plan 9 builds. Memes are sourced from the Internet. Renee French drew Glenda the Plan 9 bunny.
Plan 9 From Bell Labs is an Operating System designed by many responsible for Unix. It’s more an exploration of ideas than a complete OS. Much of Plan 9 made it into the Google ecosystem, the Go language, Windows and Linux. I wanted to spend a few hours a day over the course of a quiet week learning the bits of Plan 9 that interest me.
There were several things in particular that interested me:
The everything-as-a-file concept
9P, Distributed CPU, Auth and FS servers
Plan 9’s Programming Environment
Sam and Acme editors
There are several Plan 9 distributions available. The most well-known is 9Front. I settled on Richard Miller’s Raspberry Pi port. While he saw 9Front as a fork, I’d consider significant novel innovation versus a filling the base userland with cruft as a key distinction between fork and distribution. Semantics aside, Richard Miller’s port features wifi support and other Pi-specific features. Miller’s distribution is also the original Plan 9 4th Edition with minor changes. I’ll let him explain:
For the Raspberry Pi port I added one architecture-dependent directory to the kernel source, but the portable parts of the kernel, and everything outside the kernel, is absolutely untouched 4th Edition Bell Labs code. I have a ridiculous number of Raspberry Pi's, several x86 machines, and a work-in-progress RISC-V machine, all sharing a single root file system and source tree on a fossil + venti server. All very standard stuff.
I guess one man’s standard stuff is another’s wow!
Why I Didn’t Use 9Front
I started with 9Front as it looked the most active. I kept notes during the week organised by FQA section. After working through the drawing and GUI primitives, I had some notes to submit, but there was a picture that was less than appropriate.
I didn’t know who to speak to about the picture, so I asked WTF on Mastodon. One of the devs turned up, the conversation was less than constructive so I decided to redo everything using a different distribution. The original version of this issue mentioned specifics. People posted it on aggregator sites and things got ugly.
I don’t support using Tales From The Dork Web to beat people up at all. No matter what you might think you’re doing, do not use this to attack other people.
As I said in the original revision of this issue, 9Front doesn’t owe me change. I don’t owe the project more attention.
I reimplemented everything using Richard Miller’s Raspberry Pi Plan 9 port. As such screenshots here don’t always match dates. It turns out exploring Plan 9 on even your oldest Pi is an excellent experience. If you don’t have one it’ll work in Qemu. I tried other distributions but I found Miller’s Pi distro the best overall.
After this issue was published, Richard graciously got in touch with me. He pointed out that his Plan 9 port uses Fossil but not Venti. Fossil is a file/archival system while Venti looks like a form of Network Block storage. He’s dangled “the adventure of (effortless instantaneous) snapshots and (deduplicated) full file system history, that you get with a full fossil + venti system”, so I think I’ll explore this at some point.
Day 1 - New Year’s Eve
Installing Plan 9 on a Raspberry Pi is easy. Download, unpack and write the image. You’ll have more fun with a keyboard, 3 button mouse, HDMI connection and Ethernet cable. Before boot I changed the Pi card’s cmdline.txt to read (on one line):
readparts=1 nobootprompt=local user=glenda nvram=#S/sdM0/nvram bootargs=local!#S/sdM0/fossil ipconfig= authdom=linux sysname=gentoo
The first thing I noticed was the responsiveness on a Raspberry Pi 3B. It’s quicker than Raspbian by a country mile, albeit with quirks. Quanstro’s newbie guide is very helpful for that first 30 minutes of use. If you install Plan 9, make sure you take it with you.
Unfortunately only my teensiest keyboard worked and it’s horrific to type on. I followed these steps to connect to my Plan 9 CPU server across my network via Drawterm. I spend most of my day in remote session tools like SSH, Tmux and VNC and RDP. Drawterm didn’t feel too different to what I’m already used to.
I read Devine Lu Linvega’s Rio notes and followed some of Sigrid’s article on applying patches to enable OS themes. As this is as close as Plan 9 gets to over-the-top theming I called the system gentoo. I used the topng command to convert the screenbuffer file to a PNG across an FTP server as though it was a local file.
Day 2 - New Year’s Day - Getting To Know Plan9
Rio provides Plan 9’s GUI, which relies on a 3-button mouse for interaction. The shift key works in-lieu of a middle button. This gets tedious, so try clicking your scroll-wheel. The left mouse button selects. The middle button shows a contextual menu. The right mouse button lists other menu options. Plan 9 also features mouse chording. This means holding several buttons like a piano chord for extra functions. It’s mostly for cut and paste.
Menus appear when mouse buttons are held. Letting go selects an option. The right button menu’s first option is new. You can draw out a terminal window with the right mouse button when it’s selected.
Inside terminal windows, left and right keys act as normal. The up and down arrow keys scroll the window, not the cursor. The cursor location is set by left mouse click.
Various Plan 9 comp-sci papers live under /sys/docs. These are best viewed with the page command. This appears to render PDF files as images, or at least text can’t be selected. The first paper I read was on the sam text editor.
The sam text editor is a text editor with a command language. It shares concepts with vi and ed but has a very different implementation. When opened, sam displays a window containing two smaller blank windows inside. Holding down the right mouse button and selecting the text file changes the pointer. Right-clicking in the bottom window puts the text in the bottom and a sam command line at the top. Right clicking in the top makes text fill the window.
The editing experience is like a worse Windows notepad. The top window provides a command line interface for manipulating text. For example, to save enter ‘w’ (write). To quit, enter ‘q’. The mouse-driven context switching between writing and command windows was painful. That’s not to say sam can’t work for you. It just didn’t for me.
Web browsing on Plan 9 is a little like passing a kidney stone. Plan 9 mounts web-connectivity via the webfs filesystem at /mnt/web. There’s an example web client on the Pi distribution in /sys/src/cmd/webfs/webget.c.
This sounds like I disliked Plan 9 at first, but that's not true. It’s not bad, it’s just incomplete. Exploring WebFS was worth the disorientation. I explored it by pulling weather reports from wttr.in. Wttr.in only sends ANSI text if the user-agent matches that of curl. I modified the webget.c example to set a matching user-agent and it pulled the data down first time. No sockets needed.
Plan 9’s native terminal isn’t ANSI compliant. I emulated and ANSI compliant terminal with the vt command. ANSI glyphs weren’t rendered. I’m sure I could make it better but I was more interested in WebFS workings than front-end output.
Day 3 - 2nd Jan - Security Model and Databases
Most Operating Systems have a root or administrator user. This often comes with special features like raw socket access. In Plan 9 the host owner account (‘glenda’ by default), is a normal user. Some services run as glenda and as such the glenda user has elevated access to these services. That aside I saw no special status given to the account.
Any multi-user system needs some form of authentication mechanism. Plan9 has an encrypted store (secstore) for long-term secret storage. Factotum provides run-time key-value storage exposed as a filesystem. Security in Plan 9 documents this exceptionally well.
Update: Richard Miller told me this:
Have another look at factotum: you'll find it's more than a passive store. The clue is in the name: a factotum is a helper who does things on your behalf. The factotum process not only keeps your secret keys but performs all the critical crypto operations with those keys within its own address space, so a hacker attaching a debugger to your shell or the cpu command or any other user process (nearly), or looking at core dumps or swap images from same, will not find any security-leaking key material.
Well Richard, if you’re going to dangle these concepts in front of me I’m gonna jump for them! I’ll write more about Factotum in the future when I spend more time with it.
I use ed25519 SSH keys but Plan 9 only supports RSA. After generating and copying an RSA key across to my OpenBSD laptop I was able to SSH in from Plan 9 via the vt terminal. I used password-based authentication to access a freshly installed Raspberry Pi elsewhere. SSH and factotum behaved differently in drawterm across different distributions. I haven’t looked into why.
Factotum is an agnostic key/value tuple store that just happens to be good for secrets. Factotum exposes itself to the OS through a filesystem. The structure resembles the webfs filesystem.
The man page is excellent. The UX is terrible. Still, it’s a mind-blowing concept.
These sentences became my Plan 9 mantra for the week.
Thumbing through the wpa client I realised how often I referred to the pre-installed source code. For laypeople still reading this is highly unusual. Plan 9’s source code is highly readable, even for bad coders like me.
Another way Plan 9 exposes the everything-as-a-file model is the network database (NDB). This lives in /lib/ndb with networking exposed through /net. As with /proc, the /net hierarchy is oddly similar to Linux in some ways. The /net hierarchy is Plan9’s network communication interface. Network connections are handled through this instead of conventional sockets.
The network database stores network configuration settings in several places. This uses a brilliant NDB flat-file database structure. Users query the NDB database using tools under /bin/ndb. What makes NDB especially interesting is that it's a general purpose text-based database. Gavin Freeborn has an amazing tutorial on getting started with ndb. NDB is also available for non-Plan 9 systems thanks to plan9port. If you use the Go language or Google’s Cloud Products you may have used NDB without knowing it.
Day 4 - 3rd Jan - Namespaces and 9P
At a fundamental level a namespace is a way of referring to an object’s surface area by name. That sounds abstract, so let me back it up.
Despite Plan 9’s world-view, a lot of stuff isn’t a file in the real world. A network is a network. A website is a website. OS designers have to choose how applications will interact with these things. In Plan 9 filesystems are the de facto interaction medium. Filesystem mounts are stitched together into a patchwork quilt called a namespace. A namespace is a map of mounts in shell script form, rather than the territory. Just because you can mount something doesn’t mean you can access the contents.
It’s possible to create entire network services using nothing but shell scripts. This barely scratches the surface of what’s possible. Mount the audio file for a system on another continent and you can play audio directly to it. Need to connect two Plan 9 systems but only one has a network card? Import the networked system's /net hierarchy over serial and borrow the network connection. Need to connect to the office? Import your office desktop’s /net for an instant tunnel. There's no distinction between local and remote debugging. You can mount a remote /proc filesystem over 9p and use a local debugger.
If that sounds interesting check out The Use of Namespaces in Plan 9 under /sys/doc. As with all core Plan 9 papers, it’s well written. This paper also details the 9p protocol underpinning everything.
9P is genuinely mind-blowing. There is no distinction between local and remote resources. There are only those mounted in the namespace and those that aren’t. 9p makes any resource presentable as a filesystem shareable anywhere in the world.
Day 5 - 4th Jan - Plumbing
When we open a document on an Operating System we expect it to know which application to open. A PDF should open in a PDF viewer. A photo should open in a photo viewer. But how does Plan 9 know what to open? The answer is plumbing.
Plumbing uses a text-based filesystem to manage what happens when a file is accessed. The plumber can check the filename, source, destination, content and act on it. Here’s what rules look like:
That might look unimpressive at first. The result is that the user can define what to do with content instead of the OS or Application vendor. What happens when you mix ‘everything-is-a-file’ with ‘perform-actions-based-on-file-criteria’? Magic. It doesn’t need to matter where the file is from. Plumbing can act on it specifically or regardless.
Plumbing makes all text hypertext. Highlight a word and send it to the plumber. The plumber acts based on the rules. Select the package number from a delivery notification email. Plumbing could query deliveries without leaving your mail client. Plumbing is like file associations on steroids. In this case the steroids themselves are also on steroids.
Day 6, 5th Jan - ACME
ACME is often described as an editor. In reality it's a structured text user-interface. This falls somewhere between elements of tmux and the twin Textmode Window Manager. It looks confusing at first but has great ideas. ACME creates windows with text editing capabilities inside. But it’s so much more than an editor.
Mouse buttons work differently to the rest of Plan 9 which is frustrating at first. After some time using Acme I wish the rest of Plan 9 acted like this. In the screenshot below I have four editing panes. I opened the text file in the top-left pane by typing the full location in the title bar and clicking the right mouse button. Yes, that’s correct.
I typed the word ‘win’ into the editor and middle-clicked it, which opened the bottom left window. ‘win’ spawns a command prompt in Acme. I then middle-clicked NewCol to create the right-hand column. In a new window I typed ‘<astro’. I selected the text with the middle button. When I let go the astro command ran and the output replaced the text.
There is so much more to this that I can’t even begin to cover it here. If you’d like to see more of Acme’s sheer Black Magic Fuckery, Russ Cox’s video is superb.
Of course Acme also exports a filesystem. This allows applications to interact with Acme’s contents and the application itself. It should be possible to edit a script in Acme that:
that when run from within Acme
edits the files containing the contents of the Acme window (i.e. the script)
modifies the contents of the Acme window, and saves it
and launches the script being edited in the Acme window (i.e itself).
Acme is the M.C. Escher art of text editing.
Day 7 - 6th Jan - Programming
Plan 9 has it’s own C dialect, distinct from others you may be familiar with. There are enough gotchas to make porting painful, but it’s close enough for anything from scratch. Plan 9 splits compilers by architecture. It does this using almost randomly numbered filenames for compiler and linker. Programming Plan 9 in C was disorienting. It’s not bad, it’s just very different to anything I’m used to.
While Acme has amazing features, it has it’s share of annoyances. I was often tricked by the scrolling-the-window-but-not-the-cursor behaviour. There’s no syntax highlighting. You can jump to specific line numbers using the Sam command language but there’s no numbering. In some ways Acme is the ultimate in customizability. An editor where you can edit the menu bar is almost infinitely flexible. In other ways it’s not. For example, you’re stuck with Acme's tab handling unless you change and recompile the source.
Update: Richard Miller kindly pointed out there is a Tab command that can be used to change tab width. I also found a $tabwidth variable but haven’t tried it.
Yet Acme is incredibly powerful. You can run a terminal from it, use page to view docs or use the web command to view web pages. There’s even tic-tac-toe for it.
The C flavour will catch you out at times. The compiler naming is mildly awkward but manageable. Things got easier after building blocks for file i/o, drawing and window management. Standing on the shoulders of previous travellers helped immensely. There are other languages available and of course the rc scripting language. It is nice to have consistent tools for writing GUI applications. The drawing primitives were a joy to use. The GUI menu management was pretty sane compared to most other tools I've used. If this was in a cross-platform GUI toolkit I’d definitely try it.
Plan 9 is as filled with unpolished brilliance as Mozart’s Requiem. It’s the Sagrada Familia of Operating Systems. It’s creators left long ago but people keep building on the scaffolds. If nothing else, it’s a collection of fantastic ideas never intended for mass consumption. This is The Holy Mountain of Operating Systems.
Is this a production-grade OS? Hell no. It’s clunky, unfinished, and the filesystem model feels consistent but forced. Not everything needs to be complete. As an exploration rather than a product, I think Plan 9 is a success. Plan 9 is the Unix kool-aid acid test, brought to you by Bell Labs’ Merry Pranksters.
Richard Miller’s Plan 9 Pi distribution is a great way to give a drawer-dwelling Raspberry Pi or two a new lease of life. Even if you go no further than a wet weekend afternoon figuring it out, it’s more than you’d have done with it otherwise.
Follow the White Rabbit. Turn on, Drawterm in and hop out.
Things You May Have Missed
Jonathan Blow’s talk covers more than just civilizational collapse. It goes deep into the decline of software quality and the inter-generational loss of technical knowledge. This really is an excellent talk worth watching, and explains a lot as to why your computer is so freaking slow.
Kartik Agaram is building a computer anyone can audit. He’s spent the whole of 2020 working on his Mu Computer to make it a reality. I’m impressed how far he’s come. Oriol Ferrer Mesià has been building modern retro computer terminals.
Phaedra is the most Gemini thing I’ve seen this year. Öppen’s pulled a blinder with a 55kb (that’s right) Android Gemini client that runs all the way back to API 1. The only possible restriction comes with TLS on older devices. Also worth checking out is the Ariane client on the same page.
MVG Goes through the hated Lenslok DRM, possibly the first (and worst) Captcha. I remember bit flipping Lenslok on ZX Spectrum games as a kid. The Apple firmware protection I bypassed used similar state of the art 80s techniques. Plus ca change, eh?
The CIA have released all of their UFO documents. You can download ISOs of the PDFs, as well as some PDFs that now have indexed text all from The Black Vault.
Finally, the regrettable decline of Space Utopias shows the need for optimistic sci-fi.
Periwinkle wrote some brilliant songs from an indigenous American perspective. Her words from 1981 ring just as true today. If you like this I’d recommend the rest of the album, from Columbus had six ships to Ode to an Indian Swan. I’d like to end with a quote from holocaust survivor and Nazi hunter Simon Wiesenthal:
For evil to flourish, it only requires good men to do nothing.
I hope you’ve enjoyed this issue of Tales From The Dork Web. I’ll be back in two weeks with another issue. If you’d like it in your inbox you can sign up below.