Recent changes to this wiki:

Publish log entry
diff --git a/posts/2017/11/13/unit_and_integration_testing_an_analogy_with_cars.mdwn b/posts/2017/11/13/unit_and_integration_testing_an_analogy_with_cars.mdwn
new file mode 100644
index 0000000..a542de2
--- /dev/null
+++ b/posts/2017/11/13/unit_and_integration_testing_an_analogy_with_cars.mdwn
@@ -0,0 +1,21 @@
+[[!meta title="Unit and integration testing: an analogy with cars"]]
+[[!meta date="2017-11-13 00:09"]]
+[[!tag programming analogy testing]]
+
+A unit is a part of your program you can test in isolation. You write
+unit tests to test all aspects of it that you care about. If all your
+unit tests pass, you should know that your unit works well.
+
+Integration tests are for testing that when your various well-tested,
+high quality units are combined, integrated, they work together.
+Integration tests test the integration, not the individual units.
+
+You could think of building a car. Your units are the ball bearings,
+axles, wheels, brakes, etc. Your unit tests for the ball bearings
+might test, for example, that they can handle a billion rotations, at
+various temperatures, etc. Your integration test would assume the ball
+bearings work, and should instead test that the ball bearings are
+installed in the right way so that the car, as whole, can run a
+kilometers, and accelerate and brake every kilometer, uses only so
+much fuel, produces only so much pollution, and doesn't kill
+passengers in case of a crash.

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

Publish log entry
diff --git a/posts/2017/10/10/debian_and_the_gdpr.mdwn b/posts/2017/10/10/debian_and_the_gdpr.mdwn
new file mode 100644
index 0000000..6d15a20
--- /dev/null
+++ b/posts/2017/10/10/debian_and_the_gdpr.mdwn
@@ -0,0 +1,54 @@
+[[!meta title="Debian and the GDPR"]]
+[[!meta date="2017-10-10 18:08"]]
+[[!tag debian gdpr privacy]]
+
+[GDPR][] is a new EU regulation for privacy. The name is short for
+"General Data Protection Regulation" and it covers all organisations
+that handle personal data of EU citizens and EU residents. It will
+become enforceable May 25, 2018 ([Towel Day][]). This will affect
+Debian. I think it's time for Debian to start working on compliance,
+mainly because the GDPR requires sensible things.
+
+[GDPR]: https://en.wikipedia.org/wiki/General_Data_Protection_Regulation
+[Towel Day]: https://en.wikipedia.org/wiki/Towel_Day
+
+I'm not an expert on GDPR legislation, but here's my understanding of
+what we in Debian should do:
+
+* do a privacy impact assessment, to review and **document** what
+  data we have, and collect, and what risks that has for the people
+  whose personal data it is if the data leaks
+
+* only collect personal information for specific purposes, and only
+  use the data for those purposes
+
+* get explicit consent from each person for all collection and use of
+  their personal information; archive this consent (e.g., list
+  subscription confirmations)
+
+* allow each person to get a copy of all the personal information
+  we have about them, in a portable manner, and let them correct it if
+  it's wrong
+
+* allow people to have their personal information erased
+
+* maybe appoint one or more data protection officers (not sure this is
+  required for Debian)
+
+There's more, but let's start with those.
+
+I think Debian has at least the following systems that will need to be
+reviewed with regards to the GDPR:
+
+* db.debian.org - Debian project members, "Debian developers"
+* nm.debian.org
+* contributors.debian.org
+* lists.debian.org - **at least** membership lists, maybe archives
+* possibly irc servers and log files
+* mail server log files
+* web server log files
+* version control services and repositories
+
+There may be more; these are just off the top of my head.
+
+I expect that mostly Debian will be OK, but we can't just assume that.

Drop: comments from front page, comment feed
diff --git a/comments.mdwn b/comments.mdwn
deleted file mode 100644
index e22b50a..0000000
--- a/comments.mdwn
+++ /dev/null
@@ -1,10 +0,0 @@
-[[!sidebar content="""
-[[!inline pages="comment_pending(./posts/*)" feedfile=pendingmoderation
-description="comments pending moderation" show=-1]]
-Comments in the [[!commentmoderation desc="moderation queue"]]:
-[[!pagecount pages="comment_pending(./posts/*)"]]
-"""]]
-
-Recent comments on posts in the [[blog|index]]:
-[[!inline pages="./posts/*/Discussion or comment(./posts/*)"
-template="comment"]]
diff --git a/index.mdwn b/index.mdwn
index 65fdc03..0343655 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -1,9 +1,8 @@
 Welcome to my web log. See the [[first_post|posts/welcome]] for an
