Recent changes to this wiki:

Publish log entry
diff --git a/posts/2017/06/25/obnam_1_22_released_backup_application.mdwn b/posts/2017/06/25/obnam_1_22_released_backup_application.mdwn
new file mode 100644
index 0000000..1a30785
--- /dev/null
+++ b/posts/2017/06/25/obnam_1_22_released_backup_application.mdwn
@@ -0,0 +1,39 @@
+[[!meta title="Obnam 1.22 released (backup application)"]]
+[[!meta date="2017-06-25 15:40"]]
+[[!tag obnam announcement]]
+
+I've just released version 1.22 of Obnam, my backup application. It is
+the first release for this year. Packages are available on
+code.liw.fi/debian and in Debian unstable, and source is in git. A
+summary of the user-visible changes is below.
+
+For those interested in living dangerously and accidentally on purpose
+deleting all their data, the link below shows that status and roadmap
+for FORMAT GREEN ALBATROSS.
+<http://distix.obnam.org/obnam-dev/182bd772889544d5867e1a0ce4e76652.html>
+
+Version 1.22, released 2017-06-25
+----------------------------------
+
+* Lars Wirzenius made Obnam log the full text of an Obnam
+  exception/error message with more than one line. In particular this
+  applies to encryption error messages, which now log the gpg output.
+
+* Lars Wirzenius made `obnam restore` require absolute paths for files
+  to be restored.
+
+* Lars Wirzenius made `obnam forget` use a little less memory. The
+  amount depends on the number of genrations and the chunks they
+  refer to.
+
+* Jan Niggemann updated the German translation of the Obnam manual to
+  match recent changes in the English version.
+
+* SanskritFritz and Ian Cambell fixed the kdirstat plugin.
+
+* Lars Wirzenius changed Obnam to hide a Python stack trace when
+  there's a problem with the SSH connection (e.g., failure to
+  authenticate, or existing connection breaks).
+
+* Lars Wirzenius made the Green Albatross version of `obnam forget`
+  actually free chunks that are no longer used.

Publish
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index a8c4674..c5d0f4b 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Vmdb2 first alpha release: Debian disk image creation tool"]]
 [[!meta date="2017-06-04 15:08"]]
-[[!tag draft vmdb2 vmdebootstrap announcement]]
+[[!tag vmdb2 vmdebootstrap announcement]]
 
 tl;dr: Get vmdebootstrap replacement from <http://git.liw.fi/vmdb2> and
 run it from the source tree. Tell me if something doesn't work. Send

Fix: remove smiley
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index bc29c40..a8c4674 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -205,7 +205,6 @@ Debian maintainership and bug handling duties.
 
 If you would like vmdb2 to do more things to suit you better, I'm
 happy to explain how to write plugins to provide more types of steps.
-:)
 
 If you are currently using vmdebootstrap, either directly or as part
 of another tool, I encourage you to have a look at vmdb2. In the long

Fix: typo
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 7879c53..bc29c40 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -191,7 +191,7 @@ image and running Ansible over ssh.
 
 Finally, install a boot loader, grub. This shows the BIOS variant,
 UEFI is also supported. This also configures grub and the kernel to use a
-serial console. There's a "yarn" (test suite) to build and smoke gtest
+serial console. There's a "yarn" (test suite) to build and smoke test
 an image with vmdb2 to make sure at least the basic functionality
 works. The smoke test boots the image under Qemu, logs in as root, and
 tells the VM to power off. Very, very basic, but has already found

Fix: clean up wording
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 55bf4a5..7879c53 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -190,7 +190,7 @@ image and running Ansible over ssh.
         console: serial
 
 Finally, install a boot loader, grub. This shows the BIOS variant,
-UEFI is also supported. This also configures everything to use a
+UEFI is also supported. This also configures grub and the kernel to use a
 serial console. There's a "yarn" (test suite) to build and smoke gtest
 an image with vmdb2 to make sure at least the basic functionality
 works. The smoke test boots the image under Qemu, logs in as root, and

Fix: typo
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index a913e86..55bf4a5 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -180,7 +180,7 @@ the step.
 This is a good point to mention that writing customize scripts gets
 quite repetitive and tedious after a while, so vmdb2 has a plugin to
 run Ansible instead. You can customize your image with that instead,
-while the image is beint built and not have to wait until you boot the
+while the image is being built and not have to wait until you boot the
 image and running Ansible over ssh.
 
       - grub: bios

Fix: add self-depracation
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index f3e589a..a913e86 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -154,9 +154,9 @@ the tarball is created if it didn't exist. This way the tarball is
 used by all but the first run, which saves a bit of time. On my laptop
 and with a local mirror, debootstrap and kernel installation takes on the
 order of nine minutes (500 to 600 seconds), whereas unpacking the tar
-archive is a lot faster (around 30 seconds). When iterating over
+archive is a bit faster (takes around 30 seconds). When iterating over
 things other than debootstrap, this speeds things up something
-wonderful.
+wonderful, and seems worth the complexity.
 
 The "unless:" mechanism is generic. All the steps share some state,
 and the unpack-rootfs step sets the "rootfs_unpacked" flag in the

Fix: clarify wording
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 2af42ac..f3e589a 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -152,7 +152,7 @@ The above will run debootstrap and install a kernel into the
 filesystem, but skip doing that if the rootfs tarball was used. Also,
 the tarball is created if it didn't exist. This way the tarball is
 used by all but the first run, which saves a bit of time. On my laptop
-and local mirror, debootstrap and kernel installation takes on the
+and with a local mirror, debootstrap and kernel installation takes on the
 order of nine minutes (500 to 600 seconds), whereas unpacking the tar
 archive is a lot faster (around 30 seconds). When iterating over
 things other than debootstrap, this speeds things up something

Fix: mount points are directories, not files
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 74469b9..2af42ac 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -127,7 +127,7 @@ have an EFI partition.
         fs-tag: root-fs
 
 The above formats the partition with the ext4 filesystem, and then
-mounts it. The mount point will be a temporary file created by vmdb2,
+mounts it. The mount point will be a temporary directory created by vmdb2,
 and a tag is again given to the mount point so it can be referred to.
 
       - unpack-rootfs: root-fs

