diff options
6 files changed, 245 insertions, 15 deletions
diff --git a/blog/entry/gnus+notmuch.mdwn b/blog/entry/gnus+notmuch.mdwn
new file mode 100644
index 0000000..bae4055
--- /dev/null
+++ b/blog/entry/gnus+notmuch.mdwn
@@ -0,0 +1,103 @@
+[[!tag Emacs notmuch]]
+I'd like to share some pointers for using Gnus together with notmuch rather
+than notmuch together with notmuch's own Emacs interface, notmuch.el. I set
+about this because I recently realised that I had been poorly reimplementing
+lots of Gnus features in my init.el, primarily around killing threads and
+catching up groups, supported by a number of complex shell scripts. I've now
+switched over, and I've been able to somewhat simplify what's in my init.el,
+and drastically simplify my notmuch configuration outside of Emacs. I'm
+always more comfortable with less Unix and more Lisp when it's feasible.
+- The basic settings are `gnus-search-default-engines` and
+ `gnus-search-notmuch-remove-prefix`, explained in `(info "(gnus) Searching")`,
+ and an entry for your maildir in `gnus-secondary-select-methods`, explained
+ in `(info "(gnus) Maildir")`. Then you will have `G G` and `G g` in the
+ group buffer to make and save notmuch searches.
+- I think it's important to have something equivalent to
+ `notmuch-saved-searches` configured programmatically in your init.el, rather
+ than interactively adding each saved search to the group buffer. This is
+ because, as notmuch users know, these saved searches are more like
+ permanent, virtual inboxes than searches. You can learn how to do this by
+ looking at how `gnus-group-make-search-group` calls `gnus-group-make-group`.
+ I have some code running in `gnus-started-hook` which does something like
+ this for each saved search:
+ ``` {.el}
+ (if (gnus-group-entry group)
+ (gnus-group-set-parameter group 'nnselect-specs ...)
+ (gnus-group-make-group ...))
+ ```
+ The idea is that if you update your saved search in your init.el,
+ rerunning this code will update the entries in the group buffer. An
+ alternative would be to just kill every nnselect search in the group
+ buffer each time, and then recreate them. In addition to reading
+ `gnus-group-make-search-group`, you can look in `~/.newsrc.eld` to see the
+ sort of `nnselect-specs` group parameters you'll need your code to
+ produce.
+ I've very complicated generation of my saved searches from some variables,
+ but that's something I had when I was using notmuch.el, too, so perhaps
+ I'll describe some of the ideas in there in another post.
+- You'll likely want to globally bind a function which starts up Gnus if it's
+ not already running and then executes an arbitrary notmuch search. For that
+ you'll want `(unless (gnus-alive-p) (gnus))`, and **not**
+ `(unless (gnus-alive-p) (gnus-no-server))`. This is because you need Gnus
+ to initialise nnmaildir before doing any notmuch searches. Gnus passes
+ `--output=files` to notmuch and constructs a summary buffer of results by
+ selecting mail that it already knows about with those filenames.
+- When you're programmatically generating the list of groups, you might also
+ want to programmatically generate a topics topology. This is how you do
+ that:
+ ``` {.el}
+ (with-current-buffer gnus-group-buffer
+ (gnus-topic-mode 0)
+ (setq gnus-topic-alist nil gnus-topic topology nil)
+ ;; Now push to those two variables. You can also use
+ ;; `gnus-topic-move-matching' to move nnmaildir groups into, e.g.,
+ ;; "misc".
+ (gnus-topic-mode 1)
+ (gnus-group-list-groups))
+ ```
+ If you do this in `gnus-started-hook`, the values for those variables Gnus
+ saves into `~/.newsrc.eld` are completely irrelevant and do not need
+ backing up/syncing.
+- When you want to use `M-g` to scan for new mail in a saved search, you'll
+ need to have Gnus also rescan your nnmaildir inbox, else it won't know about
+ the filenames returned by notmuch and the messages won't appear. This is
+ similar to the `gnus` vs. `gnus-no-server` issue above. I'm using `:before`
+ advice to `gnus-request-group-scan` to scan my nnmaildir inbox each time any
+ nnselect group is to be scanned.
+- If you are used to linking to mail from Org-mode buffers, the existing
+ support for creating links works fine, and the standard `gnus:` links
+ already contain the Message-ID. But you'll probably want opening the link
+ to perform a notmuch search for id:foo rather than trying to use Gnus's own
+ jump-to-Message-ID code. You can do this using `:around` or `:override`
+ advice for `org-gnus-follow-link`: look at
+ `gnus-group-read-ephemeral-search-group` to do the search, and then call
+ `gnus-summary-goto-article`.
+I don't think that the above is especially hacky, and don't expect changes to
+Gnus to break any of it. Implementing the above for your own notmuch setup
+should get you something close enough to notmuch.el that you can take
+advantage of Gnus' unique features without giving up too much of notmuch's
+special features. However, it's quite a bit of work, and you need to be good
+at Emacs Lisp. I'd suggest reading lots of the Gnus manual and determining
+for sure that you'll benefit from what it can do before considering switching
+away from notmuch.el.
+Reading through the Gnus manual, it's been amazing to observe the extent to
+which I'd been trying to recreate Gnus in my init.el, quite oblivious that
+everything was already implemented for me so close to hand. Moreover, I used
+Gnus ten years ago when I was new to Emacs, so I should have known! I think
+that back then I didn't really understand the idea that Gnus for mail is about
+reading mail like news, and so I didn't use any of the features, back then,
+that more recently I've been unknowingly reimplementing.
diff --git a/blog/entry/rpi4-consfigurator.mdwn b/blog/entry/rpi4-consfigurator.mdwn
new file mode 100644
index 0000000..a0e714f
--- /dev/null
+++ b/blog/entry/rpi4-consfigurator.mdwn
@@ -0,0 +1,113 @@
+[[!meta title="Setting up a single-board desktop replacement with Consfigurator"]]
+The ThinkPad x220 that I had been using as an ssh terminal at home finally
+developed one too many hardware problems a few weeks ago, and so I ordered a
+Raspberry Pi 4b to replace it. Debian builds [minimal SD
+card images]( for these machines already, but I
+wanted to use the usual ext4-on-LVM-on-LUKS setup for GNU/Linux workstations.
+So I used [Consfigurator](/tech/code/consfigurator) to build a custom image.
+There are two key advantages to using Consfigurator to do something like this:
+1. As shown below, it doesn't take a lot of code to define the host, it's
+ easily customisable without writing shell scripts, and it's all
+ declarative. (It's quite a bit less code than [Debian's image-building
+ scripts](, though I haven't
+ carefully compared, and they are doing some additional setup beyond what's
+ shown below.)
+2. You can do nested block devices, as required for ext4-on-LVM-on-LUKS,
+ without writing an intensely complex shell script to expand the root
+ filesystem to fill the whole SD card on first boot. This is because
+ Consfigurator can just as easily partition and install an actual SD card as
+ it can write out a disk image, using the same host definition.
+Consfigurator already had all the capabilities to do this, but as part of this
+project I did have to come up with the high-level wrapping API, which didn't
+exist yet. My first SD card write wouldn't boot because I had to learn more
+about kernel command lines; the second wouldn't boot because of a [minor bug
+in Consfigurator regarding
+and the third build is the one I'm using, except that the first boot runs into
+a [bug in cryptsetup-initramfs]( So as far
+as Consfigurator is concerned I would like to claim that it worked on my
+second attempt, and had I not been using LUKS it would have worked on the
+first :)
+## The code
+``` {.common-lisp}
+(defhost ()
+ "Low powered home workstation in Tucson."
+ (os:debian-stable "bullseye" :arm64)
+ (timezone:configured "America/Phoenix")
+ (user:has-account "spwhitton")
+ (user:has-enabled-password "spwhitton")
+ (disk:has-volumes
+ (physical-disk
+ (partitioned-volume
+ ((partition
+ :partition-typecode #x0700 :partition-bootable t :volume-size 512
+ (fat32-filesystem :mount-point #P"/boot/firmware/"))
+ (partition
+ :volume-size :remaining
+ (luks-container
+ :volume-label "erebus_crypt"
+ :cryptsetup-options '("--cipher" "xchacha20,aes-adiantum-plain64")
+ (lvm-physical-volume :volume-group "vg_erebus"))))))
+ (lvm-logical-volume
+ :volume-group "vg_erebus"
+ :volume-label "lv_erebus_root" :volume-size :remaining
+ (ext4-filesystem :volume-label "erebus_root" :mount-point #P"/"
+ :mount-options '("noatime" "commit=120"))))
+ (apt:installed "linux-image-arm64" "initramfs-tools"
+ "raspi-firmware" "firmware-brcm80211"
+ "cryptsetup" "cryptsetup-initramfs" "lvm2")
+ (etc-default:contains "raspi-firmware"
+ "ROOTPART" "/dev/mapper/vg_erebus-lv_erebus_root"
+ "CONSOLES" "ttyS1,115200 tty0"))
+and then you just insert the SD card and, at the REPL on your laptop,
+``` {.common-lisp}
+CONSFIG> (hostdeploy-these
+ (disk:first-disk-installed-for nil #P"/dev/mmcblk0"))
+There is more general information in the [OS installation
+in the Consfigurator user's manual.
+## Other niceties
+- Configuration management that's just as easily applicable to OS installation
+ as it is to the more usual configuration of hosts over SSH drastically
+ improves the ratio of cost-to-benefit for including small customisations one
+ is used to.
+ For example, my standard Debian system configuration properties (omitted
+ from the code above) meant that when I was dropped into an initramfs shell
+ during my attempts to make an image that could boot itself, I found myself
+ availed of my custom [Space Cadet-inspired keyboard
+ layout](/blog/entry/spacecadetrebindings), without really having thought at
+ any point "let's do something to ensure I can have my usual layout while I'm
+ figuring this out." It was just included along with everything else.
+- As compared with the ThinkPad x220, it's nice how the Raspberry Pi 4b is
+ silent and doesn't have any LEDs lit by default once it's booted. A quirk
+ of my room is that one plug socket is controlled by a switch right next to
+ the switch for the ceiling light, so I've plugged my monitor into that
+ outlet. Then when I've finished using the new machine I can flick that
+ switch and the desk becomes completely silent and dark, without actually
+ having to suspend the machine to RAM, thereby stopping cron jobs, preventing
+ remote access from the office to fetch uncommitted files, etc..
diff --git a/index.mdwn b/index.mdwn
index 7631a2c..e5832e7 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -44,7 +44,7 @@ the [Debian]( operating system.
## E-mail
-`` / `` / ``
+`` / `` / ``
## OpenPGP
diff --git a/philos/teaching/philos.mdwn b/philos/teaching/philos.mdwn
index f0f9784..1700722 100644
--- a/philos/teaching/philos.mdwn
+++ b/philos/teaching/philos.mdwn
@@ -22,3 +22,10 @@ regularly for updates.
concepts that you could not expect such a student to already know -- all of
the new concepts introduced by the authors we've been reading in this
particular class.
+## Office hours
+1. You do not need to ask for an appointment unless the syllabus says
+ "by appointment only". Just show up at the times given.
+2. Office hours are for one-on-one help, not group review sessions.
diff --git a/tech/code/consfigurator.mdwn b/tech/code/consfigurator.mdwn
index c3c7f96..8bc5d8b 100644
--- a/tech/code/consfigurator.mdwn
+++ b/tech/code/consfigurator.mdwn
@@ -37,7 +37,8 @@ we can out of all that existing distro policy-compliant work!
## Installation and usage ##
Please see the [user's manual](,
-which includes a tutorial/quick start guide.
+which includes a tutorial/quick start guide. There's also [an introductory
+video]( for Consfigurator 1.0.3.
## Source code ##
diff --git a/tech/machines.mdwn b/tech/machines.mdwn
index b71c79b..2985e2a 100644
--- a/tech/machines.mdwn
+++ b/tech/machines.mdwn
@@ -9,8 +9,8 @@ Active service
: desktop workstation in Sheffield
-: desktop workstation in Tucson
+: single-board desktop replacement in Tucson
: laptop
@@ -18,23 +18,17 @@ hephaestus
: personal web, git and file server -- LXC host
-: tablet computer
+leto, rhea
+: secondary LXC hosts
: smartphone
-: secondary DNS
-Semi-active service
+: secondary MX & DNS
-: Debian Haskell Group build machine, donated by Exoscale
-: laptop 2016--2020, now with hardware issues
+: tablet computer
@@ -62,3 +56,15 @@ artemis
: low-powered ARM file server
+: Debian Haskell Group build machine, donated by Exoscale
+: desktop workstation in Tucson
+: laptop 2016--2020, ssh terminal with hardware issues 2020--2022
+: Pinebook Pro, seemingly bricked