-introduction. See the [[archive|posts]] page for all posts, and
-[[comments]] for a feed of comments only. (There is an
+introduction. See the [[archive|posts]] page for all posts. (There is an
 [[english language feed|englishfeed]] if you don't want to see Finnish.)
 
-[[Archives|posts]] [[Tags|tag]] [[Recent Comments|comments]]
+[[Archives|posts]] [[Tags|tag]]
 [Moderation policy](http://liw.fi/moderation/)
 [Main site](http://liw.fi/)
 
@@ -11,12 +10,8 @@ All content outside of comments is copyrighted by Lars Wirzenius, and
 licensed under a <a rel="license"
 href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons
 Attribution-Share Alike 3.0 Unported License</a>. Comments are
-copyrighted by their authors.
+copyrighted by their authors. (No new comments are allowed.)
 
 ---
 
 [[!inline pages="page(posts/*) and !Discussion and !tagged(draft)"]]
-
----
-
-For more, see [[the archive|posts]].

Publish: draft article on attractig contributors
diff --git a/posts/2017/10/01/attracting_contributors_to_a_new_project.mdwn b/posts/2017/10/01/attracting_contributors_to_a_new_project.mdwn
index 363f0ef..c462f51 100644
--- a/posts/2017/10/01/attracting_contributors_to_a_new_project.mdwn
+++ b/posts/2017/10/01/attracting_contributors_to_a_new_project.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Attracting contributors to a new project"]]
 [[!meta date="2017-10-01 10:21"]]
-[[!tag draft meta community]]
+[[!tag meta community]]
 
 How do you attract contributors to a new free software project?
 

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

Publish log entry
diff --git a/posts/2017/10/01/attracting_contributors_to_a_new_project.mdwn b/posts/2017/10/01/attracting_contributors_to_a_new_project.mdwn
new file mode 100644
index 0000000..363f0ef
--- /dev/null
+++ b/posts/2017/10/01/attracting_contributors_to_a_new_project.mdwn
@@ -0,0 +1,72 @@
+[[!meta title="Attracting contributors to a new project"]]
+[[!meta date="2017-10-01 10:21"]]
+[[!tag draft meta community]]
+
+How do you attract contributors to a new free software project?
+
+I'm in the very early stages of a new personal project. It is
+irrelevant for this blog post what the new project actually is.
+Instead, I am thinking about the following question:
+
+> Do I want the project to be mainly for myself, and maybe a handful
+> of others, or do I want to try to make it a more generally useful,
+> possibly even a well-known, popular project? In other words, do I
+> want to just solve a specific problem I have or try to solve it for
+> a large group of people?
+
+If it's a personal project, I'm all set. I can just start writing
+code. (In fact, I have.) If it's the latter, I'll need to attract
+contributions from others, and how do I do that?
+
+I asked that question on [Twitter][] and [Mastodon][] and got several
+suggestions. This is a summary of those, with some editorialising from
+me.
+
+[Twitter]: https://twitter.com/larswirzenius/status/913758747666862081
+[Mastodon]: https://mastodon.acc.sunet.se/@liw/79046
+
+* The most important thing is probably that the project should aim for
+  something that interests other people. The more people it interests,
+  the easier it will be to attract contributors. This should be
+  written up and displayed prominently: what does (or will) the
+  software do and what can it e used for.
+
+* Having something that kind of works, and easy to improve, seems to
+  also be key. An empty project is daunting to do anything with. Part
+  of this is that the software the project is producing should be easy
+  to install and get running. It doesn't have to be fully featured. It
+  doesn't even have to be alpha level quality. It needs to do
+  **something**.
+
+  If the project is about producing a spell checker, say, and it
+  doesn't even try to read an input file, it's probably too early for
+  anyone else to contribute. A spell checker that lists every word in
+  the input file as badly spelt is probably more attractive to
+  contribute to.
+
+* It helps to document where a new contributor should start, and how
+  they would submit their contribution. A list of easy things to work
+  on may also help. Having a roadmap of near future developent steps
+  and a long-term vision will make things easier. Having an
+  architectural document to explain how the system hangs together will
+  help.
+
+* A welcoming, constructive atmosphere helps. People should get quick
+  feedback to questions, issues, patches, in order to build momentum.
+  Make it fun for people to contibute, and they'll contribute more.
+
+* A public source code repository, and a public ticketing system, and
+  public discussion forums (mailing lists, web forums, IRC channels,
+  etc) will help.
+
+* Share the power in the project. Give others the power to make
+  decisions, or merge things from other contributors. Having a clear,
+  functioning governance structure from the start helps.
+
+I don't know if these things are all correct, or that they're enough
+to grow a successful, popular project.
+
+Karl Foger'l seminal book [Producing Open Source Software][] should
+also be mentioned.
+
+[Producing Open Source Software]: http://producingoss.com/

Publish log entry
diff --git a/posts/2017/08/13/retiring_obnam.mdwn b/posts/2017/08/13/retiring_obnam.mdwn
new file mode 100644
index 0000000..6a7b195
--- /dev/null
+++ b/posts/2017/08/13/retiring_obnam.mdwn
@@ -0,0 +1,85 @@
+[[!meta title="Retiring Obnam"]]
+[[!meta date="2017-08-13 21:48"]]
+[[!tag announcement obnam]]
+
+This is a difficult announcement to write. The summary is if you use
+Obnam you should switch to another backup program in the coming
+months.
+
+The first commit to Obnam's current code base is this:
+
+    commit 7eaf5a44534ffa7f9c0b9a4e9ee98d312f2fcb14
+    Author: Lars Wirzenius <liw@iki.fi>
+    Date:   Wed Sep 6 18:35:52 2006 +0300
+
+        Initial commit.
+
+It's followed by over 5200 more commits until the latest one, which is
+from yesterday. The NEWS file contains 58 releases. There are 20761
+lines of Python, 15384 words in the English language manual, with
+translations in German and French. The yarn test suite, which is a
+kind of a manual, is another 13382 words in English and
+pseudo-English. That's a fair bit of code and prose. Not all of it
+mine, I've had help from some wonderful people. But most of it mine.
+
+I wrote all of that because backups were fun. It was pleasing to use
+my own program to guarantee the safety of my own data. The technical
+challenges of implmenting the kind of backup program I wanted were
+interesting, and solving interesting problems is a big part of why 
+I am a programmer.
+
+Obnam has a kind user base. It's not a large user base: the Debian
+"popularity contest" service estimates it at around 500. But it's a
+user base that is kind and has treated me well. I have tried to
+reciprocate.
+
+Unfortunately, I have not had fun while developing Obnam for some time
+now. This has changed. A few years ago, I lived in Manchester, UK, and
+commuted by train to work. It was a short train ride, about 15
+minutes. At times I would sit on the floor with my laptop on my knees,
+writing code or the manual. Back then Obnam was a lot of fun. I was
+excited, and enthusiastic.
+
+In the past two years or so, I've not been able to feel that
+excitement again. My native language, Finnish, has an expression
+describing unpleasant tasks: something is as much fun as drinking tar.
+That describes Obnam in recent years for me.
+
+Obnam has not turned out well, from a maintainability point of view.
+It seems that every time I try to fix something, I break something
+else. Usuaully what breaks is speed or memory use: Obnam gets slower
+or starts using even more memory.
+
+For several years now I've been working on a new repository format for
+Obnam, code names GREEN ALBATROSS. It was meant to solve Obnam's
+problems as far as extensibility, performance, and resource use were
+concerned. It seems to have failed.
+
+I'm afraid I've had enough. I'm going to retire Obnam as a project and
+as a program, and move on to doing something else, so I can feel
+excitement and pleasure again.
+
+After some careful thought, I fear that the maintainability problems
+of Obnam can realistically only be solved by a complete rewrite from
+scratch, and I'm not up to doing that.
+
+If you use Obnam, you should migrate to some other backup solution.
+Don't worry, you have until the end of the year. I will be around and
+I intend to fix any serious bugs in Obnam; in particular, security
+flaws. But you should start looking for a replacement sooner rather
+than later.
+
+I will be asking Obnam to be removed from the Debian unstable and
+testing branches. The next Debian release (buster, Debian 10) won't
+include Obnam.
+
+The Obnam mailing lists are kindly hosted by Daniel Silverstone, and
+they will remain, but later this year I will change them to be
+moderated. The Obnam git repository will remain. The web site will
+remain, but I will add a note that Obnam is no longer maintained.
+Other Obnam online resources may disappear.
+
+If you would like to take over the Obnam project, and try to resolve
+the various issues, please contact me to discuss that.
+
+Thank you, and may you never need to restore.

Publish the TRIM blog post
diff --git a/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn b/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn
index 3ad8fba..3bfcb72 100644
--- a/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn
+++ b/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Enabling TRIM/DISCARD on Debian, ext4, luks, and lvm"]]
 [[!meta date="2017-08-05 20:58"]]
-[[!tag debian sysadmin luks discard ssd draft]]
+[[!tag debian sysadmin luks discard ssd]]
 
 I realised recently that my laptop isn't set up to send [TRIM][] or
 DISCARD commands to its SSD. That means the SSD firmware has a harder

Fix: drop unnecessary mount option
diff --git a/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn b/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn
index 1a41f23..3ad8fba 100644
--- a/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn
+++ b/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn
@@ -14,8 +14,6 @@ Since the information is a bit scattered, here's the details, for
 Debian stretch, as much for my own memory as to make sure this is
 collected into one place.
 
-* Add the `discard` option to `/etc/fstab` to all filesystems that
-  support it.
 * Append `,discard` to the fourth column on relevant lines in
   `/etc/crypttab`. For me, this means the fourth column should be
   `luks,discard`.

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

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

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

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

Publish log entry
diff --git a/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn b/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn
new file mode 100644
index 0000000..1a41f23
--- /dev/null
+++ b/posts/2017/08/05/enabling_trim_discard_on_debian_ext4_luks_and_lvm.mdwn
@@ -0,0 +1,50 @@
+[[!meta title="Enabling TRIM/DISCARD on Debian, ext4, luks, and lvm"]]
+[[!meta date="2017-08-05 20:58"]]
+[[!tag debian sysadmin luks discard ssd draft]]
+
+I realised recently that my laptop isn't set up to send [TRIM][] or
+DISCARD commands to its SSD. That means the SSD firmware has a harder
+time doing garbage collection (see whe linked Wikipedia page for more
+details.)
+
+After some searching, I found two articles by [Christopher Smart][]:
+[one][], [update][]. Those, plus some addition reading of
+documentation, and a little experimentation, allowed me to do this.
+Since the information is a bit scattered, here's the details, for
+Debian stretch, as much for my own memory as to make sure this is
+collected into one place.
+
+* Add the `discard` option to `/etc/fstab` to all filesystems that
+  support it.
+* Append `,discard` to the fourth column on relevant lines in
+  `/etc/crypttab`. For me, this means the fourth column should be
+  `luks,discard`.
+* Change in `/etc/lvm/lvm.conf` that says `issue_discards` to enable
+  it (assign 1 instead of 0).
+* Append `rd.luks.options=discard` to the `GRUB_CMDLINE_LINUX_DEFAULT`
+  value in `/etc/default/grub`
+* Run `sudo update-grub`
+* Run `sudo update-initramfs -u`
+* Reboot.
+* Run `sudo fstrim -av` - if this works, you're good! If it gives you
+  errors, then you get to debug. I have no idea what I'm talking
+  about.
+* Copy
+  `/usr/share/doc/util-linux/examples/fstrim.*` to
+  `/etc/systemd/system` and run `sudo systemctl enable fstrim.timer`.
+  This will tell systemd to run fstrim every week. (If you don't use
+  systemd you'll have to adapt the systemd bits mentioned here. I've
+  no idea how.)
+
+Note that it seems to be a possible information leak to TRIM encryped
+devices. I don't know the details, but if that bothers you, don't do
+it.
+
+I don't know of any harmful effects for enabling TRIM for everything,
+except the crypto bit above, so I wonder if it wouldn't make sense for
+the Debian installer to do this by default.
+
+[TRIM]: https://en.wikipedia.org/wiki/Trim_(computing)
+[Christopher Smart]: https://blog.christophersmart.com/about/
+[one]: https://blog.christophersmart.com/2013/06/05/trim-on-lvm-on-luks-on-ssd/
+[update]: https://blog.christophersmart.com/2016/05/12/trim-on-lvm-on-luks-on-ssd-revisited/

Publish log entry
diff --git a/posts/2017/07/19/dropping_yakking_from_planet_debian.mdwn b/posts/2017/07/19/dropping_yakking_from_planet_debian.mdwn
new file mode 100644
index 0000000..d92efbd
--- /dev/null
+++ b/posts/2017/07/19/dropping_yakking_from_planet_debian.mdwn
@@ -0,0 +1,6 @@
+[[!meta title="Dropping Yakking from Planet Debian"]]
+[[!meta date="2017-07-19 08:53"]]
+[[!tag yakking debian]]
+
+A couple of people objected to having Yakking on Planet Debian, so
+I've removed it.

Publish log entry
diff --git a/posts/2017/07/13/adding_yakking_to_planet_debian.mdwn b/posts/2017/07/13/adding_yakking_to_planet_debian.mdwn
new file mode 100644
index 0000000..60dce93
--- /dev/null
+++ b/posts/2017/07/13/adding_yakking_to_planet_debian.mdwn
@@ -0,0 +1,24 @@
+[[!meta title="Adding Yakking to Planet Debian"]]
+[[!meta date="2017-07-13 13:01"]]
+[[!tag ]]
+
+In a case of blatant self-promotion, I am going to add the [Yakking][]
+RSS feed to the Planet Debian aggregation. (But really because I think
+some of the readership of Planet Debian may be interested in the
+content.)
+
+Yakking is a group blog by a few friends aimed at new free software
+contributors. From the front page description:
+
+> Welcome to Yakking.
+>
+> This is a blog for topics relevant to someone new to free software
+> development. We assume you are already familiar with computers, and
+> are curious about participating in the production of free software.
+> You don't need to be a programmer: software development requires a
+> wide variety of skills, and you can be a valued core contributor to
+> a project without being a programmer.
+
+If anyone objects, please let me know.
+
+[Yakking]: https://yakking.branchable.com/

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