<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>GNUcode.me</title><id>https://gnucode.me/feed.xml</id><subtitle>Recent Posts</subtitle><updated>2024-04-18T01:18:57Z</updated><link href="https://gnucode.me/feed.xml" rel="self" /><link href="https://gnucode.me" /><entry><title>OpenBSD's Philosophy</title><id>https://gnucode.me/openbsds-philosophy.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2024-04-17T18:00:00Z</updated><link href="https://gnucode.me/openbsds-philosophy.html" rel="alternate" /><content type="html">&lt;p&gt;I have talked about OpenBSD before in this blog, and I recently
watched a talk by OpenBSD's leader Theo de Raadt about &lt;code&gt;pledge ()&lt;/code&gt; and
&lt;code&gt;arc4random()&lt;/code&gt;. He described OpenBSD's design philosophy so well, that
I wanted to write it down.  You should definitely take some time to
hear Theo speak.  He's entertaining, and his talks are super awesome!&lt;/p&gt;&lt;p&gt;So a long time ago (early 90s ?), a cracker (1) broke into Theo's
OpenBSD's syslog.  This got Theo to examine OpenBSD's source code to
fix any lingering bugs, and he found a lot.  He realized that trying
to constantly examine source code to prevent bugs is a never ending
process.  He wanted to ensure code quality got better over time.  He
envision an operating system that that enforced code correctness like
the below ASCII art shows.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;__________________________
| Poorly written programs |
| crash on OpenBSD.       |
| ----------------------  |
| | Correctly written  |  |
| | programs run well  |  |
| | on OpenBSD.        |  |
| ----------------------  |
---------------------------&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;He wondered if he could create features to slightly narrow the things
that applications could do.  When poorly written programs run on
OpenBSD, they crash in deterministic ways, but correct programs work
just fine.  Theo also made sure that &amp;quot;mitigations&amp;quot;, or checks to ensure
a program's correctness, &lt;em&gt;cannot&lt;/em&gt; be turned off on OpenBSD.  If a user
or a project manager has a problem with an application not working on
OpenBSD due to a toggleable security feature, then the user or project
manager will just turn off the feature.  So to ensure that programs
abide by the mitigations, OpenBSD enforces their security policies.&lt;/p&gt;&lt;p&gt;OpenBSD also makes it easy to use their security features.  If they
introduce a policy that is manatory, they try to make the API easy to
use.  If you create a security policy that is hard for the programmer
to use, then the security policy won't be used.&lt;/p&gt;&lt;p&gt;When OpenBSD creates a new mitigation, their application porters port
3rd party software packages to OpenBSD.  Typically these changes find
their way into the upstream packages.  What's awesome is that usually
other operating systems start to use OpenBSD mitigations on their
systems 5 years after OpenBSD introduced them.  Windows, Mac, and
Linux applications all benefit from the strict standards that OpenBSD
creates. Theo's talks gave two examples for this: &lt;code&gt;pledge ()&lt;/code&gt; and
&lt;code&gt;arc4random ()&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Here's a question for you.  How do you get random data?  Well you read
&lt;code&gt;/dev/random&lt;/code&gt; of course.  Simple.  Easy.  Done.  That used to be how
things were handled.  Apparently reading from &lt;code&gt;/dev/random&lt;/code&gt; has some
limitations that Theo mentioned.  Can you read from &lt;code&gt;/dev/random&lt;/code&gt;
inside the kernel?  Inside a library?  In your libc?  Reading from
&lt;code&gt;/dev/random&lt;/code&gt; is not perfect.  Theo wanted to make something better.&lt;/p&gt;&lt;p&gt;OpenBSD created &lt;code&gt;arc4random ()&lt;/code&gt; as a better source of entropy.  It is
a C function that almost any application can call (even the kernel),
most of the time.  This lets many applications, libraries, etc. easily
use random numbers.  What's surprizing to me is that many operating
systems use &lt;code&gt;arc4random ()&lt;/code&gt; or a function like it, so that more
applictions can easily request random data.  This function (or one
like it) exists on your Android phone, iPhone, iMac, and sort of on
Linux thanks to OpenBSD.&lt;/p&gt;&lt;p&gt;What's &lt;code&gt;pledge ()&lt;/code&gt; ?  Oh ho, let me tell you!  Let's take a look at a
typical program.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-C&quot;&gt;int main () {

  initialize_stuff();
  
  for (;;) {
    ;; let's run the program
  }

}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Most programs have an initialization phase followed by a loop, in
which the application runs.  The OpenBSD team realized that the
initialize phase uses most of the system calls.  After the initialize
phase, the program typically needs less system calls.  OpenBSD's
&lt;code&gt;pledge ()&lt;/code&gt; was created in response to this pattern present in most
programs.&lt;/p&gt;&lt;p&gt;&lt;code&gt;pledge ()&lt;/code&gt; is a security call, by which an application tells the
kernel, &amp;quot;I pledge to only do these things and no other.&amp;quot;  For example,
&amp;quot;I pledge to only output text&amp;quot;.  Or &amp;quot;I pledge to only access the
internet and output text.&amp;quot;  If the application tries to do something
that it has pledged not to do, then OpenBSD kills the application.&lt;/p&gt;&lt;p&gt;A really interesting blog post that talks about this is at
&lt;a href=&quot;https://justine.lol/pledge/&quot;&gt;justine's blog&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;After watching two of Theo's talks, I am fairly convinced that his
design goals are slowly working to make all POSIX operating systems
more correct and secure.  I used to dual boot Guix System and OpenBSD,
but unfortunately my spare SSD busted.  So for now I am only using
Guix System.  I personally prefer to use Guix System for my linode
server (that powers this blog), because Guix makes it easy to manage
servers.&lt;/p&gt;&lt;p&gt;I wish that the Guix developers could one day create Guix OpenBSD
System, but I have been told that Guix System assumes your libc is
&lt;code&gt;glibc&lt;/code&gt; and that OpenBSD cannot currently make isolated build
environments as well as Linux can.  Also fun fact OpenBSD is not
currently working on reproducible builds.  :)&lt;/p&gt;&lt;p&gt;My two only minor complaints with OpenBSD currently are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;I wish OpenBSD supported Wayland. This may happen in 6 months to a
year.  Fingers crossed.&lt;/li&gt;&lt;li&gt;A better filesystem: OpenBSD's FFS (fast file system) works, but it
is possible to lose data in a crash.  Filesystems are &lt;em&gt;really&lt;/em&gt; hard
to get right.  Kent Overstreet has been working on bcachefs for
almost a decade now, and it might soon become one of Linux's best
filesystems (my opinion), so I don't blame OpenBSD for not trying to
create a new next generational filesystem.  Anybody want to spend 10
years of their life creating an awesome filesystem that will
probably only work well on OpenBSD?  One might be able to port
HammerFS to OpenBSD, and a basic read-only port does exist.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If you want to try OpenBSD, give it a shot!  It works really well on
most lenovo laptops and most desktop machines.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Nerdy computer people like me use the word &amp;quot;hacker&amp;quot; to mean someone
who builds computer programs, and a &amp;quot;cracker&amp;quot; is someone who breaks
into computer systems.&lt;/li&gt;&lt;/ol&gt;</content></entry><entry><title>The Hurd on Bare Metal Update</title><id>https://gnucode.me/the-hurd-on-bare-metal-update.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2024-01-07T19:00:00Z</updated><link href="https://gnucode.me/the-hurd-on-bare-metal-update.html" rel="alternate" /><content type="html">&lt;h1&gt;Running the Hurd on Bare Metal&lt;/h1&gt;&lt;p&gt;So apparently, you can run X on the Hurd, and I am currently daily
driving the Hurd.  It's not perfect.  Once a month or so the Hurd will
lock up completely, and I will have to hard shutoff the machine and
deal with filesystem corruption.  But it does work!  You will need to
read the whole &lt;a href=&quot;https://www.debian.org/ports/hurd/hurd-install&quot;&gt;Debian wiki&lt;/a&gt; page.  There are sections that mention how
to upgrade to the unstable distribution, setting up X, and the correct
upgrade procedure:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apt update
# apt upgrade --without-new-pkgs
# apt full-upgrade&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let's install some packages and set up X.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apt install i3 xinit pinentry-gnome3
# Tell X to let any user startx (it is better to let only console
# users to start X, but that is not working for me.
# apt dpkg-reconfigure x11-common xserver-xorg-legacy&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Create a keyboard shortcut to kill X, because X may get stuck.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /etc/X11/xorg.conf.d/xorg-ctrl-backspace.conf

Section &amp;quot;InputDevice&amp;quot;
        Identifier &amp;quot;Generic KeyBoard&amp;quot;
        Driver &amp;quot;kbd&amp;quot;
        Option &amp;quot;XkbOptions&amp;quot; &amp;quot;terminate:ctrl_alt_bksp&amp;quot;
EndSection&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If, I am running X, then the best way to shutdown the computer, is to
first kill X, then from the console execute &lt;code&gt;sudo halt&lt;/code&gt;.  I tried to
issue &lt;code&gt;sudo halt&lt;/code&gt; from an &lt;code&gt;xterm&lt;/code&gt;, and that caused some filesystem
corruption on my &lt;code&gt;/home&lt;/code&gt; partition.&lt;/p&gt;&lt;p&gt;So what works?&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Emacs 29.1&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Gnus&lt;/li&gt;&lt;li&gt;magit&lt;/li&gt;&lt;li&gt;erc&lt;/li&gt;&lt;li&gt;org-mode&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;git send-email&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;netsurf web browser&lt;/p&gt;&lt;p&gt;I &amp;quot;ported&amp;quot; it via hard-coding &lt;code&gt;PATHMAX&lt;/code&gt;, which is not an ideal
solution, but at least I have a web browser that can render simple
websites like Wikipedia.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ffmpeg&lt;/p&gt;&lt;p&gt;I actually use &lt;code&gt;recordmydesktop --no-sound --fps 2&lt;/code&gt; on the Hurd
machine.  This does actually work.  I tried
using ffmpeg on my Guix System to add audio to the file, but the
audio is out of sync with the video.  I'm not sure why.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://mail.gnu.org/archive/html/bug-hurd/2023-03/msg00021.html&quot;&gt;terrible-mdns-responder&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Sergey created this as a way to easily ssh into his hurd box from a
GNU/Linux machine.  I use it like so:  &lt;code&gt;ssh joshua@pippin.local&lt;/code&gt;,
and I can ssh into my Hurd machine without having to know its IP
address.  It's pretty cool!&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;i3&lt;/p&gt;&lt;p&gt;i3 is probably the slickest window manager out there!  Since the
Hurd is currently X only, I might as well use something light-weight
that I like.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;pastebinit&lt;/p&gt;&lt;p&gt;It would be nice if netsurf would work with a pastebin, but it's
not.  So the &lt;code&gt;pastebinit&lt;/code&gt; command works.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ikiwiki&lt;/p&gt;&lt;p&gt;I can update the GNU Hurd wiki entirely using the Hurd.  That's
awesome!&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;There are some gotchas when running the Hurd.&lt;/p&gt;&lt;p&gt;If, &lt;code&gt;/home&lt;/code&gt; or &lt;code&gt;/&lt;/code&gt; are readonly, then X will refuse to start and will
not tell you why.  So, my &lt;code&gt;.bashrc&lt;/code&gt; has this in it:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat .profile | grep -A 15 'tell me'

# tell me if / or /home are writeable or not.
echo -n '/ is '
myroot=$(fsysopts / | awk '{ print $2 }')
myroot=${myroot:2}
echo $myroot
echo -n '/home is '
myhome=$(fsysopts /home | awk '{ print $2 }')
myhome=${myhome:2}
echo $myhome

if [ $myhome == &amp;quot;writable&amp;quot; ]; then
    echo &amp;quot;starting X&amp;quot;;
else
    echo &amp;quot;NOT starting X&amp;quot;;
fi&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When I have filesystem corruption, I need to umount &lt;code&gt;/&lt;/code&gt; and &lt;code&gt;/home&lt;/code&gt;
and run fsck on them.  Then reboot.  Most of the time the Hurd can
auto run fsck for you, but sometimes it is so bad that you must do it
yourself.&lt;/p&gt;&lt;p&gt;When you have to fsck the filesystem, here is how to do it. You have
to login via &lt;code&gt;root&lt;/code&gt;, then &lt;code&gt;umount /home &amp;amp;&amp;amp; umount /&lt;/code&gt;. Then run
&lt;code&gt;fsck.ext2 /dev/hd0s1 &amp;amp;&amp;amp; fsck.ext2 /dev/hd0s6&lt;/code&gt;.  Now reboot.&lt;/p&gt;&lt;p&gt;I also cannot shutoff the machine from a terminal inside X.  I first
have to kill X, and then shutoff the machine from the console.&lt;/p&gt;&lt;p&gt;Also, &lt;code&gt;apt&lt;/code&gt; is apparently not the best tool to install various
packages.  It is actually better to use &lt;code&gt;aptitude&lt;/code&gt;.  &lt;code&gt;# apt install elpa-magit&lt;/code&gt; fails, but &lt;code&gt;#aptitude install elpa-magit&lt;/code&gt; somehow works.
I do not know why.&lt;/p&gt;&lt;p&gt;This is kind of new, but &lt;code&gt;sudo&lt;/code&gt; is failing:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ sudo ls
malloc(): invalid size (unsorted)
Aborted&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I would love to get haunt running on the Hurd, and it does run!  But
it fails to build this blog.  At first it was that &lt;code&gt;guile-commonmark&lt;/code&gt;
was not installed.  Then it was that haunt could not find
&lt;code&gt;guile-commonmark&lt;/code&gt;.  The fix was pretty easy.  In the haunt source
code directory:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ export GUILE_LOAD_PATH=/usr/local/share/guile/site/3.0&amp;quot;
$ ./configure&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So that helped me build haunt correctly and it could find
guile-commonmark.  But then it needed guile-reader installed as well.
Now I can't build guile-reader.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ autoreconf -vif
autoreconf: error: automake failed with exit status: 1&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And of course the &lt;code&gt;./configure&lt;/code&gt; in the guile-reader directory failed
too.&lt;/p&gt;</content></entry><entry><title>The Hurd on Bare Metal</title><id>https://gnucode.me/the-hurd-on-bare-metal.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-08-13T14:00:00Z</updated><link href="https://gnucode.me/the-hurd-on-bare-metal.html" rel="alternate" /><content type="html">&lt;p&gt;This blog post was written on a Debian GNU/Hurd system on a IBM ThinkPad T43
with 1.5 GB of RAM. (It was edited on Guix System (running linux)). Apparently
running Emacs on the hurd in the console is actually quite stable. This post
will describe my attempt to make this T43 be my daily laptop. Let’s see
how far I can get with that eh?&lt;/p&gt;&lt;p&gt;tl;dr  Debian GNU/Hurd is shockingly stable.  If you are an emacs wiz,
then you will feel right at home.&lt;/p&gt;&lt;p&gt;The first thing to notice after you login to the Hurd is that you can
easily switch virtual consoles via &lt;code&gt;Alt-&amp;lt;right-arrow&amp;gt;&lt;/code&gt;.  It is
actually pretty awesome that you can do this.  I know literally every
other OS has this, but it is cool to have Emacs open in one console,
and have another program running on another console;  switching
between them feels beautiful.&lt;/p&gt;&lt;p&gt;Another thing to notice is that &lt;code&gt;mount&lt;/code&gt; does not work. Let's explore that shall
we?&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /etc/mtab | awk '{ print $1 &amp;quot; &amp;quot; $2 &amp;quot; &amp;quot; $3 }'

/dev/hd0s1 / ext2fs
none /run /hurd/tmpfs
none /run/lock /hurd/tmpfs
/dev/hd0s6 /home /hurd/ext2fs
proc /proc /hurd/procfs&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Actually &lt;code&gt;/etc/mtab&lt;/code&gt; is a symlink to &lt;code&gt;/proc/mounts&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ls -lha /etc/mtab

lrwxr-xr-x 1 root root 12 Apr 10 12:14 /etc/mtab -&amp;gt; /proc/mounts&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It looks like the Hurd labels MBR partitions slightly differently from Linux. It
appears that the Hurd uses &lt;code&gt;/dev/hd0s1&lt;/code&gt;, &lt;code&gt;dev/hd0s2&lt;/code&gt;, and so on.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;echo $pw | sudo -S fdisk -l /dev/hd0

Disk /dev/hd0: 37.26 GiB, 40007761920 bytes, 78140160 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x1ab32a1b

Device     Boot    Start      End  Sectors  Size Id Type
/dev/hd0s1          2048 26681343 26679296 12.7G 83 Linux
/dev/hd0s2      26683390 78139391 51456002 24.5G  5 Extended
/dev/hd0s5      26683392 28682239  1998848  976M 82 Linux swap / Solaris
/dev/hd0s6      28684288 78139391 49455104 23.6G 83 Linux&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It looks like a good place to start learning how to use the Hurd is
via &lt;code&gt;https://www.debian.org/ports/hurd/hurd-install&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;So the file that describes my network interfaces is here:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /etc/network/interfaces

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto /dev/eth0
iface /dev/eth0 inet dhcp&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So it looks like i should definitely read &lt;code&gt;man 5 interfaces&lt;/code&gt; at some
point.  And the Debian Hurd guide mentions that I should add name
servers to my /etc/resolv.conf file.  I am not certain why it says
that I should do that though, but I went ahead and added OpenDNS’ name
servers.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /etc/resolv.conf

nameserver 172.16.112.1

cat /etc/resolv.conf

nameserver 172.16.112.1
nameserver 208.67.222.222
nameserver 208.67.220.220&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so it seems like &lt;code&gt;pfinit&lt;/code&gt; is still the default GNU Hurd &lt;code&gt;TPC/IP&lt;/code&gt;
translator, which is based on an old Linux TCP/IP driver (&lt;code&gt;lwip&lt;/code&gt; or
&lt;code&gt;rumpkernel&lt;/code&gt; may one day replace it).  Apparently my internet
connectivity can be found by quering &lt;code&gt;/servers/socket/2&lt;/code&gt; (for IPv4)
and &lt;code&gt;/servers/socket/26&lt;/code&gt; (for IPv6).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# fsysopts /servers/socket/2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you run the above command you will see that the ethernet device
that the Hurd uses is &lt;code&gt;/dev/eth0&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The Hurd has a stateless (stateful is better) ethernet filter. For example, here
is how to disable ssh access:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# settrans -c /dev/eth0f /hurd/eth-filter \
           -i /dev/eth0 -r &amp;quot;not port 22&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I could then, tell the pfinit translator to use &lt;code&gt;/dev/eth0f&lt;/code&gt; instead
of &lt;code&gt;/dev/eth0&lt;/code&gt; via (I think this how you would do it):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# fsysopts /server/socket/2 --interface=/dev/eth0f&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is course is not persistant across reboots.  I would probably
need to replace &lt;code&gt;/dev/eth0&lt;/code&gt; in &lt;code&gt;/etc/network/interfaces&lt;/code&gt; with
&lt;code&gt;/dev/eth0f&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;The Hurd lets you mount cd drives as a regular user. I should be able
to look at the files in my CD drive via:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd /dev
# ./MAKEDEV cd0
# settrans /media/cdrom0 /hurd/is09660fs /dev/cd0
$ cd /media/cdrom0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Apparently the Hurd does have a network filesystem translator
(&lt;code&gt;/hurd/nfs&lt;/code&gt;), but I believe that that translator only supports
NFSv2.  So it may not be as performanent as one might want or support
the latest NSF features.&lt;/p&gt;&lt;p&gt;Since I installed the stable Hurd release from 2021, the guide
recommends that if I want a stable environment, then I can just
configure apt to use the apt sources from 2021.  That should let me
have a fairly stable Hurd distro.  So let’s try that.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /etc/apt/apt.conf.d/99ignore-valid-until

Acquire::Check-Valid-Until &amp;quot;false&amp;quot;;

cat /etc/apt/sources.list

deb [trusted=yes] https://snapshot.debian.org/archive/debian-ports/20210812T100000Z sid main
deb [trusted=yes] https://snapshot.debian.org/archive/debian-ports/20210812T100000Z unreleased main
deb-src [trusted=yes check-valid-until=no] https://snapshot.debian.org/archive/debian/20210812T100000Z sid main&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This mostly worked, but apt gave a warning about the debian gpg key
had expired.&lt;/p&gt;&lt;p&gt;Well let’s try to upgrade anyway.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apt update &amp;amp;&amp;amp; apt upgrade&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That seemed to work.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apt install debian-ports-archive-keyring
# apt update
# apt upgrade

# apt install git git-email
$ git config --global user.name &amp;quot;Joshua Branson&amp;quot;
$ git config --global user.email &amp;quot;jbranso@dismail.de&amp;quot;
$ cd; git clone https://notabug.org/jbranso/prog&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I suppose that it is time to follow &lt;a href=&quot;https://drewdevault.com/2019/12/30/dotfiles.html&quot;&gt;Drew Devault’s guide&lt;/a&gt; on how to
manage your home directory’s configuration files as a git repository.&lt;/p&gt;&lt;p&gt;I should also read the &lt;a href=&quot;https://www.debian.org/ports/hurd/hurd-doc-translator&quot;&gt;hurd-doc-translator&lt;/a&gt; webpage.&lt;/p&gt;&lt;p&gt;Apparently, the Hurd’s translators transform data into different data.
The usual case, is that a translator translates bits of the filesystem
into different data, and what is awesome is that translators run in
userspace.  Most of the time translators will need to get data from
hardware, and they will request the kernel to help them get this data.
There are some exceptions: &lt;code&gt;/dev/zero&lt;/code&gt; does not need hardware data, so
a read from &lt;code&gt;dev/zero&lt;/code&gt; is entirely run in userspace.&lt;/p&gt;&lt;p&gt;There are two kinds of translators: active and passive.  An active
translator is currently running.  You can change its settings or kill
it via the &lt;code&gt;settrans -a&lt;/code&gt; command.  The &lt;code&gt;-a&lt;/code&gt; refers to the &lt;strong&gt;active&lt;/strong&gt;
translator.  So &lt;code&gt;settrans -a file.txt&lt;/code&gt; will try to kill the userspace
translator process.  If you start a translator via the &lt;code&gt;-a&lt;/code&gt; option,
then the translator is not persistant accross reboot. For that reason,
most of the time you do not want the &lt;code&gt;-a&lt;/code&gt; option, which is what
settrans by default does.&lt;/p&gt;&lt;p&gt;If you are ever curious to know if a filesystem node has an attached translator,
then you can find out via this command:&lt;code&gt;showtrans NODE&lt;/code&gt;. It will tell you what
passive translators are set at a filesystem node.&lt;/p&gt;&lt;p&gt;Let's take a walk through some basic Hurd translators.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;settrans [OPTIONS...] NODE [TRANSLATOR ARGS...]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, I can have a text file like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/Documents/hello.txt

boring text document.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s set the &lt;code&gt;hello&lt;/code&gt; translator on that filesystem node.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;settrans -a ~/Documents/hello.txt /hurd/hello

cat ~/Documents/hello.txt

Hello, world!&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s see that the file system options are for the &lt;code&gt;/hurd/hello&lt;/code&gt;
translator:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;fsysopts ~/Documents/hello.txt

/hurd/hello --contents='Hello, world!
'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I can modify the &lt;code&gt;contents&lt;/code&gt; of the hello translator via:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;fsysopts ~/Documents/hello.txt  --contents=&amp;quot;Hello Joshua
&amp;quot;

cat ~/Documents/hello.txt

Hello Joshua&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice that we changed the options for that translator without having
to restart it with normal user privledges.&lt;/p&gt;&lt;p&gt;Now let’s make the hello translator go away:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;settrans -a ~/Documents/hello.txt

cat ~/Documents/hello.txt

boring text document.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s try to stack these translators eh?&lt;/p&gt;&lt;pre&gt;&lt;code&gt;settrans gnucode.me /hurd/httpfs http://gnucode.me

ls gnucode.me/installing-wordpress.html

gnucode.me/installing-wordpress.html

settrans -c xml /hurd/xmfls ~/gnucode.me/feed.xml
cd
ls&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here the ls command apparently hanged.  &lt;code&gt;C-c&lt;/code&gt; ended said hanging, but
the Hurd locked up on me.  I actually saw an error message that said
something like “kbd queue full.”  And then my keyboard become
unresponsive.  After a few hours, I pressed “Ctrl-Alt-Del,” and that
saved my bacon.  That killed the hurd console, and it let me switch to
a virtual console.  That enabled me to shut down the hurd gracefully.
BUT…What went wrong?  Why did &lt;code&gt;ls&lt;/code&gt; hang?&lt;/p&gt;&lt;p&gt;Well here is a clue:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ls ~/gnucode.me/feed.xml

ls: cannot access feed.xml': No such file or directory&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well, httpfs does not expose feed.xml. It does not recognize that as part of the
gnucode.me website. &lt;code&gt;httpfs&lt;/code&gt; only lists webpages that are listed on
&lt;code&gt;index.html&lt;/code&gt;. So &lt;code&gt;~/gnucode.me/feed.xml&lt;/code&gt; does not translate to the local the
filesystem. If I had to guess, I would say that xmlfs tries to run but does not
check if its underlying file exists.&lt;/p&gt;&lt;p&gt;I should also mention that I am using a very minimal &lt;code&gt;.emacs.d/init.el&lt;/code&gt;. It is
possible to get doom emacs to run on the Hurd, but the last time that I tried
it, emacs locked up on me. I was forced to do a hard shutdown, which resulted in
filesystem corruption and I had to re-install. So for now, I am using a very
simple and minimal emacs. You can actually install some emacs packages via apt.
Just search for &lt;code&gt;apt search magit&lt;/code&gt; to get you started.&lt;/p&gt;&lt;p&gt;I would like to try running i3 on the hurd at some point, because that
is a very light-weight window manager, but I have not yet tried
setting up X to run.  Partly because I only have 1.5GB of RAM, and I
have heard that X tends to lock up or be really slow on the Hurd.&lt;/p&gt;&lt;p&gt;Surprizingly the Hurd only uses about &lt;code&gt;161MB&lt;/code&gt; of RAM, when I run emacs
on the console.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;What I have done so far&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Emacs
I would love to remap control and caps, but I am not certain how
to do that in the console.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Irc (via Erc)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Gnus my email client
But I still need to set up the ability to send email.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Packages to install (glibc-doc-reference) requires enabling non-free
packages:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apt install gnupg emacs surfraw msmtp glibc-doc glibc-doc-reference&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Trying to create/open a file in emacs that ends in *.gpg crashes
Emacs.  I have no idea why.&lt;/p&gt;&lt;p&gt;Currently, msmtp cannot securely send email, because it cannot decrypt
the encrypted file that has my password.&lt;/p&gt;&lt;p&gt;My Hurd machine also has my “jbranso@dismail.de” gpg key. I was able
to import the data via an ssh session.&lt;/p&gt;&lt;p&gt;I was actually surprized that the debian wiki mentioned this command:
&lt;code&gt;service ssh restart&lt;/code&gt; and not a systemd specific command, but
apparently &lt;code&gt;man service&lt;/code&gt; is the manual that I want to read.
Apparently ssh is already running.  I verified this with:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;echo $pw1 | sudo -S service --status-all | grep ssh

[ + ]  ssh&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I really should set up Sergey's terrible MDNS responder, so that I can ssh in
the Hurd more easily, but that is a task that I will set for a later date. I
should also possibly update my hard drive to a larger drive. I think the current
one has 100GB or so. Maybe less. And it might not be a bad idea to set up an SSD
or DVD drive via the CD-ROM bay and try the rumpdisk out. I would also like to
be able to publish my blog from the Hurd too, but I have been unsuccessful to
install Haunt on my Hurd box. I should also try to install Guix on it, but I am
concerned about hard drive space at the moment.&lt;/p&gt;&lt;p&gt;Anyway, you can take a look at my &lt;a href=&quot;https://notabug.org/jbranso/hurd-home&quot;&gt;hurd
home&lt;/a&gt; git directory if you like. Safe
travels!&lt;/p&gt;</content></entry><entry><title>Setting up Chimera Linux</title><id>https://gnucode.me/setting-up-chimera-linux.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-08-09T11:59:00Z</updated><link href="https://gnucode.me/setting-up-chimera-linux.html" rel="alternate" /><content type="html">&lt;p&gt;My friend ownes a &lt;a href=&quot;https://www.raptorcs.com/TALOSII/&quot;&gt;Talos II&lt;/a&gt;, and he wanted some help setting it up.  We have
decided on setting up &lt;a href=&quot;https://chimera-linux.org/&quot;&gt;Chimera Linux&lt;/a&gt;.  Since Chimera Linux is new, we also installed the guix package manager as well.  This blog post today is more of documentation and less story telling.  You have been warned.&lt;/p&gt;&lt;h1&gt;upgrading chimera linux&lt;/h1&gt;&lt;pre&gt;&lt;code&gt;doas apk update

doas apk upgrade&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;DONE Getting X applications and gdm to run on chimera&lt;/h1&gt;&lt;p&gt;All Talos II machines have trouble running X, when a discrete GPU is installed.
Basically the Talos II has an on board GPU, which when combined with an AMD GPU,
X does not know which GPU to use. &lt;a href=&quot;https://wiki.raptorcs.com/wiki/Troubleshooting/GPU#Xorg_will_not_start_.2F_crashes_when_a_discrete_GPU_is_installed&quot;&gt;click here&lt;/a&gt; to read more on the raptor wiki.&lt;/p&gt;&lt;p&gt;I did have trouble getting my friend’s Talos II to start gdm and X, but an
update to chimera linux fixed the gdm issue.  The below sections are for others
that are using a Talos II with an AMD GPU.  You do need to configure X to
disable the onboard GPU and/or tell GDM to select a GPU at runtime.&lt;/p&gt;&lt;h2&gt;raptor pdf user’s guide:&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://wiki.raptorcs.com/w/images/e/e3/T2P9D01_users_guide_version_1_0.pdf&quot;&gt;https://wiki.raptorcs.com/w/images/e/e3/T2P9D01_users_guide_version_1_0.pdf&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;raptor wiki ways to fix this&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;Tell GDM to ignore a GPU&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In this case ignore the crappy onboard GPU.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;    lspci | grep VGA

    0005:02:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family (rev 41)
    0030:01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Ellesmere [Radeon Pro WX 7100]

    cat /etc/udev/udev.conf

    # see udev.conf(5) for details
    #
    # udevd is also started in the initrd.  When this file is modified you might
    # also want to rebuild the initrd, so that it will include the modified configuration.
    
    #udev_log=info
    #children_max=
    #exec_delay=
    #event_timeout=180
    #timeout_signal=SIGKILL
    #resolve_names=early
    TAG-=&amp;quot;seat&amp;quot;, ENV{ID_FOR_SEAT}==&amp;quot;drm-pci-0005_02_00_0&amp;quot;
    TAG-=&amp;quot;seat&amp;quot;, ENV{ID_FOR_SEAT}==&amp;quot;graphics-pci-0005_02_00_0&amp;quot;

    Do this to re-generate the initramfs.
    `doas apk fix linux-lts`&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Xorg will not start / crashes when a discrete GPU is installed&lt;/p&gt;&lt;p&gt;We chose to do the workaround 2: select a desired GPU at runtime, which means
