# The Hurd on Bare Metal — GNUcode.me
GNUcode.me is a website focusing on libre software projects, especially the GNU project.
Keywords: GNU, Emacs, Libre Software, Hurd, Guile, Guix

# The Hurd on Bare Metal

### by Joshua Branson — August 13, 2023

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?

tl;dr Debian GNU/Hurd is shockingly stable. If you are an emacs wiz, then you will feel right at home.

The first thing to notice after you login to the Hurd is that you can easily switch virtual consoles via `Alt-<right-arrow>`. 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.

Another thing to notice is that `mount` does not work. Let's explore that shall we?

    cat /etc/mtab | awk '{ print $1 " " $2 " " $3 }'

    /dev/hd0s1 / ext2fs
    none /run /hurd/tmpfs
    none /run/lock /hurd/tmpfs
    /dev/hd0s6 /home /hurd/ext2fs
    proc /proc /hurd/procfs

Actually `/etc/mtab` is a symlink to `/proc/mounts`.

    ls -lha /etc/mtab

    lrwxr-xr-x 1 root root 12 Apr 10 12:14 /etc/mtab -> /proc/mounts

It looks like the Hurd labels MBR partitions slightly differently from Linux. It appears that the Hurd uses `/dev/hd0s1`, `dev/hd0s2`, and so on.

    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

It looks like a good place to start learning how to use the Hurd is via `https://www.debian.org/ports/hurd/hurd-install`.

So the file that describes my network interfaces is here:

    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

So it looks like i should definitely read `man 5 interfaces` 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.

    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

Ok, so it seems like `pfinit` is still the default GNU Hurd `TPC/IP` translator, which is based on an old Linux TCP/IP driver (`lwip` or `rumpkernel` may one day replace it). Apparently my internet connectivity can be found by quering `/servers/socket/2` (for IPv4) and `/servers/socket/26` (for IPv6).

    # fsysopts /servers/socket/2

If you run the above command you will see that the ethernet device that the Hurd uses is `/dev/eth0`.

The Hurd has a stateless (stateful is better) ethernet filter. For example, here is how to disable ssh access:

    # settrans -c /dev/eth0f /hurd/eth-filter \
               -i /dev/eth0 -r "not port 22"

I could then, tell the pfinit translator to use `/dev/eth0f` instead of `/dev/eth0` via (I think this how you would do it):

    # fsysopts /server/socket/2 --interface=/dev/eth0f

This is course is not persistant across reboots. I would probably need to replace `/dev/eth0` in `/etc/network/interfaces` with `/dev/eth0f`.

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:

    cd /dev
    # ./MAKEDEV cd0
    # settrans /media/cdrom0 /hurd/is09660fs /dev/cd0
    $ cd /media/cdrom0

Apparently the Hurd does have a network filesystem translator (`/hurd/nfs`), 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.

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.

    cat /etc/apt/apt.conf.d/99ignore-valid-until

    Acquire::Check-Valid-Until "false";

    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

This mostly worked, but apt gave a warning about the debian gpg key had expired.

Well let’s try to upgrade anyway.

    # apt update && apt upgrade

That seemed to work.

    # apt install debian-ports-archive-keyring
    # apt update
    # apt upgrade

    # apt install git git-email
    $ git config --global user.name "Joshua Branson"
    $ git config --global user.email "jbranso@dismail.de"
    $ cd; git clone https://notabug.org/jbranso/prog

Now I suppose that it is time to follow Drew Devault’s guide on how to manage your home directory’s configuration files as a git repository.

I should also read the hurd-doc-translator webpage.

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: `/dev/zero` does not need hardware data, so a read from `dev/zero` is entirely run in userspace.

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 `settrans -a` command. The `-a` refers to the active translator. So `settrans -a file.txt` will try to kill the userspace translator process. If you start a translator via the `-a` option, then the translator is not persistant accross reboot. For that reason, most of the time you do not want the `-a` option, which is what settrans by default does.

If you are ever curious to know if a filesystem node has an attached translator, then you can find out via this command:`showtrans NODE`. It will tell you what passive translators are set at a filesystem node.

Let's take a walk through some basic Hurd translators.

    settrans [OPTIONS...] NODE [TRANSLATOR ARGS...]

For example, I can have a text file like so:

    cat ~/Documents/hello.txt

    boring text document.

Now let’s set the `hello` translator on that filesystem node.

    settrans -a ~/Documents/hello.txt /hurd/hello

    cat ~/Documents/hello.txt

    Hello, world!

Now let’s see that the file system options are for the `/hurd/hello` translator:

    fsysopts ~/Documents/hello.txt

    /hurd/hello --contents='Hello, world!
    '

I can modify the `contents` of the hello translator via:

    fsysopts ~/Documents/hello.txt  --contents="Hello Joshua
    "

    cat ~/Documents/hello.txt

    Hello Joshua

Notice that we changed the options for that translator without having to restart it with normal user privledges.

Now let’s make the hello translator go away:

    settrans -a ~/Documents/hello.txt

    cat ~/Documents/hello.txt

    boring text document.

Now let’s try to stack these translators eh?

    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

Here the ls command apparently hanged. `C-c` 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 `ls` hang?

Well here is a clue:

    ls ~/gnucode.me/feed.xml

    ls: cannot access feed.xml': No such file or directory

Well, httpfs does not expose feed.xml. It does not recognize that as part of the gnucode.me website. `httpfs` only lists webpages that are listed on `index.html`. So `~/gnucode.me/feed.xml` 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.

I should also mention that I am using a very minimal `.emacs.d/init.el`. 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 `apt search magit` to get you started.

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.

Surprizingly the Hurd only uses about `161MB` of RAM, when I run emacs on the console.

- What I have done so far

  - Emacs I would love to remap control and caps, but I am not certain how to do that in the console.

  - Irc (via Erc)

  - Gnus my email client But I still need to set up the ability to send email.

Packages to install (glibc-doc-reference) requires enabling non-free packages:

    # apt install gnupg emacs surfraw msmtp glibc-doc glibc-doc-reference

Trying to create/open a file in emacs that ends in *.gpg crashes Emacs. I have no idea why.

Currently, msmtp cannot securely send email, because it cannot decrypt the encrypted file that has my password.

My Hurd machine also has my “jbranso@dismail.de” gpg key. I was able to import the data via an ssh session.

I was actually surprized that the debian wiki mentioned this command: `service ssh restart` and not a systemd specific command, but apparently `man service` is the manual that I want to read. Apparently ssh is already running. I verified this with:

    echo $pw1 | sudo -S service --status-all | grep ssh

    [ + ]  ssh

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.

Anyway, you can take a look at my hurd home git directory if you like. Safe travels!