(λ (x) (create x) '(knowledge))

The Old Computer Challenge

Showing Abandoned Hardware a Bit of Love · August 24th, 2021

A few weeks ago I stumbled across this wonderful little blog post written by Solene, where she and a cadre of like minded friends spent a week using only their oldest computers. For most this meant something with a gig of ram (which was then software limited down to 1/2gb), and some sort of 2000's CPU on old 5400rpm hdds. Nice Windows Vista era stuff. Some took things further, one challenge used a DEC Alpha workstation running BSD, actually a lot of challengers ended up running a BSD or a Linux distribution. Reading through the various posts where people described their workflows and limitations really interested me, and it wasn't long before I set out to try the challenge myself. However as anyone who reads this blog regularly knows, I already have a bit of a penchant for ascetic systems, in fact like many posts this one was written entirely on my Droid4. How can I get more limited than that? I honestly struggled a bit with that question, I could have dug back up my Nokia n900 with it's single core armv7 cpu and 256mb of ram, but that was happily a daily driver for about a year, hardly a challenge. But outside of that most of my systems are Intel Celeron based nucs, or things well outside the challenge requirements, except one; my Viliv S5.

The Challenge & The Hardware

So for the challenge itself there are only a few rules:

  • A Single Core CPU
  • 512MB of RAM Max
  • Replace all personal computing with this system for a full week

Super straight forward, you can use whatever operating system you want, whatever hardware you want, just stick within the resource limitations and you're golden. Solene is very explicit that this is for personal computing only as well, this doesn't interfere with work in any form or fashion. There's also a caveat in there that if you need/want to VNC/SSH into a more powerful computer, then you can do that, but I tried my best not to do that for the bulk of my workflow. In the beginning of the challenge I actually had to use my droid4 for a couple of days while I tried to get my Viliv up and running, so in some sense I feel like that falls into that escape hatch clause, but once everything was running I stuck strictly to the Viliv.

So wait, what is a Viliv? I think I got that question a few dozen times in the past couple of weeks from friends and family. Well, it's an old Ultra Mobile PC (or umpc for short). Initially it came with Windows XP loaded on it, but that was long since abandoned, I think I wiped it within hours of getting it many years ago. In retrospect I should have backed it up to a drive, it had a neat custom software keyboard and interface that made the UMPC easy to use without a keyboard attached, all you needed was the integrated PS/2 mouse. For a little while I used the Viliv as a mobile console when I worked for Techknow, I had a suite of troubleshooting tools and automated fixes built into Emacs that I would use in the field. In fact I remember standing on top of a ladder, plugged into one of the timers running diagnostics and fielding questions about my weird device. Good times. Back then the Viliv S5 ran Debian 9, and it worked more or less flawlessly. Udev, graphics, everything except for the wireless interface; well that is until an unfortunate apt-get update broke it all, then it went onto a shelf to be fixed and I never got around to it. Techknow went out of business and it immediately lost all functionality and priority as life changed. So I brought it out of retirement just for this challenge!

Here's the viliv in all of its glory running that very Debian 9 setup with Openbox! Unfortunately a scrot was the only image I could find from when it was installed, I didn't think to take another photo before I started installing Alpine.

Viliv s5 running Debian 9 + Openbox

And these are the hardware specs. If you're a long time Linux user, you'll probably immediately pick up on the fact that the Atom cpu is only of the infamous first generation Poulsbo chipsets. It is every bit as miserable to work with as you imagine, even today.

  • Atom z520
  • 1Gb Ram
  • 32GB zip ssd
  • Edimax usb wlan
  • 5.5in Integrated display
  • Integrated PS/2 Mouse

Without further ado, here's how all of that went! If it seems disjointed, that's because I tried to just write in the moment as I went, but also went back and fleshed some of it out during the creation of this post, I tried to encapsulate those moments in (()).

The Challenge Day by Day

Day Zero - Setup and Goals

Today I setup my Viliv s5, it's a quirky little 32bit system, it has a gig of ram, and a 2 thread single core intel atom z520 cpu, plus a speedy 32gb pata ssd! I've had this thing for a minute, it used to run Debian 9 and was used a field support tool when I worked at Techknow.

But all of that is long past, so now it's time for it to be a toy! I spent the first night ssh'd into it from my Droid. I feel like maybe that's a little bit cheaty, but this system has a single usb port, a weak battery, a small 7in screen, and the wireless drivers don't work natively! I had to hook it up to a life support dongle just to get Alpine installed and working. My initial gut reaction here was to try and maybe get Plan9 to work on it, but sadly it just refused to render, my guess is that it's an issues with the gma500 Poulsubo driver that this system uses. The obvious choice is to just install Alpine.

Horrible blurry photo of the alpine install going

In fact, that's what I spent most of last night doing, insofar as config goes I just pulled a tried and true i3wm, the same one that I use on my nokia n900 and droid4, and then all of the dots, some books, and tools etc.

Having a cli based workflow already makes all of this pretty easy, so long as I can pull in something like fennel/lua, go, or a scheme/lisp I can create. If I can get mg/emacs I'm good for editing and writing. And the rest of my tools are all cli, like lynx and mocp. That's truthfully my daily workflow regardless of what system I use, so this isn't too jarring yet.

I think for this I want to take the chance to port gma500 support to alpine, just for me, but then for everyone! and maybe document that a bit. ((This actually already existed, it's 2021, not 2003)).

I want to get a host based inferno instance running on this sucker too! why? because I wanted plan9 on it, and that didn't work, but inferno should work if I can get the graphics to work well. I want to also maybe see about getting the native wireless chipset working here, when I tried years ago it was a complete flop, it may still be a complete flop, but I want to try my hand at some kernel stuff. That might be a good excuse to learn rust, or do it in C, and that should give me an excuse to play with nix!

Lofty goals right? But I'm also doubly provisioned (should only have 1/2gb of ram, and 1 thread but I can't disable the cpu thread, and since I can't do that I'll try and keep the ram for compilation's sake)

Day One - Fighting gma500

Getting the gma500 graphics to work wasn't really THAT bad. It's the keyboard that's a problem now. See there's kernel support for Poulsubo now, so gma_gfx was just detected. I had to add a little 10-psb.conf to /etc/X11/xorg.conf.d to get it to work, and in that I just explicitly set the gma graphics to use the modesetting drive.

Viliv s5 running i3wm on Alpine

This limits me to 2D graphics, but considering what I want to use this Viliv for it shouldn't have been a big deal. In fact I even got it to launch i3 and run my little block configuration! It looked super sweet.

However I spent the rest of this day, and the beginning of Day2 fighting with evdev and libinput. Once I got X to launch it would stop processing input from my keyboard and the integrated mouse on the device.

A bit of a nonstarter, I couldn't even get this to work in a plain xterm, startx session, and it wouldn't even let me swap TTY. In fact none of the lights on the keyboard registered either it was just dead in the water.

I spent WAY too much of my time working with this, I would ssh into it from my Droid4, much with X in various ways, poke the keyboard, restart the system. I frankly have thus far done nothing productive or interesting with the viliv other than install the base OS and then troubleshoot.

Day Two - Reigning Things In

I give up on X. It is not worth the amount of effort that this has taken me. As it is I'm over provisioned on hardware and need to adjust down.

I've been using my phone and a couple of other computers to ssh into this sucker just to try and get it working to a point where I can participate in the challenge. It's all rather silly at this point. So I give up on X and will no longer be using my phone, support computers, or anything else to try and troubleshoot this.

We've got a working terminal, tmux, and various other tools. I managed to get networking with a dongle and probably won't go any further into "how do I support this ancient shit hardware set" because this device has gotten Z E R O love from anyone, including the manufacturer. And if you think I'm joking, just look at the specs and then combine that with the form factor and plethora or proprietary input ports. It's all VERY ridiculous.

Since I'm finally starting the challenge, lets go back to basics. Here's what I'm working with.


Distro: Alpine Linux Edge i686
Kernel: 5.20.52.0-lts
CPU: Intel Atom Z520 (2) @ 1.333GHz
GPU: Intel US15W/US15X SCH [Poulsbo] Graphics Controller
RAM: 995MB
HDD: Pata zip SSD 32GB (28G usable)
Swap: 1.9Gb (the alpine base install did this)
Resolution: 1024x600
  

As you can tell, small screen, weak processor, but I have too much ram and a massive swap for no reason. We'll fix all of that and try to disable one of the cpu threads, drop swap to 512MB and drop ram to 512MB as well. Most of that can be handled with kernel parameters. Those parameters are:


	mem=512M nr_cpus=1
  

Solene suggested adding these to the grub config, but I use extlinux, so it's really /boot/extlinux.conf for me. It works the same way regardless since they're boot parameters. Here's the extlinux.conf update.


# Generated by update-extlinux 6.04_pre1-r9
DEFAULT menu.c32
PROMPT 0
MENU TITLE Alpine/Linux Boot Menu
MENU HIDDEN
MENU AUTOBOOT Alpine will be booted automatically in # seconds.
TIMEOUT 30
LABEL lts
  MENU DEFAULT
  MENU LABEL Linux lts
  LINUX vmlinuz-lts
  INITRD initramfs-lts
  APPEND root=UUID=7c63f845-69cd-445d-a9ad-295f07852b30 modules=sd-mod,usb-storage,ext4,mem=512M,nr_cpus=1 ootfstype=ext4

MENU SEPARATOR
  

Dealing with the big old honking swap is just as easy, we just delete that through fdisk, who needs swap anyways?


sudo swapoff
sudo fdisk /dev/sda
p
d 2
w
  

Great now we've got rid of the swap, but the disc space is still there, so lets just put back a smaller one. I could have just resized this, but lazy.


sudo fdisk /dev/sda
n p ENTER +512M
t 2 82
w
sudo mkswap /dev/sda2
sudo swapon /dev/sda2
  

Finally update that /etc/fstab, because we've gone and fudged with it, better safe than sorry right?


	sudo lsblk -f /dev/sda2 | tail -n1 | awk '{print $3}' <- you can grab the uuid with this then just | tee -a /etc/fstab															 
UUID=30e139ef-a882-483e-b3e6-e3fef812dcae swap swap defaults 0 0
  

Write that out, and a quick reboot and we're in low resource paradise!

Great, now that we've got all of that out of the way, running our basics (networking, udev), and with a tmux, mg and htop up we're using 35M of ram and 1.3% of our cpu! I think we've made it. Starting mocp spikes the cpu a bit, but it doesn't seem to touch memory much, and it's just when it's initially started. However we've got no sound, not so much as a peep. Looking at amixer, it looks like our speakers are actually turned off.


Simple mixer control 'Master',0
  Capabilities: pvolume pswitch pswitch-joined
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 65536
  Mono:
  Front Left: Playback 65536 [100%] [off]
  Front Right: Playback 65536 [100%] [off]
Simple mixer control 'Capture',0
  Capabilities: cvolume cswitch cswitch-joined
  Capture channels: Front Left - Front Right
  Limits: Capture 0 - 65536
  Front Left: Capture 3479 [5%] [off]
  Front Right: Capture 3479 [5%] [off]
  

A quick amixer set Master unmute fixes that, but we're hit the stuttering audio, in fact mocp gets stuck on the very first beat without playing anything else at all. The stutter hasn't gone away after actively troubleshooting it for about an hour. It looks like the system is using snd_hda_intel, blacklisting that module just disables sound entirely. A ddg via lynx shows that this is a bit of a common error with Poulsbo systems (go figure). So it's very likely that this umpc will not be used for that.

Thus far I've managed to rid myself of:

  • - Graphics of all kind (hurrah no videos or games!)
  • - Audio
  • - Sanity

I could probably reduce my system resources to about 50M and be productive since all of the resource intensive stuff was just arbitrarily made difficult or impossible by the Poulsbo nightmare, but doesn't that just make this more of a challenge? I'll have to find a USB cable for my old PDA (a nice silver HP IPAQ!) and see if I can either distribute mp3's to it via busybox's httpd or mount the system directly, that way I can enjoy my music as anachronistically as possible. If that doesn't work I'm sticking to records for the duration of this challenge.

Anyways, the last part of my 2nd day was spent syncing repos I think I might use during this challenge, and making sure weechat works. I went with tried and true on a lot of the tools I use because if I'm being honest, I just don't want to learn a new irc client or something like that. I don't mind tinkering at the system level, but I just don't care about irssi regardless of however nice it might be, right now I'd rather muck with nix, or try and compile and host an inferno instance on the viliv.

Using my Esper tool to install personal software

((Trying to compile InfernOS went poorly, in retrospect I just did it wrong. I think next time I do one of these I'll try and use Plan9 as my sole computing system and see how it goes.))

Day Three - IRC Bot!

Last night I got a bunch of personal tools compiled and installed. It's really fun using my little ticket system (tkts) to keep track of running issues with the viliv, and lofty goals.

I've also noticed that running this record, tkts, htop, weechat, and pulling down massive repos (alpine aports), uses between 100m-200m typically, so ignore my "I'll be productive in 50m" quip. I was wrong. I could probably have managed 256M to just do light work which is what the nokia n900 had, and having used that for a long while, it really isn't bad. But I also didn't ever try to maintain packages using that, just simple scripts, lua, fennel, shell or whatever. We've got a whole half gig, we are for sure nixing the aports backlog we've built up! ((My Droid4 has long since superseded the Nokia N900, a single core armv7 and 256MB wasn't ideal for mobile pocket size computing. It was far far better than nothing, especially when I had an issue with a server at work and I was out and about, but I truly appreciate the dual core armv7 and 1GB of ram the Droid4 has (plus the larger keyboard and screen), it's the ideal sweet spot for low resource light weight computing for me. Like an ultra ultra mobile pc.))

I ignored this the rest of the night? Why? Dunno. Instead I wrote an irc bot to pull stats off the viliv. This is something I normally don't really do, I've never written an irc bot before, but it was good golang practice. The viliv handled compiling and testing just fine too which was really nice. The bot hardly uses any memory, and I'm using another personal tool (atentu) to extract stats so it's like a big old wrapper on some fennel right now.

My thinking is I, or anyone in the irc server I'm on can poke the system and see if I'm actually using it and how badly it's handling things! I also took a few minutes to hammer out an rc script for it. so when we reboot we should always come back online! There's probably a memory leak in it somewhere as I'm seeing some memory growth, but I've already committed to leaving this going as long as possible. So if it fails it's part of the fun.

I think I'll grow this little bot a bit more, I've already extended atentu to be more useful just for this little project. And I think being able to dig more into the system processes would be kind of cool! Maybe a quick service monitor, ssh attempts, stuff like that. I trust the people in my server, but maybe a remote shell of some sort could be neat. They all love pubnix instances and opening the viliv once this challenge is over as a sort of unix museum/toy could be fun too.

((For anyone interested the bots code lives in this git repo in the viliv directory under src. Depending on when you read this it may be the only bot, or one of many.))

The only other thing that I did here, which is worth noting, is that getting music onto my IPAQ PDA was super easy. Modern Linux systems can just mount these things with a hot plug cable, and it's as simple as copying files back and forth. I get to jam out to some Machine Gun Kelly and Mac Miller while I wrote my Collatz/Bot software without breaking the spirit of the challenge. I was limited to only a handful of albums the entire time though because I only had a 2GB SD card to use, and I didn't feel like pulling a bunch of things off the NAS via SSH, I had a usb drive with those albums from a previous transfer and just went with it. ((At the time I didn't consider it, but I'm pretty sure I could have found some old games to side load onto it and get a gaming fix that way.))

Day Four - The Collatz Collapse \o/

I've always wanted to do a collatz conjecture calculator, it's pretty silly and pointless, but so is this challenge in a way. So I wrote one in fennel and had had it running through the first 5 million proofs. It's kept the viliv toasty at 61c. Here it is in all of its poorly optimized glory!


#!/usr/bin/fennel

(fn collatz [n]
  (with-open [f (io.open "/var/log/collatz.log" "w")]
    (local initial n)
    (let
        [t []]
      (if (< n 0)
          (print "Try a positve number.")
          (= n 0)
          (print "Try a non-zero number.")
          (do
            (while (> n 1)
              (if (= (% n 2) 0)
                  (set-forcibly! n (/ n 2))
                  (set-forcibly! n (+ (* 3 n) 1)))
              (table.insert t n))
            (f:write (.. "Entries for " initial ": " (# t) "\n"))
            (for [i 1 (# t) 1]
              (f:write (.. (. t i) " ")))
            (f:write "\n"))))))

(fn renderxy [x y]
  (for [i x y]
    (do
      (collatz i))))

(fn render []
  (local start (io.popen "grep Entries /var/log/collatz.log | awk '{print $3}' | sed 's/://'"))
  (var n (tonumber (start:read)))
  (while true
    (do
      (collatz n)
      (set n (+ n 1)))))

;(render (tonumber (. arg 1)) (tonumber (. arg 2)))
;;(collatz (tonumber (. arg 1)))
(render)
  

I used that as impoteus to add a temp sensor to atentu and added that to the bot as well as a check to see how much collatz has been processed from irc. Everyone has had a lot of fun breaking the bot, lucidiot managed to crash it entirely but that's because I was dumb and tried to grep 2mil plus lines from my 4gb collatz proof file and it chewed up all the cpu in my viliv.

Surprisingly enough the old atom z520 manages to process about 1mil collatz proofs in about 45min. A better cpu could do this way better way quicker, but I'm honestly pleased to just see it do it and have a reason to create silly things. It's learning and doing for the sake of doing.

This entire challenge has been amusing to see what can be done with very little, even systems with seemingly junk specs can be used to do something interesting, whether that's a math proof solver, or an irc bot or an irc bouncer. There's always something. ((This said, my use case is far from the daily usage, I didn't do much productive or modern things during the challenge. I simply abandoned video/audio consumption. For a lot of people this probably isn't that appealing, when I say you can "do a lot" I keep in mind that these limitations are grounds for exploration. I would probably die if this was my only computer and it could never play audio or video anything, long term that would be the uphill battle I would fight day over day until it worked!)).

This continued to get more and more ridiculous. Eventually I pushed the collatz to 20mil and filled up the hard drive. It took about 12hrs totally to get from 1 to 19977774 collatz proofs, and it ate up 24GB of hard drive space before it locked up. Fortunately the irc bot kept on working and I was able to remove one of my previously synced git repos and move the collatz log off.

((The above code snippet is actually a slightly modified version of the initial write that happened at the end of the challenge, a single collatz log file ended up being about 25GB of data per 20m proofs. This version dumps to the disc, but only as a tracking method, the initially version appended to the log file endlessly. The collatz function is actually still running, and at the time of writing this we're up to 349338461 conjectures.))

Day Five - Dealing with Disc Space

I didn't do much computer wise today, I tried to scp the collatz log over to my NAS starting at about 9am. Then the family went to the Maine Renn Faire and had a blast being anachronistic in a different way. When I got back 5.5G of the log file had been transferred, which is just silly. I dug out a usb drive and copied it that way.

((In all honesty, this is yet another example of unrealistic expectations. If this were my daily driver I wouldn't be trying to kill the CPU and choking the disc generating lists of numbers to solve and unprovable conjecture. That said, the fact that I didn't have a working computer because I killed it with poorly designed software meant that I could focus more on living and less of digital fixation. That's a great thing, and likely a very realistic example of what living with these sorts of technical limitations is truly like. If we're free of distractions, free of the flashy catching distractions of Steam, Youtube, Netflix, etc. All of these rabbit holes that we willfully dump our time and attention into, then our computation becomes implicitly more focused. We have to have a task, a goal, something to accomplish; to even want to fiddle with these limitations. Even if our workflows are luudistic on the regular, lacking the ability to hop onto a more powerful system to just "get things done" or to satisfy the distraction craving means that we choose to get things done, or find something else to do. I regularly used this excuse to find something else to do, which meant spending time with my family, in my mind this is the more human choice, and inherently better than fixating.))

Day Six - Enjoying the Weekend

Fixing the collatz disc space issue left the system sitting idle, so I queued that back up to 25m, lucid wants to push it to 100m, but it seems that the viliv can only store a little under 20m at a time. I could mount a usb drive or something temporarily or setup and nfs share, but that's effort, and not using the onboard hardware.

The rest of my day has been relaxing, cooking, playing legos with my son. It's been nice to not impulsively reach for a computer. I'm blocked from so many things without Xorg and a browser that it precludes most things that I'd waste time with, and that has just given me more reason to be more human, which I embrace with earnest.

((Additionally, I could have chosen to rewrite collatz.fnl, and eventually did much later so that I could try and push the viliv for as long as possible as an IRC bot host and collatz prover, but it's a lot more fun to play legos than write collatz conjecture solvers.))

((All told I pushed this poor design through 100m collatz proofs, which resulted in over 100GB of log files, if that helps you get a feeling for how often I used that excuse during the challenge. For me it was more interesting to see that the Viliv was doing something interesting than browsing the modern web via lynx, or checking my email yet again, both of which are things I find myself doing on my smartphone impulsively.))

Look at all the space I wasted with collatz logs

August 4th - August 24th

Its been a couple of weeks since the challenge "ended", and this post has taken me an incredible amount of time to put together despite its rough exterior, but I've nonetheless continued to tinker with the Viliv, its IRC bot, and my collatz conjecture and just generally muse about the challenge experience. That's not too surprising, the little projects were fun, and have continued to provide some small amusements during the day. It's nice to pop in and get a quick atentu output and the current collatz conjecture through IRC. Since then I've also added tkts parser, so everyone in the IRC server I'm part of can using the IRC bot as a lofi ticketing system. That's mostly being used to request extensions to the bot itself, for instance we've added an Evergiven tracker thanks to Lucidiot, we'll be the first to know next time the Evergiven blocks the Suez canal! I genuinely enjoyed the creativity and limitedness of it all, it gave me a clearer head space I think.

Reflecting on the challenge itself, I feel like my day to day computing largely fits into a suckless environment. I use neomutt, weechat, and lynx for the bulk of my online computing. Most of my software lives in git repos, or I do a lot of hobby tinkering. 99% of the things I want to do with a computer are done at the command line from a lightweight environment like XFCE or i3wm, and the computers I own and use are typically cheap netbooks or similarly under powered NUCs with little Celerons. Sure the N4000 in my Asus E203MAS blows the Viliv's z520 atom out of the water, but it wasn't an unpleasant or overly restricting experience to ditch my phone, thinkpad, and playstation for a few days. If I had used my Nokia or my Droid for the challenge then I could have additionally listened to music and played videos, or if I had had the desire to fight with the poulsbo nonsense a bit I could have possibly made it all work, but I wanted to do something other than edit config files. The real point here is that given a Linux environment I'm generally pretty happy with just a command line and can make do very very well with only that, obviously that doesn't take much at all. More importantly than that, this really reflects a personal design choice. I like these suckless style computing paradigms because they lack distraction.

They aren't flashy, most of the time they don't even look good to most people. They are functional though, they get out of the way and let you do 1 or 2 things and that's it. There's nothing that pulls me into neomutt, no ads, some simple solarized color theme is all there is. When I load the application I check my mail, I move on. I don't sit there and refresh it, or recheck it every hour to make sure I didn't miss something. This is a stark comparison to how I interact with my smartphone, or a modern computer. There's the constant impulse to check something real quick, or click on another app, or read another article. Our devices are purposefully designed with flashy colors and attention getting methods. I choose to use the opposite because I understand that I suffer from those kinds of problems, and would like to simply be more human. It's hard though, I haven't been able to ditch my smartphone because I can't even pick my son up from school these days without verifying that I'm his parent, using an android app. There are so many weird edge cases like that, that it's hard to ditch the modern attention grabbing computational world. But I can try, and this challenge has really drawn that line in the sand for me, I oddly and purposefully seek out luudistic technology as a way to self reduce, or more purposefully more meaningfully compute. I guess in a way the challenge was really me doing more of the same, I used setups very similar to what I use on my nokia, and droid, maybe next time I'll try doing a Plan9 only challenge, or Collapse OS so I can get some Forth hacking in. But even so, I'm happy knowing that if I do find a way to digitally detox myself, I'll have a very comfy suckless approach to computing, which just works for me.

Finally, I really aplaude Solene's creativity for coming up with the challenge! It has been delightful to read about over my lunch breaks at work, and I obviously was inspired enough to participate myself, and then ramble about it on the internet! I highly suggest anyone interested in taking the challenge does so, especially if you're looking for a digital detox, or to just explore how far you can push this! It's also important to show people that the technology that we consider junk can be put to some kind of use, and in recycling it you're at least helping keep that "junk" out of the landfill. Or maybe it'll help some people realize how demanding modern technology is for our attention and input, and you'll choose to do the opposite like I try to do, who knows.

And in case you were worried the Viliv was going back to the junk drawer now that the challenge is over, you'll be happy to know it has found itself a welcome home amidst my extremely cluttered desk!

The viliv's new home on my cluttered desk.

Bio

(defparameter *Will_Sinatra* '((Age . 31) (Occupation . DevOps Engineer) (FOSS-Dev . true) (Locale . Maine) (Languages . ("Lisp" "Fennel" "Lua" "Go" "Nim")) (Certs . ("LFCS"))))

"Very little indeed is needed to live a happy life." - Aurelius