that if we change the slot of the GPU, then we will have to re-create the Xorg
configuration file.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;lspci | grep VGA

0005:02:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family (rev 41)
0030:01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Ellesmere [Radeon Pro WX 7100]

cat /etc/X11/xorg.conf.d/21-gpu-driver.conf

# AST2500
Section &amp;quot;Device&amp;quot;
    Identifier     &amp;quot;GPU0&amp;quot;
    Driver         &amp;quot;modesetting&amp;quot;
    BusID          &amp;quot;PCI:2@5:0:0&amp;quot;
    VendorName     &amp;quot;ASpeed Corporation&amp;quot;
EndSection
    
# WX7100
Section &amp;quot;Device&amp;quot;
    Identifier     &amp;quot;GPU1&amp;quot;
    Driver         &amp;quot;modesetting&amp;quot; # or amdgpu if you have xf86-video-amdgpu installed
    BusID          &amp;quot;PCI:1@48:0:0&amp;quot;
    VendorName     &amp;quot;AMD Corporation&amp;quot;
EndSection
    
# this is absolutely necessary, it tells xorg which GPU to use for the screen
Section &amp;quot;Screen&amp;quot;
    Identifier     &amp;quot;Screen0&amp;quot;
    Device         &amp;quot;GPU1&amp;quot;
EndSection&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;upgrade the openBMC bios/firmware and disable onboard GPU via&lt;/p&gt;&lt;p&gt;I decided not to do this one.  It's way too complicated.  See the raptor wiki if you don't believe me.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;Where to find X logs&lt;/h2&gt;&lt;p&gt;&lt;em&gt;var/log/gdm/greeter.log
/var/lib/gdm&lt;/em&gt;.local/share/xorg/Xorg.1.log&lt;/p&gt;&lt;h2&gt;toggling gdm to use X/wayland&lt;/h2&gt;&lt;p&gt;This does not appear to work.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /etc/gdm/custom.conf | grep 'Wayland'

#WaylandEnable=false
WaylandEnable=true&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;DONE install icewm, and put that in ~/.xinitrc &amp;amp; startx&lt;/h2&gt;&lt;p&gt;Originally this did not work, because X refused to start. But after I upgraded
Chimera linux one day, it worked.&lt;/p&gt;&lt;h1&gt;Setting up Bitcoin knots/bitcoin core&lt;/h1&gt;&lt;p&gt;My friend is an avid bitcoin user. He wanted me to help him set up bitcoin on
his Talos II. If possible, he wanted me to set up bitcoin-knots, which was
forked from bitcoin-core.&lt;/p&gt;&lt;h2&gt;github repo for bitcoin-knots&lt;/h2&gt;&lt;p&gt;The github repo has lots of good information to help me out:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://bitcoinknots.org/#download&quot;&gt;https://bitcoinknots.org/#download&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/bitcoinknots/bitcoin&quot;&gt;https://github.com/bitcoinknots/bitcoin&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/bitcoinknots/bitcoin/tree/23.x-knots/doc&quot;&gt;https://github.com/bitcoinknots/bitcoin/tree/23.x-knots/doc&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/build-unix.md&quot;&gt;https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/build-unix.md&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/build-freebsd.md&quot;&gt;https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/build-freebsd.md&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/dependencies.md&quot;&gt;https://github.com/bitcoinknots/bitcoin/blob/23.x-knots/doc/dependencies.md&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I can get help from webchat.freenode.net  #bitcoin-dev&lt;/p&gt;&lt;p&gt;luke-jr says that I can compile bitcoin knots from source fairly easily.&lt;/p&gt;&lt;p&gt;download a release.  Install dependencies:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://download.qt.io/official_releases/qt/&quot;&gt;https://download.qt.io/official_releases/qt/&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;doas apk add libevent &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;./configure gmake &amp;amp;&amp;amp; gmake check &amp;amp;&amp;amp; gmake install&lt;/code&gt;&lt;/p&gt;&lt;h2&gt;NO Packaging bitcoin knots for chimera linux&lt;/h2&gt;&lt;p&gt;q66 is NOT ok with me packaging bitcoin-coin for chimera linux, because it
depends on qt5, which is soon to be replaced by qt6.  So why bother packaging
qt5 when qt6 is soon to supplant it?&lt;/p&gt;&lt;p&gt;This is the documentation for packaging in chimera.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/chimera-linux/cports&quot;&gt;https://github.com/chimera-linux/cports&lt;/a&gt;
&lt;a href=&quot;https://github.com/chimera-linux/chimerautils&quot;&gt;https://github.com/chimera-linux/chimerautils&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Alternatively I can package bitcoin knots for guix and install&lt;/h2&gt;&lt;p&gt;guix on chimera linux. And guix already has qt packaged. Do they have
5.15.2 packaged?  Why yes they do: They have qtbase version 5.15.8.&lt;/p&gt;&lt;p&gt;I have not packaged bitcoin-knots for guix yet.  Instead my friend decided to
run bitcoin-core.&lt;/p&gt;&lt;h2&gt;DONE Or I can just install bitcoin-core from guix and run that&lt;/h2&gt;&lt;h1&gt;guix stuff&lt;/h1&gt;&lt;h2&gt;installing guix on chimera linux&lt;/h2&gt;&lt;p&gt;You can install guix via these commands:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
doas chmod u+x guix-install.sh
doas ./guix-install.sh&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Add in the export line so I can use the guix binaries.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.profile

#!/usr/bin/bash

export GUIX_LOCPATH=&amp;quot;$HOME/.guix-profile/lib/locale&amp;quot;

gnome-shell --wayland&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;starting the guix daemon manually&lt;/h2&gt;&lt;pre&gt;&lt;code&gt; ~root/.config/guix/current/bin/guix-daemon &amp;amp;#x2013;build-users-group=guixbuild&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;set up guix daemon via dinit&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;cat /etc/dinit.d/guix-daemon

# guix-daemon service
type = process

# run this command as root
run-as = root
command = /root/.config/guix/current/bin/guix-daemon --build-users-group=guixbuild
# depends-on = bar
# waits-for = baz

# uncomment this next line once you know this works
# before = login.target
before = network.target&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&quot;https://davmac.org/projects/dinit/man-pages-html/dinitcheck.8.html&quot;&gt;https://davmac.org/projects/dinit/man-pages-html/dinitcheck.8.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://davmac.org/projects/dinit/man-pages-html/dinit-service.5.html&quot;&gt;https://davmac.org/projects/dinit/man-pages-html/dinit-service.5.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;So if you cannot get the daemon to autostart, then this will&lt;/p&gt;&lt;p&gt;&lt;code&gt;doas dinitctl start guix-daemon&lt;/code&gt; work.&lt;/p&gt;</content></entry><entry><title>Afterboot OpenBSD</title><id>https://gnucode.me/afterboot-openbsd.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-04-28T23:00:00Z</updated><link href="https://gnucode.me/afterboot-openbsd.html" rel="alternate" /><content type="html">&lt;h1&gt;set up doas&lt;/h1&gt;&lt;p&gt;Let’s make any user that is in the group “wheel” able to execute privledged
commands.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# cat /etc/examples/doas.conf | sed 's/keepenv/persist keepevn/' &amp;gt; /etc/doas.conf&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;install packages&lt;/h1&gt;&lt;pre&gt;&lt;code&gt;# pkg_add emacs dino netsurf dino git fish mpv firefox gpg \
  hack-fonts pkg_add isync evince libreoffice xfce4-terminal \
  xfce4-screenshooter xfce4-dict i3&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When I installed isync, I got a message that said,
the following rcscripts were installed: /etc/rc.d/saslauthd
apparently openbsd’s packaged isync, lets you set up a daemon to periodically
fetch your email.  looking at the file, I’m not sure what it is.&lt;/p&gt;&lt;p&gt;Well I could list all of the packages that I minually installed, it is actually
much easier to create a list of packages.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;pkg_info -mz | tee openbsd-pkg-list&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, when I want to re-install those packages I can just do this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# pkg_add -l list&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;clone my various repos&lt;/h1&gt;&lt;pre&gt;&lt;code&gt;cd ~/
git clone https://notabug.org/jbranso/prog
cd prog
mkdir -p gnu/guix/
cd gnu/guix
git clone https://notabug.org/jbranso/guix
mv guix guix-src
git clone https://notabug.org/jbranso/guix-config&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;update my OpenBSD install&lt;/h1&gt;&lt;p&gt;&lt;code&gt;# doas syspatch&lt;/code&gt;&lt;/p&gt;&lt;h1&gt;enable softupdates&lt;/h1&gt;&lt;p&gt;Unless you are using really old ancient hardware, you should enable softupdates.&lt;/p&gt;&lt;p&gt;change&lt;/p&gt;&lt;p&gt;&lt;code&gt;43434930490.a / ffs rw 1 1&lt;/code&gt;&lt;/p&gt;&lt;p&gt;to&lt;/p&gt;&lt;p&gt;&lt;code&gt;43434930490.a / ffs rw,softdep 1 1&lt;/code&gt;&lt;/p&gt;&lt;h1&gt;window manager stuff&lt;/h1&gt;&lt;h2&gt;modify my ~/.xsession&lt;/h2&gt;&lt;p&gt;auto start xfce, prefer utf-8, set up a background color, and lock X after some
inactivity.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.xsession


# prefer UTF-8 whenever possible
export LC_CTYPE=&amp;quot;en_US.UTF-8&amp;quot;

# use UTF-8 everywhere
export LANG=en_US.UTF-8

# specify location of kshrc
export ENV=$HOME/.kshrc

# set your background color
xsetroot -solid dimgray

xidle -delay 5 -sw -program &amp;quot;/usr/X11R6/bin/xlock -mode flag&amp;quot; \
                   -timeout 300

exec i3&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;set up polybar for i3&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://forum.endeavouros.com/t/tutorial-easy-setup-endeavour-xfce-i3-tiling-window-manager/13171&quot;&gt;https://forum.endeavouros.com/t/tutorial-easy-setup-endeavour-xfce-i3-tiling-window-manager/13171&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# doas pkg_add polybar
$ mkdir ~/.config/polybar
$ cp /usr/local/share/examples/polybar/config ~/.config/polybar&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This &lt;a href=&quot;https://github.com/polybar/polybar/wiki/Fonts&quot;&gt;wiki page&lt;/a&gt; has a lot of details about setting up fonts.&lt;/p&gt;&lt;p&gt;More information is in my &lt;a href=&quot;https://notabug.org/jbranso/openbsd-home/src/master/.config/polybar&quot;&gt;polybar config&lt;/a&gt;.&lt;/p&gt;&lt;h1&gt;If this is a laptop with a battery, then install this&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://dataswamp.org/~solene/2022-03-21-openbsd-cool-frequency.html&quot;&gt;https://dataswamp.org/~solene/2022-03-21-openbsd-cool-frequency.html&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# doas pkg_add obsdfreqd
# rcctl enable obsdfreqd
# rcctl stop apmd
# rcctl disable apmd
# rcctl start obsdfreqd&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;set up doom emacs&lt;/h1&gt;&lt;p&gt;(I also need to ensure that &lt;code&gt;~/prog/gnu/guix/&lt;/code&gt; exists because my emacs looks for
some guix snippets).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone --depth 1 https://github.com/doomemacsdoomemacs ~/.config/emacs
~/.config/emacs/bin/doom install&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;add doom emacs to path&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.profile

# $OpenBSD: dot.profile,v 1.8 2022/08/10 07:40:37 tb Exp $
#
# sh/ksh initialization
#

PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/home/joshua/.config/emacs/bin
export PATH HOME TERM&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;copy my ~/ config files&lt;/h1&gt;&lt;p&gt;cp .authinfo.gpg, .ssh, .mbsyncrc, .gnupg/&lt;/p&gt;&lt;p&gt;cp documents to ~/&lt;/p&gt;&lt;h1&gt;import my gpg keys from my usb stick.&lt;/h1&gt;&lt;p&gt;&lt;code&gt;gpg --import ./dismail.de.gpg.key.asc&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;git config --global commit.gpgsign true&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;gpg --list-secret-keys --keyid-format=long&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Copy the really long alphanumeric word from the above command.  It'll
look something like:&lt;/p&gt;&lt;p&gt;62A42A3CC13497D626FZ686C750BCFEF3A5E1572&lt;/p&gt;&lt;p&gt;&lt;code&gt;git config --global user.signingkey &amp;lt;your alphanumeric word&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;h2&gt;set up pinentry&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;pkg_add pinentry-dmenu&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There are two things that you need to do to set up pinentry-dmenu, so that when I
need to sign commits or decrypt stuff, the pinentry-dmenu popup happens.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;set up gpg agent&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.gnupg/gpg-agent.conf

pinentry-program /usr/local/bin/pinentry-dmenu
    
default-cache-ttl 3600&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;man gpg-agent&lt;/code&gt; says to do this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;You should always add the following lines to your .bashrc or whatever
initialization file is used for all shell invocations:

cat ~/.profile | grep GPG_TTY

GPG_TTY=$(tty)
export GPG_TTY&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;start a dbus session&lt;/p&gt;&lt;p&gt;This is only needed if you want to use pinentry-gnome3&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.xsession | grep dbus

# start a dbus session, which I believe gpg needs to for graphical pinentry
# I found this command in /usr/local/share/doc/pkg-readmes/dbus
if [ -x /usr/local/bin/dbus-launch -a -z &amp;quot;${DBUS_SESSION_BUS_ADDRESS}&amp;quot; ]; then
        eval `dbus-launch --sh-syntax --exit-with-x11`&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If you have difficulty getting pinentry to work, here are some steps to
manually get pinentry to work:&lt;/p&gt;&lt;p&gt;in a fish terminal a type in:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpgconf --kill gpg-agent
set GPG_TTY $(tty)
export GPG_TTY
git commit -m &amp;quot;my commit message&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;change &lt;code&gt;/etc/motd&lt;/code&gt;&lt;/h1&gt;&lt;p&gt;I once set an invalid option up in /etc/fstab that threw me in a root shell with
only root mounted.  All of a sudden vi would not work.  That below command is
how to fix it:  &lt;code&gt;export TERM=vt200&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /etc/motd

OpenBSD 7.2 (GENERIC.MP) #7: Sat Feb 25 14:07:58 MST 2023

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Please use the sendbug(1) utility to report bugs in the system.
Before reporting a bug, please try to reproduce it with the latest
version of the code.  With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.

If you are having trouble using vi in the console try this:

export TERM=vt200;&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;install haunt on OpenBSD&lt;/h1&gt;&lt;p&gt;&lt;code&gt;doas pkg_add guile info&lt;/code&gt;&lt;/p&gt;&lt;p&gt;First install guile-commonmark:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ cd ~/prog/guile
$ git clone git clone https://github.com/OrangeShark/guile-commonmark
$ cd guile-commonmark
# export AUTOCONF_VERSION=2.71
# export export AUTOMAKE_VERSION=1.16.5
# doas pkg_add autoconf automake&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Why am I seeing 2 aclocal binaries?  No idea.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ls /usr/local/bin/aclocal*
ls /usr/local/bin/automake*

/usr/local/bin/aclocal
/usr/local/bin/aclocal-1.16
/usr/local/bin/automake
/usr/local/bin/automake-1.16&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Arsen on irc helped me figure out the next incantation.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;AUTOMAKE=automake-1.16 ACLOCAL=aclocal-1.16 ./bootstrap
./configure
make
make check
# make install&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s install haunt&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone https://git.dthompson.us/haunt.git
cd haunt
AUTOMAKE=automake-1.16 ACLOCAL=aclocal-1.16 ./bootstrap
./configure
make
make check
# make install&lt;/code&gt;&lt;/pre&gt;</content></entry><entry><title>OpenBSD's hotplugd rocks!</title><id>https://gnucode.me/openbsds-hotplugd-rocks.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-04-13T11:41:00Z</updated><link href="https://gnucode.me/openbsds-hotplugd-rocks.html" rel="alternate" /><content type="html">&lt;p&gt;My last post talked about how I broke my OpenBSD laptop by telling OpenBSD that
my usbstick was essential to the boot process, and then, when I booted the
laptop, I did not have that usb stick mounted. That caused some problems. I
since learned that the preferred way of automounting a usb stick under OpenBSD
is with &lt;code&gt;hotplugd&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://man.openbsd.org/hotplugd&quot;&gt;hotplugd&lt;/a&gt; is OpenBSD’s automounting functionality, and it’s actually super simple
and easy. Just put your scripts at &lt;code&gt;/etc/hotplugd/attach&lt;/code&gt; and
&lt;code&gt;/etc/hotplugd/detach&lt;/code&gt;. And the man page gives you an example shell script, but
since I am not a big fan of &lt;code&gt;sh&lt;/code&gt; (its syntax is confusing), I decided to write
my attach script in &lt;a href=&quot;https://www.gnu.org/software/guile/&quot;&gt;GNU Guile&lt;/a&gt;. Writing that script made me want to write more
scripts in &lt;a href=&quot;https://scsh.net/&quot;&gt;scheme shell&lt;/a&gt;, but I the last time I tried to install the scheme shell
on OpenBSD, it failed to compile.&lt;/p&gt;&lt;p&gt;Anyway, it is really easy to write your own script.  &lt;code&gt;hotplugd&lt;/code&gt; will call your
script like so:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;attach &amp;lt;number&amp;gt; &amp;lt;label&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;where &lt;code&gt;&amp;lt;number&amp;gt;&lt;/code&gt; is one of the numbers in the table below and &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; is a
short descriptive string of the device.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;|---+------------------------------------|
| 0 | generic, no special info           |
|---+------------------------------------|
| 1 | CPU (carries resource utilization) |
|---+------------------------------------|
| 2 | disk drive                         |
|---+------------------------------------|
| 3 | network interface                  |
|---+------------------------------------|
| 4 | tape device                        |
|---+------------------------------------|
| 5 | serial line interface              |
|---+------------------------------------|&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I am only really interested in &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;3&lt;/code&gt;. Here is how I debbuged my attach
script, and you can easily do the same.&lt;/p&gt;&lt;p&gt;First find out what &lt;code&gt;sd&lt;/code&gt; device your usb stick is.  Before you put in your usb
stick type in:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sysctl hw.disknames

hw.disknames=sd0:ec557d42f5cbfa41,sd1:5583d235b610c8a2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now put in your usb stick and run the same command.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sysctl hw.disknames

hw.disknames=sd0:ec557d42f5cbfa41,sd1:5583d235b610c8a2,sd2:&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So now I know that my usb stick is sd2.  Let’s do a disklabel command on it:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# disklabel sd2

# /dev/rsd2c:
type: SCSI
disk: SCSI disk
label: USB Flash Drive
duid: 0000000000000000
flags:
bytes/sector: 512
sectors/track: 63
tracks/cylinder: 255
sectors/cylinder: 16065
cylinders: 1887
total sectors: 30326784
boundstart: 0
boundend: 30326784

16 partitions:
#                size           offset  fstype [fsize bsize   cpg]
  c:            14.5G                0  unused
  i:            14.5G             2048   MSDOS&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice from the output that this label is “USB Flash Drive”.  That is the label
that hotplugd will send to your attach script.&lt;/p&gt;&lt;p&gt;If you want a usb stick that is read-able/writeable accross all operating
systems, currently you will want to use the &lt;a href=&quot;https://wiki.archlinux.org/title/FAT&quot;&gt;vfat&lt;/a&gt; filesystem. That is what the
output above shows. The &lt;code&gt;fstype&lt;/code&gt; of &lt;code&gt;MSDOS&lt;/code&gt; is a vfat filesystem. This usb stick
is what I will use when I want to copy data between different OS-es (I do want
an &lt;a href=&quot;https://www.openbsd.org/faq/faq14.html#softraidCrypto&quot;&gt;encrypted OpenBSD-specific usb stick&lt;/a&gt; to store my gpg keys, but I have not yet
set that up). According to some of the smart people on the &lt;code&gt;#openbsd&lt;/code&gt; irc
channel, if you have such a usb stick, then the &lt;code&gt;i&lt;/code&gt; filesystem partition is the
one that you want to mount to read the data. And we see that above as well (&lt;code&gt;c&lt;/code&gt;
is code for the whole drive. &lt;code&gt;/dev/rsd2c&lt;/code&gt; is how you access the whole and raw
disk).&lt;/p&gt;&lt;p&gt;Ok, so now that you know what arguments that &lt;code&gt;hotplugd&lt;/code&gt; will send your script,
go ahead and write your basic script. It probably won’t be perfect, which is ok.
To test it, type in &lt;code&gt;su&lt;/code&gt; in your terminal to get to root account, and then test
your script in the exact same way that OpenBSD will use your script (&lt;code&gt;#&lt;/code&gt; means
that you are currently the root user):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# ./attach 2 &amp;quot;USB Flash Drive&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You will probably get some weird errors, and that’s ok. After you have run your
attach script, and it seemed to have no errors, verify that it properly mounted
with:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mount