Fix: clarify, sentence structure
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 1abe3ab..74469b9 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -93,9 +93,10 @@ you, please do have a look.
 
 A short tutorial: vmdb2 wants you to give it a "specification file"
 (conventionally suffixed .vmdb, because someone stole the .spec
-suffix, but vmdb2 doesn't care about the name). Below is an example
-vmdb2 image specification file are in YAML, since I like YAML, and
-specify a sequence of steps to take to build the image.
+suffix, but vmdb2 doesn't care about the name). Below is an example.
+vmdb2 image specification files are in YAML, since I like YAML, and
+specify a sequence of steps to take to build the image. Each step is a
+tiny piece of self-contained functionality provided by a plugin.
 
     steps:
       - mkimg: "{{ output }}"

Fix: remove extra period
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 80cf0af..1abe3ab 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -93,7 +93,7 @@ you, please do have a look.
 
 A short tutorial: vmdb2 wants you to give it a "specification file"
 (conventionally suffixed .vmdb, because someone stole the .spec
-suffix, but vmdb2 doesn't care about the name). Below is an example.
+suffix, but vmdb2 doesn't care about the name). Below is an example
 vmdb2 image specification file are in YAML, since I like YAML, and
 specify a sequence of steps to take to build the image.
 

Fix: word form
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 92b795b..80cf0af 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -88,7 +88,7 @@ people tell me it doesn't work, it's probably not happening.)
 
 Why would you be interested in vmdb2? There's a lot of other tools to
 do what it does, so perhaps you shouldn't care. That's fine. I like
-write tools for myself. But if this kind of tool is of interest to
+writing tools for myself. But if this kind of tool is of interest to
 you, please do have a look.
 
 A short tutorial: vmdb2 wants you to give it a "specification file"

Fix: wording
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index f4e00f8..92b795b 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -55,7 +55,7 @@ At the Cambridge mini-Debconf of November, 2016, I gave a short
 presentation of what I was going to do. I also posted about my
 [plans] to the debian-cloud list. In short, I would write a new, more
 flexible and cleaner replacement to be called vmdb2. For various
-personal reasons, I've not been able to spend a lot of time on vmdb2
+personal reasons, I've not been able to spend as much time on vmdb2
 as I'd like to, but I've now reached the point where I'd like to
 announce the first alpha version publically.
 

Fix: typo
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 3968037..f4e00f8 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -55,7 +55,7 @@ At the Cambridge mini-Debconf of November, 2016, I gave a short
 presentation of what I was going to do. I also posted about my
 [plans] to the debian-cloud list. In short, I would write a new, more
 flexible and cleaner replacement to be called vmdb2. For various
-personal reaons, I've not been able to spend a lot of time on vmdb2
+personal reasons, I've not been able to spend a lot of time on vmdb2
 as I'd like to, but I've now reached the point where I'd like to
 announce the first alpha version publically.
 

Fix: typo
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index a47be06..3968037 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -52,7 +52,7 @@ to burden a new program with my past mistakes. All new mistakes were
 called for.
 
 At the Cambridge mini-Debconf of November, 2016, I gave a short
-presentation of what I was going to do. I also possted about my
+presentation of what I was going to do. I also posted about my
 [plans] to the debian-cloud list. In short, I would write a new, more
 flexible and cleaner replacement to be called vmdb2. For various
 personal reaons, I've not been able to spend a lot of time on vmdb2

Fix: typo
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index d417ed0..a47be06 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -40,7 +40,7 @@ except if that option is given, do the other thing"), how many black
 box tests do you need to test all the functionality? If one run of the
 program takes half an hour, how long will a full test suite run?
 
-I did some hard thining about vmdebootstrap, and came to the sad
+I did some hard thinking about vmdebootstrap, and came to the sad
 conclusion that it had reached the end of its useful life as a living
 software project. There was no reasonable way to add most of the
 additional functionality people were asking for, and even maintaining

Add: secret identity
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 7ae81ac..d417ed0 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -28,7 +28,12 @@ wasn't very good, and there weren't any tests.
 Neil did heroic work forcing my crappy software into doing things I never
 envisioned. Last year he needed a break and asked me to take
 vmdebootstrap back. I did, and have been hiding from the public eye
-ever since, since I was so ashamed of the code.
+ever since, since I was so ashamed of the code. (I created a new
+identity and pretended to be an international assassin and backup
+specialist, travelling the world forcing people to have at least one
+tested backup of their system. If you've noticed reports in the press
+about people reporting near-death experiences while holding a shiny
+new USB drive, that would've been my fault.)
 
 Pop quiz: if you have a program with ten boolean options ("do this,
 except if that option is given, do the other thing"), how many black

Fix: add missing word
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index 3b00769..7ae81ac 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -25,7 +25,7 @@ who added a ton of new features. Unfortunately, it turned out that my
 initial architecture was not scaleable, and also the code I wrote
 wasn't very good, and there weren't any tests.
 
-Neil did heroic work forcing my crappy software into things I never
+Neil did heroic work forcing my crappy software into doing things I never
 envisioned. Last year he needed a break and asked me to take
 vmdebootstrap back. I did, and have been hiding from the public eye
 ever since, since I was so ashamed of the code.

Fix: add <> around link
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
index d7ef7d6..3b00769 100644
--- a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -2,7 +2,7 @@
 [[!meta date="2017-06-04 15:08"]]
 [[!tag draft vmdb2 vmdebootstrap announcement]]
 
-tl;dr: Get vmdebootstrap replacement from http://git.liw.fi/vmdb2 and
+tl;dr: Get vmdebootstrap replacement from <http://git.liw.fi/vmdb2> and
 run it from the source tree. Tell me if something doesn't work. Send
 patches.
 

creating tag page tag/vmdb2
diff --git a/tag/vmdb2.mdwn b/tag/vmdb2.mdwn
new file mode 100644
index 0000000..ffe51f0
--- /dev/null
+++ b/tag/vmdb2.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged vmdb2"]]
+
+[[!inline pages="tagged(vmdb2)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
new file mode 100644
index 0000000..d7ef7d6
--- /dev/null
+++ b/posts/2017/06/04/vmdb2_first_alpha_release_debian_disk_image_creation_tool.mdwn
@@ -0,0 +1,214 @@
+[[!meta title="Vmdb2 first alpha release: Debian disk image creation tool"]]
+[[!meta date="2017-06-04 15:08"]]
+[[!tag draft vmdb2 vmdebootstrap announcement]]
+
+tl;dr: Get vmdebootstrap replacement from http://git.liw.fi/vmdb2 and
+run it from the source tree. Tell me if something doesn't work. Send
+patches.
+
+Many years ago I wrote [vmdebootstrap][], a tool for installing Debian
+on a disk image for virtual machines. I had a clear personal need: I
+was setting up a CI system and it needed six workers: one each for
+Debian oldstable, stable, and unstable, on two architectures (i386,
+amd64). Installing Debian six times in the same way is a lot of work,
+so I figured how difficult can it be to automate it. Turns out that
+not difficult at all, except to install a bootloader.
+
+(Don't ask me why I didn't use any of the other tools for this. It was
+long ago, and while some of the tools that now exist probably did
+exist then, I like writing code and learning things while doing it.)
+
+After a while I was happy with what the program did, but didn't want
+to upload it to Debian, and didn't want to add the kinds of things
+other people wanted, so I turned vmdebootstrap over to Neil Williams,
+who added a ton of new features. Unfortunately, it turned out that my
+initial architecture was not scaleable, and also the code I wrote
+wasn't very good, and there weren't any tests.
+
+Neil did heroic work forcing my crappy software into things I never
+envisioned. Last year he needed a break and asked me to take
+vmdebootstrap back. I did, and have been hiding from the public eye
+ever since, since I was so ashamed of the code.
+
+Pop quiz: if you have a program with ten boolean options ("do this,
+except if that option is given, do the other thing"), how many black
+box tests do you need to test all the functionality? If one run of the
+program takes half an hour, how long will a full test suite run?
+
+I did some hard thining about vmdebootstrap, and came to the sad
+conclusion that it had reached the end of its useful life as a living
+software project. There was no reasonable way to add most of the
+additional functionality people were asking for, and even maintaining
+the current code was too tedious a task to consider seriously. It was
+time to make a clean break of the past and start over, without caring
+about backwards compatibility. After all, the old code wasn't going
+anywhere so anyone who needed it could still use it. There was no need
+to burden a new program with my past mistakes. All new mistakes were
+called for.
+
+At the Cambridge mini-Debconf of November, 2016, I gave a short
+presentation of what I was going to do. I also possted about my
+[plans] to the debian-cloud list. In short, I would write a new, more
+flexible and cleaner replacement to be called vmdb2. For various
+personal reaons, I've not been able to spend a lot of time on vmdb2
+as I'd like to, but I've now reached the point where I'd like to
+announce the first alpha version publically.
+
+The source code is hosted here: http://git.liw.fi/vmdb2 . There are
+.deb packages at my personal public APT repo (http://liw.fi/code/),
+but vmdb2 is easy enough to run directly from a git checkout:
+
+    sudo ./vmdb2 foo.vmdb --output foo.img
+
+There's no need to install it to try it.
+
+What works:
+
+* vmdb2 can build a disk image with Debian installed, for amd64 only
+  at this time
+* the boot loader is GRUB, either for UEFI or BIOS
+* the image boots under Qemu / KVM and also on actual hardware
+
+What doesn't work:
+
+* other architecures, including building for a foreign archiecture
+* live CD building (no squashfs support)
+
+I'm not opposed to adding support for those, but they're not directly
+interesting to me. For example, I only have amd64 machines. The best
+way to get support for additional features is to tell me how,
+preferably in the form of patches. (If I have to read tons of docs, or
+other people's code, and then write code and iterate while other
+people tell me it doesn't work, it's probably not happening.)
+
+Why would you be interested in vmdb2? There's a lot of other tools to
+do what it does, so perhaps you shouldn't care. That's fine. I like
+write tools for myself. But if this kind of tool is of interest to
+you, please do have a look.
+
+A short tutorial: vmdb2 wants you to give it a "specification file"
+(conventionally suffixed .vmdb, because someone stole the .spec
+suffix, but vmdb2 doesn't care about the name). Below is an example.
+vmdb2 image specification file are in YAML, since I like YAML, and
+specify a sequence of steps to take to build the image.
+
+    steps:
+      - mkimg: "{{ output }}"
+        size: 4G
+
+      - mklabel: msdos
+        device: "{{ output }}"
+
+      - mkpart: primary
+        device: "{{ output }}"
+        start: 0%
+        end: 100%
+        part-tag: root-part
+
+The above create an image (name is specified with the --output
+option), which is four gigabytes in size, and create a partitition
+table and a single partition that fills the whole disk. The "tag" is
+given so that later steps can easily refer to the partition.
+
+If you prefer another way to partition the disk, you can achieve that
+by adding more "mkpart" steps. For example, for UEFI you'll want to
+have an EFI partition.
+
+      - mkfs: ext4
+        partition: root-part
+
+      - mount: root-part
+        fs-tag: root-fs
+
+The above formats the partition with the ext4 filesystem, and then
+mounts it. The mount point will be a temporary file created by vmdb2,
+and a tag is again given to the mount point so it can be referred to.
+
+      - unpack-rootfs: root-fs
+
+The above unpacks a tar archive to put content into the filesystem, if
+the tar archive exists. The tar archive is specified with the
+--rootfs-tarball command line option.
+
+      - debootstrap: stretch
+        mirror: http://http.debian.net/debian
+        target: root-fs
+        unless: rootfs_unpacked
+
+      - apt: linux-image-amd64
+        fs-tag: root-fs
+        unless: rootfs_unpacked
+
+      - cache-rootfs: root-fs
+        unless: rootfs_unpacked
+
+The above will run debootstrap and install a kernel into the
+filesystem, but skip doing that if the rootfs tarball was used. Also,
+the tarball is created if it didn't exist. This way the tarball is
+used by all but the first run, which saves a bit of time. On my laptop
+and local mirror, debootstrap and kernel installation takes on the
+order of nine minutes (500 to 600 seconds), whereas unpacking the tar
+archive is a lot faster (around 30 seconds). When iterating over
+things other than debootstrap, this speeds things up something
+wonderful.
+
+The "unless:" mechanism is generic. All the steps share some state,
+and the unpack-rootfs step sets the "rootfs_unpacked" flag in the
+shared state. The "unless:" field tells vmdb2 to check for the flag
+and if it is not set, or if it is set to false ("unless it is set to
+true"), vmdb2 will execute the step. vmdb2 may get more such flags in
+the future, if there's need.
+
+      - chroot: root-fs
+        shell: |
+          sed -i '/^root:[^:]*:/s//root::/' /etc/passwd
+          echo pc-vmdb2 > /etc/hostname
+
+The above executes a couple of shell commands in a chroot of the root
+filesystem we've just created. In this case they remove a login
+password from root, and set the hostname. This is a replacement of the
+vmdebootstrap "customize" script, but it can be inserted anywhere into
+the sequence of steps. There's boot chroot and non-chroot variants of
+the step.
+
+This is a good point to mention that writing customize scripts gets
+quite repetitive and tedious after a while, so vmdb2 has a plugin to
+run Ansible instead. You can customize your image with that instead,
+while the image is beint built and not have to wait until you boot the
+image and running Ansible over ssh.
+
+      - grub: bios
+        root-fs: root-fs
+        root-part: root-part
+        device: "{{ output }}"
+        console: serial
+
+Finally, install a boot loader, grub. This shows the BIOS variant,
+UEFI is also supported. This also configures everything to use a
+serial console. There's a "yarn" (test suite) to build and smoke gtest
+an image with vmdb2 to make sure at least the basic functionality
+works. The smoke test boots the image under Qemu, logs in as root, and
+tells the VM to power off. Very, very basic, but has already found
+actual bugs in vmdb2. The smoke test needs the serial console to work.
+
+As with vmdebootstrap originally, I don't particularly want to

(Diff truncated)
Fix gpg -K output
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index eb199a4..0b9414a 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -400,7 +400,7 @@ $ <b style="color: red">gpg --import subkeys.key</b></code></blockquote>
 $ <b style="color: red">gpg -K</b> <br/>
 /home/liw/.gnupg/pubring.kbx <br/>
 ---------------------------- <br/>
-sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
+sec#  rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
 uid           [ultimate] Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
 ssb   rsa4096 2017-05-29 [S] [expires: 2018-05-29] <br/>
@@ -629,3 +629,7 @@ the above.
 * [Riseup.net's OpenPGP best practices](https://riseup.net/en/security/message-security/openpgp/best-practices)
 * [bootc's GnuPG / ssh agent setup](http://www.bootc.net/archives/2013/06/09/my-perfect-gnupg-ssh-agent-setup/)
 * [anarcat's Yubikey NEO howto](https://anarc.at/blog/2015-12-14-yubikey-howto/)
+
+Edited to fix:
+
+* Output of `gpg -K` after removing secret master key.

Publish article
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 223d11d..eb199a4 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Using a Yubikey 4 for ensafening one's encryption"]]
 [[!meta date="2017-05-29 18:03"]]
-[[!tag draft yubikey gpg]]
+[[!tag yubikey gpg]]
 
 [[!toc ]]
 

Add section headers, table of contetns
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index e0d9ff0..223d11d 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -2,6 +2,10 @@
 [[!meta date="2017-05-29 18:03"]]
 [[!tag draft yubikey gpg]]
 
+[[!toc ]]
+
+# Introduction
+
 I've written before about [using a U2F key with PAM][]. This post
 continues the theme and explains how to use a smartcard with GnuPG for
 storing OpenPGP private keys. Specifically, a Yubikey 4 card, because
@@ -28,6 +32,8 @@ versions or between Linux distributions. You will need:
 
 [ChaosKey]: http://altusmetrum.org/ChaosKey/
 
+# Terminology
+
 Some terminology:
 
 * OpenPGP is a standard of encryption keys.
@@ -70,6 +76,8 @@ Some terminology:
   corresponding secret key, so only you can send the random number
   back to the server, and thereby the server knows you're you.
 
+# Outline
+
 The process outline is:
 
 1. Create a new, signing-only master key with GnuPG.
@@ -93,6 +101,8 @@ The process outline is:
 6. Use gpg-agent as your SSH agent, and the authentication-only subkey
    on the Yubikey is used as your ssh key.
 
+# Configure GnuPG
+
 The process in more detail:
 
 * Configure GnuPG with regards to checksum and encryption algorithms.
@@ -108,6 +118,8 @@ The process in more detail:
         personal-cipher-preferences TWOFISH CAMELLIA256 AES 3DES
         keyserver pool.sks-keyservers.net
 
+# Create new keys
+
 * Create new sign-only master key.
 
 <blockquote><code>$ <b style="color: red">gpg --full-generate-key</b> <br/>
@@ -352,6 +364,8 @@ ssb  rsa4096/4477EB0AEF1C440A <br/>
  <br/>
 gpg> <b style="color: red">save</b> </code></blockquote>
 
+# Export secret keys to files, make a backup
+
 * You now have a master key and three subkeys. They are hidden in the
   `~/.gnupg` directory. It is time to "export" the secret keys out
   from there.
@@ -394,6 +408,8 @@ ssb   rsa4096 2017-05-29 [E] [expires: 2018-05-29] <br/>
 ssb   rsa4096 2017-05-29 [A] [expires: 2018-05-29] <br/>
 </code></blockquote>
 
+# Install subkeys on a Yubikey
+
 *  Now insert the Yubikey in a USB slot. We can start transferring the
    secret subkeys to the Yubikey. If you want, you can set your name
    and other information, and change PIN codes. There's several types
@@ -553,6 +569,8 @@ gpg> <b style="color: red">save</b></code></blockquote>
    subkeys on the Yubikey, and will tell you to insert it in a USB
    port if it can't find the key.
 
+# Use subkey on Yubikey as your SSH key
+
 *  To actually use the authentication-only subkey on the Yubikey for
    ssh, you need to configure your system to use gpg-agent as the SSH
    agent. Add the following line to `.gnupg/gpg-agent.conf`:
@@ -603,6 +621,8 @@ gpg> <b style="color: red">save</b></code></blockquote>
 
 *  Happy hacking.
 
+# See also
+
 See also the following links. I've used them to learn enough to write
 the above.
 

Add space before "add comment" footer
diff --git a/style.css b/style.css
index e29e61c..b70b94f 100644
--- a/style.css
+++ b/style.css
@@ -117,6 +117,10 @@ ul li, ol li {
     margin-bottom: 0.5em;
 }
 
+div.addcomment {
+    margin-top: 5em;
+}
+
 div#comments div.feedlink {
     margin-top: 2em;
 }

Typo fixes
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index c9ed2a8..e0d9ff0 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -53,7 +53,7 @@ Some terminology:
   with a single master key.
 
 * Subkeys can be dedicated for encryption, signing, and
-  authantication. You can have one of each.
+  authentication. You can have one of each.
 
 * Encryption is the process of taking a file and making it illegible
   to everyone except the owner of a secret key. When the public key is
@@ -90,7 +90,7 @@ The process outline is:
    (because there's PIN codes or passphrases and getting them wrong
    several times locks up the smartcard).
 
-6. Use gpg-agent as your SSH agent, and the authenticaion-only subkey
+6. Use gpg-agent as your SSH agent, and the authentication-only subkey
    on the Yubikey is used as your ssh key.
 
 The process in more detail:
@@ -176,7 +176,7 @@ uid           [ultimate] Lars Wirzenius (test key) &lt;liw@liw.fi&gt; </code></b
 * You now have the signing-only master key. You should now create
   three subkeys (`keyid` is the key identifier shown in the key
   listing, `A734C10BF2DF39D19DC0F6C025FB738D6EE435F7` above). Use the
-  `--expert` option to be able to add an authenticaion-only subkey.
+  `--expert` option to be able to add an authentication-only subkey.
 
 <blockquote><code>$ <b style="color: red">gpg --edit-key --expert A734C10BF2DF39D19DC0F6C025FB738D6EE435F7z</b> <br/>
 gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
@@ -545,7 +545,7 @@ ssb* rsa4096/4477EB0AEF1C440A <br/>
 gpg> <b style="color: red">save</b></code></blockquote>
 
 *  If you want to use several Yubikeys, or have a spare one just in
-   case, repeate the previous four steps (starting from importing
+   case, repeat the previous four steps (starting from importing
    subkeys back into `~/.gnupg`).
 
 *  You're now done, as far GnuPG use is concerned. Any time you need
@@ -554,13 +554,13 @@ gpg> <b style="color: red">save</b></code></blockquote>
    port if it can't find the key.
 
 *  To actually use the authentication-only subkey on the Yubikey for
-   ssh, you need to configure you systrem to use gpg-agent as the SSH
+   ssh, you need to configure your system to use gpg-agent as the SSH
    agent. Add the following line to `.gnupg/gpg-agent.conf`:
 
         enable-ssh-support
 
 *  On a Debian stretch system with GNOME, edit
-   `/etc/xdg/autostart/gnome-keyring-ssh.desktop` to have the follwing
+   `/etc/xdg/autostart/gnome-keyring-ssh.desktop` to have the following
    line, to prevent the GNOME ssh agent from starting up:
 
         Hidden=true

Tweak line-height to a bit smaller
diff --git a/style.css b/style.css
index 9861834..e29e61c 100644
--- a/style.css
+++ b/style.css
@@ -4,7 +4,7 @@ html {
     margin-left: 3em;
     margin-right: 2em;
     margin-top: 2em;
-    line-height: 150%;
+    line-height: 130%;
 }
 
 table {

Increase line heigh; fix typo
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 5ef1ae0..c9ed2a8 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -3,7 +3,7 @@
 [[!tag draft yubikey gpg]]
 
 I've written before about [using a U2F key with PAM][]. This post
-continue the theme and explains how to use a smartcard with GnuPG for
+continues the theme and explains how to use a smartcard with GnuPG for
 storing OpenPGP private keys. Specifically, a Yubikey 4 card, because
 that's what I have, but any good GnuPG compatible card should work.
 The Yubikey is both a GnuPG compatible smart card, and a U2F card. The
diff --git a/style.css b/style.css
index 73e8bab..9861834 100644
--- a/style.css
+++ b/style.css
@@ -4,6 +4,7 @@ html {
     margin-left: 3em;
     margin-right: 2em;
     margin-top: 2em;
+    line-height: 150%;
 }
 
 table {

Drop a fixme
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 2b5bae2..5ef1ae0 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -13,7 +13,7 @@ handle keys up to 2095 bits.
 [using a U2F key with PAM]: https://blog.liw.fi/posts/u2f-pam/
 
 The reason to do this is to make it harder for an attacker to steal
-your encryption keys. FIXME: Expand on this section.
+your encryption keys.
 
 I will assume you don't already have an OpenPGP key, or are willing to
 generate a new one. I will also assume you run Debian stretch; some of

Add links to ChaosKey
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index fbe2732..2b5bae2 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -26,6 +26,8 @@ versions or between Linux distributions. You will need:
   to generate a lot of entropy for the kernel. Entropy is used by
   GnuPG to create encryption keys.
 
+[ChaosKey]: http://altusmetrum.org/ChaosKey/
+
 Some terminology:
 
 * OpenPGP is a standard of encryption keys.

Add referenece to whte gpg config values come from
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 85d8f1e..fbe2732 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -95,8 +95,9 @@ The process in more detail:
 
 * Configure GnuPG with regards to checksum and encryption algorithms.
   You can use the defaults, but depending on the version of GnuPG you
-  have, they may be weaker than is recommended.
-  FIXME: Give ref to where these come from.
+  have, they may be weaker than is recommended. These values are from
+  Riseup.net OpenPGP guide, see link at the end.
+
   Add the following lines to `~/.gnupg/gpg.conf`:
 
         personal-digest-preferences SHA512

Remove finishs fixme
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index f7e5989..85d8f1e 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -2,10 +2,6 @@
 [[!meta date="2017-05-29 18:03"]]
 [[!tag draft yubikey gpg]]
 
-FIXME: The long terminal session listings need a way to mark up
-(boldface?) the parts the user types, but a code block in markdown
-doesn't allow that.
-
 I've written before about [using a U2F key with PAM][]. This post
 continue the theme and explains how to use a smartcard with GnuPG for
 storing OpenPGP private keys. Specifically, a Yubikey 4 card, because

Add links for more info
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index d77d4d8..f7e5989 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -19,7 +19,10 @@ handle keys up to 2095 bits.
 The reason to do this is to make it harder for an attacker to steal
 your encryption keys. FIXME: Expand on this section.
 
-I will assume you don't already have an OpenPGP key. You will need:
+I will assume you don't already have an OpenPGP key, or are willing to
+generate a new one. I will also assume you run Debian stretch; some of
+the desktop environment setup details may differ between Debian
+versions or between Linux distributions. You will need:
 
 * A Yubikey 4 (or other GnuPG compatible smartcard).
 * Two USB memory sticks to store master copies of the key you create.
@@ -599,4 +602,11 @@ gpg> <b style="color: red">save</b></code></blockquote>
 
 <blockquote><code>$ <b style="color: red">gpg --export-ssh-key keyid > ssh.pub</b></code></blockquote>
 
-*  FIXME: Add notes for how to set up gpg-agent as an ssh-agent.
+*  Happy hacking.
+
+See also the following links. I've used them to learn enough to write
+the above.
+
+* [Riseup.net's OpenPGP best practices](https://riseup.net/en/security/message-security/openpgp/best-practices)
+* [bootc's GnuPG / ssh agent setup](http://www.bootc.net/archives/2013/06/09/my-perfect-gnupg-ssh-agent-setup/)
+* [anarcat's Yubikey NEO howto](https://anarc.at/blog/2015-12-14-yubikey-howto/)

Add note about export auth-only subkey as ssh key
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 8339ae2..d77d4d8 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -593,4 +593,10 @@ gpg> <b style="color: red">save</b></code></blockquote>
 
         4096 SHA256:PDCzyQPpd9tiWsELM8LwaLBsMDMm42J8/eEfezNgnVc cardno:000604626953 (RSA)
 
+*  You need to export the authentication-only subkey in the SSH key
+   format. You need this for adding to `.ssh/authorized_keys`, if
+   nothing else.
+
+<blockquote><code>$ <b style="color: red">gpg --export-ssh-key keyid > ssh.pub</b></code></blockquote>
+
 *  FIXME: Add notes for how to set up gpg-agent as an ssh-agent.

Add notes on how to use gpg-agent as ssh agent
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index c1096d2..8339ae2 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -551,4 +551,46 @@ gpg> <b style="color: red">save</b></code></blockquote>
    subkeys on the Yubikey, and will tell you to insert it in a USB
    port if it can't find the key.
 
+*  To actually use the authentication-only subkey on the Yubikey for
+   ssh, you need to configure you systrem to use gpg-agent as the SSH
+   agent. Add the following line to `.gnupg/gpg-agent.conf`:
+
+        enable-ssh-support
+
+*  On a Debian stretch system with GNOME, edit
+   `/etc/xdg/autostart/gnome-keyring-ssh.desktop` to have the follwing
+   line, to prevent the GNOME ssh agent from starting up:
+
+        Hidden=true
+
+*  Edit `/etc/X11/Xsession.options` and remove or comment out the line
+   that says `use-ssh-agent`. This stops a system-started ssh-agent
+   from being started when the desktop start.
+
+*  Create the file `~/.config/autostart/gpg-agent.desktop` with the
+   following content:
+
+        [Desktop Entry]
+        Type=Application
+        Name=gpg-agent
+        Comment=gpg-agent
+        Exec=/usr/bin/gpg-agent --daemon
+        OnlyShowIn=GNOME;Unity;MATE;
+        X-GNOME-Autostart-Phase=PreDisplayServer
+        X-GNOME-AutoRestart=false
+        X-GNOME-Autostart-Notify=true
+        X-GNOME-Bugzilla-Bugzilla=GNOME
+        X-GNOME-Bugzilla-Product=gnome-keyring
+        X-GNOME-Bugzilla-Component=general
+        X-GNOME-Bugzilla-Version=3.20.0
+
+*  To test, log out, and back in again, run the following in a
+   terminal:
+
+<blockquote><code>$ <b style="color: red">ssh-add -l</b></code></blockquote>
+
+  The output should contain a line that looks like this:
+
+        4096 SHA256:PDCzyQPpd9tiWsELM8LwaLBsMDMm42J8/eEfezNgnVc cardno:000604626953 (RSA)
+
 *  FIXME: Add notes for how to set up gpg-agent as an ssh-agent.

Markup block
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 65415ce..c1096d2 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -408,8 +408,139 @@ $ <b style="color: red">gpg -card-edit</b> <br/>
    not a copy, and the subkeys will be removed from your `~/.gnupg`
    (check with `gpg -K`).
 
-        $ gpg --edit-key keyid
-        ...
+<blockquote><code>$ <b style="color: red">gpg --edit-key liw</b> <br/>
+gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
+This is free software: you are free to change and redistribute it. <br/>
+There is NO WARRANTY, to the extent permitted by law. <br/>
+ <br/>
+Secret key is available. <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb  rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb  rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb  rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">key 1</b> <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb* rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb  rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb  rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">keytocard</b> <br/>
+Please select where to store the key: <br/>
+   (1) Signature key <br/>
+   (3) Authentication key <br/>
+Your selection? <b style="color: red">1</b> <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb* rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb  rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb  rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">key 1</b> <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb  rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb  rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb  rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">key 2</b> <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb  rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb* rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb  rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">keytocard</b> <br/>
+Please select where to store the key: <br/>
+   (2) Encryption key <br/>
+Your selection? <b style="color: red">2</b> <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb  rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb* rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb  rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">key 2</b> <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb  rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb  rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb  rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">key 3</b> <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb  rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb  rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb* rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">keytocard</b> <br/>
+Please select where to store the key: <br/>
+   (3) Authentication key <br/>
+Your selection? <b style="color: red">3</b> <br/>
+ <br/>
+pub  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+ssb  rsa4096/05F88308DFB71774 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+ssb  rsa4096/2929E8A96CBA57C7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+ssb* rsa4096/4477EB0AEF1C440A <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ <br/>
+gpg> <b style="color: red">save</b></code></blockquote>
 
 *  If you want to use several Yubikeys, or have a spare one just in
    case, repeate the previous four steps (starting from importing

Note --card-edit
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index d811a5b..65415ce 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -398,10 +398,11 @@ ssb   rsa4096 2017-05-29 [A] [expires: 2018-05-29] <br/>
    of PIN codes: normal use, unblocking a locked card, and a third PIN
    code for admin operations. Changing the PIN codes is a good idea,
    otherwise everyone will just try the default of 123456 (admin
-   12345678).
+   12345678). However, I'm skipping that in the interest of brevity.
 
-        $ gpg --card-edit
-        ...
+<blockquote><code>
+$ <b style="color: red">gpg -card-edit</b> <br/>
+...</code></blockquote>
 
 *  Actually move the subkeys to the card. Note that this does a move,
    not a copy, and the subkeys will be removed from your `~/.gnupg`

Continue markin up code blocks
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index ecb2117..d811a5b 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -138,7 +138,7 @@ Real name: <b style="color: red">Lars Wirzenius</b> <br/>
 Email address: <b style="color: red">liw@liw.fi</b> <br/>
 Comment: <b style="color: red">test key</b> <br/>
 You selected this USER-ID: <br/>
-&nbsp;&nbsp;&nbsp;&nbsp;"Lars Wirzenius (test key) <liw@liw.fi>" <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;"Lars Wirzenius (test key) &lt;liw@liw.fi&gt>" <br/>
  <br/>
 Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? <b style="color: red">o</b> <br/>
 We need to generate a lot of random bytes. It is a good idea to perform <br/>
@@ -155,7 +155,7 @@ the command "--edit-key" to generate a subkey for this purpose. <br/>
 pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
-uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockquote>
+uid                      Lars Wirzenius (test key) &lt;liw@liw.fi&gt; </code></blockquote>
 
 * Note that I set a 1-year expiration for they key. The expiration
   can be extended at any time (if you have the master secret key),
@@ -169,7 +169,7 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
 ---------------------------- <br/>
 sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>A734C10BF2DF39D19DC0F6C025FB738D6EE435F7</i> <br/>
-uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi> </code></blockquote>
+uid           [ultimate] Lars Wirzenius (test key) &lt;liw@liw.fi&gt; </code></blockquote>
 
 * You now have the signing-only master key. You should now create
   three subkeys (`keyid` is the key identifier shown in the key
@@ -186,7 +186,7 @@ Secret key is available. <br/>
 sec  rsa4096/25FB738D6EE435F7 <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trust: ultimate      validity: ultimate <br/>
-[ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi> <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
  <br/>
 gpg> <b style="color: red">addkey</b> <br/>
 Please select what kind of key you want: <br/>
@@ -224,7 +224,7 @@ sec  rsa4096/25FB738D6EE435F7 <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trust: ultimate      validity: ultimate <br/>
 ssb  rsa4096/05F88308DFB71774 <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
-[ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi> <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
  <br/>
 gpg> <b style="color: red">addkey</b> <br/>
 Please select what kind of key you want: <br/>
@@ -264,7 +264,7 @@ ssb  rsa4096/05F88308DFB71774 <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
 ssb  rsa4096/2929E8A96CBA57C7 <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
-[ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi> <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
  <br/>
 gpg> <b style="color: red">addkey</b> <br/>
 Please select what kind of key you want: <br/>
@@ -346,7 +346,7 @@ ssb  rsa4096/2929E8A96CBA57C7 <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
 ssb  rsa4096/4477EB0AEF1C440A <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: A    <br/>
-[ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi> <br/>
+[ultimate] (1). Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
  <br/>
 gpg> <b style="color: red">save</b> </code></blockquote>
 
@@ -380,15 +380,17 @@ $ <b style="color: red">gpg --import subkeys.key</b></code></blockquote>
    mark, which indicates the key isn't available), and three lines
    starting with `ssb` (no hash mark).
 
-        $ gpg -K
-        /home/liw/.gnupg/pubring.kbx
-        ----------------------------
-        sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29]
-              A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
-        uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi>
-        ssb   rsa4096 2017-05-29 [S] [expires: 2018-05-29]
-        ssb   rsa4096 2017-05-29 [E] [expires: 2018-05-29]
-        ssb   rsa4096 2017-05-29 [A] [expires: 2018-05-29]
+<blockquote><code>
+$ <b style="color: red">gpg -K</b> <br/>
+/home/liw/.gnupg/pubring.kbx <br/>
+---------------------------- <br/>
+sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
+uid           [ultimate] Lars Wirzenius (test key) &lt;liw@liw.fi&gt; <br/>
+ssb   rsa4096 2017-05-29 [S] [expires: 2018-05-29] <br/>
+ssb   rsa4096 2017-05-29 [E] [expires: 2018-05-29] <br/>
+ssb   rsa4096 2017-05-29 [A] [expires: 2018-05-29] <br/>
+</code></blockquote>
 
 *  Now insert the Yubikey in a USB slot. We can start transferring the
    secret subkeys to the Yubikey. If you want, you can set your name

Markup another block
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index afdf1a3..ecb2117 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -372,8 +372,8 @@ $ <b style="color: red">gpg --export-secret-subkeys --armor keyid > subkeys.key<
    deleting the master secret key also removes the secret subkeys. But
    we can import those without importing the master secret key.
 
-        $ gpg --delete-secret-key keyid
-        $ gpg --import subkeys.key
+<blockquote><code>$ <b style="color: red">gpg --delete-secret-key keyid</b><br/>
+$ <b style="color: red">gpg --import subkeys.key</b></code></blockquote>
 
 *  Now verify that you have the secret subkeys, but not the master
    key. There should be one line starting with `sec#` (note the hash

Markup another block
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index c4de4a8..afdf1a3 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -354,8 +354,8 @@ gpg> <b style="color: red">save</b> </code></blockquote>
   `~/.gnupg` directory. It is time to "export" the secret keys out
   from there.
 
-        $ gpg --export-secret-key --armor keyid > master.key
-        $ gpg --export-secret-subkeys --armor keyid > subkeys.key
+<blockquote><code>$ <b style="color: red">gpg --export-secret-key --armor keyid > master.key</b><br/>
+$ <b style="color: red">gpg --export-secret-subkeys --armor keyid > subkeys.key</b></code></blockquote>
 
 *  You should keep these files safe. You don't want to lose them, and
    you don't want anyone else to get access to them. I recommend you

Markup indents
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index aaab34e..c4de4a8 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -184,32 +184,32 @@ There is NO WARRANTY, to the extent permitted by law. <br/>
 Secret key is available. <br/>
  <br/>
 sec  rsa4096/25FB738D6EE435F7 <br/>
-     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
-     trust: ultimate      validity: ultimate <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trust: ultimate      validity: ultimate <br/>
 [ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi> <br/>
  <br/>
 gpg> <b style="color: red">addkey</b> <br/>
 Please select what kind of key you want: <br/>
-   (3) DSA (sign only) <br/>
-   (4) RSA (sign only) <br/>
-   (5) Elgamal (encrypt only) <br/>
-   (6) RSA (encrypt only) <br/>
-   (7) DSA (set your own capabilities) <br/>
-   (8) RSA (set your own capabilities) <br/>
-  (10) ECC (sign only) <br/>
-  (11) ECC (set your own capabilities) <br/>
-  (12) ECC (encrypt only) <br/>
-  (13) Existing key <br/>
+&nbsp;&nbsp;&nbsp;(3) DSA (sign only) <br/>
+&nbsp;&nbsp;&nbsp;(4) RSA (sign only) <br/>
+&nbsp;&nbsp;&nbsp;(5) Elgamal (encrypt only) <br/>
+&nbsp;&nbsp;&nbsp;(6) RSA (encrypt only) <br/>
+&nbsp;&nbsp;&nbsp;(7) DSA (set your own capabilities) <br/>
+&nbsp;&nbsp;&nbsp;(8) RSA (set your own capabilities) <br/>
+&nbsp;&nbsp;(10) ECC (sign only) <br/>
+&nbsp;&nbsp;(11) ECC (set your own capabilities) <br/>
+&nbsp;&nbsp;(12) ECC (encrypt only) <br/>
+&nbsp;&nbsp;(13) Existing key <br/>
 Your selection? <b style="color: red">4</b> <br/>
 RSA keys may be between 1024 and 4096 bits long. <br/>
 What keysize do you want? (2048) <b style="color: red">4096</b> <br/>
 Requested keysize is 4096 bits <br/>
 Please specify how long the key should be valid. <br/>
-         0 = key does not expire <br/>
-      <n>  = key expires in n days <br/>
-      <n>w = key expires in n weeks <br/>
-      <n>m = key expires in n months <br/>
-      <n>y = key expires in n years <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 = key does not expire <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>  = key expires in n days <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>w = key expires in n weeks <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>m = key expires in n months <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>y = key expires in n years <br/>
 Key is valid for? (0) <b style="color: red">1y</b> <br/>
 Key expires at Tue 29 May 2018 06:44:52 PM EEST <br/>
 Is this correct? (y/N) <b style="color: red">y</b> <br/>
@@ -220,34 +220,34 @@ disks) during the prime generation; this gives the random number <br/>
 generator a better chance to gain enough entropy. <br/>
  <br/>
 sec  rsa4096/25FB738D6EE435F7 <br/>
-     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
-     trust: ultimate      validity: ultimate <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trust: ultimate      validity: ultimate <br/>
 ssb  rsa4096/05F88308DFB71774 <br/>
-     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
 [ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi> <br/>
  <br/>
 gpg> <b style="color: red">addkey</b> <br/>
 Please select what kind of key you want: <br/>
-   (3) DSA (sign only) <br/>
-   (4) RSA (sign only <br/>
-   (5) Elgamal (encrypt only) <br/>
-   (6) RSA (encrypt only) <br/>
-   (7) DSA (set your own capabilities) <br/>
-   (8) RSA (set your own capabilities) <br/>
-  (10) ECC (sign only) <br/>
-  (11) ECC (set your own capabilities) <br/>
-  (12) ECC (encrypt only) <br/>
-  (13) Existing key <br/>
+&nbsp;&nbsp;&nbsp;(3) DSA (sign only) <br/>
+&nbsp;&nbsp;&nbsp;(4) RSA (sign only <br/>
+&nbsp;&nbsp;&nbsp;(5) Elgamal (encrypt only) <br/>
+&nbsp;&nbsp;&nbsp;(6) RSA (encrypt only) <br/>
+&nbsp;&nbsp;&nbsp;(7) DSA (set your own capabilities) <br/>
+&nbsp;&nbsp;&nbsp;(8) RSA (set your own capabilities) <br/>
+&nbsp;&nbsp;(10) ECC (sign only) <br/>
+&nbsp;&nbsp;(11) ECC (set your own capabilities) <br/>
+&nbsp;&nbsp;(12) ECC (encrypt only) <br/>
+&nbsp;&nbsp;(13) Existing key <br/>
 Your selection? <b style="color: red">6</b> <br/>
 RSA keys may be between 1024 and 4096 bits long. <br/>
 What keysize do you want? (2048) <b style="color: red">4096</b> <br/>
 Requested keysize is 4096 bits <br/>
 Please specify how long the key should be valid <br/>
-         0 = key does not expire <br/>
-      <n>  = key expires in n days <br/>
-      <n>w = key expires in n weeks <br/>
-      <n>m = key expires in n months <br/>
-      <n>y = key expires in n years <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 = key does not expire <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>  = key expires in n days <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>w = key expires in n weeks <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>m = key expires in n months <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>y = key expires in n years <br/>
 Key is valid for? (0) <b style="color: red">1y</b> <br/>
 Key expires at Tue 29 May 2018 06:45:22 PM EEST <br/>
 Is this correct? (y/N) <b style="color: red">y</b> <br/>
@@ -258,76 +258,76 @@ disks) during the prime generation; this gives the random number <br/>
 generator a better chance to gain enough entropy. <br/>
  <br/>
 sec  rsa4096/25FB738D6EE435F7 <br/>
-     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
-     trust: ultimate      validity: ultimate <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trust: ultimate      validity: ultimate <br/>
 ssb  rsa4096/05F88308DFB71774 <br/>
-     created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: S    <br/>
 ssb  rsa4096/2929E8A96CBA57C7 <br/>
-     created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created: 2017-05-29  expires: 2018-05-29  usage: E    <br/>
 [ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi> <br/>
  <br/>
 gpg> <b style="color: red">addkey</b> <br/>
 Please select what kind of key you want: <br/>
-   (3) DSA (sign only) <br/>
-   (4) RSA (sign only) <br/>
-   (5) Elgamal (encrypt only) <br/>
-   (6) RSA (encrypt only) <br/>
-   (7) DSA (set your own capabilities) <br/>
-   (8) RSA (set your own capabilities) <br/>
-  (10) ECC (sign only) <br/>
-  (11) ECC (set your own capabilities) <br/>
-  (12) ECC (encrypt only) <br/>
-  (13) Existing key <br/>
+&nbsp;&nbsp;&nbsp;(3) DSA (sign only) <br/>
+&nbsp;&nbsp;&nbsp;(4) RSA (sign only) <br/>
+&nbsp;&nbsp;&nbsp;(5) Elgamal (encrypt only) <br/>
+&nbsp;&nbsp;&nbsp;(6) RSA (encrypt only) <br/>
+&nbsp;&nbsp;&nbsp;(7) DSA (set your own capabilities) <br/>
+&nbsp;&nbsp;&nbsp;(8) RSA (set your own capabilities) <br/>
+&nbsp;&nbsp;(10) ECC (sign only) <br/>
+&nbsp;&nbsp;(11) ECC (set your own capabilities) <br/>
+&nbsp;&nbsp;(12) ECC (encrypt only) <br/>
+&nbsp;&nbsp;(13) Existing key <br/>
 Your selection? <b style="color: red">8</b> <br/>
  <br/>
 Possible actions for a RSA key: Sign Encrypt Authenticate  <br/>
 Current allowed actions: Sign Encrypt  <br/>
  <br/>
-   (S) Toggle the sign capability <br/>
-   (E) Toggle the encrypt capability <br/>
-   (A) Toggle the authenticate capability <br/>
-   (Q) Finished <br/>
+&nbsp;&nbsp;&nbsp;(S) Toggle the sign capability <br/>
+&nbsp;&nbsp;&nbsp;(E) Toggle the encrypt capability <br/>
+&nbsp;&nbsp;&nbsp;(A) Toggle the authenticate capability <br/>
+&nbsp;&nbsp;&nbsp;(Q) Finished <br/>
  <br/>
 Your selection? <b style="color: red">a</b> <br/>
  <br/>
 Possible actions for a RSA key: Sign Encrypt Authenticate  <br/>
 Current allowed actions: Sign Encrypt Authenticate  <br/>
  <br/>
-   (S) Toggle the sign capability <br/>
-   (E) Toggle the encrypt capability <br/>
-   (A) Toggle the authenticate capability <br/>
-   (Q) Finished <br/>
+&nbsp;&nbsp;&nbsp;(S) Toggle the sign capability <br/>
+&nbsp;&nbsp;&nbsp;(E) Toggle the encrypt capability <br/>
+&nbsp;&nbsp;&nbsp;(A) Toggle the authenticate capability <br/>
+&nbsp;&nbsp;&nbsp;(Q) Finished <br/>
  <br/>
 Your selection? <b style="color: red">s</b> <br/>
  <br/>
 Possible actions for a RSA key: Sign Encrypt Authenticate  <br/>
 Current allowed actions: Encrypt Authenticate  <br/>
  <br/>
-   (S) Toggle the sign capability <br/>
-   (E) Toggle the encrypt capability <br/>
-   (A) Toggle the authenticate capability <br/>
-   (Q) Finished <br/>
+&nbsp;&nbsp;&nbsp;(S) Toggle the sign capability <br/>
+&nbsp;&nbsp;&nbsp;(E) Toggle the encrypt capability <br/>
+&nbsp;&nbsp;&nbsp;(A) Toggle the authenticate capability <br/>
+&nbsp;&nbsp;&nbsp;(Q) Finished <br/>
  <br/>
 Your selection? <b style="color: red">e</b> <br/>
  <br/>
 Possible actions for a RSA key: Sign Encrypt Authenticate  <br/>
 Current allowed actions: Authenticate  <br/>
  <br/>
-   (S) Toggle the sign capability <br/>
-   (E) Toggle the encrypt capability <br/>
-   (A) Toggle the authenticate capability <br/>
-   (Q) Finished <br/>
+&nbsp;&nbsp;&nbsp;(S) Toggle the sign capability <br/>
+&nbsp;&nbsp;&nbsp;(E) Toggle the encrypt capability <br/>
+&nbsp;&nbsp;&nbsp;(A) Toggle the authenticate capability <br/>
+&nbsp;&nbsp;&nbsp;(Q) Finished <br/>

(Diff truncated)
Markup another block
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 1e739b3..aaab34e 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -176,179 +176,179 @@ uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
   listing, `A734C10BF2DF39D19DC0F6C025FB738D6EE435F7` above). Use the
   `--expert` option to be able to add an authenticaion-only subkey.
 
-        $ gpg --edit-key --expert A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
-        gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
-        This is free software: you are free to change and redistribute it.
-        There is NO WARRANTY, to the extent permitted by law.
-        
-        Secret key is available.
-        
-        sec  rsa4096/25FB738D6EE435F7
-             created: 2017-05-29  expires: 2018-05-29  usage: SC  
-             trust: ultimate      validity: ultimate
-        [ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi>
-        
-        gpg> addkey
-        Please select what kind of key you want:
-           (3) DSA (sign only)
-           (4) RSA (sign only)
-           (5) Elgamal (encrypt only)
-           (6) RSA (encrypt only)
-           (7) DSA (set your own capabilities)
-           (8) RSA (set your own capabilities)
-          (10) ECC (sign only)
-          (11) ECC (set your own capabilities)
-          (12) ECC (encrypt only)
-          (13) Existing key
-        Your selection? 4
-        RSA keys may be between 1024 and 4096 bits long.
-        What keysize do you want? (2048) 4096
-        Requested keysize is 4096 bits
-        Please specify how long the key should be valid.
-                 0 = key does not expire
-              <n>  = key expires in n days
-              <n>w = key expires in n weeks
-              <n>m = key expires in n months
-              <n>y = key expires in n years
-        Key is valid for? (0) 1y
-        Key expires at Tue 29 May 2018 06:44:52 PM EEST
-        Is this correct? (y/N) y
-        Really create? (y/N) y
-        We need to generate a lot of random bytes. It is a good idea to perform
-        some other action (type on the keyboard, move the mouse, utilize the
-        disks) during the prime generation; this gives the random number
-        generator a better chance to gain enough entropy.
-        
-        sec  rsa4096/25FB738D6EE435F7
-             created: 2017-05-29  expires: 2018-05-29  usage: SC  
-             trust: ultimate      validity: ultimate
-        ssb  rsa4096/05F88308DFB71774
-             created: 2017-05-29  expires: 2018-05-29  usage: S   
-        [ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi>
-        
-        gpg> addkey
-        Please select what kind of key you want:
-           (3) DSA (sign only)
-           (4) RSA (sign only
-           (5) Elgamal (encrypt only)
-           (6) RSA (encrypt only)
-           (7) DSA (set your own capabilities)
-           (8) RSA (set your own capabilities)
-          (10) ECC (sign only)
-          (11) ECC (set your own capabilities)
-          (12) ECC (encrypt only)
-          (13) Existing key
-        Your selection? 6
-        RSA keys may be between 1024 and 4096 bits long.
-        What keysize do you want? (2048) 4096
-        Requested keysize is 4096 bits
-        Please specify how long the key should be valid
-                 0 = key does not expire
-              <n>  = key expires in n days
-              <n>w = key expires in n weeks
-              <n>m = key expires in n months
-              <n>y = key expires in n years
-        Key is valid for? (0) 1y
-        Key expires at Tue 29 May 2018 06:45:22 PM EEST
-        Is this correct? (y/N) y
-        Really create? (y/N) y
-        We need to generate a lot of random bytes. It is a good idea to perform
-        some other action (type on the keyboard, move the mouse, utilize the
-        disks) during the prime generation; this gives the random number
-        generator a better chance to gain enough entropy.
-        
-        sec  rsa4096/25FB738D6EE435F7
-             created: 2017-05-29  expires: 2018-05-29  usage: SC  
-             trust: ultimate      validity: ultimate
-        ssb  rsa4096/05F88308DFB71774
-             created: 2017-05-29  expires: 2018-05-29  usage: S   
-        ssb  rsa4096/2929E8A96CBA57C7
-             created: 2017-05-29  expires: 2018-05-29  usage: E   
-        [ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi>
-        
-        gpg> addkey
-        Please select what kind of key you want:
-           (3) DSA (sign only)
-           (4) RSA (sign only)
-           (5) Elgamal (encrypt only)
-           (6) RSA (encrypt only)
-           (7) DSA (set your own capabilities)
-           (8) RSA (set your own capabilities)
-          (10) ECC (sign only)
-          (11) ECC (set your own capabilities)
-          (12) ECC (encrypt only)
-          (13) Existing key
-        Your selection? 8
-        
-        Possible actions for a RSA key: Sign Encrypt Authenticate 
-        Current allowed actions: Sign Encrypt 
-        
-           (S) Toggle the sign capability
-           (E) Toggle the encrypt capability
-           (A) Toggle the authenticate capability
-           (Q) Finished
-        
-        Your selection? a
-        
-        Possible actions for a RSA key: Sign Encrypt Authenticate 
-        Current allowed actions: Sign Encrypt Authenticate 
-        
-           (S) Toggle the sign capability
-           (E) Toggle the encrypt capability
-           (A) Toggle the authenticate capability
-           (Q) Finished
-        
-        Your selection? s
-        
-        Possible actions for a RSA key: Sign Encrypt Authenticate 
-        Current allowed actions: Encrypt Authenticate 
-        
-           (S) Toggle the sign capability
-           (E) Toggle the encrypt capability
-           (A) Toggle the authenticate capability
-           (Q) Finished
-        
-        Your selection? e
-        
-        Possible actions for a RSA key: Sign Encrypt Authenticate 
-        Current allowed actions: Authenticate 
-        
-           (S) Toggle the sign capability
-           (E) Toggle the encrypt capability
-           (A) Toggle the authenticate capability
-           (Q) Finished
-        
-        Your selection? q
-        RSA keys may be btween 1024 and 4096 bits long.
-        What keysize do you want? (2048) 4096
-        Requested keysize is 4096 bits
-        Please specify how long the key should be valid.
-                 0 = key does not expire
-              <n>  = key expires in n days
-              <n>w = key expires in n weeks
-              <n>m = key expires in n months
-              <n>y = key expires in n years
-        Key is valid for? (0) 1y
-        Key expires at Tue 29 May 2018 06:45:56 PM EEST
-        Is this correct? (y/N) y
-        Really create? (y/N) y
-        We need to generate a lot of random bytes. It is a good idea to perform
-        some other action (type on the keyboard, move the mouse, utilize the
-        disks) during the prime generation; this gives the random number
-        generator a better chance to gain enough entropy.
-        
-        sec  rsa4096/25FB738D6EE435F7
-             created: 2017-05-29  expires: 2018-05-29  usage: SC  
-             trust: ultimate      validity: ultimate
-        ssb  rsa4096/05F88308DFB71774
-             created: 2017-05-29  expires: 2018-05-29  usage: S   
-        ssb  rsa4096/2929E8A96CBA57C7
-             created: 2017-05-29  expires: 2018-05-29  usage: E   
-        ssb  rsa4096/4477EB0AEF1C440A
-             created: 2017-05-29  expires: 2018-05-29  usage: A   
-        [ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi>
-        
-        gpg> save
+<blockquote><code>$ <b style="color: red">gpg --edit-key --expert A734C10BF2DF39D19DC0F6C025FB738D6EE435F7z</b> <br/>
+gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
+This is free software: you are free to change and redistribute it. <br/>
+There is NO WARRANTY, to the extent permitted by law. <br/>
+ <br/>
+Secret key is available. <br/>
+ <br/>
+sec  rsa4096/25FB738D6EE435F7 <br/>
+     created: 2017-05-29  expires: 2018-05-29  usage: SC   <br/>
+     trust: ultimate      validity: ultimate <br/>
+[ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi> <br/>
+ <br/>
+gpg> <b style="color: red">addkey</b> <br/>
+Please select what kind of key you want: <br/>
+   (3) DSA (sign only) <br/>
+   (4) RSA (sign only) <br/>
+   (5) Elgamal (encrypt only) <br/>
+   (6) RSA (encrypt only) <br/>
+   (7) DSA (set your own capabilities) <br/>

(Diff truncated)
Note what the key id in the example is
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 0c2c31f..1e739b3 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -173,8 +173,8 @@ uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
 
 * You now have the signing-only master key. You should now create
   three subkeys (`keyid` is the key identifier shown in the key
-  listing). Use the `--expert` option to be able to add an
-  authenticaion-only subkey.
+  listing, `A734C10BF2DF39D19DC0F6C025FB738D6EE435F7` above). Use the
+  `--expert` option to be able to add an authenticaion-only subkey.
 
         $ gpg --edit-key --expert A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
         gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.

Mark key id in italic
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index e671ff5..0c2c31f 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -168,7 +168,7 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
 /home/liw/.gnupg/pubring.kbx <br/>
 ---------------------------- <br/>
 sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>A734C10BF2DF39D19DC0F6C025FB738D6EE435F7</i> <br/>
 uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi> </code></blockquote>
 
 * You now have the signing-only master key. You should now create

Fix indentation
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 671202d..e671ff5 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -168,7 +168,7 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
 /home/liw/.gnupg/pubring.kbx <br/>
 ---------------------------- <br/>
 sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
-      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
 uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi> </code></blockquote>
 
 * You now have the signing-only master key. You should now create

Markup another code block
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 80e06cd..671202d 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -164,12 +164,12 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
 
 * Review the key:
 
-        $ gpg --list-secret-keys
-        /home/liw/.gnupg/pubring.kbx
-        ----------------------------
-        sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29]
-              A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
-        uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi>
+<blockquote><code> $ <b style="color: red">gpg --list-secret-keys</b> <br/>
+/home/liw/.gnupg/pubring.kbx <br/>
+---------------------------- <br/>
+sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
+      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
+uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi> </code></blockquote>
 
 * You now have the signing-only master key. You should now create
   three subkeys (`keyid` is the key identifier shown in the key

Change markup for list to be bullets, not numbers
Markdown gets the numbering wrong.
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 563656c..80e06cd 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -94,11 +94,11 @@ The process outline is:
 
 The process in more detail:
 
-1. Configure GnuPG with regards to checksum and encryption algorithms.
-   You can use the defaults, but depending on the version of GnuPG you
-   have, they may be weaker than is recommended.
-   FIXME: Give ref to where these come from.
-   Add the following lines to `~/.gnupg/gpg.conf`:
+* Configure GnuPG with regards to checksum and encryption algorithms.
+  You can use the defaults, but depending on the version of GnuPG you
+  have, they may be weaker than is recommended.
+  FIXME: Give ref to where these come from.
+  Add the following lines to `~/.gnupg/gpg.conf`:
 
         personal-digest-preferences SHA512
         cert-digest-algo SHA512
@@ -106,7 +106,7 @@ The process in more detail:
         personal-cipher-preferences TWOFISH CAMELLIA256 AES 3DES
         keyserver pool.sks-keyservers.net
 
-1. Create new sign-only master key.
+* Create new sign-only master key.
 
 <blockquote><code>$ <b style="color: red">gpg --full-generate-key</b> <br/>
 gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
@@ -157,12 +157,12 @@ pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
 uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockquote>
 
-1. Note that I set a 1-year expiration for they key. The expiration
-   can be extended at any time (if you have the master secret key),
-   but unless you do, the key won't accidentally live longer than the
-   chosen time.
+* Note that I set a 1-year expiration for they key. The expiration
+  can be extended at any time (if you have the master secret key),
+  but unless you do, the key won't accidentally live longer than the
+  chosen time.
 
-1. Review the key:
+* Review the key:
 
         $ gpg --list-secret-keys
         /home/liw/.gnupg/pubring.kbx
@@ -171,10 +171,10 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
               A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
         uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi>
 
-1. You now have the signing-only master key. You should now create
-   three subkeys (`keyid` is the key identifier shown in the key
-   listing). Use the `--expert` option to be able to add an
-   authenticaion-only subkey.
+* You now have the signing-only master key. You should now create
+  three subkeys (`keyid` is the key identifier shown in the key
+  listing). Use the `--expert` option to be able to add an
+  authenticaion-only subkey.
 
         $ gpg --edit-key --expert A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
         gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
@@ -350,14 +350,14 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
         
         gpg> save
 
-1. You now have a master key and three subkeys. They are hidden in the
-   `~/.gnupg` directory. It is time to "export" the secret keys out
-   from there.
+* You now have a master key and three subkeys. They are hidden in the
+  `~/.gnupg` directory. It is time to "export" the secret keys out
+  from there.
 
         $ gpg --export-secret-key --armor keyid > master.key
         $ gpg --export-secret-subkeys --armor keyid > subkeys.key
 
-1. You should keep these files safe. You don't want to lose them, and
+*  You should keep these files safe. You don't want to lose them, and
    you don't want anyone else to get access to them. I recommend you
    format two USB memory sticks, format them using full-disk
    encryption, and copy the exported files to both of them. Then keep
@@ -366,7 +366,7 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
    There's ways of making this part more sophisticated, but that's for
    another time.
 
-1. The next step involves some hoop-jumping. What we want is to have
+*  The next step involves some hoop-jumping. What we want is to have
    the master secret key NOT on you machine, so we tell GnuPG to
    remove it. We exported it above, so we won't lose it. However,
    deleting the master secret key also removes the secret subkeys. But
@@ -375,7 +375,7 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
         $ gpg --delete-secret-key keyid
         $ gpg --import subkeys.key
 
-1. Now verify that you have the secret subkeys, but not the master
+*  Now verify that you have the secret subkeys, but not the master
    key. There should be one line starting with `sec#` (note the hash
    mark, which indicates the key isn't available), and three lines
    starting with `ssb` (no hash mark).
@@ -390,7 +390,7 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
         ssb   rsa4096 2017-05-29 [E] [expires: 2018-05-29]
         ssb   rsa4096 2017-05-29 [A] [expires: 2018-05-29]
 
-1. Now insert the Yubikey in a USB slot. We can start transferring the
+*  Now insert the Yubikey in a USB slot. We can start transferring the
    secret subkeys to the Yubikey. If you want, you can set your name
    and other information, and change PIN codes. There's several types
    of PIN codes: normal use, unblocking a locked card, and a third PIN
@@ -401,20 +401,20 @@ uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockqu
         $ gpg --card-edit
         ...
 
-1. Actually move the subkeys to the card. Note that this does a move,
+*  Actually move the subkeys to the card. Note that this does a move,
    not a copy, and the subkeys will be removed from your `~/.gnupg`
    (check with `gpg -K`).
 
         $ gpg --edit-key keyid
         ...
 
-1. If you want to use several Yubikeys, or have a spare one just in
+*  If you want to use several Yubikeys, or have a spare one just in
    case, repeate the previous four steps (starting from importing
    subkeys back into `~/.gnupg`).
 
-1. You're now done, as far GnuPG use is concerned. Any time you need
+*  You're now done, as far GnuPG use is concerned. Any time you need
    to sign, encrypt, or decrypt something, GnuPG will look for your
    subkeys on the Yubikey, and will tell you to insert it in a USB
    port if it can't find the key.
 
-1. FIXME: Add notes for how to set up gpg-agent as an ssh-agent.
+*  FIXME: Add notes for how to set up gpg-agent as an ssh-agent.

Fix indents
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index e7e4a19..563656c 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -112,22 +112,22 @@ The process in more detail:
 gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
 This is free software: you are free to change and redistribute it. <br/>
 There is NO WARRANTY, to the extent permitted by law. <br/>
- <br/>
+&nbsp;<br/>
 Please select what kind of key you want: <br/>
-   (1) RSA and RSA (default) <br/>
-   (2) DSA and Elgamal <br/>
-   (3) DSA (sign only) <br/>
-   (4) RSA (sign only) <br/>
+&nbsp;&nbsp;&nbsp;(1) RSA and RSA (default) <br/>
+&nbsp;&nbsp;&nbsp;(2) DSA and Elgamal <br/>
+&nbsp;&nbsp;&nbsp;(3) DSA (sign only) <br/>
+&nbsp;&nbsp;&nbsp;(4) RSA (sign only) <br/>
 Your selection? <b style="color: red">4</b> <br/>
 RSA keys may be between 1024 and 4096 bits long. <br/>
 What keysize do you want? (2048) <b style="color: red">4096</b> <br/>
 Requested keysize is 4096 bits <br/>
 Please specify how long the key should be valid. <br/>
-         0 = key does not expire <br/>
-      <n>  = key expires in n days <br/>
-      <n>w = key expires in n weeks <br/>
-      <n>m = key expires in n months <br/>
-      <n>y = key expires in n years <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 = key does not expire <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>  = key expires in n days <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>w = key expires in n weeks <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>m = key expires in n months <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<n>y = key expires in n years <br/>
 Key is valid for? (0) <b style="color: red">1y</b> <br/>
 Key expires at Tue 29 May 2018 06:43:54 PM EEST <br/>
 Is this correct? (y/N) <b style="color: red">y</b> <br/>
@@ -138,7 +138,7 @@ Real name: <b style="color: red">Lars Wirzenius</b> <br/>
 Email address: <b style="color: red">liw@liw.fi</b> <br/>
 Comment: <b style="color: red">test key</b> <br/>
 You selected this USER-ID: <br/>
-    "Lars Wirzenius (test key) <liw@liw.fi>" <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;"Lars Wirzenius (test key) <liw@liw.fi>" <br/>
  <br/>
 Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? <b style="color: red">o</b> <br/>
 We need to generate a lot of random bytes. It is a good idea to perform <br/>
@@ -153,8 +153,8 @@ public and secret key created and signed. <br/>
 Note that this key cannot be used for encryption.  You may want to use <br/>
 the command "--edit-key" to generate a subkey for this purpose. <br/>
 pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
-      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
-      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
 uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockquote>
 
 1. Note that I set a 1-year expiration for they key. The expiration

Drop prompt at end
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 8ed84d1..e7e4a19 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -155,9 +155,7 @@ the command "--edit-key" to generate a subkey for this purpose. <br/>
 pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
       A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
       A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
-uid                      Lars Wirzenius (test key) <liw@liw.fi> <br/>
- <br/>
-$</code></blockquote>
+uid                      Lars Wirzenius (test key) <liw@liw.fi> </code></blockquote>
 
 1. Note that I set a 1-year expiration for they key. The expiration
    can be extended at any time (if you have the master secret key),

Add more red to boldface
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index ebd9894..8ed84d1 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -118,9 +118,9 @@ Please select what kind of key you want: <br/>
    (2) DSA and Elgamal <br/>
    (3) DSA (sign only) <br/>
    (4) RSA (sign only) <br/>
-Your selection? <b>4</b> <br/>
+Your selection? <b style="color: red">4</b> <br/>
 RSA keys may be between 1024 and 4096 bits long. <br/>
-What keysize do you want? (2048) <b>4096</b> <br/>
+What keysize do you want? (2048) <b style="color: red">4096</b> <br/>
 Requested keysize is 4096 bits <br/>
 Please specify how long the key should be valid. <br/>
          0 = key does not expire <br/>
@@ -128,19 +128,19 @@ Please specify how long the key should be valid. <br/>
       <n>w = key expires in n weeks <br/>
       <n>m = key expires in n months <br/>
       <n>y = key expires in n years <br/>
-Key is valid for? (0) <b>1y</b> <br/>
+Key is valid for? (0) <b style="color: red">1y</b> <br/>
 Key expires at Tue 29 May 2018 06:43:54 PM EEST <br/>
-Is this correct? (y/N) <b>y</b> <br/>
+Is this correct? (y/N) <b style="color: red">y</b> <br/>
  <br/>
 GnuPG needs to construct a user ID to identify your key. <br/>
  <br/>
-Real name: <b>Lars Wirzenius</b> <br/>
-Email address: <b>liw@liw.fi</b> <br/>
-Comment: <b>test key</b> <br/>
+Real name: <b style="color: red">Lars Wirzenius</b> <br/>
+Email address: <b style="color: red">liw@liw.fi</b> <br/>
+Comment: <b style="color: red">test key</b> <br/>
 You selected this USER-ID: <br/>
     "Lars Wirzenius (test key) <liw@liw.fi>" <br/>
  <br/>
-Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? <b>o</b> <br/>
+Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? <b style="color: red">o</b> <br/>
 We need to generate a lot of random bytes. It is a good idea to perform <br/>
 some other action (type on the keyboard, move the mouse, utilize the <br/>
 disks) during the prime generation; this gives the random number <br/>

Would red work?
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 6a17999..ebd9894 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -108,7 +108,7 @@ The process in more detail:
 
 1. Create new sign-only master key.
 
-<blockquote><code>$ <b>gpg --full-generate-key</b> <br/>
+<blockquote><code>$ <b style="color: red">gpg --full-generate-key</b> <br/>
 gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
 This is free software: you are free to change and redistribute it. <br/>
 There is NO WARRANTY, to the extent permitted by law. <br/>

Markup more as boldface
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index d28b647..6a17999 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -112,15 +112,15 @@ The process in more detail:
 gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
 This is free software: you are free to change and redistribute it. <br/>
 There is NO WARRANTY, to the extent permitted by law. <br/>
-&nbsp; <br/>
+ <br/>
 Please select what kind of key you want: <br/>
    (1) RSA and RSA (default) <br/>
    (2) DSA and Elgamal <br/>
    (3) DSA (sign only) <br/>
    (4) RSA (sign only) <br/>
-Your selection? 4 <br/>
+Your selection? <b>4</b> <br/>
 RSA keys may be between 1024 and 4096 bits long. <br/>
-What keysize do you want? (2048) 4096 <br/>
+What keysize do you want? (2048) <b>4096</b> <br/>
 Requested keysize is 4096 bits <br/>
 Please specify how long the key should be valid. <br/>
          0 = key does not expire <br/>
@@ -128,19 +128,19 @@ Please specify how long the key should be valid. <br/>
       <n>w = key expires in n weeks <br/>
       <n>m = key expires in n months <br/>
       <n>y = key expires in n years <br/>
-Key is valid for? (0) 1y <br/>
+Key is valid for? (0) <b>1y</b> <br/>
 Key expires at Tue 29 May 2018 06:43:54 PM EEST <br/>
-Is this correct? (y/N) y <br/>
+Is this correct? (y/N) <b>y</b> <br/>
  <br/>
 GnuPG needs to construct a user ID to identify your key. <br/>
  <br/>
-Real name: Lars Wirzenius <br/>
-Email address: liw@liw.fi <br/>
-Comment: test key <br/>
+Real name: <b>Lars Wirzenius</b> <br/>
+Email address: <b>liw@liw.fi</b> <br/>
+Comment: <b>test key</b> <br/>
 You selected this USER-ID: <br/>
     "Lars Wirzenius (test key) <liw@liw.fi>" <br/>
  <br/>
-Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o <br/>
+Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? <b>o</b> <br/>
 We need to generate a lot of random bytes. It is a good idea to perform <br/>
 some other action (type on the keyboard, move the mouse, utilize the <br/>
 disks) during the prime generation; this gives the random number <br/>

Add nbsp; to force empty line
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 585805a..d28b647 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -112,7 +112,7 @@ The process in more detail:
 gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
 This is free software: you are free to change and redistribute it. <br/>
 There is NO WARRANTY, to the extent permitted by law. <br/>
- <br/>
+&nbsp; <br/>
 Please select what kind of key you want: <br/>
    (1) RSA and RSA (default) <br/>
    (2) DSA and Elgamal <br/>

Start using boldface to indicate user input
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index eff78c5..585805a 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -108,7 +108,7 @@ The process in more detail:
 
 1. Create new sign-only master key.
 
-<blockquote><code>$ gpg --full-generate-key <br/>
+<blockquote><code>$ <b>gpg --full-generate-key</b> <br/>
 gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
 This is free software: you are free to change and redistribute it. <br/>
 There is NO WARRANTY, to the extent permitted by law. <br/>

Use <code>
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index e4f0307..eff78c5 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -108,7 +108,7 @@ The process in more detail:
 
 1. Create new sign-only master key.
 
-<blockquote>$ gpg --full-generate-key <br/>
+<blockquote><code>$ gpg --full-generate-key <br/>
 gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
 This is free software: you are free to change and redistribute it. <br/>
 There is NO WARRANTY, to the extent permitted by law. <br/>
@@ -157,7 +157,7 @@ pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
       A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
 uid                      Lars Wirzenius (test key) <liw@liw.fi> <br/>
  <br/>
-$</blockquote>
+$</code></blockquote>
 
 1. Note that I set a 1-year expiration for they key. The expiration
    can be extended at any time (if you have the master secret key),

Add <br> to force linebreaks
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index ddb22b9..e4f0307 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -108,55 +108,55 @@ The process in more detail:
 
 1. Create new sign-only master key.
 
-<blockquote>$ gpg --full-generate-key
-gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
-This is free software: you are free to change and redistribute it.
-There is NO WARRANTY, to the extent permitted by law.
-
-Please select what kind of key you want:
-   (1) RSA and RSA (default)
-   (2) DSA and Elgamal
-   (3) DSA (sign only)
-   (4) RSA (sign only)
-Your selection? 4
-RSA keys may be between 1024 and 4096 bits long.
-What keysize do you want? (2048) 4096
-Requested keysize is 4096 bits
-Please specify how long the key should be valid.
-         0 = key does not expire
-      <n>  = key expires in n days
-      <n>w = key expires in n weeks
-      <n>m = key expires in n months
-      <n>y = key expires in n years
-Key is valid for? (0) 1y
-Key expires at Tue 29 May 2018 06:43:54 PM EEST
-Is this correct? (y/N) y
-
-GnuPG needs to construct a user ID to identify your key.
-
-Real name: Lars Wirzenius
-Email address: liw@liw.fi
-Comment: test key
-You selected this USER-ID:
-    "Lars Wirzenius (test key) <liw@liw.fi>"
-
-Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
-We need to generate a lot of random bytes. It is a good idea to perform
-some other action (type on the keyboard, move the mouse, utilize the
-disks) during the prime generation; this gives the random number
-generator a better chance to gain enough entropy.
-gpg: key 25FB738D6EE435F7 marked as ultimately trusted
-gpg: directory '/home/liw/.gnupg/openpgp-revocs.d' created
-gpg: revocation certificate stored as '/home/liw/.gnupg/openpgp-revocs.d/A734C10BF2DF39D19DC0F6C025FB738D6EE435F7.rev'
-public and secret key created and signed.
-
-Note that this key cannot be used for encryption.  You may want to use
-the command "--edit-key" to generate a subkey for this purpose.
-pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29]
-      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
-      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
-uid                      Lars Wirzenius (test key) <liw@liw.fi>
-
+<blockquote>$ gpg --full-generate-key <br/>
+gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc. <br/>
+This is free software: you are free to change and redistribute it. <br/>
+There is NO WARRANTY, to the extent permitted by law. <br/>
+ <br/>
+Please select what kind of key you want: <br/>
+   (1) RSA and RSA (default) <br/>
+   (2) DSA and Elgamal <br/>
+   (3) DSA (sign only) <br/>
+   (4) RSA (sign only) <br/>
+Your selection? 4 <br/>
+RSA keys may be between 1024 and 4096 bits long. <br/>
+What keysize do you want? (2048) 4096 <br/>
+Requested keysize is 4096 bits <br/>
+Please specify how long the key should be valid. <br/>
+         0 = key does not expire <br/>
+      <n>  = key expires in n days <br/>
+      <n>w = key expires in n weeks <br/>
+      <n>m = key expires in n months <br/>
+      <n>y = key expires in n years <br/>
+Key is valid for? (0) 1y <br/>
+Key expires at Tue 29 May 2018 06:43:54 PM EEST <br/>
+Is this correct? (y/N) y <br/>
+ <br/>
+GnuPG needs to construct a user ID to identify your key. <br/>
+ <br/>
+Real name: Lars Wirzenius <br/>
+Email address: liw@liw.fi <br/>
+Comment: test key <br/>
+You selected this USER-ID: <br/>
+    "Lars Wirzenius (test key) <liw@liw.fi>" <br/>
+ <br/>
+Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o <br/>
+We need to generate a lot of random bytes. It is a good idea to perform <br/>
+some other action (type on the keyboard, move the mouse, utilize the <br/>
+disks) during the prime generation; this gives the random number <br/>
+generator a better chance to gain enough entropy. <br/>
+gpg: key 25FB738D6EE435F7 marked as ultimately trusted <br/>
+gpg: directory '/home/liw/.gnupg/openpgp-revocs.d' created <br/>
+gpg: revocation certificate stored as '/home/liw/.gnupg/openpgp-revocs.d/A734C10BF2DF39D19DC0F6C025FB738D6EE435F7.rev' <br/>
+public and secret key created and signed. <br/>
+ <br/>
+Note that this key cannot be used for encryption.  You may want to use <br/>
+the command "--edit-key" to generate a subkey for this purpose. <br/>
+pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29] <br/>
+      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
+      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7 <br/>
+uid                      Lars Wirzenius (test key) <liw@liw.fi> <br/>
+ <br/>
 $</blockquote>
 
 1. Note that I set a 1-year expiration for they key. The expiration

Use <blockquote> instead of indent
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index b697ea4..ddb22b9 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -108,56 +108,56 @@ The process in more detail:
 
 1. Create new sign-only master key.
 
-        $ gpg --full-generate-key
-        gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
-        This is free software: you are free to change and redistribute it.
-        There is NO WARRANTY, to the extent permitted by law.
-
-        Please select what kind of key you want:
-           (1) RSA and RSA (default)
-           (2) DSA and Elgamal
-           (3) DSA (sign only)
-           (4) RSA (sign only)
-        Your selection? 4
-        RSA keys may be between 1024 and 4096 bits long.
-        What keysize do you want? (2048) 4096
-        Requested keysize is 4096 bits
-        Please specify how long the key should be valid.
-                 0 = key does not expire
-              <n>  = key expires in n days
-              <n>w = key expires in n weeks
-              <n>m = key expires in n months
-              <n>y = key expires in n years
-        Key is valid for? (0) 1y
-        Key expires at Tue 29 May 2018 06:43:54 PM EEST
-        Is this correct? (y/N) y
-
-        GnuPG needs to construct a user ID to identify your key.
-
-        Real name: Lars Wirzenius
-        Email address: liw@liw.fi
-        Comment: test key
-        You selected this USER-ID:
-            "Lars Wirzenius (test key) <liw@liw.fi>"
-
-        Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
-        We need to generate a lot of random bytes. It is a good idea to perform
-        some other action (type on the keyboard, move the mouse, utilize the
-        disks) during the prime generation; this gives the random number
-        generator a better chance to gain enough entropy.
-        gpg: key 25FB738D6EE435F7 marked as ultimately trusted
-        gpg: directory '/home/liw/.gnupg/openpgp-revocs.d' created
-        gpg: revocation certificate stored as '/home/liw/.gnupg/openpgp-revocs.d/A734C10BF2DF39D19DC0F6C025FB738D6EE435F7.rev'
-        public and secret key created and signed.
-
-        Note that this key cannot be used for encryption.  You may want to use
-        the command "--edit-key" to generate a subkey for this purpose.
-        pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29]
-              A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
-              A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
-        uid                      Lars Wirzenius (test key) <liw@liw.fi>
-
-        $ 
+<blockquote>$ gpg --full-generate-key
+gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+Please select what kind of key you want:
+   (1) RSA and RSA (default)
+   (2) DSA and Elgamal
+   (3) DSA (sign only)
+   (4) RSA (sign only)
+Your selection? 4
+RSA keys may be between 1024 and 4096 bits long.
+What keysize do you want? (2048) 4096
+Requested keysize is 4096 bits
+Please specify how long the key should be valid.
+         0 = key does not expire
+      <n>  = key expires in n days
+      <n>w = key expires in n weeks
+      <n>m = key expires in n months
+      <n>y = key expires in n years
+Key is valid for? (0) 1y
+Key expires at Tue 29 May 2018 06:43:54 PM EEST
+Is this correct? (y/N) y
+
+GnuPG needs to construct a user ID to identify your key.
+
+Real name: Lars Wirzenius
+Email address: liw@liw.fi
+Comment: test key
+You selected this USER-ID:
+    "Lars Wirzenius (test key) <liw@liw.fi>"
+
+Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
+We need to generate a lot of random bytes. It is a good idea to perform
+some other action (type on the keyboard, move the mouse, utilize the
+disks) during the prime generation; this gives the random number
+generator a better chance to gain enough entropy.
+gpg: key 25FB738D6EE435F7 marked as ultimately trusted
+gpg: directory '/home/liw/.gnupg/openpgp-revocs.d' created
+gpg: revocation certificate stored as '/home/liw/.gnupg/openpgp-revocs.d/A734C10BF2DF39D19DC0F6C025FB738D6EE435F7.rev'
+public and secret key created and signed.
+
+Note that this key cannot be used for encryption.  You may want to use
+the command "--edit-key" to generate a subkey for this purpose.
+pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29]
+      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
+      A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
+uid                      Lars Wirzenius (test key) <liw@liw.fi>
+
+$</blockquote>
 
 1. Note that I set a 1-year expiration for they key. The expiration
    can be extended at any time (if you have the master secret key),

Add fixme for markup
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 788d402..b697ea4 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -2,6 +2,10 @@
 [[!meta date="2017-05-29 18:03"]]
 [[!tag draft yubikey gpg]]
 
+FIXME: The long terminal session listings need a way to mark up
+(boldface?) the parts the user types, but a code block in markdown
+doesn't allow that.
+
 I've written before about [using a U2F key with PAM][]. This post
 continue the theme and explains how to use a smartcard with GnuPG for
 storing OpenPGP private keys. Specifically, a Yubikey 4 card, because

Start section on why smartcard for gpg
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 609da4e..788d402 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -12,6 +12,9 @@ handle keys up to 2095 bits.
 
 [using a U2F key with PAM]: https://blog.liw.fi/posts/u2f-pam/
 
+The reason to do this is to make it harder for an attacker to steal
+your encryption keys. FIXME: Expand on this section.
+
 I will assume you don't already have an OpenPGP key. You will need:
 
 * A Yubikey 4 (or other GnuPG compatible smartcard).

creating tag page tag/yubikey
diff --git a/tag/yubikey.mdwn b/tag/yubikey.mdwn
new file mode 100644
index 0000000..c401f56
--- /dev/null
+++ b/tag/yubikey.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged yubikey"]]
+
+[[!inline pages="tagged(yubikey)" actions="no" archive="yes"
+feedshow=10]]

Add tags
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
index 94a78c7..609da4e 100644
--- a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Using a Yubikey 4 for ensafening one's encryption"]]
 [[!meta date="2017-05-29 18:03"]]
-[[!tag ]]
+[[!tag draft yubikey gpg]]
 
 I've written before about [using a U2F key with PAM][]. This post
 continue the theme and explains how to use a smartcard with GnuPG for

Publish log entry
diff --git a/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
new file mode 100644
index 0000000..94a78c7
--- /dev/null
+++ b/posts/2017/05/29/using_a_yubikey_4_for_ensafening_one_s_encryption.mdwn
@@ -0,0 +1,415 @@
+[[!meta title="Using a Yubikey 4 for ensafening one's encryption"]]
+[[!meta date="2017-05-29 18:03"]]
+[[!tag ]]
+
+I've written before about [using a U2F key with PAM][]. This post
+continue the theme and explains how to use a smartcard with GnuPG for
+storing OpenPGP private keys. Specifically, a Yubikey 4 card, because
+that's what I have, but any good GnuPG compatible card should work.
+The Yubikey is both a GnuPG compatible smart card, and a U2F card. The
+Yubikey 4 can handle keys up to 4096 bits. Older Yubikeys can only
+handle keys up to 2095 bits.
+
+[using a U2F key with PAM]: https://blog.liw.fi/posts/u2f-pam/
+
+I will assume you don't already have an OpenPGP key. You will need:
+
+* A Yubikey 4 (or other GnuPG compatible smartcard).
+* Two USB memory sticks to store master copies of the key you create.
+* Either a lot of patience, or a [ChaosKey][] or something else
+  to generate a lot of entropy for the kernel. Entropy is used by
+  GnuPG to create encryption keys.
+
+Some terminology:
+
+* OpenPGP is a standard of encryption keys.
+
+* GnuPG (also known as GPG or gpg) is an encryption program that
+  supports OpenPGP.
+
+* Encryption key or key pair is a secret and a public key for
+  encryption. Key and key pair are often used as synonyms.
+
+* The secret keys is yours, and only you will have it or be able to
+  you use. The public key is public, anyone can have a copy. The two
+  are linked and you can't create a secret key linked to a public key.
+  (If you can, you will become a famous cryptographer. Like Isaac
+  Newton famous among apple growers.)
+
+* Master key is the important thing to keep track of. In the
+  encryption world, the master key is what identifies you.
+
+* A subkey is a secondary key or key pair for encryption, derived from
+  the master key. Subkeys can be created and revoked almost at will,
+  and there can be any number of them. Subkeys are always associated
+  with a single master key.
+
+* Subkeys can be dedicated for encryption, signing, and
+  authantication. You can have one of each.
+
+* Encryption is the process of taking a file and making it illegible
+  to everyone except the owner of a secret key. When the public key is
+  used to encrypt, only the secret key can decrypt.
+
+* Signing is using a secret key to make a separate file that others
+  can verify using the corresponding public key. This means the
+  signer can "prove" they have the file. For example, you might sign
+  emails to prove they came from you.
+
+* Authentication is the process of proving you're you. Typically, for
+  example, a server will know your public key, and will give a large
+  random number encrypted with your public key. Only you have the
+  corresponding secret key, so only you can send the random number
+  back to the server, and thereby the server knows you're you.
+
+The process outline is:
+
+1. Create a new, signing-only master key with GnuPG.
+
+2. Create three "subkeys", one each for encryption, signing, and
+   authentication. These subkeys are what everyone else uses.
+
+3. Export copies of the master key pair and the subkey pairs and put
+   them in a safe place.
+
+4. Put the subkeys on the Yubikey.
+
+5. GnuPG will automatically use the keys from the card. You have to
+   have the card plugged into a USB port for things to work. If
+   someone steals your laptop, they won't get the private subkeys.
+   Even if they steal your Yubikey, they won't get them (the smartcard
+   is physically designed to prevent that), and can't even use them
+   (because there's PIN codes or passphrases and getting them wrong
+   several times locks up the smartcard).
+
+6. Use gpg-agent as your SSH agent, and the authenticaion-only subkey
+   on the Yubikey is used as your ssh key.
+
+The process in more detail:
+
+1. Configure GnuPG with regards to checksum and encryption algorithms.
+   You can use the defaults, but depending on the version of GnuPG you
+   have, they may be weaker than is recommended.
+   FIXME: Give ref to where these come from.
+   Add the following lines to `~/.gnupg/gpg.conf`:
+
+        personal-digest-preferences SHA512
+        cert-digest-algo SHA512
+        default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
+        personal-cipher-preferences TWOFISH CAMELLIA256 AES 3DES
+        keyserver pool.sks-keyservers.net
+
+1. Create new sign-only master key.
+
+        $ gpg --full-generate-key
+        gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
+        This is free software: you are free to change and redistribute it.
+        There is NO WARRANTY, to the extent permitted by law.
+
+        Please select what kind of key you want:
+           (1) RSA and RSA (default)
+           (2) DSA and Elgamal
+           (3) DSA (sign only)
+           (4) RSA (sign only)
+        Your selection? 4
+        RSA keys may be between 1024 and 4096 bits long.
+        What keysize do you want? (2048) 4096
+        Requested keysize is 4096 bits
+        Please specify how long the key should be valid.
+                 0 = key does not expire
+              <n>  = key expires in n days
+              <n>w = key expires in n weeks
+              <n>m = key expires in n months
+              <n>y = key expires in n years
+        Key is valid for? (0) 1y
+        Key expires at Tue 29 May 2018 06:43:54 PM EEST
+        Is this correct? (y/N) y
+
+        GnuPG needs to construct a user ID to identify your key.
+
+        Real name: Lars Wirzenius
+        Email address: liw@liw.fi
+        Comment: test key
+        You selected this USER-ID:
+            "Lars Wirzenius (test key) <liw@liw.fi>"
+
+        Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
+        We need to generate a lot of random bytes. It is a good idea to perform
+        some other action (type on the keyboard, move the mouse, utilize the
+        disks) during the prime generation; this gives the random number
+        generator a better chance to gain enough entropy.
+        gpg: key 25FB738D6EE435F7 marked as ultimately trusted
+        gpg: directory '/home/liw/.gnupg/openpgp-revocs.d' created
+        gpg: revocation certificate stored as '/home/liw/.gnupg/openpgp-revocs.d/A734C10BF2DF39D19DC0F6C025FB738D6EE435F7.rev'
+        public and secret key created and signed.
+
+        Note that this key cannot be used for encryption.  You may want to use
+        the command "--edit-key" to generate a subkey for this purpose.
+        pub   rsa4096 2017-05-29 [SC] [expires: 2018-05-29]
+              A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
+              A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
+        uid                      Lars Wirzenius (test key) <liw@liw.fi>
+
+        $ 
+
+1. Note that I set a 1-year expiration for they key. The expiration
+   can be extended at any time (if you have the master secret key),
+   but unless you do, the key won't accidentally live longer than the
+   chosen time.
+
+1. Review the key:
+
+        $ gpg --list-secret-keys
+        /home/liw/.gnupg/pubring.kbx
+        ----------------------------
+        sec   rsa4096 2017-05-29 [SC] [expires: 2018-05-29]
+              A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
+        uid           [ultimate] Lars Wirzenius (test key) <liw@liw.fi>
+
+1. You now have the signing-only master key. You should now create
+   three subkeys (`keyid` is the key identifier shown in the key
+   listing). Use the `--expert` option to be able to add an
+   authenticaion-only subkey.
+
+        $ gpg --edit-key --expert A734C10BF2DF39D19DC0F6C025FB738D6EE435F7
+        gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
+        This is free software: you are free to change and redistribute it.
+        There is NO WARRANTY, to the extent permitted by law.
+        
+        Secret key is available.
+        
+        sec  rsa4096/25FB738D6EE435F7
+             created: 2017-05-29  expires: 2018-05-29  usage: SC  
+             trust: ultimate      validity: ultimate
+        [ultimate] (1). Lars Wirzenius (test key) <liw@liw.fi>
+        
+        gpg> addkey
+        Please select what kind of key you want:
+           (3) DSA (sign only)
+           (4) RSA (sign only)
+           (5) Elgamal (encrypt only)
+           (6) RSA (encrypt only)
+           (7) DSA (set your own capabilities)
+           (8) RSA (set your own capabilities)
+          (10) ECC (sign only)

(Diff truncated)
Finish article on distix, publish it
diff --git a/posts/2017/05/27/distix_movement.mdwn b/posts/2017/05/27/distix_movement.mdwn
index 2069464..94ab0eb 100644
--- a/posts/2017/05/27/distix_movement.mdwn
+++ b/posts/2017/05/27/distix_movement.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Distix movement"]]
 [[!meta date="2017-05-27 11:07"]]
-[[!tag distix draft]]
+[[!tag distix]]
 
 [Distix][] is my distributed ticketing system. I initially wrote the
 core of it as a bit of programming performance art, to celebrate my 30

Add a clarifying sentence
diff --git a/posts/2017/05/27/distix_movement.mdwn b/posts/2017/05/27/distix_movement.mdwn
index b435065..2069464 100644
--- a/posts/2017/05/27/distix_movement.mdwn
+++ b/posts/2017/05/27/distix_movement.mdwn
@@ -8,7 +8,8 @@ years as a programmer. Distix is built on top of git and emails in
 Maildirs. It is a silent listener to your issue and bug discussions:
 as long as you ensure it gets a copy of each mail, it takes care of
 automatically arranging things into separate tickets based on email
-threading. Only the "support staff" need ever interact with Distix,
+threading. Users and customers do not need to even know Distix is
+being used. Only the "support staff" need ever interact with Distix,
 and they mostly only need to close tickets that have been dealt with.
 
 I've been using Distix for my own stuff for some time now, and

Publish log entry
diff --git a/posts/2017/05/27/distix_movement.mdwn b/posts/2017/05/27/distix_movement.mdwn
new file mode 100644
index 0000000..b435065
--- /dev/null
+++ b/posts/2017/05/27/distix_movement.mdwn
@@ -0,0 +1,41 @@
+[[!meta title="Distix movement"]]
+[[!meta date="2017-05-27 11:07"]]
+[[!tag distix draft]]
+
+[Distix][] is my distributed ticketing system. I initially wrote the
+core of it as a bit of programming performance art, to celebrate my 30
+years as a programmer. Distix is built on top of git and emails in
+Maildirs. It is a silent listener to your issue and bug discussions:
+as long as you ensure it gets a copy of each mail, it takes care of
+automatically arranging things into separate tickets based on email
+threading. Only the "support staff" need ever interact with Distix,
+and they mostly only need to close tickets that have been dealt with.
+
+I've been using Distix for my own stuff for some time now, and
+recently we've started using it at work. I slowly improve it as we
+find problems.
+
+[Distix]: http://distix.eu/
+
+It's not a sleek, smooth, finished tool. It's clunky, weird, and
+probably not what you want. But it's what I want.
+
+Changes in recent months:
+
+* There is a new website: <http://distix.eu/>. No particular good
+  reason for a new website, but I won the domain for free a couple of
+  years ago, so I might as well use it.
+
+* In addition, a ticketing system for Distix itself:
+  <http://tickets.distix.eu/>. Possibly I should've called the
+  subdomain dogfood, but I'm a serious person, not prone to trying to
+  be funny.
+
+* Mails can now be imported using IMAP.
+
+* Importing has been optimized for speed and memory use, making my own
+  production use more practical.
+
+I've discussed with a friend the possibility of writing a web UI, and
+some day maybe that will happen. For now, distix is a command line
+applicaton that can generate a static HTML site.

creating tag page tag/continuous-integration
diff --git a/tag/continuous-integration.mdwn b/tag/continuous-integration.mdwn
new file mode 100644
index 0000000..2884ae1
--- /dev/null
+++ b/tag/continuous-integration.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged continuous-integration"]]
+
+[[!inline pages="tagged(continuous-integration)" actions="no" archive="yes"
+feedshow=10]]

Remove draft tag to publish blog post
diff --git a/posts/2017/05/07/ick2_design_discussion.mdwn b/posts/2017/05/07/ick2_design_discussion.mdwn
index f052de1..330a19f 100644
--- a/posts/2017/05/07/ick2_design_discussion.mdwn
+++ b/posts/2017/05/07/ick2_design_discussion.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Ick2 design discussion"]]
 [[!meta date="2017-05-07 19:00"]]
-[[!tag draft]]
+[[!tag ick continuous-integration]]
 
 Recently, [[Daniel|http://www.digital-scurf.org/]] visited us in
 Helsinki. In addition to enjoying local food and scenerey, we spent

Typo fixes
diff --git a/posts/2017/05/07/ick2_design_discussion.mdwn b/posts/2017/05/07/ick2_design_discussion.mdwn
index b73ec78..f052de1 100644
--- a/posts/2017/05/07/ick2_design_discussion.mdwn
+++ b/posts/2017/05/07/ick2_design_discussion.mdwn
@@ -16,7 +16,7 @@ generation of Ick, or Ick2, and that's what we discussed with Daniel.
 Where pretty much everything in Ick1 is hardcoded, everything in Ick2
 will be user-configurable. It's my last, best chance to go completely
 overboard in the
-[second system syndrome][https://en.wikipedia.org/wiki/Second-system_effect]
+[second system syndrome](https://en.wikipedia.org/wiki/Second-system_effect)
 manner.
 
 Where Ick1 was written in a feverish two-week hacking session, rushed
@@ -67,7 +67,7 @@ Some decisions we made:
   other info) from YAML config files, and can't have that stuff
   hardcoded.
 
-* The MVP API will have no authantication or authorization stuff yet.
+* The MVP API will have no authentication or authorization stuff yet.
 
 The initial pipelines will be basically like this, but expressed in
 some way by the user:

Resite whiteboard image
diff --git a/posts/2017/05/07/ick2_design_discussion/whiteboard.jpg b/posts/2017/05/07/ick2_design_discussion/whiteboard.jpg
index a555ea2..a2945ef 100644
Binary files a/posts/2017/05/07/ick2_design_discussion/whiteboard.jpg and b/posts/2017/05/07/ick2_design_discussion/whiteboard.jpg differ

Add whiteboard image
diff --git a/posts/2017/05/07/ick2_design_discussion.mdwn b/posts/2017/05/07/ick2_design_discussion.mdwn
index af32683..b73ec78 100644
--- a/posts/2017/05/07/ick2_design_discussion.mdwn
+++ b/posts/2017/05/07/ick2_design_discussion.mdwn
@@ -35,6 +35,8 @@ Our "minimum viable product" or MVP for Ick2 is defined like this:
 This is a real task, and something we already do with Ick1 at work.
 It's a reasonable first step for the new program.
 
+[[!img whiteboard.jpg]]
+
 Some decisions we made:
 
 * The Ick2 controller, which decides which projects to build, and
diff --git a/posts/2017/05/07/ick2_design_discussion/whiteboard.jpg b/posts/2017/05/07/ick2_design_discussion/whiteboard.jpg
new file mode 100644
index 0000000..a555ea2
Binary files /dev/null and b/posts/2017/05/07/ick2_design_discussion/whiteboard.jpg differ

Publish log entry
diff --git a/posts/2017/05/07/ick2_design_discussion.mdwn b/posts/2017/05/07/ick2_design_discussion.mdwn
new file mode 100644
index 0000000..af32683
--- /dev/null
+++ b/posts/2017/05/07/ick2_design_discussion.mdwn
@@ -0,0 +1,160 @@
+[[!meta title="Ick2 design discussion"]]
+[[!meta date="2017-05-07 19:00"]]
+[[!tag draft]]
+
+Recently, [[Daniel|http://www.digital-scurf.org/]] visited us in
+Helsinki. In addition to enjoying local food and scenerey, we spent
+some time together in front of a whiteboard to sketch out designs for
+Ick2. Ick is my continuous integration system, and it's all Daniel's
+fault for suggesting the name. Ahem.
+
+I am currently using the first generation of Ick and it is a rigid,
+cumbersome, and fragile thing. It works well enough that I don't miss
+Jenkins, but I would like something better. That's the second
+generation of Ick, or Ick2, and that's what we discussed with Daniel.
+
+Where pretty much everything in Ick1 is hardcoded, everything in Ick2
+will be user-configurable. It's my last, best chance to go completely
+overboard in the
+[second system syndrome][https://en.wikipedia.org/wiki/Second-system_effect]
+manner.
+
+Where Ick1 was written in a feverish two-week hacking session, rushed
+because my Jenkins install at the time had broken one time too many,
+we're taking our time with Ick2. Slow and careful is the tune this
+time around.
+
+Our "minimum viable product" or MVP for Ick2 is defined like this:
+
+> Ick2 builds static websites from source in a git repository, using
+> ikiwiki, and published to a web server using rsync. A change to the
+> git repository triggers a new build. It can handle many separate
+> websites, and if given enough worker machines, can build many of
+> them concurrently.
+
+This is a real task, and something we already do with Ick1 at work.
+It's a reasonable first step for the new program.
+
+Some decisions we made:
+
+* The Ick2 controller, which decides which projects to build, and
+  what's the next build step at any one time, will be **reactive
+  only**. It will do nothing except in response to an HTTP API
+  request. This includes things like timed events. An external service
+  will need to poke the controller at the right time.
+
+* The controller will be accompanied by worker manager processes,
+  which fetch instructions of what to do next, and control actual
+  worker over ssh.
+
+* Provisioning of the workers is out of scope for the MVP. For the MVP
+  we are OK with a static list of workers. In the future we might make
+  worker registration be a dynamic things, but not for the MVP. (Parts
+  or all of this decision may be changed in the future, but we need to
+  start somewhere.)
+
+* The MVP publishing will happen by running rsync to a web server.
+  Providing credentials for the workers to do that is the sysadmin's
+  problem, not something the MVP will handle itself.
+
+* The MVP needs to handle more than one worker, and more than one
+  pipelines, and needs to build things concurrently when there's call
+  for it.
+
+* The MVP will need to read the pipelines (and their steps and any
+  other info) from YAML config files, and can't have that stuff
+  hardcoded.
+
+* The MVP API will have no authantication or authorization stuff yet.
+
+The initial pipelines will be basically like this, but expressed in
+some way by the user:
+
+1. Clone the source repoistory.
+1. Run ikiwiki --build to build the website.
+1. Run rsync to publish the website on a server.
+
+Assumptions:
+
+* Every worker can clone from the git server.
+* Every worker has all the build tools.
+* Every worker has rsync and access to every web server.
+* Every pipeline run is clean.
+
+Actions the Ick2 controller API needs to support:
+
+* List all existing projects.
+* Trigger a project to build.
+* Query what project builds are running.
+* Get build logs for a project: current log (from the running build),
+  and the most recent finished build.
+
+A sketch API:
+
+* POST /projects/foo/+trigger
+
+    Trigger build of project foo. If the git hasn't changed, the build
+    runs anyway.
+
+* GET /projects
+
+    List names of all projects.
+
+* GET /projects/foo
+
+    On second thought, I can't think of anything useful for this to
+    return for the MVP. Scratch.
+
+* GET /projects/foo/logs/current
+
+    Return entire known build log captured so far for the currently
+    running build.
+
+* GET /projects/foo/logs/previous
+
+    Return entire build log for latest finished build.
+
+* GET /work/bar
+
+    Used by worker bar: return next not-yet-finished step to run as a
+    JSON object containing fields "project" (name of project for which
+    to run the step) and "shell" (a shell command to run). The call
+    will return the same JSON object until the worker reports it as
+    having finished.
+
+* POST /work/bar/snippet
+
+    Used by worker bar to report progress on the currently running
+    step: a JSON object containing fields "stdout" (string with output
+    from the shell command's stdout), "stderr" (ditto but stderr), and
+    "exit_code" (the shell command's exit code, if it's finished, or
+    null).
+
+Sequence:
+
+* Git server has a hook that calls "GET /projects/foo/+trigger" (or
+  else this is simulated by user).
+
+* Controller add a build of project foo to queue.
+
+* Worker manager calls "GET /work/bar", gets a shell command to run,
+  and starts running it on its worker.
+
+* While worker runs shell command, every second or so, worker manager
+  calls "POST /work/bar/snippet" to report progress including
+  collected output, if any.
+
+* Controller responds with OK or KILL, and if the latter, worker kills
+  the command it is running. Worker manager continues reporting
+  progress via snippet until shell command is finished (on its own or
+  by having been killed).
+
+* Controller appends any output reported via .../snippet. When it
+  learns a shell command has finished, it updates its idea of the next
+  step to run.
+
+* When controller learns a project has finished building, it rotates
+  the current build log to be the previous one.
+
+The next step will probably be to sketch a yarn test suite of the API
+and implement a rudimentary one.

Fix link
diff --git a/posts/minipc-router.mdwn b/posts/minipc-router.mdwn
index dd73d5e..09a7884 100644
--- a/posts/minipc-router.mdwn
+++ b/posts/minipc-router.mdwn
@@ -103,4 +103,4 @@ be happy to get feedback, bug reports, and patches. Send them to me
 (liw@liw.fi) or my ticketing system (bugs@liw.fi).
 
 [installer image]: http://files.liw.fi/minipc-router/
-[ansible playbooks]: http://git.liw.fi/cgi-bin/cgit/cgit.cgi/minipc-router/tree/ansible
+[ansible playbooks]: http://git.liw.fi/cgi-bin/cgit.cgi/minipc-router/tree/ansible

Publish log entry
diff --git a/posts/2017/02/01/hacker_noir_chapter_2_development_setup_phase.mdwn b/posts/2017/02/01/hacker_noir_chapter_2_development_setup_phase.mdwn
new file mode 100644
index 0000000..b7bef8f
--- /dev/null
+++ b/posts/2017/02/01/hacker_noir_chapter_2_development_setup_phase.mdwn
@@ -0,0 +1,13 @@
+[[!meta title="Hacker Noir, chapter 2: Development setup phase"]]
+[[!meta date="2017-02-01 13:26"]]
+[[!tag noir]]
+
+It is a new month, and time to publish the next chapter in
+[Hacker Noir][]. This is chapter 2, titled
+"[Development setup phase][]". I hope you enjoy it. Feedback via
+email, irc, identi.ca, twitter are welcome. Or come talk to me at
+FOSDEM if you're there.
+
+
+[Hacker Noir]: http://noir.liw.fi/
+[Development setup phase]: http://noir.liw.fi/devsetup/

Publish
diff --git a/posts/2017/01/22/improving_debugging_via_email_followup.mdwn b/posts/2017/01/22/improving_debugging_via_email_followup.mdwn
index d2c1f25..3593409 100644
--- a/posts/2017/01/22/improving_debugging_via_email_followup.mdwn
+++ b/posts/2017/01/22/improving_debugging_via_email_followup.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Improving debugging via email, followup"]]
 [[!meta date="2017-01-22 17:35"]]
-[[!tag draft]]
+[[!tag debug]]
 
 Half a year ago I wrote a blog post about
 [[debugging over email|posts/debugging-over-email]]. This is a

Publish log entry
diff --git a/posts/2017/01/22/improving_debugging_via_email_followup.mdwn b/posts/2017/01/22/improving_debugging_via_email_followup.mdwn
new file mode 100644
index 0000000..d2c1f25
--- /dev/null
+++ b/posts/2017/01/22/improving_debugging_via_email_followup.mdwn
@@ -0,0 +1,34 @@
+[[!meta title="Improving debugging via email, followup"]]
+[[!meta date="2017-01-22 17:35"]]
+[[!tag draft]]
+
+Half a year ago I wrote a blog post about
+[[debugging over email|posts/debugging-over-email]]. This is a
+follow-up.
+
+The blog post summarised:
+
+* Have an automated way to collect all usual informaion needed for
+  debugging: versions, config and log files, etc.
+
+* Improve error messages so the users can solve their issues
+  themselves.
+
+* Give users better automated diagnostics tools.
+
+Based on further thinking and feedback, I add:
+
+* When a program notices a problem that may indicate a bug in it, it
+  should collect the necessary information itself, automatically, in a
+  way that the user just needs to send to the developers / support.
+
+* The primary goal should be to help people solve their own problems.
+
+* A secondary goal is to make the problem reproducible by the
+  developers, or otherwise make it easy to fix bugs without access to
+  the original system where the problem was manifested.
+
+I've not written any code to help with this remote debugging, but it's
+something I will start experimenting with in the near future.
+
+Further ideas welcome.

Publish draft
diff --git a/posts/2017/01/07/hacker_noir_chapter_1_negotiation.mdwn b/posts/2017/01/07/hacker_noir_chapter_1_negotiation.mdwn
index 743817a..553280d 100644
--- a/posts/2017/01/07/hacker_noir_chapter_1_negotiation.mdwn
+++ b/posts/2017/01/07/hacker_noir_chapter_1_negotiation.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Hacker Noir, chapter 1: Negotiation"]]
 [[!meta date="2017-01-07 22:46"]]
-[[!tag noir announcement draft]]
+[[!tag noir announcement ]]
 
 I participated in Nanowrimo in November, but I failed to actually
 finish the required 50,000 words during the month. Oh well. I plan on

Fix type in filename
diff --git a/posts/2017/01/07/hacker_noir_chapter_1_negotiation.mdwn b/posts/2017/01/07/hacker_noir_chapter_1_negotiation.mdwn
new file mode 100644
index 0000000..743817a
--- /dev/null
+++ b/posts/2017/01/07/hacker_noir_chapter_1_negotiation.mdwn
@@ -0,0 +1,14 @@
+[[!meta title="Hacker Noir, chapter 1: Negotiation"]]
+[[!meta date="2017-01-07 22:46"]]
+[[!tag noir announcement draft]]
+
+I participated in Nanowrimo in November, but I failed to actually
+finish the required 50,000 words during the month. Oh well. I plan on
+finishing the book eventually, anyway.
+
+Furthermore, as an open source exhibitionist I thought I'd publish
+a chapter each month. This will put a bit of pressure on me to keep
+writing, and hopefully I'll get some nice feedback too.
+
+The working title is "Hacker Noir". I've put the first chapter up on
+<http://noir.liw.fi/>.
diff --git a/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn b/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn
deleted file mode 100644
index 743817a..0000000
--- a/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn
+++ /dev/null
@@ -1,14 +0,0 @@
-[[!meta title="Hacker Noir, chapter 1: Negotiation"]]
-[[!meta date="2017-01-07 22:46"]]
-[[!tag noir announcement draft]]
-
-I participated in Nanowrimo in November, but I failed to actually
-finish the required 50,000 words during the month. Oh well. I plan on
-finishing the book eventually, anyway.
-
-Furthermore, as an open source exhibitionist I thought I'd publish
-a chapter each month. This will put a bit of pressure on me to keep
-writing, and hopefully I'll get some nice feedback too.
-
-The working title is "Hacker Noir". I've put the first chapter up on
-<http://noir.liw.fi/>.

Tweakk and fix typo
diff --git a/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn b/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn
index 5726bbe..743817a 100644
--- a/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn
+++ b/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn
@@ -1,4 +1,4 @@
-[[!meta title="Hacker Noire, chapter 1: Negotiation"]]
+[[!meta title="Hacker Noir, chapter 1: Negotiation"]]
 [[!meta date="2017-01-07 22:46"]]
 [[!tag noir announcement draft]]
 
@@ -10,4 +10,5 @@ Furthermore, as an open source exhibitionist I thought I'd publish
 a chapter each month. This will put a bit of pressure on me to keep
 writing, and hopefully I'll get some nice feedback too.
 
-I've put the first chapter up on <http://noir.liw.fi/>.
+The working title is "Hacker Noir". I've put the first chapter up on
+<http://noir.liw.fi/>.

creating tag page tag/noir
diff --git a/tag/noir.mdwn b/tag/noir.mdwn
new file mode 100644
index 0000000..f8f62bd
--- /dev/null
+++ b/tag/noir.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged noir"]]
+
+[[!inline pages="tagged(noir)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn b/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn
new file mode 100644
index 0000000..5726bbe
--- /dev/null
+++ b/posts/2017/01/07/hacker_noire_chapter_1_negotiation.mdwn
@@ -0,0 +1,13 @@
+[[!meta title="Hacker Noire, chapter 1: Negotiation"]]
+[[!meta date="2017-01-07 22:46"]]
+[[!tag noir announcement draft]]
+
+I participated in Nanowrimo in November, but I failed to actually
+finish the required 50,000 words during the month. Oh well. I plan on
+finishing the book eventually, anyway.
+
+Furthermore, as an open source exhibitionist I thought I'd publish
+a chapter each month. This will put a bit of pressure on me to keep
+writing, and hopefully I'll get some nice feedback too.
+
+I've put the first chapter up on <http://noir.liw.fi/>.

Publish log entry
diff --git a/posts/2016/11/22/debian_miniconf_in_cambridge.mdwn b/posts/2016/11/22/debian_miniconf_in_cambridge.mdwn
new file mode 100644
index 0000000..cf18040
--- /dev/null
+++ b/posts/2016/11/22/debian_miniconf_in_cambridge.mdwn
@@ -0,0 +1,27 @@
+[[!meta title="Debian miniconf in Cambridge"]]
+[[!meta date="2016-11-22 19:08"]]
+[[!tag debian vmdebootstrap qvarn talk conference]]
+
+I spent a few days in Cambridge for a minidebconf. This is a tiny
+version of the full annual Debconf. We had a couple of days for
+hacking, and another two days for talks.
+
+I spent my hacking time on thinking about vmdebootstrap (my tool for
+generating disk images with an installed Debian), and came to the
+conclusion I need to atone my sins for writing such crappy code by
+rewriting it from scratch to be nicer to use. I gave a talk about
+this, too. The
+[mailing list post](https://lists.debian.org/debian-cloud/2016/11/msg00050.html)
+has the important parts, and
+[meetings-archive](http://meetings-archive.debian.net/pub/debian-meetings/2016/miniconf_cambridge16/)
+has a video.
+
+I haven't started the rewrite, and it's not going to make it for
+stretch.
+
+I also gave two other talks, on the early days of Linux, and
+[Qvarn](http://qvarn.org), the latter being what I do at work.
+
+Thank you to ARM, for sponsoring the location, and the other sponsors
+for sponsoring food. These in-real-life meetings between developers
+are important for the productivity and social cohesion of Debian.

Allow hiearachy under posts for feeds
diff --git a/englishfeed.mdwn b/englishfeed.mdwn
index 1554294..961022a 100644
--- a/englishfeed.mdwn
+++ b/englishfeed.mdwn
@@ -1,5 +1,5 @@
 Feed for Planet Debian.
 
-[[!inline pages="posts/* and !posts/*/* and !tagged(in-finnish) and 
+[[!inline pages="page(posts/*) and !Discussion and !tagged(in-finnish) and 
                  !tagged(draft) and created_after(posts/dd-again)"
           description="liw's English language blog feed"]]
diff --git a/index.mdwn b/index.mdwn
index fac47cc..65fdc03 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -15,7 +15,7 @@ copyrighted by their authors.
 
 ---
 
-[[!inline pages="posts/* and !posts/*/* and !tagged(draft)"]]
+[[!inline pages="page(posts/*) and !Discussion and !tagged(draft)"]]
 
 ---
 

Remove tag draft to publish
diff --git a/posts/2016/10/29/obnam_1_20_released.mdwn b/posts/2016/10/29/obnam_1_20_released.mdwn
index fa26a07..e52345a 100644
--- a/posts/2016/10/29/obnam_1_20_released.mdwn
+++ b/posts/2016/10/29/obnam_1_20_released.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Obnam 1.20 released"]]
 [[!meta date="2016-10-29 12:30"]]
-[[!tag obnam announcement draft]]
+[[!tag obnam announcement]]
 
 I have just released version 1.20 of [Obnam][], my backup program.
 It's been nine months since the previous release, and that's a long

Fix release date for 1.20
diff --git a/posts/2016/10/29/obnam_1_20_released.mdwn b/posts/2016/10/29/obnam_1_20_released.mdwn
index 26b660c..fa26a07 100644
--- a/posts/2016/10/29/obnam_1_20_released.mdwn
+++ b/posts/2016/10/29/obnam_1_20_released.mdwn
@@ -31,7 +31,7 @@ development, called `green-albatross-20160813`. It is **NOT** meant
 for real use. It is likely to change in incompatible ways without
 warning. DO NOT USE it unless you're willing to lose your backup.
 
-Version 1.20, not yet released
+Version 1.20, released 2016-10-29
 ---------------------------------
 
 * The format name for `green-albatross` is renamed to

Fix link
diff --git a/posts/2016/10/29/obnam_1_20_released.mdwn b/posts/2016/10/29/obnam_1_20_released.mdwn
index 077fa9a..26b660c 100644
--- a/posts/2016/10/29/obnam_1_20_released.mdwn
+++ b/posts/2016/10/29/obnam_1_20_released.mdwn
@@ -18,7 +18,7 @@ people, and I'm grateful for those. I try to credit them by name in
 the NEWS file.
 
 [Obnam]: http://obnam.org/
-[NEWS]: yhttp://git.liw.fi/cgi-bin/cgit/cgit.cgi/obnam/tree/NEWS
+[NEWS]: http://git.liw.fi/cgi-bin/cgit/cgit.cgi/obnam/tree/NEWS
 [FORMAT GREEN ALBATROSS]: http://obnam.org/format-green-albatross/
 
 Obnam NEWS

Publish log entry
diff --git a/posts/2016/10/29/obnam_1_20_released.mdwn b/posts/2016/10/29/obnam_1_20_released.mdwn
new file mode 100644
index 0000000..077fa9a
--- /dev/null
+++ b/posts/2016/10/29/obnam_1_20_released.mdwn
@@ -0,0 +1,96 @@
+[[!meta title="Obnam 1.20 released"]]
+[[!meta date="2016-10-29 12:30"]]
+[[!tag obnam announcement draft]]
+
+I have just released version 1.20 of [Obnam][], my backup program.
+It's been nine months since the previous release, and that's a long
+time: I've had an exciting year, and not entirely in a good way.
+Unfortuntely that's eaten up a lot of my free time and enthusiasm for
+my hobby projects.
+
+See below for a snippet of [NEWS][], with a summary of the
+user-visible changes. A lot of the effort has gone into improving
+[FORMAT GREEN ALBATROSS][], but that isn't documented in the NEWS
+file.
+
+I've received patches and actionable bug reports from a number of
+people, and I'm grateful for those. I try to credit them by name in
+the NEWS file.
+
+[Obnam]: http://obnam.org/
+[NEWS]: yhttp://git.liw.fi/cgi-bin/cgit/cgit.cgi/obnam/tree/NEWS
+[FORMAT GREEN ALBATROSS]: http://obnam.org/format-green-albatross/
+
+Obnam NEWS
+==========
+
+This file summarizes changes between releases of Obnam.
+
+NOTE: Obnam has an **EXPERIMENTAL** repository format under
+development, called `green-albatross-20160813`. It is **NOT** meant
+for real use. It is likely to change in incompatible ways without
+warning. DO NOT USE it unless you're willing to lose your backup.
+
+Version 1.20, not yet released
+---------------------------------
+
+* The format name for `green-albatross` is renamed to
+  `green-albatross-20160813` and will henceforth be renamed every time
+  there's a change, to avoid confusing Lars because of backwards
+  incompatibilities. When it reaches stability and the on-disk format
+  is frozen, it'll be renamed back to a date-less version.
+
+* Those using the experimental green-albatross repository format will
+  have to start over with fresh repositories. This release contains
+  backwards incompatible changes that mean existing repositories no
+  longer work. Sorry, but that's what experimental means.
+
+* A green-albatross change is that the "chunk index" data structure is
+  no longer a single blob, and instead it's broken down into smaller
+  objects. This avoids keeping all of the chunk indexes in memory at
+  once, which should reduce memory use.
+
+* Remi Rampin started updating and continuing the French translation
+  of the Obnam manual.
+
+* Lars Wirzenius changed the default so that Obnam reads random data
+  when creating encryption key from `/dev/urandom` instead of
+  `/dev/random`. The goal is to make it less likely that Obnam stops
+  at the key generation stage on machines with little entropy. Set
+  `weak-random = no` in your configuration to override this.
+
+Minor changes:
+
+* Lars Wirzenius changed `obnam forget` so that if there is nothing to
+  do, it doesn't even try to connect to the repository.
+
+* Lars Wirzenius added a chapter on participating in the Obnam project
+  to the manual.
+
+* Lars Wirzenius changed `--one-file-system` to work for bind mounts.
+  It only works for bind mounts that exist at the time when Obnam
+  starts, however. Also, `/proc/mounts` must be an accurate list of
+  mount points.
+
+* Lars Wirzenius added the gpg command line to the error message about
+  gpg failing.
+
+Bug fixes:
+
+* The manual and manual page used to claim you could break only the
+  locks for one client. This was not true. The manuals has been fixed.
+
+* A whole bunch of typo fixes, from Andrea Gelmini.
+
+* Michel Alexandre Salim fixed a bug in the FUSE (obnam mount) plugin,
+  which was a typo in a method name (`get_clientgeneration_ids`).
+
+* Lars Wirzenius fixed `obnam restore` to require a target set with
+  `--to`. Jonathan Dowland reported the problem.
+
+* Lars Wirzenius fixed `obnam list-errors` so that it doesn't crash on
+  error classes that only exist to make the exception hierarchy
+  neater, such as `EncryptionError`. Bug reported by Rik Theys.
+
+* Ian Cambell fixed a bug in `obnam kdirstat` and its handling of FIFO
+  sockets.

Fix meta
diff --git a/posts/minipc-router.mdwn b/posts/minipc-router.mdwn
index a1b4923..dd73d5e 100644
--- a/posts/minipc-router.mdwn
+++ b/posts/minipc-router.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="A tiny PC as a router"]]
-[[!meta date="Tue, 04 Oct 2016 12:56:23 +0300"]
+[[!meta date="Tue, 04 Oct 2016 12:56:23 +0300"]]
 [[!tag minipc router]]
 
 We needed a router and wifi access point in the office, and

Set meta data
diff --git a/posts/minipc-router.mdwn b/posts/minipc-router.mdwn
index 9372f22..a1b4923 100644
--- a/posts/minipc-router.mdwn
+++ b/posts/minipc-router.mdwn
@@ -1,4 +1,5 @@
 [[!meta title="A tiny PC as a router"]]
+[[!meta date="Tue, 04 Oct 2016 12:56:23 +0300"]
 [[!tag minipc router]]
 
 We needed a router and wifi access point in the office, and

Fix CPU frequency
diff --git a/posts/minipc-router.mdwn b/posts/minipc-router.mdwn
index cd187f3..9372f22 100644
--- a/posts/minipc-router.mdwn
+++ b/posts/minipc-router.mdwn
@@ -32,7 +32,7 @@ We got some hardware:
 [[!table data="""
 Component     | Model                                                             | Cost
 Barebone      | Qotom Q190G4, VGA, 2x USB 2.0, 134x126x36mm, fanless              | 130€
-CPU           | Intel J1900, 2-2.4MHz quad-core                                   | -
+CPU           | Intel J1900, 2-2.4GHz quad-core                                   | -
 NIC           | Intel WG82583, 4x 10/100/1000                                     | -
 Memory        | Crucial CT102464BF160B, 8GB DDR3L-1600 SODIMM 1.35V CL11          | 40€
 SSD           | Kingston SSDNow mS200, 60GB mSATA                                 | 42€

Fix internal link
diff --git a/posts/minipc-router.mdwn b/posts/minipc-router.mdwn
index 5bf6358..cd187f3 100644
--- a/posts/minipc-router.mdwn
+++ b/posts/minipc-router.mdwn
@@ -101,5 +101,5 @@ If you'd like to use the images and Ansible playbooks, please do. We'd
 be happy to get feedback, bug reports, and patches. Send them to me
 (liw@liw.fi) or my ticketing system (bugs@liw.fi).
 
-[router image]: http://files.liw.fi/minipc-router/
+[installer image]: http://files.liw.fi/minipc-router/
 [ansible playbooks]: http://git.liw.fi/cgi-bin/cgit/cgit.cgi/minipc-router/tree/ansible

Add missing sentence
diff --git a/posts/minipc-router.mdwn b/posts/minipc-router.mdwn
index b8106d3..5bf6358 100644
--- a/posts/minipc-router.mdwn
+++ b/posts/minipc-router.mdwn
@@ -64,7 +64,8 @@ After assembling the hardware, we installed Debian on them:
   address with DHCP.
 
 * Log in with ssh to `ansible@10.0.0.4`, and verify that `sudo id`
-  works without password. Except you can't do this, since it's 
+  works without password. Except you can't do this, unless you put in
+  your ssh key in the authorized keys file above.
 
 * Git clone the [ansible playbooks][], adjust their parameters in
   `minipc-router.yml` as wanted, and run the playbook. Then reboot the

Tweak style.css to give tables some borders
diff --git a/style.css b/style.css
index 548971c..73e8bab 100644
--- a/style.css
+++ b/style.css
@@ -6,6 +6,19 @@ html {
     margin-top: 2em;
 }
 
+table {
+    border-collapse: collapse;
+}
+
+table, th, td {
+    border: 1px solid #ddd;
+    text-align: left;
+}
+
+th, td {
+    padding: 10px;
+}
+
 form#searchform {
     font-family: monospace;
     text-align: right;

Update blog post draft, remote draft tag
diff --git a/posts/minipc-router.mdwn b/posts/minipc-router.mdwn
index 6bc272c..b8106d3 100644
--- a/posts/minipc-router.mdwn
+++ b/posts/minipc-router.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="A tiny PC as a router"]]
-[[!tag minipc router draft]]
+[[!tag minipc router]]
 
 We needed a router and wifi access point in the office, and
 simultaneously both I and my co-worker Ivan needed such a thing at our
@@ -10,13 +10,22 @@ just that.
 * The PC solution seem to offer better performance, but this is
   actually not a major reason for us.
 
-* We want to have systems we understand and can hack. Commercial
-  routers tend to be opaque and mysterious and may or may not have
-  great security support. Installing OpenWRT on commercial routers is
-  possible, but requires finding a model that happens to be supported.
+* We want to have systems we understand and can hack. A standard x86
+  PC running Debian sounds ideal to use.
 
-  Running real Debian on standard x86 hardware as a router seems like
-  a better option, if more work initially.
+* Why not a cheap commercial router? They tend to be opaque and
+  mysterious, and can't be managed with standard tooling such as
+  Ansible. They may or may not have good security support. Also, they
+  may or may not have sufficient functionality to be nice things, such
+  as DNS for local machines, or the full power if iptables for
+  firewalling.
+
+* Why not OpenWRT? Some models of commercial routers are supported by
+  OpenWRT. Finding good hardware that is also supported by OpenWRT is
+  a task in itself, and not the kind of task especially I like to do.
+  Even if one goes this route, the environment isn't quite a standard
+  Linux system, because of various hardware limitations. (OpenWRT is a
+  worthy project, just not our preference.)
 
 We got some hardware:
 
@@ -49,7 +58,7 @@ After assembling the hardware, we installed Debian on them:
   which runs a DHCP server on eth3 (marked LAN4 on the box). You can
   log as root on the console (no password), or via ssh, but for ssh
   you need to replace the `/home/ansible/.ssh/authorized_keys` file
-  with one that contains only your key.
+  with one that contains only your public ssh key.
 
 * Connect a laptop to the Ethernet port marked LAN4, and get an IP
   address with DHCP.
@@ -80,11 +89,16 @@ There's a lot of limitations and problems:
   That's a lot of wasted space.
 
 * The router factory image embeds our public keys in the `ansible`
-  user's authorized keys file for ssh.
+  user's authorized keys file for ssh. This is because we built this
+  for ourselves first. If there's interest by others in using the
+  images, we'll solve this.
 
 * Probably a lot of stupid things. Feel free to tell us what it is
   (bugs@liw.fi would be a good address for that).
 
+If you'd like to use the images and Ansible playbooks, please do. We'd
+be happy to get feedback, bug reports, and patches. Send them to me
+(liw@liw.fi) or my ticketing system (bugs@liw.fi).
+
 [router image]: http://files.liw.fi/minipc-router/
-[ansible playbooks]:
-http://git.liw.fi/cgi-bin/cgit/cgit.cgi/minipc-router/tree/ansible
+[ansible playbooks]: http://git.liw.fi/cgi-bin/cgit/cgit.cgi/minipc-router/tree/ansible

creating tag page tag/minipc
diff --git a/tag/minipc.mdwn b/tag/minipc.mdwn
new file mode 100644
index 0000000..186a7dd
--- /dev/null
+++ b/tag/minipc.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged minipc"]]
+
+[[!inline pages="tagged(minipc)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/router
diff --git a/tag/router.mdwn b/tag/router.mdwn
new file mode 100644
index 0000000..626490c
--- /dev/null
+++ b/tag/router.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged router"]]
+
+[[!inline pages="tagged(router)" actions="no" archive="yes"
+feedshow=10]]

Add draft
diff --git a/posts/minipc-router.mdwn b/posts/minipc-router.mdwn
new file mode 100644
index 0000000..6bc272c
--- /dev/null
+++ b/posts/minipc-router.mdwn
@@ -0,0 +1,90 @@
+[[!meta title="A tiny PC as a router"]]
+[[!tag minipc router draft]]
+
+We needed a router and wifi access point in the office, and
+simultaneously both I and my co-worker Ivan needed such a thing at our
+respective homes. After some discussion, and after reading articles in
+Ars Technica about building PCs to act as routers, we decided to do
+just that.
+
+* The PC solution seem to offer better performance, but this is
+  actually not a major reason for us.
+
+* We want to have systems we understand and can hack. Commercial
+  routers tend to be opaque and mysterious and may or may not have
+  great security support. Installing OpenWRT on commercial routers is
+  possible, but requires finding a model that happens to be supported.
+
+  Running real Debian on standard x86 hardware as a router seems like
+  a better option, if more work initially.
+
+We got some hardware:
+
+[[!table data="""
+Component     | Model                                                             | Cost
+Barebone      | Qotom Q190G4, VGA, 2x USB 2.0, 134x126x36mm, fanless              | 130€
+CPU           | Intel J1900, 2-2.4MHz quad-core                                   | -
+NIC           | Intel WG82583, 4x 10/100/1000                                     | -
+Memory        | Crucial CT102464BF160B, 8GB DDR3L-1600 SODIMM 1.35V CL11          | 40€
+SSD           | Kingston SSDNow mS200, 60GB mSATA                                 | 42€
+WLAN          | AzureWave AW-NU706H, Ralink RT3070L, 300M 802.11b/g/n, half mPCIe | 17€
+mPCIe adapter | Half to full mPCIe adapter                                        | 3€
+Antennas      | 2x 2.4/5GHz 6dBi, RP-SMA, U.FL Cables                             | 7€
+"""]]
+
+These were bought at various online shops, including AliExpress and
+verkkokauppa.com.
+
+After assembling the hardware, we installed Debian on them:
+
+* Connect the PC to a monitor (VGA) and keyboard (USB), as well as
+  power.
+
+* I built a "factory image" to be put on the SSD, and a USB stick
+  [installer image][], which includes the factory one.  Write the
+  installer image on a USB stick, boot off that, then copy the factory
+  image to the SSD and reboot off the SSD.
+
+* The router now runs a very bare-bones, stripped-down Debian system,
+  which runs a DHCP server on eth3 (marked LAN4 on the box). You can
+  log as root on the console (no password), or via ssh, but for ssh
+  you need to replace the `/home/ansible/.ssh/authorized_keys` file
+  with one that contains only your key.
+
+* Connect a laptop to the Ethernet port marked LAN4, and get an IP
+  address with DHCP.
+
+* Log in with ssh to `ansible@10.0.0.4`, and verify that `sudo id`
+  works without password. Except you can't do this, since it's 
+
+* Git clone the [ansible playbooks][], adjust their parameters in
+  `minipc-router.yml` as wanted, and run the playbook. Then reboot the
+  router again.
+
+* You should now have wifi, routing (with NAT), and be generally
+  speaking able to do networking.
+
+There's a lot of limitations and problems:
+
+* There's no web UI for managing anything. If you're not comfortable
+  doing sysadmin via ssh (with or without ansible), this isn't for
+  you.
+
+* No IPv6. We didn't want to enable it yet, until we understand it
+  better. You can, if you want to.
+
+* No real firewalling, but adjust `roles/router/files/ferm.conf` as
+  you wish.
+
+* The router factory image is 4 GB in size, and our SSD is 60 GB.
+  That's a lot of wasted space.
+
+* The router factory image embeds our public keys in the `ansible`
+  user's authorized keys file for ssh.
+
+* Probably a lot of stupid things. Feel free to tell us what it is
+  (bugs@liw.fi would be a good address for that).
+
+[router image]: http://files.liw.fi/minipc-router/
+[ansible playbooks]:
+http://git.liw.fi/cgi-bin/cgit/cgit.cgi/minipc-router/tree/ansible

Fix typo
diff --git a/tag/obnam.mdwn b/tag/obnam.mdwn
index 06f0d18..a62b75f 100644
--- a/tag/obnam.mdwn
+++ b/tag/obnam.mdwn
@@ -1,3 +1,3 @@
-This tag is for blog posts that are about [Obnam](http://ognam.org/).
+This tag is for blog posts that are about [Obnam](http://obnam.org/).
 
 [[!inline archive=yes pages="link(tag/obnam)"]]

Fix broken link
Thanks, chirlu.
diff --git a/tag/obnam.mdwn b/tag/obnam.mdwn
index 8191cd3..06f0d18 100644
--- a/tag/obnam.mdwn
+++ b/tag/obnam.mdwn
@@ -1,3 +1,3 @@
-This tag is for blog posts that are about [Obnam](http://braawi.org/obnam.html).
+This tag is for blog posts that are about [Obnam](http://ognam.org/).
 
 [[!inline archive=yes pages="link(tag/obnam)"]]

Publish
diff --git a/posts/ick2-maybe.mdwn b/posts/ick2-maybe.mdwn
index 643747f..ef0ed03 100644
--- a/posts/ick2-maybe.mdwn
+++ b/posts/ick2-maybe.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Thinking about CI, maybe writing ick2"]]
-[[!tag ick draft]]
+[[!tag ick]]
 
 A year ago I got tired of Jenkins and wrote a CI system for myself,
 [Ick][]. It's served me well since, but it's a bit clunky and awkward

creating tag page tag/ick
diff --git a/tag/ick.mdwn b/tag/ick.mdwn
new file mode 100644
index 0000000..823ea8d
--- /dev/null
+++ b/tag/ick.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged ick"]]
+
+[[!inline pages="tagged(ick)" actions="no" archive="yes"
+feedshow=10]]