/dev/sd1a on / type ffs (local, softdep)
/dev/sd1k on /home type ffs (local, nodev, nosuid, softdep)
/dev/sd1d on /tmp type ffs (local, nodev, nosuid, softdep)
/dev/sd1f on /usr type ffs (local, nodev, softdep)
/dev/sd1g on /usr/X11R6 type ffs (local, nodev, softdep)
/dev/sd1h on /usr/local type ffs (local, nodev, wxallowed, softdep)
/dev/sd1j on /usr/obj type ffs (local, nodev, nosuid, softdep)
/dev/sd1i on /usr/src type ffs (local, nodev, nosuid, softdep)
/dev/sd1e on /var type ffs (local, nodev, nosuid, softdep)
/dev/sd2i on /mnt/usb type msdos (local, nodev, noexec)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And it look like I properly mounted my usb stick (the last line says it was).&lt;/p&gt;&lt;p&gt;One thing that users might find confusing is that OpenBSD passes in &lt;code&gt;2&lt;/code&gt;, but
Guile accepted the &lt;code&gt;2&lt;/code&gt; as a string.&lt;/p&gt;&lt;p&gt;My simple &lt;a href=&quot;https://notabug.org/jbranso/prog/src/master/gnu/guile/scripts/attach&quot;&gt;attach script&lt;/a&gt; works for me.  It will only auto mount vfat filesystems,
and I am pretty sure that weird things will happen if I plug in two usb sticks
at once, but it works.&lt;/p&gt;</content></entry><entry><title>Accidentally Deleting fstab</title><id>https://gnucode.me/accidentally-deleting-fstab.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-04-05T20:00:00Z</updated><link href="https://gnucode.me/accidentally-deleting-fstab.html" rel="alternate" /><content type="html">&lt;p&gt;The end of my previous blog post was a bit of a cliff hanger:&lt;/p&gt;&lt;p&gt;I did have a great time the next day. I was hoping to automount my usb
stick on boot. So I added this beauty to my &lt;code&gt;/etc/fstab&lt;/code&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;sd1i /mnt/usb msdos rw 1 2&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The next time I booted it threw me into a rescue shell with only &lt;code&gt;/&lt;/code&gt; mounted.&lt;/p&gt;&lt;p&gt;This is the story of how I fixed a broken fstab on OpenBSD.  The day began like
any other.  It was cold and dark as I arose to play with my new OpenBSD
computer.  It was time to reboot!  That magical moment when OpenBSD &lt;a href=&quot;https://www.openbsd.org/innovations.html&quot;&gt;relinks the
kernel at boot&lt;/a&gt;.  How cool is that?&lt;/p&gt;&lt;p&gt;My admiration for this world class operating continues to rise as it boots, and
OpenBSD proudly slaps me in the face (I did not write down the OpenBSD error
message, but this is essentially what it said):&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;mount cannot find device sd1i.  You are now in a resque shell.&lt;/p&gt;&lt;p&gt;root&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Hmmm. Well that’s a bummer. It looks like I had told OpenBSD that that usb stick
was necesary for boot. I also did not have the usb stick plugged in, and OpenBSD
needed me to write &lt;code&gt;/dev/sd1i&lt;/code&gt; not &lt;code&gt;sd1i&lt;/code&gt;. It might be a good project idea to
add &lt;a href=&quot;https://man.openbsd.org/opendev&quot;&gt;opendev&lt;/a&gt; support to OpenBSD’s mount. Any takers?&lt;/p&gt;&lt;p&gt;Anyway, to fix this, I attempted to delete that last line from &lt;code&gt;/etc/fstab&lt;/code&gt;. I
tried to type out &lt;code&gt;cd /etc/&lt;/code&gt;. Instead I got gibberish. Testing the keyboard a
bit, I noticed that the keyboard was in the qwerty layout. I use dvorak. And my
laptop keyboard physically shows a dvorak keyboard layout. It’s really hard to
type correctly on a keyboard when pressing “‘,.pyf” is “qwerty”. Well let’s
change my keyboard layout (notice that all commands below are run as the &lt;code&gt;root&lt;/code&gt;
user. The &lt;code&gt;#&lt;/code&gt; means you are running as a root user).&lt;/p&gt;&lt;p&gt;I painstakingly typed out the following command.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# wsconctl keyboard.encoding=us.dvorak&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Awesome, that is an improvement. Let’s change &lt;code&gt;/etc/fstab&lt;/code&gt;. The following
commands did not work, because the shell could not find the binary:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;nano /etc/fstab&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;vim /etc/fstab&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;vi /etc/fstab&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Well that’s weird.  Is &lt;code&gt;/usr/bin&lt;/code&gt; not mounted?&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# mount

/dev/sd1a on / type ffs (ro)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oh great! I only have &lt;code&gt;/&lt;/code&gt; mounted! So my commands are limited, and &lt;code&gt;/&lt;/code&gt; is
mounted read only. So even if I find a text editor that I can use, I cannot
modify &lt;code&gt;/etc/fstab&lt;/code&gt;. How do I mount &lt;code&gt;/&lt;/code&gt; read-write? According to the irc people
who helped me out, this is how: you update the mount information based on what
&lt;code&gt;/etc/fstab&lt;/code&gt; says.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# mount -uvw /
# mount

/dev/sd1a on / type ffs (rw)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Awesome, &lt;code&gt;fstab&lt;/code&gt; is editable! I tried to edit &lt;code&gt;/etc/fstab&lt;/code&gt; but &lt;code&gt;vi&lt;/code&gt; was not
available, probably because &lt;code&gt;vi&lt;/code&gt; is located in &lt;code&gt;/usr&lt;/code&gt;, which is not yet mounted.&lt;/p&gt;&lt;p&gt;What I should have done was &lt;code&gt;mount -U&lt;/code&gt;.  This just mounts all mount points
listed in &lt;code&gt;/etc/fstab&lt;/code&gt;.  I did not read that option in the manpage yet.  So I
decided to manually try to guess which filesytem was which.&lt;/p&gt;&lt;p&gt;Well let’s print out human read-able file sizes of my filesystem partitions and
that will give me some clue which filesystem is which. (please note that I am
intentionally removing the offsets).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# disklabel -h sd1

16 partitions:
#                size           offset  fstype [fsize bsize   cpg]
  a:             1.0G                   4.2BSD   2048 16384 12960
  b:             8.0G                     swap
  c:           931.5G                   unused
  d:             4.0G                   4.2BSD   2048 16384 12960
  e:            19.5G                   4.2BSD   2048 16384 12960
  f:            30.0G                   4.2BSD   2048 16384 12960
  g:             1.0G                   4.2BSD   2048 16384 12960
  h:            20.0G                   4.2BSD   2048 16384 12960
  i:             3.0G                   4.2BSD   2048 16384 12960
  j:             6.0G                   4.2BSD   2048 16384 12960
  k:           300.0G                   4.2BSD   4096 32768 26062&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok. Clearly the 300G is my &lt;code&gt;/home&lt;/code&gt;. I can mount that now.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# mount /dev/sd1k /home&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok. How do I mount &lt;code&gt;/usr&lt;/code&gt; so that I have text editors? I don’t really know which
partition is which. I guess I will just guess. Eventually I did correctly mount
&lt;code&gt;/usr&lt;/code&gt;, so now I should have access to some text editors! So now I could edit
&lt;code&gt;fstab&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# vim /etc/fstab

vim: unknown command&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok.  vim is not installed.  Let’s try vi.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# vi /etc/fstab

vi: unknown terminal type&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So vi doesn’t run on the console?  That’s odd.  Ok.  Lets see what &lt;code&gt;head&lt;/code&gt;
shows me:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# head /etc/fstab

5583d235b610c8a2.a /          ffs rw,softdep 1 1
5583d235b610c8a2.k /home      ffs rw,softdep,nodev,nosuid 1 2
5583d235b610c8a2.d /tmp       ffs rw,softdep,nodev,nosuid 1 2
5583d235b610c8a2.f /usr       ffs rw,softdep,nodev 1 2
5583d235b610c8a2.g /usr/X11R6 ffs rw,softdep,nodev 1 2
5583d235b610c8a2.h /usr/local ffs rw,wxallowed,softdep,nodev 1 2
5583d235b610c8a2.j /usr/obj   ffs rw,softdep,nodev,nosuid 1 2
5583d235b610c8a2.i /usr/src   ffs rw,softdep,nodev,nosuid 1 2
5583d235b610c8a2.e /var       ffs rw,softdep,nodev,nosuid 1 2
5583d235b610c8a2.b none swap sw&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hey would you look at that! There is no line with &lt;code&gt;/mnt/usb&lt;/code&gt;. I should be able
to just overwrite &lt;code&gt;fstab&lt;/code&gt; with the output of &lt;code&gt;head&lt;/code&gt;. Please do NOT copy or
execute the following command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# head /etc/fstab &amp;gt; /etc/fstab&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I wish I had read the irc chat before I had executed the above command. In the
words of a wise sage, “the redirection happens before head runs, so you’ll just
get a blank file.” And that is exactly what happened. &lt;code&gt;/etc/fstab&lt;/code&gt; was empty.
Now how do I mount filesystem partitions in the correct locations? “Out of the
frying pan and into the fire.”&lt;/p&gt;&lt;p&gt;Some of the people on irc mentioned that &lt;code&gt;/var/backups&lt;/code&gt; should have a copy of my
&lt;code&gt;fstab&lt;/code&gt;.  Unfortunately, that backup command had not run yet.  This was a fresh
OpenBSD install afterall.&lt;/p&gt;&lt;p&gt;One of the people on the OpenBSD chat showed me this &lt;a href=&quot;https://github.com/openbsd/src/blob/master/sbin/disklabel/editor.c#L91&quot;&gt;link&lt;/a&gt;, which was super
helpful, because it shows you the default size of the various partitions that
the auto installer sets up. With that information, I was able to re-mount all my various
partitions.  Then someone on irc chat gave me this beauty of a command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# mount | awk '{ print $1 &amp;quot; &amp;quot; $3 &amp;quot; &amp;quot; $5 &amp;quot; rw 0 0&amp;quot;}' &amp;gt; /etc/fstab&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That created my &lt;code&gt;fstab&lt;/code&gt; for me!  Let’s check it out!&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# cat /etc/fstab

sd1.a /          ffs rw 1 1
sd1.k /home      ffs rw 1 2
sd1.d /tmp       ffs rw 1 2
sd1.f /usr       ffs rw 1 2
sd1.g /usr/X11R6 ffs rw 1 2
sd1.h /usr/local ffs rw 1 2
sd1.j /usr/obj   ffs rw 1 2
sd1.i /usr/src   ffs rw 1 2
sd1.e /var       ffs rw 1 2
sd1.b none swap sw&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmm, well the mount options are absent, and it is NOT using UIDs…But this
should be enough to boot into a complete system. So I rebooted. Upon reboot, I
was able to change the mount points to UIDs and copy the proper mount options
from my desktop OpenBSD. I then very quickly set up &lt;a href=&quot;https://man.openbsd.org/hotplugd&quot;&gt;hotplugd&lt;/a&gt;, which I will
explain next time.  Until then!&lt;/p&gt;</content></entry><entry><title>Libreboot Full Disk encryption on OpenBSD</title><id>https://gnucode.me/libreboot-full-disk-encryption-on-openbsd.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-03-30T23:00:00Z</updated><link href="https://gnucode.me/libreboot-full-disk-encryption-on-openbsd.html" rel="alternate" /><content type="html">&lt;p&gt;So I previously talked about my &lt;a href=&quot;http://gnucode.me/installing-openbsd-on-a-vm.html&quot;&gt;interest&lt;/a&gt; &lt;a href=&quot;http://gnucode.me/dual-booting-openbsd-guix-system.html&quot;&gt;in OpenBSD&lt;/a&gt;. Well last week, I
have been more and more impressed with OpenBSD, especially after watching
&lt;a href=&quot;https://undeadly.org/cgi?action=article;sid=20230325163416&quot;&gt;Theo’s recent talk&lt;/a&gt;. I recently installed OpenBSD on my desktop, and I was
satisfied. There are some things that I knew how to do on GNU Guix that I do not
yet know how to do on OpenBSD. For example, there is a minor issue with the
sound being a bit wonky but that is not a deal breaker.&lt;/p&gt;&lt;p&gt;A few days ago I switched to OpenBSD on my laptop. So now, with the exception of
my PinePhone, all of my computing devices are using OpenBSD.  The OpenBSD
installer is getting support for autoencrypting your hard drive, but I wanted to
document the manual set up process if I ever decide to set up a RAID+ecryption.
I do not believe the installer will support RAID+encryption anytime soon.&lt;/p&gt;&lt;p&gt;The real problem was trying to get libreboot to even recognize the OpenBSD usb
installer stick. The best method to boot OpenBSD on libreboot is to use the
seaBIOS payload. I could NOT get this to work. I must have booted and rebooted
10+ times trying to get this to work. I even opened up a grub command line
prompt, and it could not SEE the usb stick. &lt;a href=&quot;https://misc.openbsd.narkive.com/auaZDqBe/bsd-rd-fails-to-boot-up-on-libreboot-x200-how-to-find-out-why&quot;&gt;Others have reported this problem.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;In grub you can get a feel for what partitions are available via:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; ls

(hd0) (hd0,msdos1)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This seems to only show my GNU/Linux Guix System partition.  That’s not a good
sign.  There is another way to check.  I can type out the following
&lt;code&gt;set root=(hd0,msdos1)/&lt;/code&gt;&lt;/p&gt;&lt;p&gt;and then press TAB:&lt;/p&gt;&lt;p&gt;I was able to see &lt;code&gt;/bin&lt;/code&gt;, &lt;code&gt;/boot&lt;/code&gt;, &lt;code&gt;/etc&lt;/code&gt;, etc. Going into &lt;code&gt;/var&lt;/code&gt;, I saw
&lt;code&gt;guix/&lt;/code&gt;. So clearly &lt;code&gt;hd0&lt;/code&gt; is my current SSD that has GNU/Linux Guix System. And
grub and libreboot did NOT see the OpenBSD usb stick. I kept rebooting, tried
searching for the OpenBSD stick, and finally the grub console showed me
something other than &lt;code&gt;(hd0,msdos1)&lt;/code&gt;. I think I have to use the right-most usb
port. I think that is the secret.&lt;/p&gt;&lt;p&gt;Technically, &lt;a href=&quot;https://notabug.org/swiftgeek/libreboot/src/master/docs/bsd/openbsd.md&quot;&gt;grub can boot
OpenBSD&lt;/a&gt;,
at least grub as packaged by Libreboot, but that is NOT advisable. And grub's
ability to boot OpenBSD may disappear at any moment. Seeing no other option, I
typed in this command to boot OpenBSD via grub:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; kopenbsd (usb0)/7.2/amd64/bsd.rd
grub&amp;gt; boot&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And OpenBSD started booting!  Woo hoo!  At the OpenBSD installer I typed in “s”
to exit to the shell so that I could set up full disc encryption.&lt;/p&gt;&lt;p&gt;Before we get to the disc encryption, let me give a quick overview of how
OpenBSD sets up partitions. OpenBSD supports both MBR and GPT partitions, which
divide the physical disc into sections (MBR is old; GPT is the modern way to do
it, and most people will want GPT on newer machines so for the rest of this blog
post I will just talk about GPT). All operating systems recognize and use GPT
partitions. Linux will install its filesystem partitions into seperate GPT
partitions, which means that a &amp;quot;partition&amp;quot; in Linux means the GPT
partition and the filesystem partion.  Here's a handy graphic:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;|--------------+------------+----------------|
|              | Linux      |                |
|--------------+------------+----------------|
| GPT partiton | filesystem | mount location |
|              | partition  |                |
|--------------+------------+----------------|
| /dev/sda1    | ext4       | /              |
| /dev/sda2    | btrfs      | /etc           |
| /dev/sda3    | xfs        | /boot          |
| ...          | ...        | ...            |
| /dev/sda128  | vfat       | /boot/efi      |
|              |            |                |
| /dev/sdb1    | ext4       | /data          |
|--------------+------------+----------------|&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OpenBSD is a little different. It uses one big GPT partition, and then it
further splits up that one big GPT partition into filesystem partitions, which
can be examined via &lt;a href=&quot;https://man.openbsd.org/disklabel&quot;&gt;disklabel&lt;/a&gt;. So in
OpenBSD &lt;code&gt;sd0&lt;/code&gt; and &lt;code&gt;sd1&lt;/code&gt; refer to the first and second hard drive. &lt;code&gt;/dev/sd0c&lt;/code&gt;
refers to the one big GPT partition and &lt;code&gt;/dev/sd0a&lt;/code&gt; by convention is the &lt;code&gt;/&lt;/code&gt;
partition. &lt;code&gt;/dev/sd0b&lt;/code&gt; is swap by convention and &lt;code&gt;d&lt;/code&gt; through &lt;code&gt;p&lt;/code&gt; could refor to
any other arbitrary mount point. So &amp;quot;partition&amp;quot; in OpenBSD may refer to the GPT
partion or the filesystem partitions.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;|--------------+-------------+----------------|
|              | OpenBSD     |                |
|--------------+-------------+----------------|
| GPT partiton | filesystem  | mount location |
|              | partition   |                |
|              | (FFS)       |                |
|--------------+-------------+----------------|
| /dev/sd01    | /dev/sd0a   | /              |
| /dev/sd01    | /dev/sd0b   | swap           |
| /dev/sd01    | /dev/sd0c   | not mounted    |
| /dev/sd01    | /dev/sd0d   | /home          |
|              | ...         |                |
| /dev/sd01    | /dev/sd0e   | /tmp           |
|              |             |                |
| /dev/sd11    | /dev/sd1i   | /data          |
|--------------+-------------+----------------|&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I would highly recommend the OpenBSD
&lt;a href=&quot;https://www.openbsd.org/faq/faq14.html#intro&quot;&gt;faq&lt;/a&gt; page about this (as well as
the disklabel man page), which will also act as a more official version of this
blog post. Now on with the blog post!&lt;/p&gt;&lt;p&gt;Let’s figure out which drive is my usb stick, and which drive is my SSD with
Guix on it.  Please note that I did not write the output of this command down.
Your output might look different.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sysctl hw.disknames

hw.disknames=sd0:ec557d42f5cbfa41,sd1:&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I typed in the next two commands to try to get a feel for which drive was my
SSD.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;doas disklabel sd0
doas disklabel sd1&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I forget what the above commands output-ed, but looking at the output I was able
to determine that &lt;code&gt;sd0&lt;/code&gt; was my GNU/Linux Guix System.  Now it was time to set up a
&lt;a href=&quot;https://www.openbsd.org/faq/faq14.html#softraidFDE&quot;&gt;full disc encryption&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd /dev &amp;amp;&amp;amp; sh MAKEDEV sd0
dd if=/dev/urandom of=/dev/rsd0c bs=1m&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That second command took 8+ hours to complete.  It wrote random data on the
whole SSD.  That way, if an attacker ever stole my hard drive, when they
examined my hard drive, they would not see:&lt;/p&gt;&lt;p&gt;00000000EncryptedData0000000EncryptedData000000&lt;/p&gt;&lt;p&gt;Instead they would see&lt;/p&gt;&lt;p&gt;RandomDataRandomDataRandomDataRandomDataRandomDataRandomData&lt;/p&gt;&lt;p&gt;where only the 2nd and 5th =RandomData= are actually my encrypted files.  Trying
to figure what is data and what is just random ones and zeros would be really
hard.  However, I should probably ask on &lt;code&gt;#openbsd&lt;/code&gt; irc to make sure that I
wrote the right command.  Is there a way to search your raw hard drive for a
section of disc that is just 10,000 zeros?&lt;/p&gt;&lt;p&gt;Anway, let’s partition the &lt;code&gt;sd0&lt;/code&gt; drive and format it as a RAID.  Random encrypted
data will go to &lt;code&gt;sd0&lt;/code&gt;.  OpenBSD will read files from the unencrypted &lt;code&gt;sd1&lt;/code&gt;,
which will be encrypted and stored on &lt;code&gt;sd0&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;fdisk -iy sd0
sd0&amp;gt; *a* *a*
sd0&amp;gt;size: [ ... ] ***
sd0&amp;gt; FS type: *RAID*
sd0&amp;gt; *w*
sd0&amp;gt; *q*&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This next command will ask you for a passphrase.  If you use an alternative
keyboard layout, then make your command use numbers and special characters on
the 1-9 section.  That way you can still type in the secret password on boot,
because OpenBSD changes your keyboard layout after you unlock your encrypted
volumes.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;bioctl -c C -l sd0a softraid0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s set up &lt;code&gt;sd1&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd /dev &amp;amp;&amp;amp; sh MAKEDEV sd1
dd if=/dev/zero of=/dev/rsd1c bs=1m count=1
exit&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will return us to the main installer.  When the installer asks you which
hard drive to install OpenBSD on, I said &lt;code&gt;sd1&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;[...]
Available disks are: sd0 sd1.
Which disk is the root disk? ('?' for details) [sd0] *sd1*&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And that was that! I did a few things to set up &lt;code&gt;XFCE&lt;/code&gt;, which I quickly
abandoned in favor of i3, and I was off to the races. Then I realized that my
full-disk decryption passphrase was pretty weak. Basically, because I use a
physical &lt;a href=&quot;https://en.wikipedia.org/wiki/Dvorak_keyboard_layout&quot;&gt;dvorak keyboard
layout&lt;/a&gt;, and OpenBSD uses
the standard &lt;a href=&quot;https://en.wikipedia.org/wiki/QWERTY&quot;&gt;qwerty&lt;/a&gt; layout when you type
in the password to decrypt the disk, my initial full disk encryption password
was just numbers. Now, I wanted to change it to my normal password.&lt;/p&gt;&lt;p&gt;Apparently you can do so while the encrypted volume &lt;a href=&quot;https://dev.to/nabbisen/openbsd-disk-encryption-change-passphrase-4i8l&quot;&gt;is
mounted&lt;/a&gt;!
I made sure that I changed the keyboard layout to the standard qwerty, when I typed in
the new passphase.&lt;/p&gt;&lt;pre&gt;&lt;code&gt; doas bioctl -P sd1  # I was using the dvorak layout here&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In another terminal I typed in:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; setxkbmap -layout us&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then I moved to the terminal that was asking me to change the full disk
encryption password.&lt;/p&gt;&lt;pre&gt;&lt;code&gt; Old Passphrase:    # I typed in the numbers
 New Passphrase:    # I typed in an awesome password
 Confirm Passphrase:  # I typed it in again.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let's get back to dvorak:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; setxkbmap -layout dvorak&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That's better. I did have a great time the next day. I was hoping to
automatically automount my usb stick on boot. So I added this beauty to my
&lt;code&gt;/etc/fstab&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;sd2i /mnt/usb msdos rw 1 2&lt;/code&gt;&lt;/p&gt;&lt;p&gt;The next time I booted it threw me into a rescue shell with only &lt;code&gt;/&lt;/code&gt; mounted.
That was a wild ride to fix, bit I will explain how I fixed that next time!&lt;/p&gt;</content></entry><entry><title>Installing Fedora on Power9</title><id>https://gnucode.me/installing-fedora-on-power9.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-03-06T13:30:00Z</updated><link href="https://gnucode.me/installing-fedora-on-power9.html" rel="alternate" /><content type="html">&lt;p&gt;My friend has a &lt;a href=&quot;https://www.raptorcs.com/TALOSII/&quot;&gt;TalosII&lt;/a&gt; machine. He currently uses void linux, but void has
dropped their &lt;a href=&quot;https://en.wikipedia.org/wiki/Power_ISA&quot;&gt;Power ISA&lt;/a&gt; support. So I convinced him to give Debian Gnu/Linux a
try.  First we downloaded the &lt;a href=&quot;https://www.debian.org/&quot;&gt;debian&lt;/a&gt; image:&lt;/p&gt;&lt;p&gt;We navigated our way around the website to download a &lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/&quot;&gt;complete debian DVD image&lt;/a&gt;,
which was about 5 GB. We then tried to figure out how to &lt;a href=&quot;https://www.debian.org/CD/verify&quot;&gt;verify the installer
image&lt;/a&gt;, which basically means, to check that the file we downloaded was not
malware.&lt;/p&gt;&lt;p&gt;Well let’s first import the debian GPG keys:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
    &amp;quot;1046 0DAD 7616 5AD8 1FBC  0CE9 9880 21A9 64E6 EA7D&amp;quot;


gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
    &amp;quot;DF9B 9C49 EAA9 2984 3258  9D76 DA87 E80D 6294 BE9B&amp;quot;


gpg --keyserver hkp://keyserver.ubuntu.com --recv-key \
    &amp;quot;F41D 3034 2F35 4669 5F65  C669 4246 8F40 09EA 8AC3&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s double check that we have those signing keys:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --list-keys | grep debian

uid           [ unknown] Debian CD signing key &amp;lt;debian-cd@lists.debian.org&amp;gt;
uid           [ unknown] Debian CD signing key &amp;lt;debian-cd@lists.debian.org&amp;gt;
uid           [ unknown] Debian Testing CDs Automatic Signing Key &amp;lt;debian-cd@lists.debian.org&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sweet. Now what? How do we actually and practically, via what commands,
verify the installer images? Well the debian page is not specific about
what to do next. So I had to searching the internet for how to verify debian
images. And I found this awesome &lt;a href=&quot;https://danilodellaquila.com/en/blog/how-to-verify-authenticity-of-downloaded-debian-iso-images&quot;&gt;blog post&lt;/a&gt;.  Here’s how we do it:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;wget https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/SHA512SUMS
wget https://cdimage.debian.org/debian-cd/current/ppc64el/iso-dvd/SHA512SUMS.sign

gpg --verify SHA512SUMS.sign
gpg --verify SHA512SUMS.sign SHA512SUMS

sha512sum -c SHA512SUMS 2&amp;gt;/dev/null | grep debian-11.6.0-ppc64el-netinst.iso

debian-11.6.0-ppc64el-netinst.iso: OK&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We then tried to boot the usb debian power image.  That failed to boot.  Then we
tried burning that image to a DVD.  That did not work.&lt;/p&gt;&lt;p&gt;So I am guessing that Debian GNU/Linux will work on power, BUT the graphical
installer does not currently work on Debian (I found out later that the Debian
ncuruses installer does work on power).&lt;/p&gt;&lt;p&gt;My friend then installed Ubuntu server. Ubuntu server's installer actually
worked! Then we just turned Ubuntu server into a Xubuntu like environment via
command like: &lt;code&gt;sudo apt install xfce -y&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Then we rebooted and everything worked! Well, &lt;code&gt;Gnome&lt;/code&gt; did not. And &lt;code&gt;Xubuntu&lt;/code&gt; did
not, but then we used &lt;code&gt;gdm&lt;/code&gt; to log into &lt;code&gt;xfce&lt;/code&gt; desktop. That worked flawlessly.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;netsurf&lt;/code&gt; web browser also worked really well!  Which meant we could use any
website that had virtually no javascript.&lt;/p&gt;&lt;p&gt;Then I thought, it would be great to have a modern web browser working on my
friend’s desktop...&lt;/p&gt;&lt;p&gt;Well it looks like Firefox can run on Power9!&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.talospace.com/search/label/Firefox&quot;&gt;https://www.talospace.com/search/label/Firefox&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The latest blog post says that you can run Firefox version 110 on
Power9.  You can either add in a &lt;code&gt;--disable-webrtc&lt;/code&gt; in your
&lt;code&gt;.mozconfig&lt;/code&gt; or you can compile Firefox with a tiny patch.&lt;/p&gt;&lt;p&gt;AND nonguix has a recipe for building Firefox.  Let’s see if I can
just install &lt;code&gt;guix&lt;/code&gt; set up the &lt;code&gt;nonguix channel&lt;/code&gt; and build Firefox that way!&lt;/p&gt;&lt;p&gt;If the nonguix packaged Firefox doesn’t work, then I can try to set
build firefox from source via this video:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Hx42tyEWPxk&quot;&gt;https://www.youtube.com/watch?v=Hx42tyEWPxk&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Devaun was also a possiblity.  That is a fork of debian that does not use
&lt;code&gt;systemd&lt;/code&gt;.  My friend is not a big fan of systemd.&lt;/p&gt;&lt;p&gt;I was also told that Fedora is probably the easiest linux distribution, in which
to run GNU/Linux on Power9.&lt;/p&gt;&lt;p&gt;Well installing Fedora was actually easy.  The installer just worked.
(Apparently Debian GNU/Linux disables the ast driver by default, which means a
VGA display will not work).  And I have a working Firefox.  Apparently I can run
a slightly older version of firefox that has a &lt;a href=&quot;https://copr.fedorainfracloud.org/coprs/sharkcz/talos/&quot;&gt;working javascript JIT.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;My friend now has a working Xfce desktop courtesy from &lt;a href=&quot;https://getfedora.org/&quot;&gt;Fedora GNU/Linux&lt;/a&gt;. My only
concern is that this &lt;a href=&quot;https://www.talospace.com/2022/12/fedora-37-mini-review-on-blackbird-and.html&quot;&gt;blog post&lt;/a&gt; seems to suggest that updating Fedora on a Power9
machine is going to be quite annoying. I would not want to have to re-install
Fedora every time they upgrade. I personally no longer have any issues upgrading
my laptop to my distro latest release, because I have found that GNU Guix System
just works really well.  And if an upgrade breaks, then I can always roll back
to the previous known working system during the boot process.&lt;/p&gt;&lt;p&gt;It looks like Fedora can support something like this:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://sysguides.com/install-fedora-36-with-snapper-and-grub-btrfs/&quot;&gt;https://sysguides.com/install-fedora-36-with-snapper-and-grub-btrfs/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Maybe it is already enabled by default.  Who knows.&lt;/p&gt;&lt;p&gt;I would personally love to recommend my friend to use GNU Guix System, but
currently you cannot boot Guix System from Power9.  The next step for me in this
journey to help my friend set up his TalosII is to make sure his AMDGPU works.
This &lt;a href=&quot;https://wiki.raptorcs.com/wiki/Troubleshooting/GPU,&quot;&gt;wiki article&lt;/a&gt; should help with that.&lt;/p&gt;&lt;p&gt;Also from the &lt;code&gt;#talos-workstation&lt;/code&gt; chat log on irc, I found out that the Linux
kernel is having some issues with the graphics drivers on Power9.  Currently the
user is required to do some manual fiddling.  However those workarounds should
not be necessary by kernel 6.3ish.  So until my friend runs Linux 6.3, he will
probably have the best desktop experience in Xfce or KDE.  Gnome has some minor
issues apparently.&lt;/p&gt;</content></entry><entry><title>Creating New Build Systems</title><id>https://gnucode.me/creating-new-build-systems.html</id><author><name>Mitchell Schmeisser &lt;mitchellschmeisser@librem.one&gt;</name><email>jbranso@dismail.de</email></author><updated>2023-02-24T12:00:00Z</updated><link href="https://gnucode.me/creating-new-build-systems.html" rel="alternate" /><content type="html">&lt;p&gt;In Guix each package must specify a so-called &lt;code&gt;build-system&lt;/code&gt;, which
knows how to bring a package from its inputs to deployment.
Build systems are responsible for setting up the environment and performing
build actions within that environment. The most ubiquitous of these is the
&lt;a href=&quot;https://www.gnu.org/software/automake/manual/html_node/GNU-Build-System.html&quot;&gt;&lt;code&gt;gnu-build-system&lt;/code&gt;&lt;/a&gt;.
Guix builds packages using this build system via the usual
&lt;code&gt;./configure &amp;amp;&amp;amp; make &amp;amp;&amp;amp; make install&lt;/code&gt; process.&lt;/p&gt;&lt;p&gt;Any package can alter its build system by removing some steps or
adding extra ones. This is extremely common and almost every package
makes some adjustment to the build process. A &lt;code&gt;build-system&lt;/code&gt; in Guix
hides away some of the common configuration choices. For example, there is
no need to specify &lt;code&gt;make&lt;/code&gt; or &lt;code&gt;gcc&lt;/code&gt; as native inputs when using the &lt;code&gt;gnu-build-system&lt;/code&gt;,
because they are added implicitly when a package is lowered into a &lt;em&gt;bag&lt;/em&gt;.&lt;/p&gt;&lt;h2&gt;Anatomy of a Guix Build System&lt;/h2&gt;&lt;p&gt;The job of a build system is to compile our &lt;em&gt;packages&lt;/em&gt; into &lt;em&gt;bags&lt;/em&gt;.
Bags are a lower level representation of a package without all the bells and whistles
(Makes sense since we are implementing them here),
the bags are further refined to derivations which are used by the
build daemon to create an isolated environment suitable for our
&lt;em&gt;build phases&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Below is how guix defines a build system.
It's surprisingly simple with just three items, two of which are for human consumption.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-record-type* &amp;lt;build-system&amp;gt; build-system make-build-system
    build-system?
    (name        build-system-name)         ; symbol
    (description build-system-description)  ; short description
    (lower       build-system-lower))       ; args ... -&amp;gt; bags&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The last field &lt;code&gt;lower&lt;/code&gt; is a function which takes the list of arguments
given in the &lt;code&gt;(package ... (arguments ...))&lt;/code&gt; field.
The keyword arguments that we are allowed to supply when writing the
package are defined by the build-system.&lt;/p&gt;&lt;h1&gt;Code Strata&lt;/h1&gt;&lt;p&gt;Guix builds are implemented in two parts.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Code that compiles &lt;code&gt;packages-&amp;gt;derivations&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Derivations are the language the Guix Daemon speaks.
They describe everything about how to &lt;em&gt;derive&lt;/em&gt; our package
from the inputs to the environment and all the code on how to drive
the build tools.
This code is run in a poorly defined &amp;quot;user&amp;quot; environment.
Guix produces derivations that actually can be influenced by
undeclared aspects of the environment, like manually installed Guile
packages or code added with the `-L` flag.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The guix daemon runs the builder code in as isolated and reproducible build environment to produce the package from its inputs.&lt;/p&gt;&lt;p&gt;This code is executed in an explicitly defined build environment
with nothing being introduced from the host.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Code that runs in the host environment &lt;em&gt;stages&lt;/em&gt; code, which will run in isolation.
This is where G-Expressions really shine.
They provide the syntax to describe this relationship.&lt;/p&gt;&lt;h1&gt;Build Phases&lt;/h1&gt;&lt;p&gt;All programs are built more or less the same way.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Unpack the source code.&lt;/p&gt;&lt;p&gt;Whether it's tarball or a version controlled repository, the guix daemon must
copy the software's source tree into our build environment.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Patch the shebangs.&lt;/p&gt;&lt;p&gt;Many projects contain scripts written to aid the build process.
In Linux, executable scripts can contain a so-called &lt;em&gt;shebang&lt;/em&gt;,
which contains an absolute path to the program, which is meant to
interpret it: e.g. &lt;code&gt;#!/bin/sh&lt;/code&gt;. Most distributions provide a
POSIX compliant shell interpreter at this location. Guix System does not do this.
Instead, Guix System's &lt;code&gt;sh&lt;/code&gt; is yet another component in the store, so all of these files must
be patched to point to the new location, which is only known at
build time.  We cannot rely on our &lt;code&gt;PATH&lt;/code&gt; to store this information,
because the Linux kernel does not respect such things.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Configure the build.&lt;/p&gt;&lt;p&gt;Whether it is autotools or CMake or ninja, etc., if you are relying
on tools from the host system, then you have a step, which enables the
host system to tell you where to find those tools.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Patch the generated shebangs.&lt;/p&gt;&lt;p&gt;Sometimes the configure phases creates scripts, which run during the build phase,
these often contain references to &lt;code&gt;/bin/sh&lt;/code&gt;, and so guix must patch these scripts as well.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Build!&lt;/p&gt;&lt;p&gt;That's right folks we are off to the races, and the program is building.
Usually this takes the form of a call to &lt;code&gt;make&lt;/code&gt;, with a handful of
flags and last minute definitions, but there are other more &lt;em&gt;exotic&lt;/em&gt; methods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Test.&lt;/p&gt;&lt;p&gt;Now that guix built our software, we should test it before we sent software
updates to users. This helps the guix project catch and eleminate software
bugs before they impact guix users. Not all packages have tests, and guix
developers occasionally disables some packages' testsuites, but the
guix policy is to run the software's testsuite, if it is exists.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Install.&lt;/p&gt;&lt;p&gt;Now that we've verified everything works as expected, it is time to run
&lt;code&gt;make install&lt;/code&gt; or the equivalent.  This phase copies our build artifacts into
their final resting place in the store.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Validate the Installation.&lt;/p&gt;&lt;p&gt;Here guix checks that our outputs do not contain any component paths, which
are not specified by the package inputs. That would lead to incomplete
deployment, harm &lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;reproducible builds&lt;/a&gt;,
and would be &amp;quot;bad&amp;quot;.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;There are more steps, but they are not universally applicable.
Of course no generic model, such as this, captures all the chaos of the
world, and every package has exceptions to it.&lt;/p&gt;&lt;p&gt;Guix implements &lt;em&gt;build phases&lt;/em&gt; as a list of lambdas.
As such our package can modify this list and add/delete/replace
lambdas as they require. It is so common Guix provides a syntax
for manipulating build phases: &lt;code&gt;modify-phases&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;A build system contains a default set of phases called &lt;code&gt;%standard-phases&lt;/code&gt;.
Every build system starts with the &lt;code&gt;gnu-build-system&lt;/code&gt;, &lt;code&gt;%standard-phases&lt;/code&gt;,
and modifies it to their needs.
It is then provided to the packages using that build system.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;cmake-build-system&lt;/code&gt; is nearly identical to the &lt;code&gt;gnu-build-system&lt;/code&gt;
except two phases.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;;;
;; Excerpt from `guix/build/cmake-build-system.scm`
;;
(define %standard-phases
  ;; Everything is the same as the GNU Build System, except for the `configure'
  ;; and 'check' phases.
  (modify-phases gnu:%standard-phases
    (delete 'bootstrap)
    (replace 'check check)
    (replace 'configure configure)))&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;The Zephyr Build System&lt;/h2&gt;&lt;p&gt;Zephyr uses &lt;code&gt;cmake&lt;/code&gt; to perform &lt;em&gt;physical component composition&lt;/em&gt;.
It searches the filesystem and generates scripts, which the toolchain will
use to successfully combine those components into a firmware image.&lt;/p&gt;&lt;p&gt;The fact that Zephyr provides this mechanism is one reason I chose to
target zephyr in the first place.&lt;/p&gt;&lt;p&gt;This separation of projects in an embedded context is a really great thing.
It brings many of the advantages to the Linux world such as
code re-use, smaller binaries, more efficient cache/RAM usage, etc.
It also allows us to work as independent groups and compose
contributions from many teams.&lt;/p&gt;&lt;p&gt;It also brings all of the complexity. Suddenly all of the problems
that plague traditional deployment now apply to our embedded
system. The fact that the libraries are statically linked at compile
time instead of dynamically at runtime is simply an implementation detail.&lt;/p&gt;&lt;p&gt;We now have dependencies which we must track and compose in the correct environments.
The Zephyr Project offers a tool to help manage this new complexity: &lt;a href=&quot;https://docs.zephyrproject.org/latest/develop/west/index.html&quot;&gt;The West Meta-tool&lt;/a&gt;!
To call it a &amp;quot;meta-tool&amp;quot; is an abuse of language.  It is not even meta
enough to bootstrap itself and relies on &lt;a href=&quot;https://docs.zephyrproject.org/latest/develop/getting_started/index.html&quot;&gt;other package managers&lt;/a&gt; to get
started.
In fact, it is not even suitable for managing multiple embedded projects as a composition!
The project recommends &lt;a href=&quot;https://docs.zephyrproject.org/latest/build/sysbuild/index.html&quot;&gt;Yet Another Tool&lt;/a&gt; for this very common use case.&lt;/p&gt;&lt;p&gt;In fact, West does not really bring anything new to the table, and we can
replace it in the same way we can replace every other language specific package
manager, like node (js), Cabol (haskell), Dub (D), etc. &lt;strong&gt;PUTTING SOFTWARE ON
THE SYSTEM IS THE JOB OF THE PACKAGE MANAGER!&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;West is the way it is for a reason. It is very practical to design the package
manager in this way, because it enables Windows users to access the build
environment. A more in-depth discussion on the material conditions, which lead
to this or that design decision of the West tool is beyond the scope of this
post. Let's instead explain how to provide a meta-tool and bootstrap complex
embedded systems, from the ground up, in a flexible, composable, and
&lt;em&gt;reproducible&lt;/em&gt; way.&lt;/p&gt;&lt;h1&gt;Why not use &lt;code&gt;cmake-build-system&lt;/code&gt;?&lt;/h1&gt;&lt;p&gt;A fair question! Zephyr's CMake scripts require additional information
about the build to be provided at configure time. Most tedius for
zephyr-packages is the &lt;code&gt;ZEPHYR_MODULES&lt;/code&gt; variable, which must be formatted and
passed to CMake on the command line.&lt;/p&gt;&lt;h1&gt;Host Side&lt;/h1&gt;&lt;p&gt;Our job at this level is to take packages described using the &lt;code&gt;package&lt;/code&gt; syntax and
lower it into a derivation that the guix-daemon can understand.&lt;/p&gt;&lt;p&gt;Here is the derivation for building hello world for the &lt;code&gt;frdm_k64f&lt;/code&gt; (hashes removed for brevity).
The &lt;code&gt;package&lt;/code&gt; syntax provides a human friendly veneer over this garbage.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;Derive
    ([(&amp;quot;debug&amp;quot;,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--debug&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;)
      ,(&amp;quot;out&amp;quot;,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr-&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;)]
     ,[(&amp;quot;/gnu/store/...-newlib-nano-3.3.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-hal-nxp-3.1.0-0.708c958.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-make-4.3.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-findutils-4.8.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-grep-3.6.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-sed-4.8.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-ld-wrapper-0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-bash-minimal-5.1.8.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-hal-cmsis-5.8.0-0.093de61.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-gawk-5.1.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-gzip-1.10.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-six-1.16.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-zephyr-3.1.0-0.zephyr--checkout.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-linux-libre-headers-5.10.35.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-3.9.9.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-diffutils-3.8.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-arm-zephyr-eabi-nano-toolchain-12.1.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-pyelftools-0.28.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-guile-3.0.7.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-dateutil-2.8.2.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-patch-2.7.6.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-gcc-10.3.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-bzip2-1.0.8.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-dtc-1.6.1.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-cmake-minimal-3.21.4.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-pyyaml-6.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-packaging-21.3.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-arm-zephyr-eabi-binutils-2.38.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-glibc-2.33.drv&amp;quot;,[&amp;quot;out&amp;quot;,&amp;quot;static&amp;quot;])
       ,(&amp;quot;/gnu/store/...-qemu-7.2.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-ninja-1.10.2.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-tar-1.34.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-xz-5.2.5.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-binutils-2.37.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-pykwalify-1.7.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-zephyr-3.1.0-0.zephyr-.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-glibc-utf8-locales-2.33.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-gdb-arm-zephyr-eabi-12.1.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-module-import-compiled.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-file-5.39.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-pyparsing-3.0.6.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-python-docopt-0.6.2.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-arm-zephyr-eabi-sdk-0.15.0.drv&amp;quot;,[&amp;quot;out&amp;quot;])
       ,(&amp;quot;/gnu/store/...-coreutils-8.32.drv&amp;quot;,[&amp;quot;out&amp;quot;])]
     ,[&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--builder&amp;quot;,&amp;quot;/gnu/store/...-module-import&amp;quot;]
     ,&amp;quot;x86_64-linux&amp;quot;,&amp;quot;/gnu/store/...-guile-3.0.7/bin/guile&amp;quot;,[&amp;quot;--no-auto-compile&amp;quot;
     ,&amp;quot;-L&amp;quot;,&amp;quot;/gnu/store/...-module-import&amp;quot;
     ,&amp;quot;-C&amp;quot;,&amp;quot;/gnu/store/...-module-import-compiled&amp;quot;
     ,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--builder&amp;quot;]
     ,[(&amp;quot;debug&amp;quot;,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr--debug&amp;quot;)
       ,(&amp;quot;out&amp;quot;,&amp;quot;/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-0.zephyr-&amp;quot;)])&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Lowering packages to bags&lt;/h3&gt;&lt;p&gt;We must provide the build system with a function which the following lambda form.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(lambda* (name #:key #:allow-other-keys) ...)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This means it takes one required argument &lt;code&gt;name&lt;/code&gt; and any amount of keys.
Individual procedures can specify keys they are interested in such as
&lt;code&gt;inputs&lt;/code&gt; or &lt;code&gt;outputs&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Which keys are ultimately supported is defined by our &lt;code&gt;lower&lt;/code&gt; function
and our &lt;em&gt;build phases&lt;/em&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;;; Use module-ref instead of referencing the variables directly
;; to avoid circular dependencies.
(define %zephyr-build-system-modules
  `((mfs build zephyr-build-system)
,@%cmake-build-system-modules))

(define default-zephyr-base
  (module-ref (resolve-interface '(mfs packages zephyr))
      'zephyr))

(define default-zephyr-sdk
  (module-ref (resolve-interface '(mfs packages zephyr))
      'arm-zephyr-eabi-sdk))

(define default-ninja
  (module-ref (resolve-interface '(gnu packages ninja))
      'ninja))

(define default-cmake
  (module-ref (resolve-interface '(gnu packages cmake))
      'cmake-minimal))


(define* (lower name
        #:key source inputs native-inputs outputs system target
        (zephyr default-zephyr-base)
        (sdk default-zephyr-sdk)
        (ninja default-ninja)
        (cmake default-cmake)
        #:allow-other-keys
        #:rest arguments)
  &amp;quot;Return a bag for NAME.&amp;quot;
  (define private-keywords `(#:zephyr #:inputs #:native-inputs #:target))
  (bag
(name name)
(system system)
(target target)
(build-inputs `(,@(if source `((&amp;quot;source&amp;quot; ,source)) '())
        ,@`((&amp;quot;cmake&amp;quot; ,cmake))
        ,@`((&amp;quot;zephyr-sdk&amp;quot; ,sdk))
        ,@`((&amp;quot;zephyr&amp;quot; ,zephyr))
        ,@`((&amp;quot;ninja&amp;quot; ,ninja))
        ,@native-inputs
        ,@(standard-packages)))
;; Inputs need to be available at build time
;; since everything is statically linked.
(host-inputs inputs)
(outputs outputs)
(build zephyr-build)
(arguments (strip-keyword-arguments private-keywords arguments))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here our &lt;code&gt;lower&lt;/code&gt; function provides default values for the packages
every zephyr package needs, the SDK, CMake, and &lt;code&gt;ZEPHYR_BASE&lt;/code&gt; and adds
them to the build-inputs.&lt;/p&gt;&lt;p&gt;Notice we also strip out some keywords, which do not get passed to the
build function, because they get included as part of the broader
abstractions the build system provides.&lt;/p&gt;&lt;p&gt;At this step it would be great to have a parser which could work out
the required sdk from a &lt;code&gt;.config,&lt;/code&gt; but this requires compiling the kconfig,
which requires at least the sdk cmake files.
There might be a way to make it happen, but until then if a board needs a different
sdk, then they can specify it in an argument keyword.&lt;/p&gt;&lt;h3&gt;Lowering Bags to Derivations&lt;/h3&gt;&lt;p&gt;Here is the definition for the actual build procedure. There is a lot
of abstract trickery going on here, so do not worry if you don't understand it,
I barely understand it!
It's mostly copy and pasted from the CMake build system.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define* (zephyr-build name inputs
               #:key guile source
               board
               (outputs '(&amp;quot;out&amp;quot;)) (configure-flags ''())
               (search-paths '())
               (make-flags ''())
               (out-of-source? #t)
               (tests? #f)
               (test-target &amp;quot;test&amp;quot;)
               (parallel-build? #t) (parallel-tests? #t)
               (validate-runpath? #f)
               (patch-shebangs? #t)
               (phases '%standard-phases)
               (system (%current-system))
               (substitutable? #t)
               (imported-modules %zephyr-build-system-modules)

               ;; The modules referenced here contain code
               ;; which will be staged in the build environment with us.
               ;; Our build gexp down below will only be able to access this code
               ;; and we must be careful not to reference anything else.
               (modules '((zephyr build zephyr-build-system)
                      (guix build utils))))
    &amp;quot;Build SOURCE using CMAKE, and with INPUTS. This assumes that SOURCE
    provides a 'CMakeLists.txt' file as its build system.&amp;quot;

    ;; This is the build gexp. It handles staging values from our host
    ;; system into code that our build system can run.
    (define build
    (with-imported-modules imported-modules
      #~(begin
          (use-modules #$@(sexp-&amp;gt;gexp modules))
          #$(with-build-variables inputs outputs
          #~(zephyr-build #:source #+source
                  #:system #$system
                  #:outputs %outputs
                  #:inputs %build-inputs
                  #:board #$board
                  #:search-paths '#$(sexp-&amp;gt;gexp
                             (map search-path-specification-&amp;gt;sexp
                              search-paths))
                  #:phases #$(if (pair? phases)
                         (sexp-&amp;gt;gexp phases)
                         phases)
                  #:configure-flags #$(if (pair? configure-flags)
                              (sexp-&amp;gt;gexp configure-flags)
                              configure-flags)
                  #:make-flags #$make-flags
                  #:out-of-source? #$out-of-source?
                  #:tests? #$tests?
                  #:test-target #$test-target
                  #:parallel-build? #$parallel-build?
                  #:parallel-tests? #$parallel-tests?
                  #:validate-runpath? #$validate-runpath?
                  #:patch-shebangs? #$patch-shebangs?
                  #:strip-binaries? #f)))))

    (mlet %store-monad ((guile (package-&amp;gt;derivation (or guile (default-guile))
                              system #:graft? #f)))
    (gexp-&amp;gt;derivation name build
              #:system system
              #:target #f
              #:graft? #f
              #:substitutable? substitutable?
              #:guile-for-build guile)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally we define our build system which the package definitions can reference.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define zephyr-build-system
  (build-system
    (name 'zephyr)
    (description &amp;quot;The standard Zephyr build system&amp;quot;)
    (lower lower)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Easy right?&lt;/p&gt;&lt;h1&gt;Build Side&lt;/h1&gt;&lt;p&gt;The build side is not as complex as you might initially expect.
Our build system is almost exactly the same as the CMake build system
except our configure phase passes different values to CMake.
Our job is much easier.&lt;/p&gt;&lt;h3&gt;Locating Modules&lt;/h3&gt;&lt;p&gt;Zephyr CMake requires the zephyr &lt;em&gt;modules&lt;/em&gt; which are needed for the
build to be supplied on the command line.
Unfortunately for us, the
&lt;a href=&quot;https://docs.zephyrproject.org/3.1.0/develop/application/index.html#important-build-vars&quot;&gt;documentation&lt;/a&gt;
is wrong, and the &lt;code&gt;ZEPHYR_MODULES&lt;/code&gt; environment variable is not honored.
Thus we must implement some other solution for locating modules, until
this that is fixed.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Input Scanning&lt;/strong&gt; - Lucky for us we are keeping detailed information
about our dependencies. It is a simple matter to write a file tree
walker which collects all the zephyr modules in our inputs.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define* (find-zephyr-modules directories)
  &amp;quot;Return the list of directories containing zephyr/module.yml found
   under DIRECTORY, recursively. Return the empty list if DIRECTORY is
   not accessible.&amp;quot;
  (define (module-directory file)
    (dirname (dirname file)))

  (define (enter? name stat result)
    ;; Skip version control directories.
    ;; Shouldn't be in the store but you never know.
    (not (member (basename name) '(&amp;quot;.git&amp;quot; &amp;quot;.svn&amp;quot; &amp;quot;CVS&amp;quot;))))

  (define (leaf name stat result)
    ;; Add module root directory to results
    (if (and (string= &amp;quot;module.yml&amp;quot; (basename name))
         (string= &amp;quot;zephyr&amp;quot; (basename (dirname name))))
      (cons (module-directory name) result)
      result))

  (define (down name stat result) result)
  (define (up name stat result) result)
  (define (skip name stat result) result)

  (define (find-modules directory)
    (file-system-fold enter? leaf down up skip error
              '() (canonicalize-path directory)))

  (append-map find-modules directories))

(define (zephyr-modules-cmake-argument modules)
   &amp;quot;Return a proper CMake list from MODULES, a list of filepaths&amp;quot;
   (format #f &amp;quot;-DZEPHYR_MODULES='~{~a~^;~}'&amp;quot; modules))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here are two functions. The first one &lt;code&gt;find-zephyr-modules&lt;/code&gt; walks a
list of directories (package inputs) and returns a list of every module it finds.
The second one is just for syntactic convenience when writing the CMake invokation.
This is also slightly more robust than West's module discovery, because it allows for
a single repository to provide multiple modules which are not &lt;em&gt;technically&lt;/em&gt; required
to be at the top level.&lt;/p&gt;&lt;p&gt;From here we just need to provide alternate implementations of &lt;code&gt;configure&lt;/code&gt; and &lt;code&gt;install&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define* (configure #:key outputs (configure-flags '())
            inputs (out-of-source? #t)
            build-type
            #:allow-other-keys)
      &amp;quot;Configure the given package.&amp;quot;
      (let* ((out        (assoc-ref outputs &amp;quot;out&amp;quot;))
         (abs-srcdir (getcwd))
         (srcdir     (if out-of-source?
                 (string-append &amp;quot;../&amp;quot; (basename abs-srcdir))
                 &amp;quot;.&amp;quot;)))
    (format #t &amp;quot;source directory: ~s (relative from build: ~s)~%&amp;quot;
        abs-srcdir srcdir)
    (when out-of-source?
      (mkdir &amp;quot;../build&amp;quot;)
      (chdir &amp;quot;../build&amp;quot;))
    (format #t &amp;quot;build directory: ~s~%&amp;quot; (getcwd))

    ;; this is required because zephyr tries to optimize
    ;; future calls to the build scripts by keep a cache.
    (setenv &amp;quot;XDG_CACHE_HOME&amp;quot; (getcwd))

    (let ((args `(,srcdir
              ,@(if build-type
                (list (string-append &amp;quot;-DCMAKE_BUILD_TYPE=&amp;quot;
                         build-type))
                '())
              ;; enable verbose output from builds
              &amp;quot;-DCMAKE_VERBOSE_MAKEFILE=ON&amp;quot;
              ,(zephyr-modules-cmake-argument
            (find-zephyr-modules (map cdr inputs)))
              ,@configure-flags)))
      (format #t &amp;quot;running 'cmake' with arguments ~s~%&amp;quot; args)
      (apply invoke &amp;quot;cmake&amp;quot; args))))

    (define* (install #:key outputs #:allow-other-keys)
      (let* ((out (string-append (assoc-ref outputs &amp;quot;out&amp;quot;) &amp;quot;/lib/firmware&amp;quot;))
         (dbg (string-append (assoc-ref outputs &amp;quot;debug&amp;quot;) &amp;quot;/share/zephyr&amp;quot;)))
    (mkdir-p out)
    (mkdir-p dbg)
    (copy-file &amp;quot;zephyr/.config&amp;quot; (string-append dbg &amp;quot;/config&amp;quot;))
    (copy-file &amp;quot;zephyr/zephyr.map&amp;quot; (string-append dbg &amp;quot;/zephyr.map&amp;quot;))
    (copy-file &amp;quot;zephyr/zephyr.elf&amp;quot; (string-append out &amp;quot;/zephyr.elf&amp;quot;))
    (copy-file &amp;quot;zephyr/zephyr.bin&amp;quot; (string-append out &amp;quot;/zephyr.bin&amp;quot;))))

;; Define new standard-phases
(define %standard-phases
      (modify-phases cmake:%standard-phases
    (replace 'configure configure)
    (replace 'install install)))

;; Call cmake build with our new phases
(define* (zephyr-build #:key inputs (phases %standard-phases)
               #:allow-other-keys #:rest args)
  (apply cmake:cmake-build #:inputs inputs #:phases phases args))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;One thing to note is the &amp;quot;debug&amp;quot; output. This exists so we don't
retain references to our build environment and make the file system
closure huge. If you put all of the build outputs in the same store
path, then the deployment closure will grow from 2MB to 833MB.&lt;/p&gt;&lt;h1&gt;Defining Zephyr Packages&lt;/h1&gt;&lt;p&gt;Now that we have a proper build system, it's time to define some packages!&lt;/p&gt;&lt;h3&gt;Zephyr Base&lt;/h3&gt;&lt;p&gt;Zephyr base contains the Zephyr source code. It is equivalent (in my mind
anyway) to the linux kernel, in that packages' definitions' specifications,
which target the linux kernel, can be minimal.&lt;/p&gt;&lt;p&gt;The selection of operating system actually comes from the toolchain. For
example, we build linux packages with the &lt;a href=&quot;https://www.gnu.org/software/autoconf/manual/autoconf-2.65/html_node/Specifying-Target-Triplets.html&quot;&gt;gnu
triplet&lt;/a&gt;.
When we select the &lt;code&gt;arm-linux-gnueabihf,&lt;/code&gt; we are specifying our operating system.&lt;/p&gt;&lt;p&gt;It is the same for Zephyr. When we build for zephyr we use the &lt;code&gt;arm-zephyr-eabi&lt;/code&gt;
toolchain. However, unlike linux applications, zephyr applications are
embedded firmware images and are generally statically linked.
Thus this package just consists of its source code and is not compiled directly.
We cannot compile it now because applications/modules provide the required Kconfig
options.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-public zephyr
  (let ((version &amp;quot;3.1.0&amp;quot;)
    (commit &amp;quot;zephyr-v3.1.0&amp;quot;))
    (package
      (name &amp;quot;zephyr&amp;quot;)
      (version version)
      (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
      (source (origin (method git-fetch)
              (uri (git-reference
                (url &amp;quot;https://github.com/zephyrproject-rtos/zephyr&amp;quot;)
                (commit commit)))
              (file-name (git-file-name name version))
              (sha256
               (base32 &amp;quot;1yl5y9757xc3l037k3g1dynispv6j5zqfnzrhsqh9cx4qzd485lx&amp;quot;))
              (patches
               ;; this patch makes this package work in a symlinked profile
               (search-patches &amp;quot;zephyr-3.1-linker-gen-abs-path.patch&amp;quot;))))
      (build-system copy-build-system)
      (arguments
       `(#:install-plan
     '((&amp;quot;.&amp;quot; &amp;quot;zephyr-workspace/zephyr&amp;quot;))
     #:phases
     (modify-phases %standard-phases
       (add-after 'unpack 'patch-cmake-scripts
         (lambda* _
           (format #t &amp;quot;~a~&amp;amp;&amp;quot; (getcwd))
           ;; Some cmake scripts assume the presence of a
           ;; git repository in the source directory.
           ;; We will just hard-code that information now
           (substitute* &amp;quot;CMakeLists.txt&amp;quot;
         ((&amp;quot;if\\(DEFINED BUILD_VERSION\\)&amp;quot; all)
          (format #f &amp;quot;set(BUILD_VERSION \&amp;quot;~a-~a\&amp;quot;)~&amp;amp;~a&amp;quot;
              ,version ,commit all))))))))
      (propagated-inputs
       (list python-3
         python-pyelftools
         python-pykwalify
         python-pyyaml
         python-packaging))
      (native-search-paths
       (list (search-path-specification
          (variable &amp;quot;ZEPHYR_BASE&amp;quot;)
          (files '(&amp;quot;zephyr-workspace/zephyr&amp;quot;)))))
      (synopsis &amp;quot;Source code for zephyr rtos&amp;quot;)
      (description &amp;quot;Zephyr rtos source code.&amp;quot;)
      (license license:apsl2))))

(define-public zephyr-3.2.0-rc3
      (package (inherit zephyr)
    (version &amp;quot;3.2.0-rc3&amp;quot;)
    (source (origin (method git-fetch)
            (uri (git-reference
                  (url &amp;quot;https://github.com/zephyrproject-rtos/zephyr&amp;quot;)
                  (commit &amp;quot;v3.2.0-rc3&amp;quot;)))
            (file-name (git-file-name &amp;quot;zephyr&amp;quot; version))
            (sha256
             (base32 &amp;quot;06ksd9zj4j19jq0zg3lms13jx0gxzjc41433zgb91cnd2cqmn5cb&amp;quot;))
            (patches
             (search-patches &amp;quot;zephyr-3.1-linker-gen-abs-path.patch&amp;quot;))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here we use the &lt;code&gt;copy-build-system&lt;/code&gt; which takes a list of source destination
pairs. In our case, we just copy everything to the output directory, but not
before patching some files to accomodate our special environment.&lt;/p&gt;&lt;p&gt;While developing this I wanted to test some toolchain/board features
on the latest release of Zephyr. I included an example of that package
definition to show how we can easily accomodate side by side package
variants and experiment without breaking anything.&lt;/p&gt;&lt;h3&gt;Modules&lt;/h3&gt;&lt;p&gt;It's finally time to define some firmware!
Zephyr packages some examples in &lt;code&gt;$ZEPHYR_BASE/samples&lt;/code&gt; including a
basic hello world. The k64 development board is already supported
by Zephyr so building the example is trivial.&lt;/p&gt;&lt;p&gt;In order to actually target the k64 we need to two modules, the NXP
hardware abstraction layer, and CMSIS.
Looking at &lt;code&gt;$ZEPHYR_BASE/west.yml&lt;/code&gt; we can see the repositories
and commits which contain these modules. This is how West does
dependency management.&lt;/p&gt;&lt;p&gt;Defining these packages is not so bad (see footnote 1).&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-public hal-cmsis
      (package
    (name &amp;quot;hal-cmsis&amp;quot;)
    (version &amp;quot;5.8.0&amp;quot;)
    (home-page &amp;quot;https://developer.arm.com/tools-and-software/embedded/cmsis&amp;quot;)
    (source (origin
          (method git-fetch)
          (uri (git-reference
            (url &amp;quot;https://github.com/zephyrproject-rtos/cmsis&amp;quot;)
            (commit &amp;quot;093de61c2a7d12dc9253daf8692f61f793a9254a&amp;quot;)))
          (file-name (git-file-name name version))
          (sha256
           (base32 &amp;quot;0f7cipnwllna7iknsnz273jkvrly16yr6wm4y2018i6njpqh67wi&amp;quot;))))
    (build-system zephyr-module-build-system)
    (arguments `(#:workspace-path  &amp;quot;/modules/hal/cmsis&amp;quot;))
    (synopsis &amp;quot;Zephyr module providing the Common Microcontroller
    Software Interface Standard&amp;quot;)
    (description &amp;quot;Zephyr module providing the Common Microcontroller
    Software Interface Standard&amp;quot;)
    (license license:apsl2)))

(define-public hal-nxp
      (package
    (name &amp;quot;hal-nxp&amp;quot;)
    (version &amp;quot;3.1.0&amp;quot;)
    (home-page &amp;quot;https://nxp.com&amp;quot;)
    (source (origin
          (method git-fetch)
          (uri (git-reference
            (url &amp;quot;https://github.com/zephyrproject-rtos/hal_nxp&amp;quot;)
            (commit &amp;quot;708c95825b0d5279620935a1356299fff5dfbc6e&amp;quot;)))
          (file-name (git-file-name name version))
          (sha256
           (base32 &amp;quot;1c0i26bpk6cyhr1q4af183jclfmxshv4d15i7k3cz7brzb12m8q1&amp;quot;))))
    (build-system zephyr-module-build-system)
    (arguments `(#:workspace-path  &amp;quot;/modules/hal/nxp&amp;quot;))
    (native-search-paths
     (list (search-path-specification
        (variable &amp;quot;ZEPHYR_MODULES&amp;quot;)
        (files `(,(string-append %zephyr-workspace-name module-path)))
        (separator &amp;quot;;&amp;quot;))))
    (synopsis &amp;quot;Zephyr module for NXP Hardware Abstraction Layer&amp;quot;)
    (description &amp;quot;Provides sources for NXP HAL zephyr module&amp;quot;)
    (license license:bsd-3)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With these two modules defined we can write &lt;code&gt;zephyr-hello-world-frdm-k64f&lt;/code&gt;.&lt;/p&gt;&lt;h3&gt;Hello world&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-public zephyr-hello-world-frdm-k64f
      (package
    (name &amp;quot;zephyr-hello-world-frdm-k64f&amp;quot;)
    (version (package-version zephyr))
    (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
    (source (file-append (package-source zephyr)
                 &amp;quot;/samples/hello_world&amp;quot;))
    (build-system zephyr-build-system)
    (arguments
     '(#:configure-flags '(&amp;quot;-DBOARD=frdm_k64f&amp;quot;)))
    (outputs '(&amp;quot;out&amp;quot; &amp;quot;debug&amp;quot;))
    (inputs
     (list hal-cmsis
           hal-nxp))
    (synopsis &amp;quot;Hello world example from Zephyr Project&amp;quot;)
    (description &amp;quot;Sample package for zephyr project&amp;quot;)
    (license license:apsl2)))&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Building&lt;/h3&gt;&lt;p&gt;Our above definition can be built using the following:
When testing package definitions, I use the &lt;code&gt;-L&lt;/code&gt; flag to point to the local
repository to load the new packages. I will be omitting that flag as
if I had ~guix pull~ed successfully from &lt;a href=&quot;https://github.com/paperclip4465/guix-zephyr&quot;&gt;guix-zephyr&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;guix build zephyr-hello-world-frdm-k64f

/gnu/store/...-zephyr-hello-world-frdm-k64f-3.1.0-debug
/gnu/store/...-zephyr-hello-world-frdm-k64f-3.1.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This actually doesn't fully test our toolchain. The hello world
example, by default, will use a zephyr provided
minimal implementation of the C library and will not link against
newlib.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define-public zephyr-hello-world-newlib-frdm-k64f
      (package
    (inherit zephyr-hello-world-frdm-k64f)
    (name &amp;quot;zephyr-hello-world-newlib-frdm-k64f&amp;quot;)
    (arguments
     (substitute-keyword-arguments (package-arguments zephyr-hello-world-frdm-k64f)
       ((#:configure-flags flags)
        `(append
          '(&amp;quot;-DCONFIG_MINIMAL_LIBC=n&amp;quot;
        &amp;quot;-DCONFIG_NEWLIB_LIBC=y&amp;quot;)
          ,flags))))))

    guix build zephyr-hello-world-newlib-frdm-k64f

/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0-debug
/gnu/store/...-zephyr-hello-world-newlib-frdm-k64f-3.1.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Woohoo!&lt;/p&gt;&lt;h1&gt;Further Musings&lt;/h1&gt;&lt;p&gt;One thing I learned while going through the pains of getting this
working is that even though the components are &amp;quot;modular&amp;quot; there is
still a lot rigid interdependencies, especially on the zephyr base.
Just having two versions of Zephyr in the code base made component
composition fragile.
Modules rely on specific features from the kernel.
This is hidden from developers normally by west automagically walking
the `west.yml` of all of the declared dependencies recursively to
discover the graph.&lt;/p&gt;&lt;p&gt;While there are many benefits to a modularized build system, a monolithic build
system, like Zephyr, does have many benefits too.&lt;/p&gt;&lt;p&gt;Part of the problem comes from the domain itself. If you really want to be able
to target the most resource constrained systems and deal with the &amp;quot;industrial
mess&amp;quot; that comes from every board being unique, you have to be as generic and
flexible as possible, which is hard in a guix-like modular build system.&lt;/p&gt;&lt;p&gt;Superficially the problem is solved in the same way Linux solved it, using
device trees and having a very stable userland interface. However, unlike Linux
where the device tree is compiled to a binary blob and interpreted by drivers at
runtime, Zephyr device trees are compiled to a &lt;code&gt;.h&lt;/code&gt; file and are mostly
interpreted by the C pre-processor using an elaborate set of macros.&lt;/p&gt;&lt;p&gt;It goes beyond simply abstracting the hardware using clever hacks.
Zephyr applications (and any zephyr module) can also introduce new
&amp;quot;kernel&amp;quot; code, configuration options, and even linker script fragments
at build time.
Essentially the Zephyr CMake build system acts like a reverse ld.
Instead of linking libraries after compilation, it discovers these
things before gcc is ever invoked and provides additional code
generation steps.&lt;/p&gt;&lt;p&gt;Zephyr does not have a stable &amp;quot;userland&amp;quot; interface for the same
reason Linux does not have a stable &amp;quot;kernel module&amp;quot; interface.
Because Zephyr applications are so tightly coupled to the hardware
they run on it is not uncommon to bypass Zephyr utilities and directly
touch hardware and memory.&lt;/p&gt;&lt;p&gt;In this way they are more related to kernel modules
than userspace applications such as GNU Hello.&lt;/p&gt;&lt;p&gt;Perhaps there is a lispy way to track several zephyr releases without reducing
the ability to freely modify components in the usual ways...I invite you dear
reader to developer code to explore that possibility.&lt;/p&gt;&lt;p&gt;It is use-able for Guix anyway.&lt;/p&gt;&lt;h1&gt;Why a Special Build System? Why not &lt;code&gt;--target=frdm_k64f&lt;/code&gt;?&lt;/h1&gt;&lt;p&gt;That is a fair question!
At first glance you might imagine the following incantation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;guix build --target=arm-zephyr-eabi hello&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The problem with calling the toolchain directly is that the architecture
is specified by the board selection. It is not generally useful to
compile a board to a different architecture.&lt;/p&gt;&lt;p&gt;Perhaps maybe something like this then.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;guix build --target=frdm_k64f hello&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above command tells GNU hello to link against arm-zephyr-newlib and run on
a specific board. The problem is that while this &lt;em&gt;may&lt;/em&gt; work for GNU Hello, it
will not work for anything, which requires inputs that are discovered by normal
methods. Only packages which target zephyr explicitly could benefit from such an
interface, and at that point, you may as well record which board is being targeted
in the package definition.&lt;/p&gt;&lt;p&gt;In general not all zephyr applications can run on every board zephyr
can run on, so the usefulness of the above command is dubious.&lt;/p&gt;&lt;p&gt;I think if you have firmware which targets multiple boards it is
better to define a package for every board. It is likely every board
will require special configuration flags anyway.&lt;/p&gt;&lt;h1&gt;Conclusion&lt;/h1&gt;&lt;p&gt;Zephyr has a very complex build process which can be difficult to
understand and frustrating to set up.&lt;/p&gt;&lt;p&gt;Using Guix to define firmware packages makes these problems disappear.
It is trivial to create a channel which contains all of the quirks of
your platform and share it with a team or student.&lt;/p&gt;&lt;p&gt;Packages defined this way serve as a reproducible starting point for
future hardware revisions and variations.&lt;/p&gt;&lt;h1&gt;Footnotes&lt;/h1&gt;&lt;ol&gt;&lt;li&gt;I also made a &lt;code&gt;zephyr-module-build-system&lt;/code&gt; as well which is just the
&lt;code&gt;copy-build-system&lt;/code&gt; that mimics the default zephyr workspace layout as provided
by west. This way we do not need to provide the same install-plan for every
module we package. However as I use the &lt;code&gt;copy-build-system&lt;/code&gt; more often, it
doesn't really provide much over just using the copy-build system.&lt;/li&gt;&lt;/ol&gt;</content></entry><entry><title>Building Toolchains with Guix</title><id>https://gnucode.me/building-toolchains-with-guix.html</id><author><name>Mitchell Schmeisser &lt;mitchellschmeisser@librem.one&gt;</name><email>jbranso@dismail.de</email></author><updated>2023-02-23T23:00:00Z</updated><link href="https://gnucode.me/building-toolchains-with-guix.html" rel="alternate" /><content type="html">&lt;p&gt;Today's post is a guest post from my new internet friend Mitchell. We met on the
#guix irc channel, and I offered to post a few of his blog posts on this blog.  Without further ado,
here is Michell's first blog post (it's pretty fantastic)!&lt;/p&gt;&lt;h1&gt;Overview&lt;/h1&gt;&lt;p&gt;In order to deploy embedded software using Guix we first need to teach Guix
how to build it. Since Guix bootstraps everything this means we must teach Guix
how to build our toolchain.&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;https://zephyrproject.org&quot;&gt;Zephyr Project&lt;/a&gt; uses its own fork of GCC with custom configs for
the architectures supported by the project.&lt;/p&gt;&lt;h1&gt;Anatomy of a toolchain&lt;/h1&gt;&lt;p&gt;Toolchains are responsible for taking high level descriptions of programs and
lowering them down to a series of equivalent machine instructions. This process
involves more than just a compiler. The compiler uses the &lt;code&gt;binutils&lt;/code&gt; to
manipulate it’s internal representation down to a given architecture. It
also needs the C standard library as well as a few other libraries needed for
some compiler optimizations.&lt;/p&gt;&lt;p&gt;The C library provides the interface to the underlying kernel. System calls like &lt;code&gt;write&lt;/code&gt;
and &lt;code&gt;read&lt;/code&gt; are provided by &lt;code&gt;Glibc&lt;/code&gt; on most Linux distributions.&lt;/p&gt;&lt;p&gt;In embedded systems smaller implementations like &lt;code&gt;newlib&lt;/code&gt; and &lt;code&gt;newlib-nano&lt;/code&gt; are used.&lt;/p&gt;&lt;h1&gt;Bootstrapping a Toolchain&lt;/h1&gt;&lt;p&gt;In order to compile GCC we need a C library that’s been compiled for
our target architecture. How can we cross compile our C library if we
need our C library to build a cross compiler? The solution is to build
a simpler compiler that doesn’t require the C library to function.
It will not be capable of as many optimizations and it will be very slow,
however it will be able to build the C libraries as well as the complete version
of GCC.&lt;/p&gt;&lt;p&gt;In order to build the simpler compiler we need to compile the &lt;code&gt;binutils&lt;/code&gt; to
work with our target architecture.
The &lt;code&gt;binutils&lt;/code&gt; can be bootstrapped with our host GCC and have no target dependencies.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://crosstool-ng.github.io/docs/toolchain-construction/&quot;&gt;For more information read this.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Doesn’t sound so bad right? It isn’t… in theory.
However internet forums since time immemorial have been
littered with the laments of those who came before.
From incorrect versions of &lt;code&gt;ISL&lt;/code&gt; to the wrong C library being linked
or the host linker being used, etc.
The one commonality between all of these issues is the environment.
Building GCC is difficult because isolating build environments is hard.&lt;/p&gt;&lt;p&gt;In fact as of &lt;code&gt;v0.14.2&lt;/code&gt; the zephyr SDK repository took down the build
instructions and posted a sign that read “Building this is too
complicated, don’t worry about it.” (I’m paraphrasing, but
&lt;a href=&quot;https://github.com/zephyrproject-rtos/sdk-ng/tree/v0.14.2#build-process&quot;&gt;not by
much&lt;/a&gt;.)&lt;/p&gt;&lt;p&gt;We will neatly side step all of these problems and not
risk destroying or polluting our host system with garbage
by using Guix to manage our environments for us.&lt;/p&gt;&lt;p&gt;Our toolchain only requires the first pass compiler because
newlib(-nano) is statically linked and introduced to the toolchain
by normal package composition.&lt;/p&gt;&lt;h1&gt;Defining the Packages&lt;/h1&gt;&lt;p&gt;All of the base packages are defined in &lt;code&gt;zephyr/packages/zephyr.scm&lt;/code&gt;.
Zephyr modules are defined in &lt;code&gt;zephyr/packages/zephyr-xyz.scm&lt;/code&gt;, following
the pattern of other module systems implemented by Guix.&lt;/p&gt;&lt;h2&gt;Binutils&lt;/h2&gt;&lt;p&gt;First thing we need to build is the &lt;code&gt;arm-zephyr-eabi&lt;/code&gt; binutils.
This is very easy in Guix.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define-module (zephyr packages zephyr)
    #:use-module (guix packages)

(define-public arm-zephyr-eabi-binutils
  (let ((xbinutils (cross-binutils &amp;quot;arm-zephyr-eabi&amp;quot;)))
    (package
  (inherit xbinutils)
  (name &amp;quot;arm-zephyr-eabi-binutils&amp;quot;)
  (version &amp;quot;2.38&amp;quot;)
  (source
   (origin (method git-fetch)
       (uri (git-reference
             (url &amp;quot;https://github.com/zephyrproject-rtos/binutils-gdb&amp;quot;)
             (commit &amp;quot;6a1be1a6a571957fea8b130e4ca2dcc65e753469&amp;quot;)))
       (file-name (git-file-name name version))
       (sha256 (base32 &amp;quot;0ylnl48jj5jk3jrmvfx5zf8byvwg7g7my7jwwyqw3a95qcyh0isr&amp;quot;))))
  (arguments
   `(#:tests? #f
     ,@(substitute-keyword-arguments (package-arguments xbinutils)
         ((#:configure-flags flags)
      `(cons &amp;quot;--program-prefix=arm-zephyr-eabi-&amp;quot; ,flags)))))
  (native-inputs
   (append
    (list texinfo
      bison
      flex
      gmp
      dejagnu)
    (package-native-inputs xbinutils)))
  (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
  (synopsis &amp;quot;binutils for zephyr RTOS&amp;quot;))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The function &lt;code&gt;cross-binutils&lt;/code&gt; returns a package which has been
configured for the given gnu triplet.  We simply inherit that package
and replace the source.
The zephyr build system expects the binutils to be prefixed with
&lt;code&gt;arm-zephyr-eabi-&lt;/code&gt; which is accomplished by adding another flag to the
&lt;code&gt;#:configure-flags&lt;/code&gt; argument.&lt;/p&gt;&lt;p&gt;We can test our package definition using the &lt;code&gt;-L&lt;/code&gt; flag with &lt;code&gt;guix build&lt;/code&gt;
to add our packages.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix build -L guix-zephyr zephyr-binutils

/gnu/store/a947nb4rb2vymz2gaqnafgm1bsq4ipqp-zephyr-binutils-2.38&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This directory contains the results of &lt;code&gt;make install&lt;/code&gt;.&lt;/p&gt;&lt;h2&gt;GCC sans libc&lt;/h2&gt;&lt;p&gt;This one is a bit more involved. Don’t be afraid!
This version of GCC wants ISL version 0.15. It’s easy enough
to make that happen. Inherit the current version of ISL and swap
out the source and update the version. For most packages the build process doesn’t
change that much between versions.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define-public isl-0.15
  (package
(inherit isl)
(version &amp;quot;0.15&amp;quot;)
(source (origin
      (method url-fetch)
      (uri (list (string-append &amp;quot;mirror://sourceforge/libisl/isl-&amp;quot;
                    version &amp;quot;.tar.gz&amp;quot;)))
      (sha256
       (base32
        &amp;quot;11vrpznpdh7w8jp4wm4i8zqhzq2h7nix71xfdddp8xnzhz26gyq2&amp;quot;))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Like the binutils, there is a function for creating cross-gcc packages. This one
accepts keywords specifying which binutils and libc to use. If libc isn’t
given (like here), gcc is configured with many options disabled to facilitate
being built without libc. Therefore we need to add the extra options we want (I
got them from the SDK configuration scripts on the &lt;a href=&quot;https://github.com/zephyrproject-rtos/sdk-ng&quot;&gt;sdk
github&lt;/a&gt; as well as the commits to
use for each of the tools. ).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define-public gcc-arm-zephyr-eabi-12
  (let ((xgcc (cross-gcc &amp;quot;arm-zephyr-eabi&amp;quot;
             #:xbinutils zephyr-binutils)))
    (package
  (inherit xgcc)
  (version &amp;quot;12.1.0&amp;quot;)
  (source (origin (method git-fetch)
          (uri (git-reference
                (url &amp;quot;https://github.com/zephyrproject-rtos/gcc&amp;quot;)
                (commit &amp;quot;0218469df050c33479a1d5be3e5239ac0eb351bf&amp;quot;)))
          (file-name (git-file-name (package-name xgcc) version))
          (sha256
           (base32 &amp;quot;1s409qmidlvzaw1ns6jaanigh3azcxisjplzwn7j2n3s33b76zjk&amp;quot;))
          (patches
           (search-patches &amp;quot;gcc-12-cross-environment-variables.patch&amp;quot;
                   &amp;quot;gcc-cross-gxx-include-dir.patch&amp;quot;))))
  (native-inputs
   (modify-inputs (package-native-inputs xgcc)
     ;; Get rid of stock ISL
     (delete &amp;quot;isl&amp;quot;)
     ;; Add additional dependencies that xgcc doesn't have
     ;; including our special ISL
     (prepend flex
          perl
          python-3
          gmp
          isl-0.15
          texinfo
          python
          mpc
          mpfr
          zlib)))
  (arguments
   (substitute-keyword-arguments (package-arguments xgcc)
     ((#:phases phases)
      `(modify-phases ,phases
         (add-after 'unpack 'fix-genmultilib
       (lambda _
         (substitute* &amp;quot;gcc/genmultilib&amp;quot;
           ((&amp;quot;#!/bin/sh&amp;quot;) (string-append &amp;quot;#!&amp;quot; (which &amp;quot;sh&amp;quot;))))
         #t))

         (add-after 'set-paths 'augment-CPLUS_INCLUDE_PATH
       (lambda* (#:key inputs #:allow-other-keys)
         (let ((gcc (assoc-ref inputs  &amp;quot;gcc&amp;quot;)))
           ;; Remove the default compiler from CPLUS_INCLUDE_PATH to
           ;; prevent header conflict with the GCC from native-inputs.
           (setenv &amp;quot;CPLUS_INCLUDE_PATH&amp;quot;
               (string-join
                (delete (string-append gcc &amp;quot;/include/c++&amp;quot;)
                    (string-split (getenv &amp;quot;CPLUS_INCLUDE_PATH&amp;quot;)
                          #\:))
                &amp;quot;:&amp;quot;))
           (format #t
               &amp;quot;environment variable `CPLUS_INCLUDE_PATH' changed to ~a~%&amp;quot;
               (getenv &amp;quot;CPLUS_INCLUDE_PATH&amp;quot;))
           #t)))))

     ((#:configure-flags flags)
      ;; The configure flags are largely identical to the flags used by the
      ;; &amp;quot;GCC ARM embedded&amp;quot; project.
      `(append (list &amp;quot;--enable-multilib&amp;quot;
             &amp;quot;--with-newlib&amp;quot;
             &amp;quot;--with-multilib-list=rmprofile&amp;quot;
             &amp;quot;--with-host-libstdcxx=-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm&amp;quot;
             &amp;quot;--enable-plugins&amp;quot;
             &amp;quot;--disable-decimal-float&amp;quot;
             &amp;quot;--disable-libffi&amp;quot;
             &amp;quot;--disable-libgomp&amp;quot;
             &amp;quot;--disable-libmudflap&amp;quot;
             &amp;quot;--disable-libquadmath&amp;quot;
             &amp;quot;--disable-libssp&amp;quot;
             &amp;quot;--disable-libstdcxx-pch&amp;quot;
             &amp;quot;--disable-nls&amp;quot;
             &amp;quot;--disable-shared&amp;quot;
             &amp;quot;--disable-threads&amp;quot;
             &amp;quot;--disable-tls&amp;quot;
             &amp;quot;--with-gnu-ld&amp;quot;
             &amp;quot;--with-gnu-as&amp;quot;
             &amp;quot;--enable-initfini-array&amp;quot;)
           (delete &amp;quot;--disable-multilib&amp;quot; ,flags)))))
  (native-search-paths
   (list (search-path-specification
      (variable &amp;quot;CROSS_C_INCLUDE_PATH&amp;quot;)
      (files '(&amp;quot;arm-zephyr-eabi/include&amp;quot;)))
         (search-path-specification
      (variable &amp;quot;CROSS_CPLUS_INCLUDE_PATH&amp;quot;)
      (files '(&amp;quot;arm-zephyr-eabi/include&amp;quot;
           &amp;quot;arm-zephyr-eabi/c++&amp;quot;
           &amp;quot;arm-zephyr-eabi/c++/arm-zephyr-eabi&amp;quot;)))
         (search-path-specification
      (variable &amp;quot;CROSS_LIBRARY_PATH&amp;quot;)
      (files '(&amp;quot;arm-zephyr-eabi/lib&amp;quot;)))))
  (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
  (synopsis &amp;quot;GCC for zephyr RTOS&amp;quot;))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This GCC can be built like so.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix build -L guix-zephyr gcc-cross-sans-libc-arm-zephyr-eabi

/gnu/store/qmp8bzmwwimw0r6fh165hgfhkxkxilpj-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0-lib
/gnu/store/38rli0rbn7ksmym3wq99cr4p2cjdz4a7-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Great! We now have our stage-1 compiler.&lt;/p&gt;&lt;h2&gt;Newlib(-nano)&lt;/h2&gt;&lt;p&gt;The newlib package is quite straight forward (relatively).
It is mostly adding in the relevent configuration flags and patching
the files the &lt;code&gt;patch-shebangs&lt;/code&gt; phase missed.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  (define-public zephyr-newlib
  (package
    (name &amp;quot;zephyr-newlib&amp;quot;)
    (version &amp;quot;3.3&amp;quot;)
    (source (origin
          (method git-fetch)
          (uri (git-reference
            (url &amp;quot;https://github.com/zephyrproject-rtos/newlib-cygwin&amp;quot;)
            (commit &amp;quot;4e150303bcc1e44f4d90f3489a4417433980d5ff&amp;quot;)))
          (sha256
           (base32 &amp;quot;08qwjpj5jhpc3p7a5mbl7n6z7rav5yqlydqanm6nny42qpa8kxij&amp;quot;))))
    (build-system gnu-build-system)
    (arguments
     `(#:out-of-source? #t
       #:configure-flags '(&amp;quot;--target=arm-zephyr-eabi&amp;quot;
               &amp;quot;--enable-newlib-io-long-long&amp;quot;
               &amp;quot;--enable-newlib-io-float&amp;quot;
               &amp;quot;--enable-newlib-io-c99-formats&amp;quot;
               &amp;quot;--enable-newlib-retargetable-locking&amp;quot;
               &amp;quot;--enable-newlib-lite-exit&amp;quot;
               &amp;quot;--enable-newlib-multithread&amp;quot;
               &amp;quot;--enable-newlib-register-fini&amp;quot;
               &amp;quot;--enable-newlib-extra-sections&amp;quot;
               &amp;quot;--disable-newlib-wide-orient&amp;quot;
               &amp;quot;--disable-newlib-fseek-optimization&amp;quot;
               &amp;quot;--disable-newlib-supplied-syscalls&amp;quot;
               &amp;quot;--disable-newlib-target-optspace&amp;quot;
               &amp;quot;--disable-nls&amp;quot;)
       #:phases
       (modify-phases %standard-phases
     (add-after 'unpack 'fix-references-to-/bin/sh
       (lambda _
         (substitute* '(&amp;quot;libgloss/arm/cpu-init/Makefile.in&amp;quot;
                &amp;quot;libgloss/arm/Makefile.in&amp;quot;
                &amp;quot;libgloss/libnosys/Makefile.in&amp;quot;
                &amp;quot;libgloss/Makefile.in&amp;quot;)
           ((&amp;quot;/bin/sh&amp;quot;) (which &amp;quot;sh&amp;quot;)))
         #t)))))
    (native-inputs
     `((&amp;quot;xbinutils&amp;quot; ,zephyr-binutils)
       (&amp;quot;xgcc&amp;quot; ,gcc-arm-zephyr-eabi-12)
       (&amp;quot;texinfo&amp;quot; ,texinfo)))
    (home-page &amp;quot;https://www.sourceware.org/newlib/&amp;quot;)
    (synopsis &amp;quot;C library for use on embedded systems&amp;quot;)
    (description &amp;quot;Newlib is a C library intended for use on embedded
systems.  It is a conglomeration of several library parts that are easily
usable on embedded products.&amp;quot;)
    (license (license:non-copyleft
          &amp;quot;https://www.sourceware.org/newlib/COPYING.NEWLIB&amp;quot;))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And the build.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix build -L guix-zephyr zephyr-newlib

/gnu/store/4lx37gga1jv3ckykrxsfgwy9slaamln4-zephyr-newlib-3.3&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Complete toolchain&lt;/h2&gt;&lt;p&gt;Note that the toolchain is &lt;em&gt;Mostly&lt;/em&gt; complete. libstdc++ does not build because
`arm-zephyr-eabi` is not `arm-none-eabi` so a dynamic link check is
performed/failed. I cannot figure out how crosstool-ng handles this.&lt;/p&gt;&lt;p&gt;Anyway, now that we’ve got the individual tools it’s time to create
our complete toolchain. For this we need to do some package transformations.
Because these transformations are must be done for every combination of
binutils/gcc/newlib, it is best to create a function which we can reuse for
every version of the SDK.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define (arm-zephyr-eabi-toolchain xgcc newlib version)
  &amp;quot;Produce a cross-compiler zephyr toolchain package with the compiler XGCC and the C
library variant NEWLIB.&amp;quot;
  (let ((newlib-with-xgcc (package (inherit newlib)
                   (native-inputs
                    (alist-replace &amp;quot;xgcc&amp;quot; (list xgcc)
                           (package-native-inputs newlib))))))
    (package
  (name (string-append &amp;quot;arm-zephyr-eabi&amp;quot;
               (if (string=? (package-name newlib-with-xgcc)
                     &amp;quot;newlib-nano&amp;quot;)
               &amp;quot;-nano&amp;quot; &amp;quot;&amp;quot;)
               &amp;quot;-toolchain&amp;quot;))
  (version version)
  (source #f)
  (build-system trivial-build-system)
  (arguments
   '(#:modules ((guix build union)
            (guix build utils))
     #:builder
     (begin
       (use-modules (ice-9 match)
            (guix build union)
            (guix build utils))
       (let ((out (assoc-ref %outputs &amp;quot;out&amp;quot;)))
         (mkdir-p out)
         (match %build-inputs
       (((names . directories) ...)
        (union-build (string-append out &amp;quot;/arm-zephyr-eabi&amp;quot;)
                 directories)
        #t))))))
  (inputs
   `((&amp;quot;binutils&amp;quot; ,zephyr-binutils)
     (&amp;quot;gcc&amp;quot; ,xgcc)
     (&amp;quot;newlib&amp;quot; ,newlib-with-xgcc)))
  (synopsis &amp;quot;Complete GCC tool chain for ARM zephyrRTOS development&amp;quot;)
  (description &amp;quot;This package provides a complete GCC tool chain for ARM
bare metal development with zephyr rtos.  This includes the GCC arm-zephyr-eabi cross compiler
and newlib (or newlib-nano) as the C library.  The supported programming
language is C.&amp;quot;)
  (home-page (package-home-page xgcc))
  (license (package-license xgcc)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function creates a special package which consists of the toolchain in a special directory hierarchy, i.e &lt;code&gt;arm-zephyr-eabi/&lt;/code&gt;.
Our complete toolchain definition looks like this.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define-public arm-zephyr-eabi-toolchain-0.15.0
  (arm-zephyr-eabi-toolchain
   gcc-arm-zephyr-eabi-12
   zephyr-newlib
   &amp;quot;0.15.0&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To build:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix build -L guix-zephyr arm-zephyr-eabi-toolchain

/gnu/store/9jnanr27v6na5qq3dlgljraysn8r1sad-arm-zephyr-eabi-toolchain-0.15.0&lt;/code&gt;&lt;/pre&gt;&lt;h1&gt;Integrating with Zephyr Build System&lt;/h1&gt;&lt;p&gt;Zephyr uses CMake as it’s build system. It contains numerous CMake files in both the so-called &lt;code&gt;ZEPHYR_BASE&lt;/code&gt;,
the zephyr source code repository, as well as a handful in the SDK which help select the correct toolchain
for a given board.&lt;/p&gt;&lt;p&gt;There are standard locations the build system will look for the SDK. We are not
using any of them. Our SDK lives in the store, immutable forever. According to
&lt;a href=&quot;https://docs.zephyrproject.org/latest/develop/west/without-west.html&quot;&gt;this
webpage&lt;/a&gt;,
the variable &lt;code&gt;ZEPHYR_SDK_INSTALL_DIR&lt;/code&gt; needs to point to our custom spot.&lt;/p&gt;&lt;p&gt;We also need to grab the cmake files from the &lt;a href=&quot;https://github.com/zephyrproject-rtos/sdk-ng&quot;&gt;repository&lt;/a&gt; and create a file &lt;code&gt;sdk_version&lt;/code&gt; which
contains the version string &lt;code&gt;ZEPHYR_BASE&lt;/code&gt; uses to find a compatible SDK.&lt;/p&gt;&lt;p&gt;Along with the SDK proper we need to include a number of python packages required by the build system.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  (define-public zephyr-sdk
  (package
    (name &amp;quot;zephyr-sdk&amp;quot;)
    (version &amp;quot;0.15.0&amp;quot;)
    (home-page &amp;quot;https://zephyrproject.org&amp;quot;)
    (source (origin (method git-fetch)
            (uri (git-reference
              (url &amp;quot;https://github.com/zephyrproject-rtos/sdk-ng&amp;quot;)
              (commit &amp;quot;v0.15.0&amp;quot;)))
            (file-name (git-file-name name version))
            (sha256 (base32 &amp;quot;04gsvh20y820dkv5lrwppbj7w3wdqvd8hcanm8hl4wi907lwlmwi&amp;quot;))))
    (build-system trivial-build-system)
    (arguments
     `(#:modules ((guix build union)
          (guix build utils))
       #:builder
       (begin
     (use-modules (guix build union)
              (ice-9 match)
              (guix build utils))
     (let* ((out (assoc-ref %outputs &amp;quot;out&amp;quot;))
        (cmake-scripts (string-append (assoc-ref %build-inputs &amp;quot;source&amp;quot;)
                          &amp;quot;/cmake&amp;quot;))
        (sdk-out (string-append out &amp;quot;/zephyr-sdk-0.15.0&amp;quot;)))
       (mkdir-p out)

       (match (assoc-remove! %build-inputs &amp;quot;source&amp;quot;)
         (((names . directories) ...)
          (union-build sdk-out directories)))

       (copy-recursively cmake-scripts
                 (string-append sdk-out &amp;quot;/cmake&amp;quot;))

       (with-directory-excursion sdk-out
         (call-with-output-file &amp;quot;sdk_version&amp;quot;
           (lambda (p)
         (format p &amp;quot;0.15.0&amp;quot;)))
         #t)))))
    (propagated-inputs
     (list
      arm-zephyr-eabi-toolchain-0.15.0
      zephyr-binutils
      dtc))
    (native-search-paths
     (list (search-path-specification
        (variable &amp;quot;ZEPHYR_SDK_INSTALL_DIR&amp;quot;)
        (files '(&amp;quot;&amp;quot;)))))
    (synopsis &amp;quot;SDK for zephyrRTOS&amp;quot;)
    (description &amp;quot;zephyr-sdk contains bundles a complete gcc toolchain as well
as host tools like dtc, openocd, qemu, and required python packages.&amp;quot;)
    (license license:apsl2)))&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Testing&lt;/h2&gt;&lt;p&gt;In order to test we will need an environment with the SDK installed.
We can take advantage of &lt;code&gt;guix shell&lt;/code&gt; to avoid installing test packages into
our home environment. This way, if it causes problems, we can just exit the shell
and try again.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix shell -L guix-zephyr zephyr-sdk cmake ninja git&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;ZEPHYR_BASE&lt;/code&gt; can be cloned into a temporary workspace to test our toolchain
functionality (For now. Eventually we will need to create a package for
&lt;code&gt;zephyr-base&lt;/code&gt; that our guix zephyr-build-system can use).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mkdir /tmp/zephyr-project
cd /tmp/zephyr-project
git clone https://github.com/zephyrproject-rtos/zephyr
export ZEPHYR_BASE=/tmp/zephyr-project/zephyr&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In order to build for the test board (k64f in this case) we need to get a hold
of the vendor Hardware Abstraction Layers and CMSIS (These will also need to
become guix packages to allow the build system to compose modules).&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone https://github.com/zephyrproject-rtos/hal_nxp &amp;amp;&amp;amp;
git clone https://github.com/zephyrproject-rtos/cmsis&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To inform the build system about this module we pass it in with &lt;code&gt;-DZEPHYR_MODULES=&lt;/code&gt; which is
a semicolon separated list of paths containing a module.yml file.&lt;/p&gt;&lt;p&gt;To build the hello world sample we use the following incantation.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cmake -Bbuild $ZEPHYR_BASE/samples/hello_world \
  -GNinja \
  -DBOARD=frdm_k64f \
  -DBUILD_VERSION=3.1.0 \
  -DZEPHYR_MODULES=&amp;quot;/tmp/zephyr-project/hal_nxp;/tmp/zephyr-project/cmsis&amp;quot; \
    &amp;amp;&amp;amp; ninja -Cbuild&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If everything is set up correctly we will end up with a &lt;code&gt;./build&lt;/code&gt;
directory with all our build artifacts. The SDK is installed correctly!&lt;/p&gt;</content></entry><entry><title>Nextcloud and Guix System Server</title><id>https://gnucode.me/nextcloud-and-guix-system-server.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-02-22T17:00:00Z</updated><link href="https://gnucode.me/nextcloud-and-guix-system-server.html" rel="alternate" /><content type="html">&lt;p&gt;So I have wanted to run &lt;a href=&quot;https://nextcloud.com/&quot;&gt;nextcloud&lt;/a&gt; for a while now. In my humble opinion, guix
system makes maintaining websites super easy, so I would prefer to run nextcloud
on guix system. Unfortunately, nextcloud will NOT be packaged in guix anytime
soon for two reasons:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Guix does not currently have a php build system or any php packages, though
there is a 80% completed &lt;a href=&quot;https://issues.guix.gnu.org/42338&quot;&gt;work-in-progress issue.&lt;/a&gt; So the php bits of nextcloud
cannot be packaged properly.&lt;/li&gt;&lt;li&gt;Nextcloud has a lot of javascript dependencies, and javascript is &lt;a href=&quot;https://dustycloud.org/blog/javascript-packaging-dystopia/&quot;&gt;notoriously
hard to package for guix.&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;It seems like the easiest way to currently run nextcloud on guix system is by
using the &lt;a href=&quot;https://github.com/nextcloud/all-in-one&quot;&gt;all in one docker image.&lt;/a&gt; Please consider this a guide to set up
running nextcloud on guix system via a linode, which currently costs me about $5
per month.&lt;/p&gt;&lt;p&gt;Note, that while this is the easiest method to run nextcloud, apparently this
all in one docker image has some security issues:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;The AIO image mounts the Docker socket, which is a security risk since it allows
full access to other container as well as running any new container. It’s a bad
idea and should be avoided.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;tl;dr  Here are the 6 simple steps that you need to do:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Set up a &lt;a href=&quot;https://guix.gnu.org/en/cookbook/en/html_node/Running-Guix-on-a-Linode-Server.html#Running-Guix-on-a-Linode-Server&quot;&gt;linode guix system server.&lt;/a&gt;  &lt;code&gt;info &amp;quot;Guix Cookbook&amp;quot; RET i linode RET&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Buy a domain name.  I use &lt;a href=&quot;https://hover.com&quot;&gt;hover.com&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Point your domain name at your linode IP address.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Set up a basic nginx static website without encryption.  This means that you
don’t want to define &lt;code&gt;(service certbot-service-type)&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo mkdir -p /srv/www/html/yourdomainname.com
    
# the command I did was this:
sudo mkdir -p /srv/www/html/the-nx.com
    
sudo chgrp -R users /srv
sudo chmod -R g+rwx /srv&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Inside your newly created directory (&lt;em&gt;srv/www/html/yourdomainname.com&lt;/em&gt;), put
a simple HTML file and call it “index.html”. You could use this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html class=&amp;quot;no-js&amp;quot; lang=&amp;quot;&amp;quot;&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
        &amp;lt;meta http-equiv=&amp;quot;x-ua-compatible&amp;quot; content=&amp;quot;ie=edge&amp;quot;&amp;gt;
        &amp;lt;title&amp;gt;the nx&amp;lt;/title&amp;gt;
        &amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;&amp;quot;&amp;gt;
        &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1&amp;quot;&amp;gt;
        &amp;lt;link rel=&amp;quot;apple-touch-icon&amp;quot; href=&amp;quot;/apple-touch-icon.png&amp;quot;&amp;gt;
    
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;!--[if lt IE 8]&amp;gt;
            &amp;lt;p class=&amp;quot;browserupgrade&amp;quot;&amp;gt;
            You are using an &amp;lt;strong&amp;gt;outdated&amp;lt;/strong&amp;gt; browser. Please
            &amp;lt;a href=&amp;quot;http://browsehappy.com/&amp;quot;&amp;gt;upgrade your browser&amp;lt;/a&amp;gt; to improve
            your experience.
            &amp;lt;/p&amp;gt;
        &amp;lt;![endif]--&amp;gt;
    
        &amp;lt;p&amp;gt;Hello!&amp;lt;/p&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now set up a basic nginx configuration for a static website without
encryption. It will end up looking something like:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service nginx-service-type
         (nginx-configuration
          (server-blocks
           (list
            (nginx-server-configuration
             (server-name '(&amp;quot;the-nx.com&amp;quot;))
             (listen (list &amp;quot;80&amp;quot; &amp;quot;[::]:80&amp;quot;))
             (root &amp;quot;/srv/www/html/the-nx.com&amp;quot;))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you need to reconfigure so that the &lt;code&gt;nginx&lt;/code&gt; user is created:&lt;/p&gt;&lt;p&gt;&lt;code&gt;sudo guix system reconfigure config.scm&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Now, nginx is running, but you will probably need to give nginx access to
read the files in your /srv directory.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo chown -R nginx /srv
sudo chmod -R u-rwx /srv&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Open up a web browser and go to &lt;a href=&quot;http://yourdomainname.com&quot;&gt;http://yourdomainname.com&lt;/a&gt; and check to see
that you see a basic website.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Now you need to turn your basic static website, into a site that has https
support.  Now you need to edit your nginx config and add in a certbot config:&lt;/p&gt;&lt;p&gt;Before your &lt;code&gt;(operating-system ...)&lt;/code&gt; declartion, define this bit of code:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(define %nginx-deploy-hook
  (program-file
   &amp;quot;nginx-deploy-hook&amp;quot;
   #~(let ((pid (call-with-input-file &amp;quot;/var/run/nginx/pid&amp;quot; read)))
       (kill pid SIGHUP))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Also make sure that you add in a &lt;code&gt;certbot&lt;/code&gt; service and a modified &lt;code&gt;nginx&lt;/code&gt;
service that look like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service certbot-service-type
         (certbot-configuration
          (email &amp;quot;mysubscriptions@member.fsf.org&amp;quot;)
          (webroot &amp;quot;/srv/www/&amp;quot;)
          (certificates
           (list
            (certificate-configuration
             (name &amp;quot;the-nx.com&amp;quot;)
             (domains '(&amp;quot;the-nx.com&amp;quot; &amp;quot;www.the-nx.com&amp;quot;))
             (deploy-hook %nginx-deploy-hook))))))
    
(service nginx-service-type
         (nginx-configuration
          (server-blocks
           (list
            (nginx-server-configuration
             (server-name '(&amp;quot;the-nx.com&amp;quot;))
             (listen (list &amp;quot;80&amp;quot;
                           &amp;quot;443 ssl http2&amp;quot;
                           &amp;quot;[::]:80&amp;quot;
                           &amp;quot;[::80]:443 ssl http2&amp;quot;))
             (root &amp;quot;/srv/www/html/the-nx.com&amp;quot;)
             (ssl-certificate &amp;quot;/etc/letsencrypt/live/the-nx.com/fullchain.pem&amp;quot;)
             (ssl-certificate-key &amp;quot;/etc/letsencrypt/live/the-nx.com/privkey.pem&amp;quot;)
             (locations
              (list
               (nginx-location-configuration ;; for certbot
                (uri &amp;quot;/.well-known&amp;quot;)
                (body (list &amp;quot;root /srv/www;&amp;quot;))))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we will have to reconfigure again to set up certbot:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure config.scm
    
# tell certbot to set up our certificates
sudo /var/lib/certbot/renew-certificates&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you should be able to go to &lt;a href=&quot;https://yourdomainname.com&quot;&gt;https://yourdomainname.com&lt;/a&gt; and see your site
in glorious encrypted mode!&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Modify your guix config based on my &lt;a href=&quot;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/the-nx.com-current-config.scm&quot;&gt;the-nx.com-current-config.scm&lt;/a&gt;.
You will need to enable these services &lt;code&gt;(dbus-service)&lt;/code&gt;, &lt;code&gt;(service docker-service-type)&lt;/code&gt;, &lt;code&gt;(elogind service)&lt;/code&gt;, &lt;code&gt;(service certbot-service-type)&lt;/code&gt;,
and &lt;code&gt;(service nginx-service-type)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I just ran this command, and my local nextcloud just started working.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo docker run \
--sig-proxy=false \
--name nextcloud-aio-mastercontainer \
--restart always \
--publish 80:80 \
--publish 8080:8080 \
--publish 8443:8443 \
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
nextcloud/all-in-one:latest&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following is the same quick guide as above, but has more details:&lt;/p&gt;&lt;p&gt;I decided to create a new linode image following the linode cookbook guide, and
I noticed a tiny error in the guide:&lt;/p&gt;&lt;p&gt;&lt;code&gt;sudo apt-get install gpg&lt;/code&gt; failed.  It worked after I ran &lt;code&gt;sudo apt-get update&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Also the basic config example needs to migrate to the new &amp;lt;swap-space&amp;gt; record.
It gave me this warning message:&lt;/p&gt;&lt;p&gt;/root/config.scm:11:0: warning: List elements of the field ’swap-devices’ should
now use the &amp;lt;swap-space&amp;gt; record, as the old method is deprecated. See “(guix)
operating-system Reference” for more details.&lt;/p&gt;&lt;p&gt;The cookbook guide also should probably mention that you may need to login to
the server for the first time using linode’s weblish, and set up the root passwd
with &lt;code&gt;passwd&lt;/code&gt;. Then set up your user password with &lt;code&gt;passwd &amp;lt;username&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Now that we have a basic site set up, let’s set up certbot and the nginx services:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service certbot-service-type
         (certbot-configuration
          (email &amp;quot;mysubscriptions@member.fsf.org&amp;quot;)
          (webroot &amp;quot;/srv/www/&amp;quot;)
          (certificates
           (list
            (certificate-configuration
             (name &amp;quot;the-nx.com&amp;quot;)
             (domains '(&amp;quot;the-nx.com&amp;quot; &amp;quot;www.the-nx.com&amp;quot;))
             (deploy-hook %nginx-deploy-hook))))))

(nginx-configuration
 (server-blocks
  (list
   (nginx-server-configuration
    (server-name '(&amp;quot;the-nx.com&amp;quot;))
    (listen (list &amp;quot;80&amp;quot;
                  &amp;quot;443 ssl http2&amp;quot;
                  ;;&amp;quot;[::]:80&amp;quot;
                  ;;&amp;quot;[::80]:443 ssl http2&amp;quot;
                  ))
    (root &amp;quot;/srv/www/html/the-nx.com&amp;quot;)
    (ssl-certificate &amp;quot;/etc/letsencrypt/live/the-nx.com/fullchain.pem&amp;quot;)
    (ssl-certificate-key &amp;quot;/etc/letsencrypt/live/the-nx.com/privkey.pem&amp;quot;)
    (locations
     (list
      (nginx-location-configuration ;; for certbot
       (uri &amp;quot;/.well-known&amp;quot;)
       (body (list &amp;quot;root /srv/www;&amp;quot;)))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s reconfigure and get a certbot certificate.  &lt;code&gt;ssh&lt;/code&gt; into the-nx.com and
run these commands:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure the-nx.com-current-config.scm

# tell certbot to set up our certificates
sudo /var/lib/certbot/renew-certificates&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So now my server has a valid certificate. It is time change the nginx
configuration to proxy incoming requests to the docker all in one image.&lt;/p&gt;&lt;p&gt;Ok, maybe I can use sexpressions to tell nginx to redirect all incoming traffic
to &lt;code&gt;the-nx.com&lt;/code&gt; to the docker nextcloud image:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(nginx-location-configuration
 (uri &amp;quot;/&amp;quot;)
 (body
  (list
   &amp;quot;proxy_pass http://127.0.0.1:9000;\n&amp;quot;
   &amp;quot;proxy_set_header X-Real-IP $remote_addr;\n&amp;quot;
   &amp;quot;proxy_set_header Host $host;\n&amp;quot;
   &amp;quot;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n&amp;quot;
   &amp;quot;client_max_body_size 0;\n&amp;quot;
   &amp;quot;# Websocket\n&amp;quot;
   &amp;quot;proxy_http_version 1.1;\n&amp;quot;
   &amp;quot;proxy_set_header Upgrade $http_upgrade;\n&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I am going to deploy this image, and take a look at the generated nginx
configuration file.  I ran this command on my T400 laptop:&lt;/p&gt;&lt;p&gt;&lt;code&gt;guix deploy the-nx.com-current-config.scm&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Well, that’s super annoying. I do not know which nginx.conf file is the right
one:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;find /gnu/store -name '*nginx.conf'

/gnu/store/7m1ygzqk6njn5mywqmhwbydbb2z4b9li-nginx.conf
/gnu/store/0gcfj61q4943h94jdqq7i9y0a0v9jr9q-nginx.conf
/gnu/store/4mzrp39w5i4v94kxf98gxc13ws79l88n-nginx.conf
/gnu/store/0nia2iqfw63ziasibbgq321wr9b3152n-nginx.conf
/gnu/store/pf8d0sj1yf9b2ndsbc61yj3h6rp4pck2-nginx.conf
/gnu/store/9nra62v41wsk08xf3msw5a1z35gji2gx-nginx-1.23.2/share/nginx/conf/nginx.conf
/gnu/store/4b1szfyn0snwzf3lm1snvaapk6diz3yq-nginx.conf
/gnu/store/fv5rg3nf5999vyg6qvp4sbgjysnkn1fc-nginx.conf
/gnu/store/vmjwj2zwblcz4wx2whsmxdfc7zxcgjh5-nginx.conf
/gnu/store/n3m2lihq9cjm6mxdln57q5nrbjgz53s6-nginx.conf
/gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/nginx.conf&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I guess I will reboot, run &lt;code&gt;guix system delete-generations&lt;/code&gt; and &lt;code&gt;guix gc&lt;/code&gt;, and
run the above command again:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;find /gnu/store -name '*nginx.conf'

/gnu/store/7m1ygzqk6njn5mywqmhwbydbb2z4b9li-nginx.conf
/gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/nginx.conf&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well that looks promising.  Let's check out my nginx.conf file.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /gnu/store/i2mzdhg8wlbxv7iza8y4qk5v0vmvp27q-nginx.conf

user nginx nginx;
pid /var/run/nginx/pid;
error_log /var/log/nginx/error.log info;
events { }
http {
    client_body_temp_path /var/run/nginx/client_body_temp;
    proxy_temp_path /var/run/nginx/proxy_temp;
    fastcgi_temp_path /var/run/nginx/fastcgi_temp;
    uwsgi_temp_path /var/run/nginx/uwsgi_temp;
    scgi_temp_path /var/run/nginx/scgi_temp;
    access_log /var/log/nginx/access.log;
    include /gnu/store/jnl72hx0papzb42kbd1f19qx35w76lmg-nginx-1.23.2/share/nginx/conf/mime.types;

    server {
      listen 443 ssl http2;
      server_name the-nx.com ;
      ssl_certificate /etc/letsencrypt/live/the-nx.com/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/the-nx.com/privkey.pem;
      root /srv/www/html/the-nx.com;
      index index.html ;
      server_tokens off;

      location /.well-known {
        root /srv/www;
      }
      location / {
        proxy_pass http://127.0.0.1:9000;

        proxy_set_header X-Real-IP $remote_addr;

        proxy_set_header Host $host;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        client_max_body_size 0;

        # Websocket

        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;

      }

    }
    server {
      listen 80;
      listen [::]:80;
      server_name the-nx.com www.the-nx.com ;
      root /srv/http;
      index index.html ;
      server_tokens off;

      location /.well-known {
        root /srv/www/;
      }
      location / {
        return 301 https://$host$request_uri;
      }

    }

}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The generated configuration seems pretty wonky, and I am suprised that nginx is
still running, but it is still running.  And I suppose that it should work.&lt;/p&gt;&lt;p&gt;I was able to get nextcloud to start with this command:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo docker run --sig-proxy=false --name nextcloud-aio-mastercontainer \
 --restart always \
 --publish 8080:8080 \
 -e APACHE_PORT=9000 \
 --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
 --volume /var/run/docker.sock:/var/run/docker.sock:ro  \
 nextcloud/all-in-one:latest&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So now I can login at the-nx.com:8080 and configure various stuff. Also I really
need to set up a firewall. That’s probably a really good idea.  Also what’s nice
about this docker image is that it will start itself if you update the guix
system server and reboot.&lt;/p&gt;&lt;p&gt;MORE BONUS CONTENT:&lt;/p&gt;&lt;p&gt;If you see this blog post, and you decide to set up your nextcloud on a guix
system server, and if your nginx config doesn’t seem to be proxying requests to
your docker container, then you may follow these steps to delete the docker
image and start over:&lt;/p&gt;&lt;p&gt;This &lt;a href=&quot;https://help.nextcloud.com/t/aio-this-site-can-t-provide-a-secure-connection/128478/5&quot;&gt;page&lt;/a&gt; has some good commands for deleting the docker image and starting
over:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo docker stop nextcloud-aio-mastercontainer &amp;amp;&amp;amp; \\
sudo docker rm nextcloud-aio-mastercontainer &amp;amp;&amp;amp; \\
sudo docker container prune -f &amp;amp;&amp;amp; \\
sudo docker volume prune -f &amp;amp;&amp;amp; \\
sudo docker pull nextcloud/all-in-one:latest&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so it looks like the nextcloud all in one documentation has a &lt;a href=&quot;https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md&quot;&gt;page&lt;/a&gt; for
understanding the reverse proxy.&lt;/p&gt;&lt;p&gt;It would also be nice to get my nextcloud image to sync my contacts.  I probably just need to add in another nginx
location line for that.  That will be a project for another day.&lt;/p&gt;</content></entry><entry><title>Upgrading the PinePhone</title><id>https://gnucode.me/upgrading-the-pinephone.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-02-04T18:00:00Z</updated><link href="https://gnucode.me/upgrading-the-pinephone.html" rel="alternate" /><content type="html">&lt;p&gt;So I have been running this to upgrade the pinephone for a while now:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apk upgrade
# apk update

# apk upgrade
# apk update&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Today, when I rebooted I got a message that said that my pinephone’s version was
no longer supported.  I should &lt;a href=&quot;https://postmarketos.org/upgrade&quot;&gt;upgrade&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;I figured that I will probably do this again, so I might as well write down the
steps for how to do the upgrade.&lt;/p&gt;&lt;p&gt;Before I really get started in this, I want to get set up in the &lt;a href=&quot;https://wiki.postmarketos.org/wiki/Matrix_and_IRC&quot;&gt;matrix chat
room.&lt;/a&gt; I used the web based interface for the matrix chat. It had me create an
online account, and verify my email address, then I could talk in the matrix
channel. That was easy, moving onto the next step.&lt;/p&gt;&lt;p&gt;First install &lt;code&gt;postmarketos-release-upgrade&lt;/code&gt; package:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;# apk add postmarketos-release-upgrade&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next I want to create a &lt;a href=&quot;https://wiki.postmarketos.org/wiki/Backup_and_restore_your_data&quot;&gt;backup&lt;/a&gt;, of the pinephone incase the upgrade fails or
breaks the phone and I have to install postmarketOS.&lt;/p&gt;&lt;p&gt;Ok, in the pinephone’s terminal, start the sshd daemon:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo service sshd start&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So possibly the best way to upgrade your pinephone is to connect the phone to
your laptop/desktop via a usb cord and enable &lt;a href=&quot;https://wiki.postmarketos.org/wiki/USB_Internet#Linux&quot;&gt;usb internet.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Apparently after you connect the phone to your host machine, you should be able
to run:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ssh user@172.16.42.1&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That didn’t work.  And it is quickly looking to me like the usb internet upgrade
option is NOT going to work.  Or rather, it will work, but it will take me a lot
of time to get it to work.&lt;/p&gt;&lt;p&gt;So instead of using the usb internet upgrade option, I will try connecting the
pinephone to the internet via an ethernet cord (I personally disabled the wifi
on the phone to try to save power). Then I will make a backup of the pinephone.&lt;/p&gt;&lt;p&gt;Ok, now that I have my phinephone connected to an ethernet port, I used my
laptop to ssh into the pinephone.&lt;/p&gt;&lt;p&gt;I found my pinephone’s ip address via running this on the pinephone’s terminal:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ip a&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so the looking at eth0:  the pinephone’s ip address is:&lt;/p&gt;&lt;p&gt;SOME.IP.Address.04&lt;/p&gt;&lt;p&gt;So, I can now ssh into the phone via:&lt;/p&gt;&lt;p&gt;&lt;code&gt;ssh user@SOME.IP.Address.04&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Since I have ssh-agent set up, lets set up ssh key login:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ssh-copy-id user@SOME.IP.ADDRESS.04&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s create a backup on my host comptuter (laptop):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mkdir ~/postmarket-os-backup
rsync -avz --exclude=.cache user@SOME.IP.ADDRESS.04:/home/user/ .

fish: Unknown command: rsync
fish:
rsync --server --sender -vlogDtprze.iLsfxCIvu . /home/user/
^
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [Receiver=3.2.7]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well that seems like a weird problem.  Let’s go join the fish irc channel.&lt;/p&gt;&lt;p&gt;Well the channel is here:&lt;/p&gt;&lt;p&gt;&lt;code&gt;#fish&lt;/code&gt; at irc.oftc.net&lt;/p&gt;&lt;p&gt;I can find out how to connect via going to oftc.net.  They ever have a &lt;a href=&quot;https://webchat.oftc.net/&quot;&gt;webchat&lt;/a&gt;.
That makes it easy.  Just put in a goofy nickname and you are in the chat room!&lt;/p&gt;&lt;p&gt;It took the fish people a while to respond, so I also asked in the &lt;code&gt;#guix&lt;/code&gt;
channel, while I was waiting. A guix user said that I should try this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix shell --network -C coreutils rsync openssh-sans-x&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then run my rsync command.&lt;/p&gt;&lt;p&gt;That didn’t work, but then the &lt;code&gt;#fish&lt;/code&gt; people just asked me if I have rsync
installed on my pinephone…I didn’t realize I needed it installed on both
devices.&lt;/p&gt;&lt;p&gt;So let’s do that on the pinephone: &lt;code&gt;sudo apk add rsync&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Let’s try this again.  On my laptop I ran this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;rsync -avz --exclude=.cache user@SOME.IP.ADDRESS.04:/home/user/ ~/postmarket-os-backup&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok that worked!&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;https://wiki.postmarketos.org/wiki/Upgrade_to_a_newer_postmarketOS_release&quot;&gt;postmarketOS wiki&lt;/a&gt; recommends that I use tmux or screen to update the
pinephone, in case the ssh connection breaks. Well I believe that I have tried
updating the pinephone before using just an ssh connection, and the ssh
connection dropped. I did not know if they phone was done updating or if it had
just died. So I forcefully shut off the device, and it failed to boot. Fun
times.&lt;/p&gt;&lt;p&gt;Well let’s go ask in the postmarketOS irc channel or &lt;a href=&quot;https://wiki.postmarketos.org/wiki/Category:Community&quot;&gt;matrix&lt;/a&gt; and ask about using
tmux or screen. How does it make sure that the ssh connection does not break? I
can also check out the archlinux wiki. Also it seems as if tmux is more user
friendly, so I will check out the &lt;a href=&quot;https://wiki.archlinux.org/title/Tmux&quot;&gt;tmux&lt;/a&gt; page to learn more about it.&lt;/p&gt;&lt;p&gt;Well let’s go ahead and install tmux on my laptop: &lt;code&gt;guix install tmux&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Let’s try to run an ssh connection on the pinephone via tmux.  I think this
is how you do it:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;tmux
ssh user@&amp;lt;IP address of the pinephone&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well I asked in the postmarketOS irc channel why they reccommend using tmux in
case the ssh connection drops, and this is the answer that I got:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;if you use tmux, you can just restore your tmux session if the ssh connection drops
and the command will still be running in there&lt;/p&gt;&lt;p&gt;run tmux
then if the connection drops
tmux list-sessions
and then
tmux attach-session
I think&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Then if the ssh connection gets dropped, I can open up a new terminal and do
this &lt;code&gt;tmux attach&lt;/code&gt;, and I will be right back where I was. This &lt;a href=&quot;https://www.youtube.com/watch?v=JQ0yDCVu44E&quot;&gt;video&lt;/a&gt; explains
that.  That is pretty awesome!&lt;/p&gt;&lt;p&gt;Here &lt;a href=&quot;https://mutelight.org/practical-tmux&quot;&gt;are&lt;/a&gt; &lt;a href=&quot;https://blog.hawkhost.com/2010/06/28/tmux-the-terminal-multiplexer/&quot;&gt;some&lt;/a&gt; &lt;a href=&quot;https://blog.hawkhost.com/2010/07/02/tmux-%E2%80%93-the-terminal-multiplexer-part-2&quot;&gt;tmux&lt;/a&gt; &lt;a href=&quot;https://man.archlinux.org/man/tmux.1&quot;&gt;resources.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Next, I ran the following to update the pinephone:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;tmux
ssh user@&amp;lt;my Pinephone IP address&amp;gt;
postmarketos-release-upgrade&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since, my phinephone had an ethernet connection, the upgrade process was over
inside 5 minutes, and the phone rebooted itself. Nice work postmarketos
developers!&lt;/p&gt;</content></entry><entry><title>Setting up a Firewall</title><id>https://gnucode.me/setting-up-a-firewall.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2023-01-23T13:00:00Z</updated><link href="https://gnucode.me/setting-up-a-firewall.html" rel="alternate" /><content type="html">&lt;p&gt;Edit: Feb 12: The below firewall does NOT work. I currently do NOT use a
firewall on my servers.&lt;/p&gt;&lt;p&gt;So my guix system servers have been running without a firewall.  I have decided
to actually fix that.  Unfortunately, OpenBSD’s pf does not work on linux.  It
seems like the best packaged firewall for GNU Guix System is currently provided
by the netfilter service.  Luckily Guix’s default server provides a good basic
configuration for enabling ssh access to the machine.  That configuration looks
like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;

    # early drop of invalid connections
    ct state invalid drop

    # allow established/related connections
    ct state { established, related } accept

    # allow from loopback
    iifname lo accept

    # allow icmp
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept

    # allow ssh
    tcp dport ssh accept

    # reject everything else
    reject with icmpx type port-unreachable
  }
  chain forward {
    type filter hook forward priority 0; policy drop;
  }
  chain output {
    type filter hook output priority 0; policy accept;
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So it looks like I just need to add in policies just after the &lt;code&gt;#allow ssh&lt;/code&gt;
line.&lt;/p&gt;&lt;p&gt;It seems like the easiest way to test this service out, is to first, &lt;code&gt;guix install nft&lt;/code&gt;, then put your configuration into a file.  Then load in those
firewall rules via &lt;code&gt;sudo nft -f nftables.conf&lt;/code&gt;.  If those rules end up breaking
things, you can revert the firewall to allow everything via &lt;code&gt;sudo nft flush ruleset&lt;/code&gt;.  You can also list the current ruleset via &lt;code&gt;sudo nft list ruleset&lt;/code&gt;.
You can also check the syntax in &lt;code&gt;nftables.conf&lt;/code&gt; via &lt;code&gt;sudo nft -cf nftable.conf&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Well I had a firewall working fairly well.  I tested the firewall rules via
&lt;code&gt;sudo nft -f nftables-lamora.conf&lt;/code&gt;, and it worked really well. But this scheme
code seemed to break everything on the server.  Now, I can’t login to lamora and
the websites it hosts are not working.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service nftables-service-type
         (nftables-configuration
          (ruleset
           (mixed-text-file &amp;quot;nftables.conf&amp;quot;
                            &amp;quot;./nftables-lamora.conf&amp;quot;))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I reached out to linode support, and I am able to boot the machine in a rescue
image, which is pretty awesome.  From there I might be able to mount the
&lt;code&gt;/dev/sda&lt;/code&gt; drive such that &lt;code&gt;/gnu/store&lt;/code&gt; is set up properly.  But I think that is
pretty much beyond me.  Too much work to get correct.  So instead, I shall start
from scratch I suppose.  :(&lt;/p&gt;&lt;p&gt;What if I had just run,&lt;/p&gt;&lt;pre&gt;&lt;code&gt;mount /dev/sda /mnt
chroot /mnt
sudo guix system roll-back&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That might have worked.  But it also might not have and it might have just taken me
longer too.&lt;/p&gt;&lt;p&gt;Looks like I have a small basic guix image lying around that I can tell linode
to use.  Let’s try that.&lt;/p&gt;&lt;p&gt;Well that caused a kernel panic. That didn’t work. Probably because I told
linode to set the root password, and linode doesn’t know how to mess with guix
system?&lt;/p&gt;&lt;p&gt;So I whiped my linode server, and started over.  And it looks like
I need to modify the current cookbook entry about running guix system on linode via
adding in&lt;/p&gt;&lt;p&gt;&lt;code&gt;sudo apt-get update&lt;/code&gt;, then &lt;code&gt;sudo apt-get install gpg&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Here are some of the commands that I used to set up my new linode server.  It's on the
same IP address.  It's currently hosting gnucode.me.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;wget https://notabug.org/jbranso/linode-guix-system-configuration/raw/master/gnucode.me-initial-config.scm
mount /dev/sdc /mnt
sudo guix system reconfigure locke-lamora-initial-config.scm
guix install git
mkdir -p ~/prog/gnu/guix/guix-config/
cd ~/prog/gnu/guix/guix-config/
git clone https://notabug.org/jbranso/linode-guix-system-configuration
cd ../
git clone https://git.sr.ht/~whereiseveryone/guixrus
sudo mkdir -p /srv/www/html&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I need to git clone my various static websites on the server.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd /srv/www/html
sudo git clone https://notabug.org/jbranso/gnucode.me.git
sudo git clone https://notabug.org/jbranso/propernaming.git
sudo git clone https://notabug.org/jbranso/gnu-hurd.com.git
sudo mv propernaming propernaming.org&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So I believe that I need to chmod the files in /srv/www/html, so that nginx can
actually serve them. Unfortunately, I cannot do a &lt;code&gt;sudo chown -R nginx /srv&lt;/code&gt;,
because my current guix system does not have an nginx user yet. But I believe
that I can still reconfigure the system, even if nginx will not be able to serve
the html files. After I have reconfigured, then I should be able chown the owner
of /srv to nginx. In the end I actually just did a &lt;code&gt;cd /srv; sudo chmod -R o+r *&lt;/code&gt; and just made every file readable by everyone. That sort of violates the
principle of least privledge, oh well.&lt;/p&gt;&lt;p&gt;Now that I have made some modifications to my gnucode.me-current-config.scm that
comments out various certificate files that are not there yet, I can attempt to
reconfigure on the server:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cd prog/gnu/guix/guix-config/linode-guix-system-configuration/
sudo guix system reconfigure gnucode.me-current-config.scm

guix system: error: aborting reconfiguration because commit
9fe5b490df83ff32e2e0a604bf636eca48b9e240 of channel 'guix' is not a descendant
of 900d33527c9286a811f064d4bb8f4a9b18d1db0b&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well let’s try this updating everything.  And I believe that you need to do a
guix pull as root at least once.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;su
guix pull;
exit;
guix pull;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oh yeah, I also need to power down my linode, delete the debian partition, and
resize the guix partition to full size.&lt;/p&gt;&lt;p&gt;Now I believe that I cannot reconfigure my server with the current
&lt;code&gt;gnucode.me-current-config.scm&lt;/code&gt;, because nginx will fail to start because the
letsencrypt scripts are not there yet. So I need to modify the nginx bits before
I can start the service. I also decided to set up &lt;code&gt;guix deploy&lt;/code&gt; on my gnucode.me
machine, so that reconfiguring the remote server is faster.&lt;/p&gt;&lt;p&gt;Ok, so I have my current-config for gnucode.me deployed.  Geez, guix deploy is
sooo super fast!  And all you need to do is to set up ssh-agent  and customize a
deployment list.  I set up ssh-agent via my &lt;code&gt;.bash_profile&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat .bash_profile | grep eval -A 1

if [[ -z $DISPLAY ]] &amp;amp;&amp;amp; [[ $(tty) = /dev/tty6 ]]; then
    eval `ssh-agent -s`
    ssh-add
    exec dbus-run-session sway
fi&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now all you need to do is customize this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(list (machine
       (operating-system %system)
       (environment managed-host-environment-type)
       (configuration (machine-ssh-configuration
                       (host-name &amp;quot;45.56.66.20&amp;quot;)
                       (system &amp;quot;x86_64-linux&amp;quot;)
                       (user &amp;quot;joshua&amp;quot;)
                       (identity &amp;quot;~/.ssh/id_rsa&amp;quot;)
                       (host-key &amp;quot;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJgL0hBTWmCVGGvNJYa+YS+fEXs89v0GbdkQ+M+LdZlf root@(none)&amp;quot;)
                       (port 63355)))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The port is the ssh port.  And the ssh-ed25519 is found on your remote server’s
&lt;code&gt;etc/ssh/ssh_host_ed25519_key.pub&lt;/code&gt; file.&lt;/p&gt;&lt;p&gt;Now nginx serves my websites via http.  Let’s get https working.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo /var/lib/certbot/renew-certificates&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Alright, now I can set up my config.scm to allow nginx to serve web traffic via https.&lt;/p&gt;&lt;p&gt;Well, can I get a nftables service running now?&lt;/p&gt;&lt;p&gt;At first it seemed that &lt;code&gt;(service nftables-service-type)&lt;/code&gt; is apparently good
enough to be a decent firewall for my server. Then very quickly I realized that
it was a terrible firewall for a server, because it blocked all http and https
traffic.&lt;/p&gt;&lt;p&gt;It looks like the arch linux wiki has a decent configuration example for a server:&lt;/p&gt;&lt;p&gt;https://wiki.archlinux.org/title/Nftables#Examples&lt;/p&gt;&lt;p&gt;So I just took the example nftables configuration for a server and used that.
The configuration file is here:&lt;/p&gt;&lt;p&gt;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/nftables.scm&lt;/p&gt;&lt;p&gt;Let me know if you see that I did something silly in it, because I probably did.&lt;/p&gt;&lt;p&gt;Bonus paragraph! It took me about 2-4 hours to re-set up my server just the way
it was before, except I haven't set up email yet. If you crashed your server
lost your backups, how long would it take you to set up you server, just as it
was? 2-4 hours is longer than I expected, but I think guix's declarative
approach certainly is pretty awesome!&lt;/p&gt;</content></entry><entry><title>Submitting Opensmtpd Service to Guixrus</title><id>https://gnucode.me/submitting-opensmtpd-service-to-guixrus.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-12-22T15:00:00Z</updated><link href="https://gnucode.me/submitting-opensmtpd-service-to-guixrus.html" rel="alternate" /><content type="html">&lt;p&gt;EDIT 02-24-2023:  Through this whole process, I have used this guide to set up email.
If you are going to try to set up your own email service, do check it out:
&lt;a href=&quot;https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/&quot;&gt;https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I was recently encouraged by the delightfully friendly raghavgururajan to try to
merge my opensmtpd service project into guixrus, which is a small community
actively working to upstream packages and services into guix proper.  I figured,
why not?  Sounds like fun.  The following post will describe my developmental
workflow, which is probably pretty poor…&lt;/p&gt;&lt;p&gt;tl;dr&lt;/p&gt;&lt;p&gt;Soonish, I will clean up the code for a proper ~opensmtpd-service-type~ with
~opensmtpd-records~ for guix system. It may take 6 months to get it in a clean
state. Until it is merged, you may find it here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://git.sr.ht/~whereiseveryone/guixrus/commit/255875f7d86e92bb64006a59be26c64430c0c046&quot;&gt;https://git.sr.ht/~whereiseveryone/guixrus/commit/255875f7d86e92bb64006a59be26c64430c0c046&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The current documentation is here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd-records-documentation.txt&quot;&gt;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd-records-documentation.txt&lt;/a&gt;&lt;/p&gt;&lt;p&gt;My server's config is here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/linode-locke-lamora-current-config.scm&quot;&gt;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/linode-locke-lamora-current-config.scm&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The current task list is here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd.org&quot;&gt;https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd.org&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Added, the guixrus channel to my ~/.config/guix/channels.scm&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat ~/.config/guix/channels.scm

(cons* (channel  ;; for firefox-wayland
        (name 'nonguix)
        (url &amp;quot;https://gitlab.com/nonguix/nonguix&amp;quot;)
        ;; Enable signature verification:
        (introduction
         (make-channel-introduction
          &amp;quot;897c1a470da759236cc11798f4e0a5f7d4d59fbc&amp;quot;
          (openpgp-fingerprint
           &amp;quot;2A39 3FFF 68F4 EF7A 3D29  12AF 6F51 20A0 22FB B2D5&amp;quot;))))
       (channel  ;; for sway-latest
        (name 'guixrus)
        (url &amp;quot;https://git.sr.ht/~whereiseveryone/guixrus&amp;quot;)
        (introduction
         (make-channel-introduction
          &amp;quot;7c67c3a9f299517bfc4ce8235628657898dd26b2&amp;quot;
          (openpgp-fingerprint
           &amp;quot;CD2D 5EAA A98C CB37 DA91  D6B0 5F58 1664 7F8B E551&amp;quot;))))
       %default-channels)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Before I submit the patch, I should make sure that the code actually works. To
do that, I logged into my gnucode.me server tried to set up the opensmtpd
server.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix pull --url=https://notabug.org/jbranso/guix/src/newOpensmtpdBranch \
    --branch=newOpensmtpdBranch

Updating channel 'guix' from Git repository at 'https://notabug.org/jbranso/guix'...
guix pull: error: Git error: cannot locate remote-tracking branch 'origin/keyring'

guix pull --url=https://notabug.org/jbranso/guix \
    --commit=8abbb6c442d135ae8e7c1cb0e17525478fafe8f0

Updating channel 'guix' from Git repository at 'https://notabug.org/jbranso/guix'...
guix pull: error: Git error: cannot locate remote-tracking branch 'origin/keyring'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmm, well my opensmtpd service is NOT using signed commits.  That’s probably the
problem.  Hmmm…  Well I guess I need to start signing my commits.  Generate an
gpg key.  grrr….&lt;/p&gt;&lt;p&gt;These three pages are seem promising:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://moser-isi.ethz.ch/gpg.html&quot;&gt;https://moser-isi.ethz.ch/gpg.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://wiki.debian.org/Keysigning&quot;&gt;https://wiki.debian.org/Keysigning&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://risanb.com/code/backup-restore-gpg-key/&quot;&gt;https://risanb.com/code/backup-restore-gpg-key/&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --full-generate-key

gpg: directory '/home/joshua/.gnupg/openpgp-revocs.d' created
h.lgpg: revocation certificate stored as '/home/joshua/.gnupg/openpgp-revocs.d/LOTSOFNUMBERS.rev'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I copied my Revocation-Certificate into my spare usb:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo cp .gnupg/openpgp-revocs.d/LOTSOFNUMBERS.rev /mnt/gnucode.gpg.rev&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s export my gpg key to the server.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --auto-key-locate keyserver -a --send-keys 67A42A3CC23F979886F9686C750BCFEF3A579572

gpg -a --export gnucode

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBGOSU7sBEAC/8renj2OgTHKJfbqz7CRplPQ0su8aasJXTkunx70IhVpTFBS+
9Bwvjbo7HM2aBYD/NYa6n24J3OXla17uDxFt2i63ojhbl5AVntac3ZOeyn661Y2U
r9szIRM+edTieWZZvY5G49ZFTH5VJ+jZS2leRLpIqsYCst+Ru61MdUUggBNvPgBm
q97HAylBqQs0kf7XfctyqKbkChLsvkuD5cR1X8BQL8KAn/KDXrDSwj4hIO+tSdv5
VmaTC+6/xbdqfq6gpywJMEPkLNUjCArlF+Oz5UqQvLh1lRXWPejzFa0LmXsviqb3
RmQh+9cNvDVge+kYIRWHhCXY5dTau7ABnYsgxnW3zlBkFNbc+I5Sqiz6LDcuInlA
QznFw90GL3l0+1WGzeAD5DhNx6hgpOYvFZV7S3OgbOGeOHvF7bFBixB6Pa3oByMn
euKqol+rOZiUkjcaxo5XUKsglFLgOaxfmZujO7lwoipYXxiyD7jf1+ou1WZ5C3l+
YCOnia2qWE5DRpR/WDBRLQl3ZrCUtDQW7dKNAuweEgDT5T53k2m3Gqu1Z28SrzIS
is+SHZcZhv4dx9Cs6sX6me3WzQ3wgoI9DNW5v8XGitaGQFjIRI33Y8MeGjEBMip3
ZnT6Cl8WJgd0JBXsPQnKw1EO1sh2S5cU5drvHkuCPMA/PaBb8XrNpobSlwARAQAB
tDNKb3NodWEgQWxsZW4gQnJhbnNvbiAoZ251Y29kZSkgPGpicmFuc29AZGlzbWFp
bC5kZT6JAk4EEwEIADgWIQRnpCo8wj+XmIb5aGx1C8/vOleVcgUCY5JTuwIbAwUL
CQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRB1C8/vOleVcgwwEACp4ZwBIM/4Udc9
ndZvUJeegSP0W7o86v+9ELXfXdX99ZO0iErr6/XTWxov0mw7AaoDJRdETBTkYeU0
/CDrLcjklW8b7RZe98+Cr0+IB9XSozpqNVhiP7/TogL80lkbu2+Khtk29E/UYupt
8rihR+2tkDKPaWOufGgi+6ftw8A9P9jlFsV1N1Oxo4rA+gbcXHtxbDiZ1dR2UOAS
Ge7TJPpIjgSiG+nm6b9BIoAxLpjf5JrwpNm5wvDXic1YP27GC2Il9Ny7TdGyKpn9
RCZXR1yEMQTVNn4iEiMK6XIcoAFUS1oWAP2JKQ4bCfcxM/VGx31rsGgNL36iW6yj
zLD9yJYhbvm536CiRb2cTco+lAmwS9/iM4Bdpp/H9fZFPp2CxeB02mOd/P0HkC+2
Po2KXpEj6Ettjp0xJcAQye75vRvjDMkHvTvugfY4FQg6V6a6N3jxSbfwuFUp426F
fgfki4Y7OWm47mYa7goI4oDOG2qUdN5YkbhpVA+j2tGGHbbXmUtvj4MES4fnaSkF
vc6+xMZpFTWcFRt8rVTqS1Vu1w8zfT/VUV+FC/J6hdSxIQJ4dg4WsaD2kzGflZzO
miTyxMYPvdQ6I7Nshp/bEyfd9F40sXm/kzL6r+qm9+ly2uR5V+bIo9gu6CfkM0ZJ
DDiIf9wkk+xSb/AGj1YVazQKpKS0wLkCDQRjklO7ARAAzrtyGaOFTtCHlItxxb51
s0Qt5LZwG3sNUjI9P7n3oZrzI35sbPrWxWCX2MMW0gUIx79dlMzQBt1RXQEKiipr
RdSrtuclTytxaMtLRP+VtmcRQkGgKb20ipCvFHX4oA7L+3Y8s2RQBsz+wo9h55Dt
iQRxoONm9biHXBUZ4EJnR4B8z0dp9j+fctTR4ds6OI3jIeKHcd4AALYIpyBnh5ue
5Iictiv0evBjcogfCttHlg/NK3TVZpq8YYOG8x+8XVrvvJ5WKtmXduZuFIL3+Wmv
jBv807a4zGLPLpB6OcD7fj/12Eo9n7d9gHZOV200rPguzt9YMIoRGgtSEEpMsvrJ
5upiFLPULj/14arXePdqZshlU01U0uE6glGJRUt7IVyU+1LbziQ8JqBlVTnRRYrb
uKDFqzmtd3zhLDPAPLkv7xLtEjYUPcFDmrf33dz22FHUGeOB0G5Ur+e9qTedfmj0
r5sHaoCspZzDcVR8sKyuUdAnRAGxJs9eIFUq2GkyxZGgfJoU2A9RMxg+YTfFfdQV
guvvPj6udOF4ugmIW1EnDXza08UyDqOITLIadNu4GqZL407JRIRtYfw48qQgL3Zo
6lqxC/3n7orkuRU/cKvHArqQt1sP7ZYzAy5N/yoY0/m3o2RV9Li7SkF2m5By8EjH
RNvQMPsipdvjWf4I+jLaAM0AEQEAAYkCNgQYAQgAIBYhBGekKjzCP5eYhvlobHUL
z+86V5VyBQJjklO7AhsMAAoJEHULz+86V5Vy6U0QAJtjybCfDAqE5DIcKkiBDbIN
erk+MTU+uOROuVigDCyvqJUuxtGaJPIRWdBQuHcQxnf6Bv1xoAeDk/7hyL7i5+rz
9vWZnSZRr4DB6pY8G5jz/HGdML4luEtuOrE5UMN8Bf5PM/9sj/c1QSuMhpAMw5TL
GoAu+MY/uDCHLb2nzwLIaCPFDTX0q5HgFQA7Do78fdxxPLqPlbg9xeTsAP5P6Egb
/8NUUa1SM4mfygriyL82nLH9SvwtnEbItovAWE+GH4XkE8xSjvWl6MpCk0+H0Xtr
WdbxtKqE7BPzs0lN3NOi+mOJABDt5ozPGfVcUsB/nqz00YiF33CQWu0ote1Q1TKn
NPOCLqFM3F1rG2z7Bf/LP9p6CpmfQGr54XmKpGinYNr8dqRtLEMVERCxGI+BuNhZ
ppQLuqOlHinKPaBO58LCwLA0uMScbmjgTQrJiXolCGHYXorCx3rcqitvMzbAcswr
wMeAXMREYKGM84Pf8fGxv+GZZwfQJHQNbOFrOTpnRITDAZvzKBD97yWkXcLGt6B7
A5iRXOI8sv9CGM3kI78b+MCcgbz8HNGF2RQipGNQZhEgL4ixbhpMaMVUuTo7BrKr
M3IeyVwUMpUBFbk5OqLsMqPbL2VvL6x1zgg4P0LmGQYoikKiwmPl/OyRQW6btWCG
1f7+w1RrcKjUANLQNjXm
=Vl9S
-----END PGP PUBLIC KEY BLOCK-----

gpg -a --export gnucode &amp;gt; gnucode.pub
sudo cp gnucode.pub /mnt/&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s backup the gpg key.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  gpg --export-secret-keys --armor gnucode &amp;gt; secret-key-backup.asc
sudo mv secret-key-backup.asc /mnt/&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If I ever need to move that gpg key to another computer, all I have to do is:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --import /path/to/secret-key-backup.asc&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s try testing a signed commit.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git config --global commit.gpgsign true&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&quot;https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key&quot;&gt;https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key&lt;/a&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;gpg --list-secret-keys --keyid-format=long

# git config --global user.signingkey MYSIGNINGKEY
git config --global alias.logs &amp;quot;log --show-signature&amp;quot;
git commit -m &amp;quot;mail.scm: minor sanitization improvements.&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok well let’s try this to see what the error was:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;GIT_TRACE=1 git commit -m &amp;quot;blah&amp;quot; -S

23:07:37.656401 git.c:460               trace: built-in: git commit -m blah -S
23:07:37.678825 run-command.c:655       trace: run_command: gpg --status-fd=2 -bsau 750BCFEF3A579572
error: gpg failed to sign the data
fatal: failed to write commit object

gpg --status-fd=2 -bsau 750BCFEF3A579572&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As I was running through the above command, I realized that, it is possible that
I did not have pinentry installed:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix install pinentry

git logs&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I think I will try rebooting and check to see if I can still sign git
commits.&lt;/p&gt;&lt;p&gt;And after I rebooted, I cannot sign commits with emacs…&lt;/p&gt;&lt;p&gt;Emacs says “hint: Waiting for your editor to close the file…”
“Waiting for Emacs”&lt;/p&gt;&lt;p&gt;Well online, I see this as a possible solution&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git config --global core.editor emacs&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well that didn’t quite work.  I was able to squash two commits, via emacs, but
only after I had the gpg agent had cached my private key password.  That makes
me think that magit is having a hard time querying my for my password.&lt;/p&gt;&lt;p&gt;Well let me try updating doom emacs.  I doubt that will work, but I’ll try it.
That didn’t work.  :(&lt;/p&gt;&lt;p&gt;Well I found a possible error here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/magit/with-editor/issues/69&quot;&gt;https://github.com/magit/with-editor/issues/69&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://emacs.stackexchange.com/questions/74097/magit-cannot-commit-emacsclient-on-path-pop-os&quot;&gt;https://emacs.stackexchange.com/questions/74097/magit-cannot-commit-emacsclient-on-path-pop-os&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://magit.vc/manual/with-editor/Configuring-With_002dEditor.html&quot;&gt;https://magit.vc/manual/with-editor/Configuring-With_002dEditor.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Then I thought, how about I disable the with-editor elisp package that doom
emacs ships and instead &lt;code&gt;guix install emacs-with-editor&lt;/code&gt;.  Let’s try that.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat .doom.d/packages.el | grep with-editor

(package! with-editor :disable t)

doom upgrade
doom sync
guix install emacs-with-editor&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nope.  That didn’t work either.  Hmmm.  I can get emacs to commit the message,
after the gpg agent caches my key’s password.&lt;/p&gt;&lt;p&gt;Well let’s try running emacs without any configuration:  &lt;code&gt;emacs -q&lt;/code&gt;.  Nope.  That
also didn’t work.  :(&lt;/p&gt;&lt;p&gt;My current theory is that my wayland only session is prohibiting the pinentry
from displaying, which is NOT allowing me to enter in my gpg password.  I shall
try temporarily enabling Xwayland and see if that fixed it.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat config | grep xwayland

# disable xwayland.  Just trying it out
xwayland enable&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Yup!  That fixed it.  With the above, I can now sign my commits with emacs!  But
I would rather keep my wayland only session.  Let’s try pinetry-bemenu:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix package -i pinentry-bemenu -r pinentry

cat config | grep xwayland

# disable xwayland.
xwayland disable&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well that didn’t work.  Let’s try pinetry-gnome3.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix package -r pinentry-bemenu -i pinentry-gnome3&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nope.  It’s X only.  Let’s try qt:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix package -r pinentry-gnome3 -i pinentry-qt&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nope.  That also seems to be X only.  grr.  Maybe this bemenu thing works, but I
need to configure it properly.&lt;/p&gt;&lt;p&gt;Well let’s install pinentry, and temporarily enable xwayland.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix package -r pinentry-tty -i pinentry

cat config | grep xwayland

# enable xwayland.
xwayland enable&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well I should probably try eventually to edit &lt;code&gt;.config/gpg.conf&lt;/code&gt; and tell it to
use pinentry-bemu as the pinentry program.&lt;/p&gt;&lt;p&gt;I think that spending all that time working on getting gpg key signing to work
was probably a big waste of time.  :(   I think instead of keeping my opensmtpd
code in guix-src/gnu/services/mail.scm, I will move it to
guixrus/services/opensmtpd.scm.  Then I can just copy opensmtpd.scm file to my
linode server, and manually load in that code to start my opensmtpd service.&lt;/p&gt;&lt;p&gt;First I will delete the opensmtpd record stuff in gnu/services/mail.scm.  I
don’t want myself getting confused where I am storing my developmental code.&lt;/p&gt;&lt;p&gt;Now I will cp my opensmtpd.scm code into my linode service git repo.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cp opensmtpd.scm ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/
ls ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm
cat ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm | tail

/home/joshua/prog/gnu/guix/guix-config/linode-guix-system-configuration/guixrus/services/opensmtpd.scm
          (service-extension pam-root-service-type
                             (const %opensmtpd-pam-services))
          (service-extension profile-service-type
                             (compose list opensmtpd-configuration-package))
          (service-extension shepherd-root-service-type
                             opensmtpd-shepherd-service)
          (service-extension setuid-program-service-type
                             opensmtpd-set-gids)))
   (description &amp;quot;Run the OpenSMTPD, a lightweight @acronym{SMTP, Simple Mail
Transfer Protocol} server.&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I will commit the changes to my linode git repo and push them.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git add opensmtpd.scm
git commit -m &amp;quot;copying opensmtpd.scm from guixrus.&amp;quot;

[master 7399550] copying opensmtpd.scm from guixrus.
 1 file changed, 7 insertions(+)
 rename opensmtpd.scm =&amp;gt; guixrus/services/opensmtpd.scm (99%)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmmm, was that commit signed?  No idea.&lt;/p&gt;&lt;p&gt;Now let’s push that commit.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let's log into the gnucode service and pull that commit.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git pull
cat opensmtpd.scm | tail

Updating a8d88b9..7399550
Fast-forward
 opensmtpd.scm =&amp;gt; guixrus/services/opensmtpd.scm | 7 +++++++
 1 file changed, 7 insertions(+)
 rename opensmtpd.scm =&amp;gt; guixrus/services/opensmtpd.scm (99%)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I am realizing that it will probably be easiest to reconfigure my server with my
opensmtpd records, if my server has the same directory structure as my local
machine. Namely my git repos are in the same directories. So I did some changes
on my server to make sure that my server's directory structure matches my local
one. Now my server’s &lt;code&gt;config.scm&lt;/code&gt; is no longer at
~/linode-guix-system-configuration/linode-locke-lamora-current-config.scm. Now
it is at:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;find . -name '*current-config.scm'

./prog/gnu/guix/guix-config/linode-guix-system-configuration/linode-locke-lamora-current-config.scm&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I want to make sure that my remote server has a copy of the guixrus source code
with my newest commit committing &lt;code&gt;services/opensmtpd.scm&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;So, I made a guixrus repo on &lt;a href=&quot;https://notabug.org/jbranso/guixrus&quot;&gt;notabug.org&lt;/a&gt;, then I pulled that repo on my server:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;git clone  https://notabug.org/jbranso/guixrus

git show HEAD | head

commit 147a9ce316be2f9f7c9ed25b3e097fd84b8b01eb
Author: Joshua Branson &amp;lt;jbranso@dismail.de&amp;gt;
Date:   Thu Dec 22 09:21:19 2022 -0500

    services (opensmtpd): add opensmtpd records to enhance opensmtpd-configuration.

    Openmstpd-configuration may only be configured by a config-file that
    uses the smtpd.conf syntax.  This patch, enables one to configure
    opensmtpd by using record types.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It would be nice to test the configuration locally, to see if it will work
before I push it to the server.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix system vm linode-locke-lamora-current-config.scm

guix system: error: (cert &amp;quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&amp;quot;) is invalid.
hint: Try a file.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above is actually a good sign.  I do not have that certificate locally, but
it is available on the server.  If that is the only error, then let’s go ahead
and try to reconfigure the server.&lt;/p&gt;&lt;p&gt;The relevant opensmtpd-service looks like:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;(service opensmtpd-service-type
         (let ([action-receive (opensmtpd-local-delivery
                                (name &amp;quot;receive&amp;quot;)
                                (method (opensmtpd-maildir
                                         (pathname &amp;quot;/home/%{rcpt.user}/Maildir&amp;quot;)
                                         (junk #t)))
                                (virtual (opensmtpd-table
                                          (name &amp;quot;vusers&amp;quot;)
                                          (data '((&amp;quot;joshua@gnucode.me&amp;quot;  . &amp;quot;joshua&amp;quot;)
                                                  (&amp;quot;jbranso@gnucode.me&amp;quot; . &amp;quot;joshua&amp;quot;)
                                                  (&amp;quot;postmaster@gnucode.me&amp;quot; .  &amp;quot;joshua&amp;quot;))))))]
               [pki-gnucode (opensmtpd-pki
                             (domain &amp;quot;smtp.gnucode.me&amp;quot;)
                             (cert &amp;quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&amp;quot;)
                             (key &amp;quot;/etc/letsencrypt/live/gnucode.me/privkey.pem&amp;quot;))]
               [filter-dkimsign (opensmtpd-filter
                                 (name &amp;quot;dkimsign&amp;quot;)
                                 (exec #t)
                                 (proc (list (file-append opensmtpd-filter-dkimsign &amp;quot;/libexec/opensmtpd/filter-dkimsign&amp;quot;)
                                             &amp;quot; -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k &amp;quot;
                                             &amp;quot;/etc/dkim/private.key &amp;quot;
                                             &amp;quot;user nobody group nogroup&amp;quot;)))]
               [table-creds (opensmtpd-table
                             (name &amp;quot;creds&amp;quot;)
                             (data
                              (list
                               (cons &amp;quot;joshua&amp;quot;
                                     &amp;quot;$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86.&amp;quot;))))])
           (opensmtpd-configuration
            (interfaces
             (list
              ;; this forum help suggests that I listen on 0.0.0.0 and NOT eth0
              ;; https://serverfault.com/questions/726795/opensmtpd-wont-work-at-reboot
              ;; this listens for email from the outside world
              (opensmtpd-interface
               (interface &amp;quot;eth0&amp;quot;)
               (port 25)
               (secure-connection &amp;quot;tls&amp;quot;)
               (pki pki-gnucode))
              ;; this lets local users logged into the system via ssh send email
              (opensmtpd-interface
               (interface &amp;quot;lo&amp;quot;)
               (port 25)
               (secure-connection &amp;quot;tls&amp;quot;)
               (pki pki-gnucode))
              (opensmtpd-interface
               (interface &amp;quot;eth0&amp;quot;)
               (port 465)
               (secure-connection &amp;quot;smtps&amp;quot;)
               (pki pki-gnucode)
               (auth table-creds)
               (filters (list filter-dkimsign)))
              (opensmtpd-interface
               (interface &amp;quot;eth0&amp;quot;)
               (port 587)
               (secure-connection &amp;quot;tls-require&amp;quot;)
               (pki pki-gnucode)
               (auth table-creds)
               (filters (list filter-dkimsign)))))
            (matches (list
                      (opensmtpd-match
                       (action (opensmtpd-relay
                                (name &amp;quot;relay&amp;quot;)))
                       (options
                        (list
                         (opensmtpd-option
                          (option &amp;quot;for any&amp;quot;))
                         (opensmtpd-option
                          (option &amp;quot;from any&amp;quot;))
                         (opensmtpd-option
                          (option &amp;quot;auth&amp;quot;)))))
                      (opensmtpd-match
                       (action action-receive)
                       (options
                        (list
                         (opensmtpd-option
                          (option &amp;quot;from any&amp;quot;))
                         (opensmtpd-option
                          (option &amp;quot;for domain&amp;quot;)
                          (data (opensmtpd-table
                                 (name &amp;quot;vdoms&amp;quot;)
                                 (data (list &amp;quot;gnucode.me&amp;quot;
                                             &amp;quot;gnu-hurd.com&amp;quot;))))))))
                      (opensmtpd-match
                       (action action-receive)
                       (options
                        (list
                         (opensmtpd-option
                          (option &amp;quot;for local&amp;quot;))))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I was curious to see how outdated my server is.  It’s dated apparently.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix system describe

[1mGeneration 118  Aug 14 2022 02:45:18[0m    (current)
  file name: /var/guix/profiles/system-118-link
  canonical file name: /gnu/store/7jkrafkf61bw3fdxlrlzvkrl98ys1icj-system
  label: GNU with Linux-Libre 5.18.16
  bootloader: grub
  root device: /dev/sda
  kernel: /gnu/store/iz6xn1b1dyk6pwaf6dym3jm3vwnh4gz9-linux-libre-5.18.16/bzImage
  channels:
    guix:
      repository URL: https://git.savannah.gnu.org/git/guix.git
      branch: master
      commit: 43decd1f7ea4ebd911199ad10c0ca555d0dffbd6
  configuration file: /gnu/store/rv7rhwn5kd9yxv8kayqlsgxwyhcz55ca-configuration.scm&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let's try reconfiguring my server with the opensmtpd configuration.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;guix pull
sudo guix system reconfigure linode-locke-lamora-current-config.scm

In srfi/srfi-1.scm:
   586:29 19 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
   586:29 18 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
   586:29 17 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
   586:29 16 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
   586:29 15 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type mingetty 7f8…&amp;gt; …))
   586:29 14 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type agetty 7f8c1…&amp;gt; …))
   586:29 13 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type syslog 7f8c1…&amp;gt; …))
   586:29 12 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type console-font…&amp;gt; …))
   586:29 11 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type virtual-term…&amp;gt; …))
   586:17 10 (map1 (#&amp;lt;&amp;lt;service&amp;gt; type: #&amp;lt;service-type opensmtpd 7f…&amp;gt; …))
In guixrus/services/opensmtpd.scm:
  2567:27  9 (opensmtpd-shepherd-service #&amp;lt;&amp;lt;opensmtpd-configuration&amp;gt;…&amp;gt;)
  2541:19  8 (opensmtpd-configuration-&amp;gt;mixed-text-file #&amp;lt;&amp;lt;opensmtpd-…&amp;gt;)
   2496:3  7 (opensmtpd-configuration-&amp;gt;string #&amp;lt;&amp;lt;opensmtpd-configura…&amp;gt;)
   2421:9  6 (opensmtpd-configuration-fieldname-&amp;gt;string #&amp;lt;&amp;lt;opensmtp…&amp;gt; …)
  2430:10  5 (list-of-records-&amp;gt;string (#&amp;lt;&amp;lt;opensmtpd-interface&amp;gt; i…&amp;gt; …) …)
  2434:17  4 (loop (#&amp;lt;&amp;lt;opensmtpd-interface&amp;gt; interface: &amp;quot;eth0&amp;quot; fam…&amp;gt; …))
   1848:5  3 (opensmtpd-interface-&amp;gt;string #&amp;lt;&amp;lt;opensmtpd-interface&amp;gt; in…&amp;gt;)
In unknown file:
           2 (string-append &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;&amp;quot; &amp;quot;tls &amp;quot; #&amp;lt;unspecified&amp;gt; &amp;quot;p…&amp;quot; …)
In ice-9/boot-9.scm:
  1685:16  1 (raise-exception _ #:continuable? _)
  1685:16  0 (raise-exception _ #:continuable? _)

ice-9/boot-9.scm:1685:16: In procedure raise-exception:
In procedure string-append: Wrong type (expecting string): #&amp;lt;unspecified&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ahh, I know what that problem is!  Let’s fix that.  So now I have make a local
commit.  Push it to my notabug.org/guixrus, ssh into lamora, run &lt;code&gt;git pull&lt;/code&gt; on
the guixrus repo, then try to reconfigure.  This seems like a very odd/poor way
to test changes.  By making a commit locally, pushing it, pulling it, and then
wondering if the reconfigure will work.  I should really set up guix deploy.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure linode-locke-lamora-current-config.scm

 module-import-compiled  1.0MiB                                         1.6MiB/s 00:01 [##################] 100.0%
building /gnu/store/mw8x4pbl11a5pdgxqcw2vvczdccpmicf-switch-to-system.scm.drv...
making '/gnu/store/0v5sbvlx9r151gjlc906lxyhps7xx1h8-system' the current system...
setting up setuid programs in '/run/setuid-programs'...
populating /etc from /gnu/store/1n0l349b03h7dclwai9l0kxglb8kwyv0-etc...
checking syntax of /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf
/gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf:14: syntax error
/gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf:21: no such dispatcher: relay&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so I have a configuration error.  Let’s take a look at the generated
configuration file:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The first error is this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf | grep '&amp;lt;&amp;quot;&amp;lt;&amp;quot;'

listen on eth0 filter &amp;quot;dkimsign&amp;quot; smtps port 465 pki smtp.gnucode.me auth &amp;lt;&amp;quot;&amp;lt;&amp;quot;creds&amp;quot;&amp;gt;&amp;quot;&amp;gt;
listen on eth0 filter &amp;quot;dkimsign&amp;quot; tls-require port 587 pki smtp.gnucode.me auth &amp;lt;&amp;quot;&amp;lt;&amp;quot;creds&amp;quot;&amp;gt;&amp;quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It should be &amp;lt;“creds”&amp;gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Another error is this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /gnu/store/51hahfmqlkj9jfxa2cqbm6dd05qrzxzd-smtpd.conf  | grep match

match !for any !from any !auth action &amp;quot;relay&amp;quot;
match !from any !for domain &amp;lt;&amp;quot;vdoms&amp;quot;&amp;gt; action &amp;quot;receive&amp;quot;
match !for local action &amp;quot;receive&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;These match options should NOT be false. Let's quickly fix those issues
reconfigure again:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure linode-locke-lamora-current-config.scm

checking syntax of /gnu/store/a69a5vn2r94glh58wlfq41ygfl38ikgn-smtpd.conf
configuration OK&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That’s a good sign!&lt;/p&gt;&lt;p&gt;Let’s reboot and see what happens!&lt;/p&gt;&lt;p&gt;Well when I reboot, smtpd refused to start.  Let’s look at the config file.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /gnu/store/a69a5vn2r94glh58wlfq41ygfl38ikgn-smtpd.conf

filter &amp;quot;dkimsign&amp;quot; proc-exec &amp;quot;/gnu/store/n2f5waxzdzcsdvh0xydhnc174n3kingw-opensmtpd-filter-dkimsign-0.6/libexec/opensmtpd/filter-dkimsign -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k /etc/dkim/private.key user nobody group nogroup&amp;quot;

mta max-deferred 100

table &amp;quot;creds&amp;quot; { &amp;quot;joshua&amp;quot; = &amp;quot;$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86.&amp;quot; }
table &amp;quot;vusers&amp;quot; { &amp;quot;joshua@gnucode.me&amp;quot; = &amp;quot;joshua&amp;quot;, &amp;quot;jbranso@gnucode.me&amp;quot; = &amp;quot;joshua&amp;quot;, &amp;quot;postmaster@gnucode.me&amp;quot; = &amp;quot;joshua&amp;quot; }
table &amp;quot;vdoms&amp;quot; { &amp;quot;gnucode.me&amp;quot;, &amp;quot;gnu-hurd.com&amp;quot; }

pki smtp.gnucode.me cert &amp;quot;/etc/letsencrypt/live/gnucode.me/fullchain.pem&amp;quot;
pki smtp.gnucode.me key &amp;quot;/etc/letsencrypt/live/gnucode.me/privkey.pem&amp;quot;

listen on eth0 tls port 25 pki smtp.gnucode.me
listen on lo tls port 25 pki smtp.gnucode.me
listen on eth0 filter &amp;quot;dkimsign&amp;quot; smtps port 465 pki smtp.gnucode.me auth &amp;lt;&amp;quot;creds&amp;quot;&amp;gt;
listen on eth0 filter &amp;quot;dkimsign&amp;quot; tls-require port 587 pki smtp.gnucode.me auth &amp;lt;&amp;quot;creds&amp;quot;&amp;gt;

action &amp;quot;relay&amp;quot; relay

action &amp;quot;receive&amp;quot; maildir &amp;quot;/home/%{rcpt.user}/Maildir&amp;quot; junk virtual &amp;lt;&amp;quot;vusers&amp;quot;&amp;gt;

match for any from any auth action &amp;quot;relay&amp;quot;
match from any for domain &amp;lt;&amp;quot;vdoms&amp;quot;&amp;gt; action &amp;quot;receive&amp;quot;
match for local action &amp;quot;receive&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It seems to be just fine...hmmm.  What does the error log say?&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /var/log/maillog | tail

Dec 22 10:05:41 localhost smtpd[19325]: warn: lost processor: dkimsign exited abnormally
Dec 22 10:05:41 localhost smtpd[19328]: dkimsign: Can't open key file (/etc/dkim/private.key): No such file or directory
Dec 22 10:05:41 localhost smtpd[19330]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
Dec 22 10:05:41 localhost smtpd[19325]: Exiting
Dec 22 11:22:18 localhost smtpd[268]: info: OpenSMTPD 6.8.0p2 starting
Dec 22 11:22:18 localhost smtpd[269]: warn: lost processor: dkimsign exited abnormally
Dec 22 11:22:18 localhost smtpd[272]: dkimsign: Can't open key file (/etc/dkim/private.key): No such file or directory
Dec 22 11:22:18 localhost smtpd[274]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
Dec 22 11:22:18 localhost smtpd[269]: Exiting&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, well I think I found the problem. haha.  Let’s see, ah, looks like that key
is here:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;find . -name '*key'

/etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s commit my current-config locally, push it upstream, pull it from my server
and reconfigure.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo guix system reconfigure linode-locke-lamora-current-config.scm

checking syntax of /gnu/store/42q90z8n03zi9rx29gwdnms4sdr2g2p9-smtpd.conf
configuration OK&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After I rebooted, smtpd still was not starting.  Let’s try to find out why:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /var/log/maillog | tail

Dec 22 11:38:03 localhost smtpd[498]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
Dec 22 11:38:03 localhost smtpd[493]: warn: lost processor: dkimsign exited abnormally
Dec 22 11:38:03 localhost smtpd[496]: dkimsign: Can't open key file (/etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key): Permission denied
Dec 22 11:38:03 localhost smtpd[493]: Exiting
Dec 22 11:40:02 localhost dovecot: master: Dovecot v2.3.19.1 (9b53102964) starting up for imap (core dumps disabled)
Dec 22 11:42:41 localhost smtpd[258]: info: OpenSMTPD 6.8.0p2 starting
Dec 22 11:42:41 localhost smtpd[259]: warn: lost processor: dkimsign exited abnormally
Dec 22 11:42:41 localhost smtpd[262]: dkimsign: Can't open key file (/etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key): Permission denied
Dec 22 11:42:41 localhost smtpd[264]: warn: invalid envelope a565cee5a763bf31: unknown dispatcher
Dec 22 11:42:41 localhost smtpd[259]: Exiting&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, this is just a permissions error.  That’s an easy fix!  I changed a
&lt;code&gt;sudo chown -R smtpd /etc/opensmtpd&lt;/code&gt;.  Then I got this beauty:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo herd start smtpd

Service smtpd has been started.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Woo hoo!  Now let’s try to send an email and see if it works!&lt;/p&gt;&lt;p&gt;I sent an email to gmail, and if you select an email in gmail, you can click on
view original.  It showed me that I did pass dkimsigning!  That’s awesome!  And
my email was in my gmail inbox.  That’s a really good sign!  Now I am off to
submit a patch to guixrus!&lt;/p&gt;&lt;p&gt;I did get a tip from someone on irc that mentioned that I should verify my
dkimsigning and SPF via https://dkimvalidator.com/ And when I used that tool, I
discovered that my SPF was failing, so I will need to fix that.&lt;/p&gt;</content></entry><entry><title>Simple Mispelling Problem</title><id>https://gnucode.me/simple-mispelling-problem.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-11-22T11:00:00Z</updated><link href="https://gnucode.me/simple-mispelling-problem.html" rel="alternate" /><content type="html">&lt;p&gt;Edit: Yes I am aware that I misspelled &amp;quot;mispelling&amp;quot;. I figure it's funny if I
leave it as it is. :)&lt;/p&gt;&lt;p&gt;I had this simple coding problem that I wanted to solve.  Here's the problem:&lt;/p&gt;&lt;p&gt;Suppose you are writing an guix service &lt;a href=&quot;https://notabug.org/jbranso/guix/src/newOpensmtpdBranch/gnu/services/mail.scm&quot;&gt;(like I happen to be)&lt;/a&gt;, and you are
sanitizing user input for various records.  Suppose your user mispells an
option.  Wouldn't it be nice to include a nice helpful hint on what he probably
did wrong?&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(opensmtpd-option (option &amp;quot;forany&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;error: (option &amp;quot;forany&amp;quot;) is invalid.
hint: Try &amp;quot;for rcpt-to&amp;quot;, &amp;quot;for domain&amp;quot;, &amp;quot;for local&amp;quot;, &amp;quot;for any&amp;quot;, or &amp;quot;for&amp;quot;.&lt;/p&gt;&lt;p&gt;Using &lt;code&gt;string-prefix-length-ci&lt;/code&gt;, I was able to construct a fairly naive
prococedure that tries to guess what the user meant to type.  Here's what I came
up with:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;;; if strings is (list &amp;quot;auth&amp;quot; &amp;quot;for any&amp;quot; &amp;quot;from local&amp;quot;)
;; Then this will return &amp;quot;Try \&amp;quot;auth\&amp;quot;, \&amp;quot;for any\&amp;quot;, or \&amp;quot;from local\&amp;quot;.&amp;quot;
(define (try-string strings)
  (string-append &amp;quot;Try &amp;quot;
                 (let loop ((strings strings))
                   (cond ((= 1 (length strings))
                          (string-append
                           &amp;quot;or \&amp;quot;&amp;quot; (car strings) &amp;quot;\&amp;quot;.\n&amp;quot;))
                         (else
                          (string-append
                           &amp;quot;\&amp;quot;&amp;quot; (car strings) &amp;quot;\&amp;quot;, &amp;quot;
                           (loop (cdr strings))))))))

;; suppose string is &amp;quot;for anys&amp;quot;
;; and strings is (list &amp;quot;for any&amp;quot; &amp;quot;for local&amp;quot; &amp;quot;for domain&amp;quot;)
;; then hint-string will return &amp;quot;Did you mean &amp;quot;for any&amp;quot;?&amp;quot;
(define* (hint-string string strings
                      #:key (fieldname #f))
  (if (not (string? string))
      (try-string strings)
      (let loop ((current-max 1)
                 (loop-strings strings)
                 (hint-strings '()))
        (if (null? loop-strings)
            (cond ((= 1 (length hint-strings)) ;; only one worthwhile match
                   (if fieldname
                       (string-append &amp;quot;Did you mean (&amp;quot; fieldname &amp;quot; \&amp;quot;&amp;quot;
                                      (car hint-strings) &amp;quot;\&amp;quot;) ?\n&amp;quot;)
                       (string-append &amp;quot;Did you mean \&amp;quot;&amp;quot; (car hint-strings)
                                      &amp;quot;\&amp;quot;?\n&amp;quot;)))
                  (else (if (null? hint-strings)
                            (try-string strings)
                            (try-string hint-strings))))
            (let* ((element-string (car loop-strings))
                   (element-max
                    (string-prefix-length-ci element-string string)))
              (cond ((&amp;gt; element-max current-max)
                     (loop element-max (cdr loop-strings)
                           (list element-string)))
                    ((= element-max current-max)
                     (loop current-max (cdr loop-strings)
                           (cons element-string hint-strings)))
                    (else (loop current-max
                                (cdr loop-strings) hint-strings))))))))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It won't recognize that &amp;quot;or any&amp;quot; or &amp;quot;bor any&amp;quot; should match &amp;quot;for any&amp;quot;, but for
most mispellings, it should be half decent, provided the user got the first
character right.&lt;/p&gt;&lt;p&gt;What do you all think?  How would you write such a procedure?&lt;/p&gt;&lt;p&gt;EDIT: Well it turns out that the guix developers actually have a
(string-closest) procedure.  The relevant code can be found in
(guix utils) and (guix combinators):&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;(define fold2
  (case-lambda
    ((proc seed1 seed2 lst)
     &amp;quot;Like `fold', but with a single list and two seeds.&amp;quot;
     (let loop ((result1 seed1)
                (result2 seed2)
                (lst     lst))
       (if (null? lst)
           (values result1 result2)
           (call-with-values
               (lambda () (proc (car lst) result1 result2))
             (lambda (result1 result2)
               (loop result1 result2 (cdr lst)))))))
    ((proc seed1 seed2 lst1 lst2)
     &amp;quot;Like `fold', but with two lists and two seeds.&amp;quot;
     (let loop ((result1 seed1)
                (result2 seed2)
                (lst1    lst1)
                (lst2    lst2))
       (if (or (null? lst1) (null? lst2))
           (values result1 result2)
           (call-with-values
               (lambda () (proc (car lst1) (car lst2) result1 result2))
             (lambda (result1 result2)
               (loop result1 result2 (cdr lst1) (cdr lst2)))))))))

(define (string-distance s1 s2)
  &amp;quot;Compute the Levenshtein distance between two strings.&amp;quot;
  ;; Naive implemenation
  (define loop
    (mlambda (as bt)
      (match as
        (() (length bt))
        ((a s ...)
         (match bt
           (() (length as))
           ((b t ...)
            (if (char=? a b)
                (loop s t)
                (1+ (min
                     (loop as t)
                     (loop s bt)
                     (loop s t))))))))))

  (let ((c1 (string-&amp;gt;list s1))
        (c2 (string-&amp;gt;list s2)))
    (loop c1 c2)))

(define* (string-closest trial tests #:key (threshold 3))
  &amp;quot;Return the string from TESTS that is the closest from the TRIAL,
according to 'string-distance'.  If the TESTS are too far from TRIAL,
according to THRESHOLD, then #f is returned.&amp;quot;
  (identity                              ;discard second return value
    (fold2 (lambda (test closest minimal)
             (let ((dist (string-distance trial test)))
               (if (and  (&amp;lt; dist minimal) (&amp;lt; dist threshold))
                   (values test dist)
                   (values closest minimal))))
           #f +inf.0
           tests)))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A lot of the above code is a little bit above my head, but it sure looks cool.&lt;/p&gt;&lt;p&gt;And it actually works better than mine.:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-scheme&quot;&gt;;; old scheme code
(display (hint-string &amp;quot;bor any&amp;quot; (list &amp;quot;for any&amp;quot; &amp;quot;auth&amp;quot; &amp;quot;rdns&amp;quot;)))

Try &amp;quot;for any&amp;quot;, &amp;quot;auth&amp;quot;, or &amp;quot;rdns&amp;quot;.

;; It didn't match any string.  :(

;; Let's try guix's (string-closest _) ...

(string-closest &amp;quot;bor any&amp;quot; (list &amp;quot;for any&amp;quot; &amp;quot;auth&amp;quot; &amp;quot;rdns&amp;quot;))

$1 = &amp;quot;for any&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Awesome!&lt;/p&gt;</content></entry><entry><title>Doom Emacs rocks!</title><id>https://gnucode.me/doom-emacs-rocks.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-11-15T13:00:00Z</updated><link href="https://gnucode.me/doom-emacs-rocks.html" rel="alternate" /><content type="html">&lt;p&gt;I have been using Doom emacs for about 6 months now, and I must say the
experience is truly wonderful!  It is hands down the best Emacs distribution
that I have ever used.  And it is &lt;em&gt;sooo fast&lt;/em&gt;!&lt;/p&gt;&lt;p&gt;I used to own my own emacs config, which is something that everyone should do at
some point to help you learn more about emacs, but maintaining your own emacs
config is really hard.  You have to:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Fix any bugs that you have. &lt;a href=&quot;https://elpa.gnu.org/packages/bug-hunter.html&quot;&gt;bug hunter is really helpful for this&lt;/a&gt;&lt;/li&gt;&lt;li&gt;examine any cool packages that you may want to add.&lt;/li&gt;&lt;li&gt;Keep up to date with new packages that are probably better than the packages
that you are using.&lt;/li&gt;&lt;li&gt;Update packages and deal with any new bugs they introduce.&lt;/li&gt;&lt;li&gt;Stay sane with all the complexity.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I did the above for some time, and it is doable.  I maintained my own Emacs for
so long, because it was one of the few coding projects that I actively used and
worked on.  The problem was that my config’s stability varied week to week, and
it made it harder to focus on actually helping &lt;a href=&quot;https://guix.gnu.org&quot;&gt;GNU Guix&lt;/a&gt;.  At a certain point I
decided that I would rather let someone else maintain a config, so that I could
spend more time helping a free software project.&lt;/p&gt;&lt;p&gt;I also realized that since I use Doom emacs so often, and it is in need of
&lt;a href=&quot;https://liberapay.com/hlissner&quot;&gt;funding,&lt;/a&gt; that I should probably go ahead and chip in.  I highly reccommend you
to check out Doom Emacs, and consider donating.  Currently the maintainer of
Doom can only allocate 12 hours per week on the project, but hopefully the
community will be able to support his work full time.&lt;/p&gt;</content></entry><entry><title>PinePhone Update</title><id>https://gnucode.me/pinephone-update.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-11-02T12:40:00Z</updated><link href="https://gnucode.me/pinephone-update.html" rel="alternate" /><content type="html">&lt;p&gt;When I was using Mobian GNU/Linux, I had some issues with the PinePhone. Namely,
my phone no longer received SMS text messages. I switched to &lt;a href=&quot;https://postmarketos.org/&quot;&gt;PostMarketOS&lt;/a&gt;, and
my issues seemed to have gone away, at least if I keep using the phone as a dumb
phone.  I have disabled wifi on the phone, because I really don’t use it.&lt;/p&gt;&lt;p&gt;It would be nice if I could get the PinePhone to work well with &lt;a href=&quot;https://jmp.chat&quot;&gt;JMP.chat&lt;/a&gt;, but
currently the texts from my desktop machine do NOT sync well with the phone.  So
if I use two devices, I end up in a weird situation with out of sync text
messages, which is really confusing.  Plus using the internet on the phone
drains the battery.  So I have just disabled the internet on the phone via the
hardware kill switches.&lt;/p&gt;&lt;p&gt;Texting works flawlessly, but I cannot get SMS images.  Also the phone volume
for calls is pretty poor.  And sometimes when I make phone calls, I cannot hear
what the other person is saying.  So that is a little odd.&lt;/p&gt;&lt;p&gt;I highly recommend installing the reversed engineered and nearly &lt;a href=&quot;https://github.com/the-modem-distro/pinephone_modem_sdk&quot;&gt;libre custom
firmware&lt;/a&gt; for the PinePhone’s modem. It was actually &lt;a href=&quot;https://www.youtube.com/watch?v=aokclNgnIbE&quot;&gt;super easy to do&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;It might also not be a bad idea to edit the official PinePhone wiki and mention
that &lt;a href=&quot;https://tello.com/&quot;&gt;Tello&lt;/a&gt; is a fairly cheap provider. I pay them $8 per month and I have no
data and unlimited calling and texting texts.  That’s pretty good.&lt;/p&gt;&lt;p&gt;That’s the main update for today!&lt;/p&gt;</content></entry><entry><title>Installing OpenBSD on a VM</title><id>https://gnucode.me/installing-openbsd-on-a-vm.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-08-05T07:00:00Z</updated><link href="https://gnucode.me/installing-openbsd-on-a-vm.html" rel="alternate" /><content type="html">&lt;p&gt;I am of the opinion, that in order to learn how to use an operating system, you
have to use it often.  Since I am madly in love with Guix System, but have an
interest in the GNU/Hurd and OpenBSD, I might as well install those OSs on a
virtual machine!  I have already done that with the GNU/Hurd, and today I also
did it for OpenBSD.&lt;/p&gt;&lt;p&gt;I was not that hard to do.  I used this guide to &lt;a href=&quot;https://wiki.qemu.org/index.php/Hosts/BSD#OpenBSD&quot;&gt;install OpenBSD on a vm.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;First let’s create a qemu img for OpenBSD.&lt;/p&gt;&lt;p&gt;&lt;code&gt;qemu-img create -f qcow2 hd0.qcow2.img 100G&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Now, let's create an install script.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat install-bsd.sh

#!/bin/sh

qemu-system-x86_64 -m 2048 \
  -no-reboot \
  -cdrom cd71.iso \
  -drive if=virtio,file=hd0.qcow2.img,format=qcow2 \
  -enable-kvm \
  -netdev user,id=mynet0,hostfwd=tcp:127.0.0.1:7922-:22 \
  -device virtio-net,netdev=mynet0 \
  -smp 2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As always installing OpenBSD is an absolute breeze.  I do not know how to
manually partition things, so I just chose the auto install.  Also OpenBSD
supports a &lt;code&gt;us.swapcaps.dvorak&lt;/code&gt; keyboard layout.  That’s my layout!  How cool is
that!?  And it sets up that layout for the console and X by default.  Guix
System does that, but not so well for wayland.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat run-bsd.sh&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let's create a run script.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;#!/bin/sh

qemu-system-x86_64 -m 4G \
  -no-reboot \
  -drive if=virtio,file=hd0.qcow2.img,format=qcow2 \
  -enable-kvm \
  -netdev user,id=mynet0,hostfwd=tcp:127.0.0.1:7922-:22 \
  -device virtio-net,netdev=mynet0 \
  -smp 2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I find the &lt;code&gt;-no-reboot&lt;/code&gt; option helpful, because OpenBSD likes to try to autoreboot
itself, even when you give it the command: &lt;code&gt;halt&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;I have ran OpenBSD before for about a week before, and it is always a pleasure
to read man afterboot.  With OpenBSD the man pages are absolutely excelent.&lt;/p&gt;&lt;p&gt;One of the first things I did was:&lt;/p&gt;&lt;p&gt;&lt;code&gt;# cp /etc/examples/doas.conf /etc/&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Now my user &lt;code&gt;berno&lt;/code&gt; can use &lt;code&gt;doas&lt;/code&gt; to install packages!  Let’s install Emacs!&lt;/p&gt;&lt;p&gt;&lt;code&gt;doas pkg_add emacs&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Also OpenBSD has a habit of printing clues to the console after you type in a
command. For examle, after you install a package, OpenBSD tells you that it has
installed README files in &lt;code&gt;/usr/local/bsah/blah/README/emacs/&lt;/code&gt;. I find it really
cool that it reminds you of this.  Also, when you run &lt;code&gt;doas syspatch&lt;/code&gt; it will
tell you that it updated syspatch.  It  will also say something like:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Please run syspatch again to apply the patches.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;That’s a handy tip!  And indeed, &lt;code&gt;doas syspatch -c&lt;/code&gt; showed that the patches had
not yet been applied.&lt;/p&gt;&lt;p&gt;Also whilst searching for the internet for how to install OpenBSD on a vm image,
I came accross &lt;a href=&quot;https://www.skreutz.com/posts/autoinstall-openbsd-on-qemu/&quot;&gt;blog post&lt;/a&gt; that describes that you can automate OpenBSD installs.
That might be something to play with later!&lt;/p&gt;&lt;p&gt;I would like to also set up my local OpenBSD to set up ssh.  That way I could do
something like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;#+BEGIN_SRC shell :dir /ssh:berno@localhost:/home/berno  :exports both
ls | wc -l
#+END_SRC

#+RESULTS:
: 9&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I also think it would be fabulous if the OpenBSD team started to make a
guix-like package manager/distro.  I imagine that they could use perl to do it,
since it seems like OpenBSD has embraced perl as their scripting language, and I
think it their man pages show that perl can use some rather low lever operating
system interfaces.&lt;/p&gt;</content></entry><entry><title>Status Update July 2022</title><id>https://gnucode.me/status-update-july-2022.html</id><author><name>Joshua Branson</name><email>jbranso@dismail.de</email></author><updated>2022-08-02T13:00:00Z</updated><link href="https://gnucode.me/status-update-july-2022.html" rel="alternate" /><content type="html">&lt;p&gt;So I recently bought a guix system server! It cost me about $250. It’s got 16GB
of RAM (I can upgrade to 32GB) with a 4TB harddrive. I may play with RAID at
some point, but that’s a little down the line. If you want some help getting
something like this for yourself, please contact me. This blog post is my first
attempt at trying to figure out how to connect to &lt;code&gt;copertino&lt;/code&gt;, to the
internet.  Now on with the blog post!&lt;/p&gt;&lt;p&gt;So when you are like me, and you start to wonder how the internets work, a good
thing to learn first is difference between &lt;strong&gt;WAN&lt;/strong&gt; and &lt;strong&gt;LAN&lt;/strong&gt;. LAN is your local area
network. When you are at home, on your computer, you are on your LAN. If your
computer talks to another computer in your house, then those machines are using
the LAN. When your computer talks to &lt;code&gt;www.gnu.org&lt;/code&gt;, your computer is accessing
the WAN, which is the wide area network, usually called the internet.&lt;/p&gt;&lt;p&gt;Computers talk to each other via IP addresses.  An IP address is a numerical ID
that is unique to each computer.  Computers use IP address as essentially phone
numbers to reach out and say, “Hey what time are we having this binary number
crunching date?”  What’s interesting, is computers have more than just a phone
number, they have a phone number, plus several extensions.&lt;/p&gt;&lt;p&gt;When you call a business, and they say, “Thanks for calling Bank of Scotland.
Please press 5 to talk to a manager, 4 to talk to a sales person, and 3 to open
an account.  Thanks!”  5, 4, and 3 are extensions.  Computers have the same
thing, on steroids.  They calls extensions ports, and there are like 50,000+
ports.  Ports are usually set up to be used by specific applications.  For
example, your web browser uses port 80 and 443 to visit websites.&lt;/p&gt;&lt;p&gt;Here’s a crazy example.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ping -c 1 gnu.org&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;PING gnu.org (209.51.188.116): 56 data bytes
64 bytes from 209.51.188.116: icmp&amp;lt;sub&amp;gt;seq&amp;lt;/sub&amp;gt;=0 ttl=55 time=39.078 ms
— gnu.org ping statistics —
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 39.078/39.078/39.078/0.000 ms&lt;/p&gt;&lt;p&gt;So, we now know that gnu.org is serving it’s website on 209.51.188.116.  Try
posting this in a web browser url:  209.51.188.116.  You’ll end up at
savannah.nongnu.org, which is a website that the fabulous people at GNU run.&lt;/p&gt;&lt;p&gt;Anyway, let’s take a look at your IP address:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ip address show&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;1: lo: &amp;lt;LOOPBACK,MULTICAST,UP,LOWER&amp;lt;sub&amp;gt;UP&amp;lt;/sub&amp;gt;&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope global lo
valid&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; forever preferred&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; forever
2: enp0s25: &amp;lt;BROADCAST,MULTICAST,UP,LOWER&amp;lt;sub&amp;gt;UP&amp;lt;/sub&amp;gt;&amp;gt; mtu 1500 qdisc pfifo&amp;lt;sub&amp;gt;fast&amp;lt;/sub&amp;gt; state UP group default qlen 1000
link/ether 00:1c:25:9a:37:ba brd ff:ff:ff:ff:ff:ff
inet 192.168.1.122/24 brd 192.168.1.255 scope global dynamic noprefixroute enp0s25
valid&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; 22986sec preferred&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; 22986sec
inet6 fe80::36a7:f91e:a1e0:16fe/64 scope link noprefixroute
valid&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; forever preferred&amp;lt;sub&amp;gt;lft&amp;lt;/sub&amp;gt; forever
3: wlp2s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether b6:cf:27:17:7c:fc brd ff:ff:ff:ff:ff:ff permaddr e4:ce:8f:59:d6:bf&lt;/p&gt;&lt;p&gt;Let’s take the above output line by line:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;1: lo: &amp;lt;LOOPBACK,MULTICAST,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet *127.0.0.1/8* scope global lo
       valid_lft forever preferred_lft forever


lo is your loopback device, which is fancy talk for &amp;quot;ME&amp;quot;. The embolded
*127.0.0.1* is a universal alias for &amp;quot;ME&amp;quot;. If you have a web site running on
your computer, typing in 127.0.0.1:80 lets you access that website. 127.0.0.1:80
means, talk to the computer at address 127.0.0.1 (which is me), and request the
content on port 80.

2: *enp0s25*: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:1c:25:9a:37:ba brd ff:ff:ff:ff:ff:ff
    *inet* *192.168.1.122/24* brd 192.168.1.255 scope global dynamic noprefixroute enp0s25
       valid_lft 22986sec preferred_lft 22986sec
    *inet6* *fe80::36a7:f91e:a1e0:16fe/64* scope link noprefixroute
       valid_lft forever preferred_lft forever

*enp0s25* is your ethernet device.  Anything that begins with an 'e' is usually
 an ethernet device.  Ethernet is usually the blue cable that you
 plug into your laptop or server.  Laptops increasingly do not have ethernet,
 which is sad 'cause ethernet is faster than wifi.


*init* means IPv4. Remember when I said that computers have IP address? Well
than have one that looks like *192.168.1.122*. That is the IPv4 address. People
now adays have phones, tablets, gaming consoles, smart watches, etc. and each
need an IP address. As a result, the IPv4 address space is getting a little
crowded. So some smart people introduced IPv6, which has much more unique IDs.
(Keep reading to see an example IPv6 address).


Unfortunately for me, an IP address of 192.168.number.number is a LAN IP. That
means I have to be in my house to talk to view my personal website. I cannot
view that website at work. :(


*init6* is IPv6. And *fe80::36a7:f91e:a1e0:16fe* is this computer's IPv6
 address. fe80 is also a LAN IPv6 address. The outside world cannot use that
 address to talk to this local computer.

3: *wlp2s0*: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether b6:cf:27:17:7c:fc brd ff:ff:ff:ff:ff:ff permaddr e4:ce:8f:59:d6:bf

This is my wifi device.  Anything that begins with an 'w' is usually a wifi device.

ip route&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;default via 192.168.1.1 dev enp0s25 proto dhcp metric 100
192.168.1.0/24 dev enp0s25 proto kernel scope link src 192.168.1.122 metric 100&lt;/p&gt;&lt;p&gt;The number after &lt;strong&gt;default&lt;/strong&gt; is the default gateway. That is my router’s LAN IP
address. If I type that into a web browser, when I am at home, then I can log
into my router. Usually your router’s username and password is on a stick on the
back of your router.&lt;/p&gt;&lt;p&gt;Also, it should be possible for me to log into the router and tell it to open up
ports 80 and 443 (http and https), so that anyone connecting to say
&lt;code&gt;www.copertino.me&lt;/code&gt; would be connecting to my computer only, AND NOT my
roommates’ laptop. However, an attacker could still potentially break into my
guix system computer, and attack my roommate’s computer.&lt;/p&gt;&lt;p&gt;Also, if you decide to play around with customizing your router, I would
recommend OpenBSD. OpenBSD potentially has some binary blobs for wifi, which is
why the &lt;a href=&quot;https://www.gnu.org/distros/free-distros.en.html&quot;&gt;FSF&lt;/a&gt; will not endorse it as a free distro. but if you don’t use wifi,
then there is no software freedom issues. Anyway, I have recently developed
quite the crush on OpenBSD, and I found this &lt;a href=&quot;https://openbsdrouterguide.net/&quot;&gt;guide&lt;/a&gt;, that helps you use OpenBSD
for your router. It’s actually quite comprehensive:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;In this guide we’re going to take a look at how we can use cheap and “low end”
hardware to build an amazing OpenBSD router with firewalling capabilities,
segmented local area networks, DNS with domain blocking, DHCP and more.&lt;/p&gt;&lt;p&gt;We will use a setup in which the router segments the local area network (LAN)
into three separate networks, one for the grown-ups in the house, one for the
children, and one for public facing servers (a DMZ), such as a private web
server or mail server. We will also look at how we can use DNS to block out ads,
porn, and other websites on the Internet. The OpenBSD router can also be used on
small to mid-size offices.&lt;/p&gt;&lt;/blockquote&gt;</content></entry></feed>