Recent changes to this wiki:

Added a comment: mkimage.sh is in (jessie) /usr/share/docker.io/contrib/
diff --git a/blog/entry/docker_run_debian/comment_1_4eb62c71f6a98dbedd796b45fef13cfa._comment b/blog/entry/docker_run_debian/comment_1_4eb62c71f6a98dbedd796b45fef13cfa._comment
new file mode 100644
index 0000000..8660db8
--- /dev/null
+++ b/blog/entry/docker_run_debian/comment_1_4eb62c71f6a98dbedd796b45fef13cfa._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="OlivierBerger"
+ ip="86.201.115.185"
+ subject="mkimage.sh is in (jessie) /usr/share/docker.io/contrib/"
+ date="2014-07-28T14:46:59Z"
+ content="""
+The mkimage.sh and its accompanying mkimage/debootstrap script are in /usr/share/docker.io/contrib/ as part of docker.io Debian package.
+
+So I guess this answers some of your questions.
+
+See https://wiki.debian.org/Cloud/CreateDockerImage for some hints on their usage.
+"""]]

fix link
diff --git a/blog.mdwn b/blog.mdwn
index fa344a6..86c6f0b 100644
--- a/blog.mdwn
+++ b/blog.mdwn
@@ -28,7 +28,7 @@ My other blogs:
 
 * [git-annex dev blog](http://git-annex.branchable.com/design/assistant/blog)
 * [olduse.net blog](http://olduse.net/blog/)
-* [after 1 minute on my modem](http://http://1-minute-modem.branchable.com)
+* [after 1 minute on my modem](http://1-minute-modem.branchable.com)
 
 Other feeds:
 

add news item for github-backup 1.20140721
diff --git a/code/github-backup/news/version_1.20131101.mdwn b/code/github-backup/news/version_1.20131101.mdwn
deleted file mode 100644
index 6d3ef4e..0000000
--- a/code/github-backup/news/version_1.20131101.mdwn
+++ /dev/null
@@ -1,11 +0,0 @@
-github-backup 1.20131101 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Now also backs up the repos a user is watching, when run with a user's
-     name. Useful if you want to back up repositories that you have not forked;
-     just watch them and run github-backup.
-   * Can now log in to github, to avoid increasingly small API rate limits.
-     Set GITHUB\_USER and GITHUB\_PASSWORD environment to enable.
-     Note that a few api calls don't use authentication; see
-     https://github.com/fpco/github/issues/40
-   * Build-Depend on git. Closes: #[728481](http://bugs.debian.org/728481)
-   * Don't include tmp directory in files stored in the github branch."""]]
\ No newline at end of file
diff --git a/code/github-backup/news/version_1.20140721.mdwn b/code/github-backup/news/version_1.20140721.mdwn
new file mode 100644
index 0000000..db35154
--- /dev/null
+++ b/code/github-backup/news/version_1.20140721.mdwn
@@ -0,0 +1,3 @@
+github-backup 1.20140721 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Fix typo in fix for url parsing. Closes: #[755261](http://bugs.debian.org/755261)"""]]
\ No newline at end of file

add news item for github-backup 1.20140720
diff --git a/code/github-backup/news/version_1.20131006.mdwn b/code/github-backup/news/version_1.20131006.mdwn
deleted file mode 100644
index 77b4373..0000000
--- a/code/github-backup/news/version_1.20131006.mdwn
+++ /dev/null
@@ -1,7 +0,0 @@
-github-backup 1.20131006 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Ported to Windows.
-   * Improve error message when it fails to query github for repositories
-     belonging to a user. Closes: #[705084](http://bugs.debian.org/705084)
-   * Various updates to internal git and utility libraries shared with git-annex.
-   * Makefile now uses cabal to build."""]]
\ No newline at end of file
diff --git a/code/github-backup/news/version_1.20140720.mdwn b/code/github-backup/news/version_1.20140720.mdwn
new file mode 100644
index 0000000..5d8f796
--- /dev/null
+++ b/code/github-backup/news/version_1.20140720.mdwn
@@ -0,0 +1,5 @@
+github-backup 1.20140720 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Deal with trailing slashes on github repo urls. Closes: #[755261](http://bugs.debian.org/755261)
+   * Fix bug introduced by change to embedded git libraries
+     in last release. Closes: #[755262](http://bugs.debian.org/755262)"""]]
\ No newline at end of file

ocracode
diff --git a/blog/entry/laptop_death.mdwn b/blog/entry/laptop_death.mdwn
index 63bcd35..085e383 100644
--- a/blog/entry/laptop_death.mdwn
+++ b/blog/entry/laptop_death.mdwn
@@ -54,3 +54,10 @@ Toshiba passport USB drive, this new one refuses to recognize it unless I
 plug it into a USB 1.0 hub. Oh well..
 
 [[!meta title="laptop death"]]
+
+---
+
+Update: [[Ocracode]] for this trip:
+
+OBX1.1 P6 L7 SA3d+++b+c++ U2(rearended,laptop death) T4f2b1 R2T Bb+m++++n++  
+F+++u++ SC+s-g6 H+f0i3 V+++s++m0 E++r+
diff --git a/ocracode.mdwn b/ocracode.mdwn
index 627fb04..d4d7903 100644
--- a/ocracode.mdwn
+++ b/ocracode.mdwn
@@ -2,7 +2,7 @@ This is the Ocracoke beach camping trip code. To construct the code
 sequence representing your vacation on Ocracoke, write down code sequences
 for each quality of the trip, separating each code sequence with a space
 (or newline at the end of a line). 
-!
+
 You may want to explain part of a code sequence, if so put a short
 explaination (of one or two words) in parentheses immediatly after the part
 of the code it is qualifiying, with no extra whitespace.
@@ -105,3 +105,13 @@ describe your camping trip to Ocracoke.
 * Description of examples of various ratings, all levels
 * Nostalgia factor
 * Bug: Sb indicates back of campground but also burr factor.
+
+# Years
+
+* [[2005, 2006|blog/entry/beach_trip]]
+* [[2007|blog/entry/another_week_at_the_beach]]
+* [[2008|blog/entry/vacation]]
+* [[2009|blog/entry/vacation2]]
+* [[2010|blog/entry/at_the_beach]]
+* [[2011|blog/entry/summer_trips_wrapup]]
+* [[2013|blog/entry/laptop_death]]

Revert "foo"
This reverts commit 8dcedf96bb015f9abf91c32d1daa3bdfaa928b04.
diff --git a/ocracode.mdwn b/ocracode.mdwn
new file mode 100644
index 0000000..627fb04
--- /dev/null
+++ b/ocracode.mdwn
@@ -0,0 +1,107 @@
+This is the Ocracoke beach camping trip code. To construct the code
+sequence representing your vacation on Ocracoke, write down code sequences
+for each quality of the trip, separating each code sequence with a space
+(or newline at the end of a line). 
+!
+You may want to explain part of a code sequence, if so put a short
+explaination (of one or two words) in parentheses immediatly after the part
+of the code it is qualifiying, with no extra whitespace.
+
+If the trip had multiple distinct parts, you can indicate this by writing
+down the main letter for the code and then describing the individual parts,
+separated by a slash (`/`).
+
+Some sections of the code involve rating things with plusses or minuses;
+here is a general scale:
+
+* `--` - Abysmal.
+* `-` - Below average.
+* `++` - Average.
+* `+++` - Excellent.
+* `++++` - Special.
+
+Sample code: 
+
+	OBX1.1 P1/7 L7 SA5s++b++c+++/A17d++b-c-- U4(setup alone,Kai,Daddy swims)
+	T6f2-b0 R1w Bn-b++m++ F++u++ SC++s++g1 H+++f2i5 V+++ E+++r++
+
+* `OBX1.1` - This indicates the beginning of an Ocracoke code block and
+  gives the version number.
+* `P` - Number of people. Follow with number of people in party.
+* `L` - Length of trip. Follow with number of days.
+* `S` - Site number. Following the number can be a letter code describing
+  the site's location:
+
+  * `d` - Dune site.
+  * `b` - Too near bathrooms.
+  * `s` - Too near showers.
+  * `b` - At back of campground.
+
+  The overall quality of the site is indicated with plusses/minuses after the
+  number.
+
+  The burr and cactus level of the site can be indicated with a `b` (for
+  burrs) and a `c` (cactus), followed by the same plusses/minuses.
+
+* `U` - Uniqueness factor of trip. Count up things that are unique about
+  the trip and write down the number.
+* `T` - Tradition factor. Count up the approximate number of Ocracoke
+  traditions that were done again this year and write down the number.
+
+  * `f` - Success at feeding the ranger. Count up number of times fed and
+    write down number. Write a minus for each failure too.
+  * `b` - Number of ranger badges obtained.
+
+* `R` - Rain factor. Count up number of days of rain and write down the
+  number. Can also be followed with letter codes describing the weather:
+
+  * `h` - Left due to hurricane.
+  * `t` - Tent destroyed.
+  * `c` - Slept in car.
+  * `T` - Thunderstorms.
+  * `d` - Dry as a bone.
+  * `s` - Too cold to swim.
+  * `w` - Lots of wind.
+
+* `B` - Bug factor. Rate the number/ferocity of biting flies (`b`),
+  mosquitoes (`m`) and no-see-ums (`n`) with plusses/minuses. More are
+  "better".
+
+* `F` - Food factor. Rate the quality/quantity of food.
+
+  * `u` - Food uniqueness subfactor. Was the food consumed the same meals
+    as always (which is average), or new and special or a new restaurant,
+    etc? Rate it.
+
+* `SC` - Sociability factor. Were new friends made, or did we just hang out
+  in the usual group (the average)? Rate it.
+
+  * `s` - Solitude sub-factor. Was there time for quiet walks on the beach,
+    space for swimming alone, etc? Rate it.
+  * `g` - Games sub-factor. Approximate number of card, board, etc games
+    played.
+
+* `H` - Heat factor. Rate the average heat level of the trip. (Hotter is
+  better.)
+
+  * `f` - Number of ferrys taken to escape the heat.
+  * `i` - Approximate number of 10 lb bags of ice melted per day.
+
+* `V` - View factor. How pleasant was the scenery this time around.
+
+  * `s` - How good was the stargazing? See the Milky Way?
+  * `m` - Number of meteors seen.
+
+* `E` - Overall enjoyment of trip.
+
+  * `r` - Relaxation subfactor. How relaxed will you be coming back? Or
+     will you need a vacation from the vacation?
+
+This page is in a wiki so feel free to edit it to add codes necessary to
+describe your camping trip to Ocracoke.
+
+# TODO
+
+* Description of examples of various ratings, all levels
+* Nostalgia factor
+* Bug: Sb indicates back of campground but also burr factor.

add news item for github-backup 1.20140707
diff --git a/code/github-backup/news/version_1.20130622.mdwn b/code/github-backup/news/version_1.20130622.mdwn
deleted file mode 100644
index 5ebe7ea..0000000
--- a/code/github-backup/news/version_1.20130622.mdwn
+++ /dev/null
@@ -1,3 +0,0 @@
-github-backup 1.20130622 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Add missing unix-compat build dependency. Closes: #[713279](http://bugs.debian.org/713279)"""]]
\ No newline at end of file
diff --git a/code/github-backup/news/version_1.20140707.mdwn b/code/github-backup/news/version_1.20140707.mdwn
new file mode 100644
index 0000000..ed63eea
--- /dev/null
+++ b/code/github-backup/news/version_1.20140707.mdwn
@@ -0,0 +1,7 @@
+github-backup 1.20140707 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Add --exclude to skip backing up a specific repository
+     when backing up a user or organization's repositories.
+     Closes: #[754072](http://bugs.debian.org/754072)
+   * Converted to using optparse-applicative.
+   * Multiple usernames can now be specified to back up at once."""]]
\ No newline at end of file

blog update
diff --git a/blog/entry/laptop_death.mdwn b/blog/entry/laptop_death.mdwn
new file mode 100644
index 0000000..63bcd35
--- /dev/null
+++ b/blog/entry/laptop_death.mdwn
@@ -0,0 +1,56 @@
+So I was at Ocracoke island, camping with family, and I brought my laptop
+along as I've done probably half a dozen times before. An enormous
+thuderstorm came up. It rained for 8 hours and thundered for 3 of those.
+Some lightning cracks quite close by as we crouched in the food tent, our
+feet up off the increasingly wet ground "just in case". The campground
+flooded. Luckily we were camped in the dunes and tents mostly avoided being
+flooded with 2-3 inches of water. (That was just the warmup; a hurricane
+hit a week after we left.)
+
+My laptop was in my tent when this started, and I got soaked to the skin
+just running over there and throwing it up on the thermarest to keep it out
+of any flooding and away from any drips. It seemed ok, so best not to try
+to move it to the car in that downpour.
+
+Next time I checked, it turned out the top vent of the tent was slightly
+open and dripping. The laptop bag was damp. But inside it seemed ok. Rain
+had slackened to just heavy, so I ran it down to the car. Laptop appeared
+barely damp, but it was hard to tell as I had quite forgotten what "dry"
+was. Turned it on for 10 seconds to check the time. It was 7:30 and
+we still had to cook dinner in this mess. Transferred it to a dry bag.
+
+(By the way, in some situations, discovering you have a single dry towel
+you didn't know you had is the best gift in the world!)
+
+Next morning, the laptop was dead. When powered on, the fan came on full,
+the screen stayed black, and after a few seconds it turned itself back off.
+
+I need this for work, so it was a crash priority to get it fixed or a
+replacement. Before I even got home, I had logged onto Lenovo's website to
+check warantee status and found 2 things:
+
+1. They needed some number from a sticker on the bottom of my laptop.
+   Which was no longer there.
+2. The process required some stange login on an entirely
+   different IBM website.
+
+At this point, I had a premonition of how the beuracracy would go. Reading 
+Sesse's [Blehnovo](http://blog.sesse.net/blog/tech/2014-07-07-23-47_blehnovo.html),
+I see I was right. I didn't even try. I ordered a replacement with priority
+shipping.
+
+When I got home, I pulled the laptop apart to try to debug it.
+I still don't know what's wrong with it. The SSD may be damaged; it seems
+to cause anything I put it into to fail to work.
+
+New laptop arrived in 2 days. Since this model is now a year old, it was
+a few hundred dollars cheaper this time around. And now I have an extra
+power supply, and a replacment keyboard, and a replacement fan etc. And
+I've escaped the dead USB port and broken rocker switch of the old laptop
+too.
+
+The only weird thing is that, while my old laptop had no problem with my
+Toshiba passport USB drive, this new one refuses to recognize it unless I
+plug it into a USB 1.0 hub. Oh well..
+
+[[!meta title="laptop death"]]

update
diff --git a/boxen.mdwn b/boxen.mdwn
index 0a58485..69bc61f 100644
--- a/boxen.mdwn
+++ b/boxen.mdwn
@@ -26,7 +26,7 @@ Mostly mythical creatures.
 
 Mostly birds.
 
-* [[kite]]
+* [[kite]] {*}
 * chicken
 * [[turtle]] {*}
 * [[dodo]] {*}
@@ -40,7 +40,7 @@ Mostly birds.
 * [[pell]] {*}
 * orca
 * [[clam]] {*}
-* diatom {*}
+* [[diatom]] {*}
 * [[elephant]] {*}
 
 ## small machines
diff --git a/boxen/diatom.mdwn b/boxen/diatom.mdwn
new file mode 100644
index 0000000..8c6bb7d
--- /dev/null
+++ b/boxen/diatom.mdwn
@@ -0,0 +1 @@
+In digital ocean.
diff --git a/boxen/kite.mdwn b/boxen/kite.mdwn
index 8fc2124..3ae04c2 100644
--- a/boxen/kite.mdwn
+++ b/boxen/kite.mdwn
@@ -1,4 +1,2 @@
-Kite was my main server, but has been retired.
-
-[[wren]] is sometimes referred to as "kite", since it serves the
-kitenet.net domain.
+Kite is the main server for kitenet.net. (Replacing wren, which replaced a
+previous kite.)
diff --git a/boxen/wren.mdwn b/boxen/wren.mdwn
index 7f8bdfe..8fbd16d 100644
--- a/boxen/wren.mdwn
+++ b/boxen/wren.mdwn
@@ -1,5 +1,5 @@
 Wren serves [kitenet.net](http://kitenet.net/) and associated domains, and is
-my main server.
+my main server. However, it's EOL.
 
 Wren is a KVM instance hosted by Steve Kemp at
 [kvm-hosting.org](http://www.xen-hosting.org/), in the UK.

add news item for github-backup 1.20140704
diff --git a/code/github-backup/news/version_1.20130618.mdwn b/code/github-backup/news/version_1.20130618.mdwn
deleted file mode 100644
index 27d2d63..0000000
--- a/code/github-backup/news/version_1.20130618.mdwn
+++ /dev/null
@@ -1,3 +0,0 @@
-github-backup 1.20130618 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Much better creation and committing to the github branch."""]]
\ No newline at end of file
diff --git a/code/github-backup/news/version_1.20140704.mdwn b/code/github-backup/news/version_1.20140704.mdwn
new file mode 100644
index 0000000..f645de0
--- /dev/null
+++ b/code/github-backup/news/version_1.20140704.mdwn
@@ -0,0 +1,6 @@
+github-backup 1.20140704 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Avoid making signed commits when committing to the github-backup branch
+     and the user has commit.gpgsign=true.
+     Closes: #[753720](http://bugs.debian.org/753720)
+   * Various updates to internal git and utility libraries shared with git-annex."""]]
\ No newline at end of file

link
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
index 2d30178..de63850 100644
--- a/blog/entry/docker_run_debian.mdwn
+++ b/blog/entry/docker_run_debian.mdwn
@@ -27,8 +27,8 @@ and
 mkimage.sh -t tianon/debian:wheezy -d . debootstrap --variant=minbase --components=main --include=inetutils-ping,iproute wheezy http://http.debian.net/debian
 </pre>
 
-I don't know where `mkimage.sh` is. And anyway, I have no reason to trust
-that this image is built the way it claims to be built. So, the question
+I don't know where `mkimage.sh` is. [Update: Probably /usr/share/docker.io/contrib/mkimage-debootstrap.sh or a modified version]
+And anyway, I have no reason to trust that this image is built the way it claims to be built. So, the question
 remains: What is in this image?
 
 To find out, I did a `debootstap --variant=minbase stable` and diffed

update
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
index bc529dd..2d30178 100644
--- a/blog/entry/docker_run_debian.mdwn
+++ b/blog/entry/docker_run_debian.mdwn
@@ -130,7 +130,7 @@ Here are some ideas for things Debian could do to improve this:
 
 * Make a package that can build docker images of Debian, in a fully
   reproducible fashion. Ie, same versions of debs in, same byte
-  stream out. (See also [#746394](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=746394)
+  stream out.
 * If it makes sense for the docker image to not contain
   all the packages in a standard debootstrap (maybe leaving out init systems),
   or to contain other packages, write down the rationalle for this,
@@ -143,6 +143,7 @@ Here are some ideas for things Debian could do to improve this:
   debs.
 * Provide some way to verify, through gpg signatures, that docker
   has pulled an actual trusted image and not some https-MITMed thing.
+  (See also [#746394](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=746394)
 
 PS, if this wasn't enough fun, just consider the tweaks made to the "Debian"
 images on all the VPS hosts out there.

update
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
index 6206fd7..bc529dd 100644
--- a/blog/entry/docker_run_debian.mdwn
+++ b/blog/entry/docker_run_debian.mdwn
@@ -130,7 +130,7 @@ Here are some ideas for things Debian could do to improve this:
 
 * Make a package that can build docker images of Debian, in a fully
   reproducible fashion. Ie, same versions of debs in, same byte
-  stream out.
+  stream out. (See also [#746394](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=746394)
 * If it makes sense for the docker image to not contain
   all the packages in a standard debootstrap (maybe leaving out init systems),
   or to contain other packages, write down the rationalle for this,

updates
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
index 310a554..6206fd7 100644
--- a/blog/entry/docker_run_debian.mdwn
+++ b/blog/entry/docker_run_debian.mdwn
@@ -98,13 +98,10 @@ it hangs while trying to run initctl.
 
 ## missing devices
 
-Several devices are missing, including `/dev/full`, `/dev/null`,
-`/dev/zero`, `/dev/[u]random`, `/dev/shm`, and `/dev/loopN`. Docker
-probably fixes some of these up when running the image, but it certianly
-works ok with an image with all these missing devices present, so I don't
-know the rationalle for omitting them.
+Some versions of the debian image are missing things in `/dev`. See
+[this bug](https://github.com/tianon/docker-brew-debian/issues/5).
 
-(See also [this bug](https://github.com/tianon/docker-brew-debian/issues/5))
+(I had listed some device files that I thought were missing, but I was wrong.)
 
 ## some gpg thing is different
 
@@ -135,8 +132,9 @@ Here are some ideas for things Debian could do to improve this:
   reproducible fashion. Ie, same versions of debs in, same byte
   stream out.
 * If it makes sense for the docker image to not contain
-  all the packages in a standard debootstrap, or to contain other packages,
-  write down the rationalle for this, and make a --variant=docker.
+  all the packages in a standard debootstrap (maybe leaving out init systems),
+  or to contain other packages, write down the rationalle for this,
+  and make a --variant=docker.
 * Make a package that provides appropriate tweaks for Debian
   in a container. This might include a policy-rc.d that allows restarting
   daemons on upgrade if they're already running in the container, and

update
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
index 2346dd5..310a554 100644
--- a/blog/entry/docker_run_debian.mdwn
+++ b/blog/entry/docker_run_debian.mdwn
@@ -127,7 +127,7 @@ on an x86 system thanks to qemu). But I'm not going to link to them,
 because again, you should only trust docker images you built yourself. To
 help increase your mistrust of me, I present this IRC snippet:
 
-> <joeyh> I'll bet I could publish an image that just did a killall5 as root on startup and get plenty of people to nuke their container hosts
+	<joeyh> I'll bet I could publish an image that just did a killall5 as root on startup and get plenty of people to nuke their container hosts
 
 Here are some ideas for things Debian could do to improve this:
 

update
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
index abce096..2346dd5 100644
--- a/blog/entry/docker_run_debian.mdwn
+++ b/blog/entry/docker_run_debian.mdwn
@@ -27,7 +27,7 @@ and
 mkimage.sh -t tianon/debian:wheezy -d . debootstrap --variant=minbase --components=main --include=inetutils-ping,iproute wheezy http://http.debian.net/debian
 </pre>
 
-I don't know where `mkimage.sh` is. And I anyway, I have no reason to trust
+I don't know where `mkimage.sh` is. And anyway, I have no reason to trust
 that this image is built the way it claims to be built. So, the question
 remains: What is in this image?
 

update
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
index 7cf4a03..abce096 100644
--- a/blog/entry/docker_run_debian.mdwn
+++ b/blog/entry/docker_run_debian.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="what does docker.io run -it debian sh run?"]]
 
-When you run `docker.io run -it debian sh` it goes off and gets
+When you type `docker.io run -it debian sh`, it goes off and gets
 "debian" and runs it. But what is in this "debian" image? How was it built?
 
 The docker hub [does not really say](https://registry.hub.docker.com/_/debian/).

blog
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
index 32a4f01..7cf4a03 100644
--- a/blog/entry/docker_run_debian.mdwn
+++ b/blog/entry/docker_run_debian.mdwn
@@ -1,20 +1,18 @@
-[[!meta title="what does docker.io run -it debian bash run?"]]
+[[!meta title="what does docker.io run -it debian sh run?"]]
 
-When you run `docker.io run -it debian bash` it goes off and gets
-"debian" and runs it. But what is in this image? How was it built?
+When you run `docker.io run -it debian sh` it goes off and gets
+"debian" and runs it. But what is in this "debian" image? How was it built?
 
 The docker hub [does not really say](https://registry.hub.docker.com/_/debian/).
 All it tells us is this is a "(Semi) Official Debian base image"
-and that its sources.list uses http.debian.net for geolocation. There's a
-link to <https://github.com/dotcloud/stackbrew/blob/master/library/debian>
-which in turn uses a very strange git repository,
-<http://github.com/tianon/docker-brew-debian> 
-"Git is not a fan of what we're doing here." (This repository was put
-together by Debian maintainer Tianon Gravi.)
-
-No wonder, since the actual content of that git repository is a
-succession of compressed "rootfs" tarballs in git branches.
-(Oddly, this compression defeats git deltas.)
+and that its sources.list uses http.debian.net for geolocation. 
+
+There's a link to <https://github.com/dotcloud/stackbrew/blob/master/library/debian>
+which in turn uses a very strange git repository, owned by Debian
+maintainer Tianon Gravi, that contains compressed
+tarballs of Debian: <http://github.com/tianon/docker-brew-debian>
+"Git is not a fan of what we're doing here."
+
 The "source", such as it is, that is used to build this image consists of:
 
 <pre>
@@ -40,10 +38,14 @@ from which I found the following interesting differences.
 ## added packages
 
 The image has iputils-ping and netbase and iproute added. These are not in
-a minbase debootstrap, but are in a regular debootstrap. I actually
-think it's quite weird that the docker image is based on a minbase debootstrap,
-since this means they have to add back important stuff like this on an ad-hoc
-basis.
+a minbase debootstrap, but are in a regular debootstrap. It's
+rather weird that the docker image is based on a minbase debootstrap,
+since this means they have to add back important stuff like this on an
+ad-hoc basis.
+
+> If the expectation is that an experienced Unix person who found it missing
+> would say "What on earth is going on, where is 'foo'?", it must be an
+> 'important' package. -- Debian Policy
 
 ## apt hooks
 
@@ -62,10 +64,12 @@ to avoid wasting disk space, even at the expense of making apt slower (by
 disabling caches) and losing translations.
 
 I am curious if apt might ever invoke the DPkg::Post-Invoke twice in an
-apt run in which it runs apt twice. I'm also curious whether deleting
+upgrade in which it runs dpkg twice. I'm also curious whether deleting
 `/var/cache/apt/archives/lock` could cause a problem.
 
-(dpkg is also configured to use unsafe-io)
+## unsafe-io
+
+dpkg is configured to use unsafe-io.
 
 ## motd
 
@@ -73,27 +77,74 @@ apt run in which it runs apt twice. I'm also curious whether deleting
 Linux viper 3.12.20-gentoo #1 SMP Sun May 18 12:36:24 MDT 2014 x86_64
 </pre>
 
+Yes, that's "gentoo". Presumably this tells us something about the
+build host.
+
 ## policy-rc.d
 
-/usr/sbin/policy-rc.d contains "exit 101", which prevents daemons from
-being automatically started after they are `apt-get install`ed.
+`/usr/sbin/policy-rc.d` contains "exit 101", which prevents daemons from
+being automatically started after they are installed. This may or may
+not be desirable, depending on what you're doing with docker.
 
 It notably also prevents restarting running daemons in this container if
 they're upgraded for eg, a security fix. It would almost certianly be better
-if this script allowed restarting daemons.
+if this script allowed restarting running daemons.
 
 ## diversions
 
-`/sbin/initctl` is diverted and replaced with /bin/true. This is a workaround
-for what is IMHO a bug in sysvinit; when upgraded inside a docker container
+`/sbin/initctl` is diverted and replaced with /bin/true. This is a
+workaround for a bug in sysvinit; when upgraded inside a docker container
 it hangs while trying to run initctl.
 
 ## missing devices
 
+Several devices are missing, including `/dev/full`, `/dev/null`,
+`/dev/zero`, `/dev/[u]random`, `/dev/shm`, and `/dev/loopN`. Docker
+probably fixes some of these up when running the image, but it certianly
+works ok with an image with all these missing devices present, so I don't
+know the rationalle for omitting them.
+
+(See also [this bug](https://github.com/tianon/docker-brew-debian/issues/5))
+
+## some gpg thing is different
+
+> Binary files pure-debootstrap/etc/apt/trustdb.gpg and from-docker/etc/apt/trustdb.gpg differ
+
+Oh well, that can't be important.. Or can it? I did not check.
+
+## conclusions
+
+I would hardly consider this to be an "(Semi) Official Debian image".
+Some of the changes are quite dubious. The build environment is not Debian.
+There is no guarantee you'll get the same image I examined. Diffing
+thousands of lines of filesystem changes is not particularly fun or
+reliable way to spot accidental or malicious changes.
 
+I'd recommend only trusting docker images you build yourself. I have some
+docker images published somewhere that are built with 100% straight
+debootstrap with no modifications (and even an armel image that can be used
+on an x86 system thanks to qemu). But I'm not going to link to them,
+because again, you should only trust docker images you built yourself. To
+help increase your mistrust of me, I present this IRC snippet:
 
-## conclusion
+> <joeyh> I'll bet I could publish an image that just did a killall5 as root on startup and get plenty of people to nuke their container hosts
 
+Here are some ideas for things Debian could do to improve this:
 
+* Make a package that can build docker images of Debian, in a fully
+  reproducible fashion. Ie, same versions of debs in, same byte
+  stream out.
+* If it makes sense for the docker image to not contain
+  all the packages in a standard debootstrap, or to contain other packages,
+  write down the rationalle for this, and make a --variant=docker.
+* Make a package that provides appropriate tweaks for Debian
+  in a container. This might include a policy-rc.d that allows restarting
+  daemons on upgrade if they're already running in the container, and
+  otherwise prevents running daemons.
+* Make a `low-disk-space` package that eg, prevents apt from caching
+  debs.
+* Provide some way to verify, through gpg signatures, that docker
+  has pulled an actual trusted image and not some https-MITMed thing.
 
-[[!meta title="docker run debian"]]
+PS, if this wasn't enough fun, just consider the tweaks made to the "Debian"
+images on all the VPS hosts out there.

blog update
diff --git a/blog/entry/docker_run_debian.mdwn b/blog/entry/docker_run_debian.mdwn
new file mode 100644
index 0000000..32a4f01
--- /dev/null
+++ b/blog/entry/docker_run_debian.mdwn
@@ -0,0 +1,99 @@
+[[!meta title="what does docker.io run -it debian bash run?"]]
+
+When you run `docker.io run -it debian bash` it goes off and gets
+"debian" and runs it. But what is in this image? How was it built?
+
+The docker hub [does not really say](https://registry.hub.docker.com/_/debian/).
+All it tells us is this is a "(Semi) Official Debian base image"
+and that its sources.list uses http.debian.net for geolocation. There's a
+link to <https://github.com/dotcloud/stackbrew/blob/master/library/debian>
+which in turn uses a very strange git repository,
+<http://github.com/tianon/docker-brew-debian> 
+"Git is not a fan of what we're doing here." (This repository was put
+together by Debian maintainer Tianon Gravi.)
+
+No wonder, since the actual content of that git repository is a
+succession of compressed "rootfs" tarballs in git branches.
+(Oddly, this compression defeats git deltas.)
+The "source", such as it is, that is used to build this image consists of:
+
+<pre>
+FROM scratch
+ADD rootfs.tar.xz /
+CMD ["/bin/bash"]
+</pre>
+
+and 
+
+<pre>
+mkimage.sh -t tianon/debian:wheezy -d . debootstrap --variant=minbase --components=main --include=inetutils-ping,iproute wheezy http://http.debian.net/debian
+</pre>
+
+I don't know where `mkimage.sh` is. And I anyway, I have no reason to trust
+that this image is built the way it claims to be built. So, the question
+remains: What is in this image?
+
+To find out, I did a `debootstap --variant=minbase stable` and diffed
+the entire docker debian image against it. The diff was 6738 lines,
+from which I found the following interesting differences.
+
+## added packages
+
+The image has iputils-ping and netbase and iproute added. These are not in
+a minbase debootstrap, but are in a regular debootstrap. I actually
+think it's quite weird that the docker image is based on a minbase debootstrap,
+since this means they have to add back important stuff like this on an ad-hoc
+basis.
+
+## apt hooks
+
+<pre>
+DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };
+APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };
+
+Dir::Cache::pkgcache "";
+Dir::Cache::srcpkgcache "";
+
+Acquire::Languages "none";
+</pre>
+
+These are some strange modifications to apt's config. The intent is clearly
+to avoid wasting disk space, even at the expense of making apt slower (by
+disabling caches) and losing translations.
+
+I am curious if apt might ever invoke the DPkg::Post-Invoke twice in an
+apt run in which it runs apt twice. I'm also curious whether deleting
+`/var/cache/apt/archives/lock` could cause a problem.
+
+(dpkg is also configured to use unsafe-io)
+
+## motd
+
+<pre>
+Linux viper 3.12.20-gentoo #1 SMP Sun May 18 12:36:24 MDT 2014 x86_64
+</pre>
+
+## policy-rc.d
+
+/usr/sbin/policy-rc.d contains "exit 101", which prevents daemons from
+being automatically started after they are `apt-get install`ed.
+
+It notably also prevents restarting running daemons in this container if
+they're upgraded for eg, a security fix. It would almost certianly be better
+if this script allowed restarting daemons.
+
+## diversions
+
+`/sbin/initctl` is diverted and replaced with /bin/true. This is a workaround
+for what is IMHO a bug in sysvinit; when upgraded inside a docker container
+it hangs while trying to run initctl.
+
+## missing devices
+
+
+
+## conclusion
+
+
+
+[[!meta title="docker run debian"]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 3b778ab..85dda47 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,6 +14,6 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 38 "watched it all, liked it" 8 "watched some, boring" 3 "too long for me" 14 "too haskell for me" 12 "not interested"]]
+[[!poll 39 "watched it all, liked it" 8 "watched some, boring" 3 "too long for me" 14 "too haskell for me" 12 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]

add news item for etckeeper 1.12
diff --git a/code/etckeeper/news/version_1.12.mdwn b/code/etckeeper/news/version_1.12.mdwn
new file mode 100644
index 0000000..54084cf
--- /dev/null
+++ b/code/etckeeper/news/version_1.12.mdwn
@@ -0,0 +1,7 @@
+etckeeper 1.12 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Portability fixes. Thanks, Harald Dunkel.
+   * Add support for pushing to multiple remote repositories.
+     Thanks, Rouben.
+   * Fix handling of git ignores like dir/*
+     Thanks, Pim van den Berg"""]]
\ No newline at end of file
diff --git a/code/etckeeper/news/version_1.7.mdwn b/code/etckeeper/news/version_1.7.mdwn
deleted file mode 100644
index ecd3540..0000000
--- a/code/etckeeper/news/version_1.7.mdwn
+++ /dev/null
@@ -1,3 +0,0 @@
-etckeeper 1.7 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Fix hilarious typo hardcoding my name. Closes: #[718425](http://bugs.debian.org/718425)"""]]
\ No newline at end of file

add news item for alien 8.91
diff --git a/code/alien/news/version_8.85.mdwn b/code/alien/news/version_8.85.mdwn
deleted file mode 100644
index 1c74f4f..0000000
--- a/code/alien/news/version_8.85.mdwn
+++ /dev/null
@@ -1,3 +0,0 @@
-alien 8.85 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Avoid breaking on spaces in filenames. Closes: #[618636](http://bugs.debian.org/618636)"""]]
\ No newline at end of file
diff --git a/code/alien/news/version_8.91.mdwn b/code/alien/news/version_8.91.mdwn
new file mode 100644
index 0000000..cadb314
--- /dev/null
+++ b/code/alien/news/version_8.91.mdwn
@@ -0,0 +1,5 @@
+alien 8.91 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Support other deb data.tar compression schemes in fallback code.
+     Closes: #[718364](http://bugs.debian.org/718364)
+     Thanks, Guillem Jover"""]]
\ No newline at end of file

add news item for debhelper 9.20140613
diff --git a/code/debhelper/news/version_9.20131127.mdwn b/code/debhelper/news/version_9.20131127.mdwn
deleted file mode 100644
index f89a21d..0000000
--- a/code/debhelper/news/version_9.20131127.mdwn
+++ /dev/null
@@ -1,4 +0,0 @@
-debhelper 9.20131127 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * dh\_compress: Exclude several more compressed file formats.
-     Closes: #[730483](http://bugs.debian.org/730483)"""]]
\ No newline at end of file
diff --git a/code/debhelper/news/version_9.20140613.mdwn b/code/debhelper/news/version_9.20140613.mdwn
new file mode 100644
index 0000000..1b3eae3
--- /dev/null
+++ b/code/debhelper/news/version_9.20140613.mdwn
@@ -0,0 +1,6 @@
+debhelper 9.20140613 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Pass --disable-silent-rules in dh\_auto\_configure if DH\_VERBOSE is set.
+     Closes: #[751207](http://bugs.debian.org/751207). Thanks, Helmut Grohne.
+   * Minor typos. Closes: #[741144](http://bugs.debian.org/741144), #[744176](http://bugs.debian.org/744176)
+   * dh\_installinit: Fix uninitialized value warning when --name is used."""]]
\ No newline at end of file

add
diff --git a/screencasts/git-annex_views_demo.mdwn b/screencasts/git-annex_views_demo.mdwn
new file mode 100644
index 0000000..b0bed18
--- /dev/null
+++ b/screencasts/git-annex_views_demo.mdwn
@@ -0,0 +1,11 @@
+A quick screencast demoing an experimental new git-annex feature,
+<a href="https://git-annex.branchable.com/tips/metadata_driven_views">metadata driven views</a>.
+
+<video controls src="https://downloads.kitenet.net/videos/git-annex/git-annex_views_demo.ogg"></video>
+
+[video](https://downloads.kitenet.net/videos/git-annex/git-annex_views_demo.ogg)
+
+Credits: 
+
+* RichiH for <https://github.com/RichiH/conference_proceedings>
+* Michi for keyboard cat cameo

link
diff --git a/screencasts/git-annex_assistant_lan.mdwn b/screencasts/git-annex_assistant_lan.mdwn
index e94cd60..b0ae228 100644
--- a/screencasts/git-annex_assistant_lan.mdwn
+++ b/screencasts/git-annex_assistant_lan.mdwn
@@ -1,6 +1,6 @@
 <video controls width=400>
-<source src="https://downloads.kitenet.net/videos/git-annex/git-annex-lan.ogv">
+<source src="https://downloads.kitenet.net/videos/git-annex/git-annex-lan.webm">
 </video><br>
-A <a href="https://downloads.kitenet.net/videos/git-annex/git-annex-lan.ogv">10 minute screencast</a>
+A <a href="https://downloads.kitenet.net/videos/git-annex/git-annex-lan.webm">10 minute screencast</a>
 showing how to use the <a href="https://git-annex.branchable.com/assistant/">git-annex assistant</a> on a local
 network, with your own server.

update
diff --git a/screencasts.mdwn b/screencasts.mdwn
index c254951..3ad2927 100644
--- a/screencasts.mdwn
+++ b/screencasts.mdwn
@@ -1,11 +1,3 @@
-[[!template id=note text="""
-Here is a feed that contains only the videos:
-
-[[!inline pages="screencasts/* and (*.ogg or *.avi or *.mpeg or *.mp3)"
-feedpages="created_after(blog/entry/moving_my_email_archives_and_packages_to_git-annex)"
-show=3 feedshow=20 archive=yes feedfile=videos]]
-"""]]
-
 I'm hoping to do some screecasts on various technical subjects. As I do
 them, they will appear here.
 

lin
diff --git a/screencasts/git-annex_assistant_lan.mdwn b/screencasts/git-annex_assistant_lan.mdwn
index 3c667bb..e94cd60 100644
--- a/screencasts/git-annex_assistant_lan.mdwn
+++ b/screencasts/git-annex_assistant_lan.mdwn
@@ -2,5 +2,5 @@
 <source src="https://downloads.kitenet.net/videos/git-annex/git-annex-lan.ogv">
 </video><br>
 A <a href="https://downloads.kitenet.net/videos/git-annex/git-annex-lan.ogv">10 minute screencast</a>
-showing how to use the [[git-annex assistant|/assistant]] on a local
+showing how to use the <a href="https://git-annex.branchable.com/assistant/">git-annex assistant</a> on a local
 network, with your own server.

update
diff --git a/boxen.mdwn b/boxen.mdwn
index d566600..0a58485 100644
--- a/boxen.mdwn
+++ b/boxen.mdwn
@@ -39,6 +39,9 @@ Mostly birds.
 * [[finch]]
 * [[pell]] {*}
 * orca
+* [[clam]] {*}
+* diatom {*}
+* [[elephant]] {*}
 
 ## small machines
 
@@ -46,7 +49,6 @@ Mostly birds.
 * [[slug]]
 * snail
 * [[stick]]
-* [[clam]]
 
 ## phones
 
diff --git a/boxen/elephant.mdwn b/boxen/elephant.mdwn
new file mode 100644
index 0000000..9005468
--- /dev/null
+++ b/boxen/elephant.mdwn
@@ -0,0 +1,5 @@
+storage and backup. 
+
+Panel: <https://www.prometeus.net/billing/clientarea.php>
+
+Panel 2: <https://solusvm.prometeus.net/>
diff --git a/screencasts/git-annex_assistant_lan.mdwn b/screencasts/git-annex_assistant_lan.mdwn
new file mode 100644
index 0000000..3c667bb
--- /dev/null
+++ b/screencasts/git-annex_assistant_lan.mdwn
@@ -0,0 +1,6 @@
+<video controls width=400>
+<source src="https://downloads.kitenet.net/videos/git-annex/git-annex-lan.ogv">
+</video><br>
+A <a href="https://downloads.kitenet.net/videos/git-annex/git-annex-lan.ogv">10 minute screencast</a>
+showing how to use the [[git-annex assistant|/assistant]] on a local
+network, with your own server.

orphaning
diff --git a/code.mdwn b/code.mdwn
index a5b4354..ac175f0 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -12,7 +12,6 @@ The stuff that's swapped into my local cache at the moment.
 [[debian-installer]]
 [[debhelper]]
 [[moreutils]]
-[[pristine-tar]]
 [[myrepos|mr]]
 [[etckeeper]]
 [[mpdtoys]]
@@ -58,6 +57,7 @@ Passed on to others, or dead and buried:
 [[mooix]]
 [[wmbattery]]
 [[sleepd]]
+[[pristine-tar]]
 
 ## Misc
 

add news item for sleepd 2.05
diff --git a/code.mdwn b/code.mdwn
index 20381a1..a5b4354 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -29,9 +29,7 @@ have my hands in it somewhat.
 [[alien]]
 [[debconf]]
 [[dpkg-repack]]
-[[wmbattery]]
 [[Words2Nums]]
-[[sleepd]]
 [[pdmenu]]
 [[filters]]
 [[os-prober]]
@@ -58,6 +56,8 @@ Passed on to others, or dead and buried:
 [[flashybrid]]
 [[satutils]]
 [[mooix]]
+[[wmbattery]]
+[[sleepd]]
 
 ## Misc
 
diff --git a/code/sleepd/news/version_2.04.mdwn b/code/sleepd/news/version_2.04.mdwn
deleted file mode 100644
index 72a3c1c..0000000
--- a/code/sleepd/news/version_2.04.mdwn
+++ /dev/null
@@ -1,3 +0,0 @@
-sleepd 2.04 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Fix getopt for --force-hal option. Closes: #[600168](http://bugs.debian.org/600168)"""]]
\ No newline at end of file
diff --git a/code/sleepd/news/version_2.05.mdwn b/code/sleepd/news/version_2.05.mdwn
new file mode 100644
index 0000000..f4c4cf4
--- /dev/null
+++ b/code/sleepd/news/version_2.05.mdwn
@@ -0,0 +1,12 @@
+sleepd 2.05 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ Joey Hess ]
+   * Stop building with flash-in-the-pan HAL. Instead update acpi
+     interface to use /sys/class/power\_supply.
+     Note that this needs acpica\_version 20011018.
+     Closes: #[613169](http://bugs.debian.org/613169), #[678966](http://bugs.debian.org/678966)
+     (Patch developed by Andrew Shadura.)
+   * Orphaned the package.
+ * [ Andrew Shadura ]
+   * Add UPower support.
+   * Use Debhelper 9, so we can have hardening flags automatically."""]]
\ No newline at end of file

add news item for wmbattery 2.43
diff --git a/code/wmbattery/news/version_2.38.mdwn b/code/wmbattery/news/version_2.38.mdwn
deleted file mode 100644
index 390c54c..0000000
--- a/code/wmbattery/news/version_2.38.mdwn
+++ /dev/null
@@ -1,4 +0,0 @@
-wmbattery 2.38 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Magic header file reordering to work around the disgusting
-     linux-libc-dev/libc headers conflicts (#435700). Closes: #[463811](http://bugs.debian.org/463811)"""]]
\ No newline at end of file
diff --git a/code/wmbattery/news/version_2.43.mdwn b/code/wmbattery/news/version_2.43.mdwn
new file mode 100644
index 0000000..8efe25d
--- /dev/null
+++ b/code/wmbattery/news/version_2.43.mdwn
@@ -0,0 +1,5 @@
+wmbattery 2.43 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Orphaned the package. It will probably be removed as it does not work with
+     current kernels.
+   * Added -i to display as icon. Thanks, Tovar Closes: #[732398](http://bugs.debian.org/732398)"""]]
\ No newline at end of file

blog update
diff --git a/blog/entry/how_I_wrote_init_by_accident.mdwn b/blog/entry/how_I_wrote_init_by_accident.mdwn
new file mode 100644
index 0000000..ea76d3b
--- /dev/null
+++ b/blog/entry/how_I_wrote_init_by_accident.mdwn
@@ -0,0 +1,55 @@
+I wrote my own `init`. I didn't mean to, and in the end, it took 2 lines of
+code. Here's how.
+
+[Propellor](http://propellor.branchable.com/) has the nice feature of
+supporting provisioning of Docker containers. Since Docker normally runs
+just one command inside the container, I made the command that docker
+runs be propellor, which runs inside the container and takes care of
+provisioning it according to its configuration.
+
+For example, here's a real live configuration of a container:
+
+[[!format haskell """
+        -- Exhibit: kite's 90's website.
+        , standardContainer "ancient-kitenet" Stable "amd64"
+                & Docker.publish "1994:80"
+                & Apt.serviceInstalledRunning "apache2"
+                & Git.cloned "root" "git://kitenet-net.branchable.com/" "/var/www"
+                        (Just "remotes/origin/old-kitenet.net")
+"""]]
+
+When propellor is run inside this container, it takes care of installing
+apache, and since the property states apache should be running, it also starts
+the daemon if necessary.
+
+At boot, docker remembers the command that was used to start the container
+last time, and runs it again. This time, apache is already installed,
+so propellor simply starts the daemon.
+
+This was surprising, but it was just what I wanted too! The only missing
+bit to make this otherwise entirely free implementation of init work properly
+was two lines of code:
+
+[[!format haskell """
+                void $ async $ job reapzombies
+  where
+        reapzombies = void $ getAnyProcessStatus True False
+"""]]
+
+Propellor-as-init also starts up a simple equalivilant of rsh on a named pipe
+(for communication between the propellor inside and outside the container),
+and also runs a root login shell (so the user can attach to the container and
+administer it). Also, running a compiled program from the host system
+inside a container, which might use a different distribution or
+architecture was an interesting challenge 
+(solved using the method described in [[completely_linux_distribution-independent_packaging]]).
+So it wasn't entirely trivial, but as far as init goes, it's probably
+one of the simpler implementations out there.
+
+I know that there are various other solutions on the space of an init for
+Docker -- personally I'd rather the host's systemd integrated with it
+so I could see the status of the container's daemons in `systemctl status`.
+If that does happen, perhaps I'll eventually be able to remove 2 lines of code
+from propellor.
+
+[[!meta title="how I wrote init by accident"]]

blog update
diff --git a/blog/entry/who_needs_whiteboards_when_you_have_strange_seed_pods_from_the_jungle.mdwn b/blog/entry/who_needs_whiteboards_when_you_have_strange_seed_pods_from_the_jungle.mdwn
new file mode 100644
index 0000000..6bb9f73
--- /dev/null
+++ b/blog/entry/who_needs_whiteboards_when_you_have_strange_seed_pods_from_the_jungle.mdwn
@@ -0,0 +1,10 @@
+[[pics/git-annex-routing.jpg]]
+
+Discussing git-annex routing with Vince and Fernao.  Might not look like
+much, but we seem to be close to cracking the most interesting problem with
+git-annex routing. I need to translate and read Vince's thesis and build some
+simulations..
+
+(Seed pod, cup, camera = fixed node; mini brick = usb drive; leaves = data.)
+
+[[!meta title="who needs whiteboards when you have strange seed pods from the jungle"]]
diff --git a/blog/pics/git-annex-routing.jpg b/blog/pics/git-annex-routing.jpg
new file mode 100644
index 0000000..063cfc6
Binary files /dev/null and b/blog/pics/git-annex-routing.jpg differ

add post
diff --git a/blog/entry/radio_brazil.mdwn b/blog/entry/radio_brazil.mdwn
new file mode 100644
index 0000000..03a66a6
--- /dev/null
+++ b/blog/entry/radio_brazil.mdwn
@@ -0,0 +1,3 @@
+[[!img pics/radiobrazil.png]]
+
+Live radio broadcast going on in the tent while I teach Mill to use ikiwiki.
diff --git a/blog/pics/radiobrazil.png b/blog/pics/radiobrazil.png
new file mode 100644
index 0000000..c00cb69
Binary files /dev/null and b/blog/pics/radiobrazil.png differ

update
diff --git a/blog/entry/the_real_Brazil.mdwn b/blog/entry/the_real_Brazil.mdwn
index 590ec80..a51b459 100644
--- a/blog/entry/the_real_Brazil.mdwn
+++ b/blog/entry/the_real_Brazil.mdwn
@@ -11,4 +11,7 @@ a flat plain, playing chicken against oncoming trucks.
 Night swim in the river in Correntina, followed by a whole grilled fish and
 ice cold guarana. Bliss.
 
+Push starting the car in a small cattle-farming village when it wouldn't
+start.
+
 The first sight of ocean waves and the drum circle last night.

fix
diff --git a/blog/pics/braziltrip.jpg b/blog/pics/braziltrip.jpg
index fbd1784..1105b00 100644
Binary files a/blog/pics/braziltrip.jpg and b/blog/pics/braziltrip.jpg differ

foo
diff --git a/blog/entry/the_real_Brazil.mdwn b/blog/entry/the_real_Brazil.mdwn
index 1048dcb..590ec80 100644
--- a/blog/entry/the_real_Brazil.mdwn
+++ b/blog/entry/the_real_Brazil.mdwn
@@ -5,7 +5,7 @@
 After 3 days of travel, including 22 hours driving from Brasilia to the
 coast of Bahia, I can't say much more. A few things not pictured above..
 
-The 3 hours of car-swallowing potholes in an arrow-straight highway in
+The two hours of car-swallowing potholes in an arrow-straight highway in
 a flat plain, playing chicken against oncoming trucks.
 
 Night swim in the river in Correntina, followed by a whole grilled fish and

scale
diff --git a/blog/entry/the_real_Brazil.mdwn b/blog/entry/the_real_Brazil.mdwn
index a966181..1048dcb 100644
--- a/blog/entry/the_real_Brazil.mdwn
+++ b/blog/entry/the_real_Brazil.mdwn
@@ -1,4 +1,4 @@
-[[!img pics/braziltrip.jpg size=1024x]]
+[[!img pics/braziltrip.jpg size=1024x caption="(click to enlarge)"]]
 
 "This is the real Brazil" -- Fernao
 

fix
diff --git a/blog/pics/braziltrip.jpg b/blog/pics/braziltrip.jpg
index 322862b..fbd1784 100644
Binary files a/blog/pics/braziltrip.jpg and b/blog/pics/braziltrip.jpg differ

scale
diff --git a/blog/entry/the_real_Brazil.mdwn b/blog/entry/the_real_Brazil.mdwn
index 045d898..a966181 100644
--- a/blog/entry/the_real_Brazil.mdwn
+++ b/blog/entry/the_real_Brazil.mdwn
@@ -1,4 +1,4 @@
-[[!img pics/braziltrip.jpg width=1024]]
+[[!img pics/braziltrip.jpg size=1024x]]
 
 "This is the real Brazil" -- Fernao
 

revised
diff --git a/blog/entry/Correntina_BR.mdwn b/blog/entry/Correntina_BR.mdwn
deleted file mode 100644
index b2c6a0f..0000000
--- a/blog/entry/Correntina_BR.mdwn
+++ /dev/null
@@ -1,15 +0,0 @@
-[[!img pics/gasstationbr.jpg]]
-
-Day 1 of a 2 day drive from Brasilia to the coast of Bahia.
-
-Correntina is a nice town in either in the middle of nowhere, or the edge,
-not sure yet. The final road on the way here was 3 hours of 2-lane highway
-infested with car-swallowing potholes. Many times an oncoming truck would
-swerve into our lane just ahead to avoid a pothole. Luckily just as dark
-fell we got to a part where the potholes had been repaired.
-
-Night swim in the river in Correntina, followed by a whole grilled fish and
-guaraña. Bliss.
-
-[[!meta title="Correntina BR"]]
-[[!meta date="Sun, 27 Apr 2014 22:12:55 -0300"]]
diff --git a/blog/entry/the_real_Brazil.mdwn b/blog/entry/the_real_Brazil.mdwn
new file mode 100644
index 0000000..045d898
--- /dev/null
+++ b/blog/entry/the_real_Brazil.mdwn
@@ -0,0 +1,14 @@
+[[!img pics/braziltrip.jpg width=1024]]
+
+"This is the real Brazil" -- Fernao
+
+After 3 days of travel, including 22 hours driving from Brasilia to the
+coast of Bahia, I can't say much more. A few things not pictured above..
+
+The 3 hours of car-swallowing potholes in an arrow-straight highway in
+a flat plain, playing chicken against oncoming trucks.
+
+Night swim in the river in Correntina, followed by a whole grilled fish and
+ice cold guarana. Bliss.
+
+The first sight of ocean waves and the drum circle last night.
diff --git a/blog/pics/braziltrip.jpg b/blog/pics/braziltrip.jpg
new file mode 100644
index 0000000..322862b
Binary files /dev/null and b/blog/pics/braziltrip.jpg differ
diff --git a/blog/pics/gasstationbr.jpg b/blog/pics/gasstationbr.jpg
deleted file mode 100644
index 2f6095f..0000000
Binary files a/blog/pics/gasstationbr.jpg and /dev/null differ

date
diff --git a/blog/entry/Correntina_BR.mdwn b/blog/entry/Correntina_BR.mdwn
index 35b8acb..b2c6a0f 100644
--- a/blog/entry/Correntina_BR.mdwn
+++ b/blog/entry/Correntina_BR.mdwn
@@ -12,3 +12,4 @@ Night swim in the river in Correntina, followed by a whole grilled fish and
 guaraña. Bliss.
 
 [[!meta title="Correntina BR"]]
+[[!meta date="Sun, 27 Apr 2014 22:12:55 -0300"]]

update
diff --git a/blog/entry/Correntina_BR.mdwn b/blog/entry/Correntina_BR.mdwn
index 86ce857..35b8acb 100644
--- a/blog/entry/Correntina_BR.mdwn
+++ b/blog/entry/Correntina_BR.mdwn
@@ -2,11 +2,11 @@
 
 Day 1 of a 2 day drive from Brasilia to the coast of Bahia.
 
-Correntina is either in the middle of nowhere, or the edge, not sure yet. The
-final road on the way here was 2 hours of 2-lane highway infested with
-car-swallowing potholes. Many times an oncoming truck would swerve into our
-lane just ahead to avoid a pothole. Luckily just as dark fell we got to a
-part where the potholes had been repaired.
+Correntina is a nice town in either in the middle of nowhere, or the edge,
+not sure yet. The final road on the way here was 3 hours of 2-lane highway
+infested with car-swallowing potholes. Many times an oncoming truck would
+swerve into our lane just ahead to avoid a pothole. Luckily just as dark
+fell we got to a part where the potholes had been repaired.
 
 Night swim in the river in Correntina, followed by a whole grilled fish and
 guaraña. Bliss.

blog update
diff --git a/blog/entry/Correntina_BR.mdwn b/blog/entry/Correntina_BR.mdwn
new file mode 100644
index 0000000..86ce857
--- /dev/null
+++ b/blog/entry/Correntina_BR.mdwn
@@ -0,0 +1,14 @@
+[[!img pics/gasstationbr.jpg]]
+
+Day 1 of a 2 day drive from Brasilia to the coast of Bahia.
+
+Correntina is either in the middle of nowhere, or the edge, not sure yet. The
+final road on the way here was 2 hours of 2-lane highway infested with
+car-swallowing potholes. Many times an oncoming truck would swerve into our
+lane just ahead to avoid a pothole. Luckily just as dark fell we got to a
+part where the potholes had been repaired.
+
+Night swim in the river in Correntina, followed by a whole grilled fish and
+guaraña. Bliss.
+
+[[!meta title="Correntina BR"]]
diff --git a/blog/pics/gasstationbr.jpg b/blog/pics/gasstationbr.jpg
new file mode 100644
index 0000000..2f6095f
Binary files /dev/null and b/blog/pics/gasstationbr.jpg differ

propellor website
diff --git a/code/propellor.mdwn b/code/propellor.mdwn
index 85b2ae5..4e8fd36 100644
--- a/code/propellor.mdwn
+++ b/code/propellor.mdwn
@@ -1,4 +1,4 @@
 property-based host configuration management in haskell
 
+* [propellor's website](https://propellor.branchable.com/)
 * [[Read my blog post about it|/blog/entry/propellor]]
-* [clone its git repository](http://git.kitenet.net/?p=propellor.git;a=summary)

sytax changes
diff --git a/blog/entry/propellor-driven_DNS_and_backups.mdwn b/blog/entry/propellor-driven_DNS_and_backups.mdwn
index 9e2f3ea..a1e0184 100644
--- a/blog/entry/propellor-driven_DNS_and_backups.mdwn
+++ b/blog/entry/propellor-driven_DNS_and_backups.mdwn
@@ -4,13 +4,13 @@ servers and I just had it deploy mine. Including generating DNS zone files.
 Configuration is dead simple, as far as DNS goes:
 
 [[!format haskell """
+		& alias "ns1.example.com"
 		& Dns.secondary hosts "joeyh.name"
                 & Dns.primary hosts "example.com"
-                        ( Dns.mkSOA "ns1.example.com" 100
-                                [ NS (AbsDomain "ns1.example.com")
-                                , NS (AbsDomain "ns2.example.com")
-                                ]
-                        ) []
+                        (Dns.mkSOA "ns1.example.com" 100)
+                        [ (RootDomain, NS $ AbsDomain "ns1.example.com")
+			, (RootDomain, NS $ AbsDomain "ns2.example.com")
+                        ]
 """]]
 
 The awesome thing is that propellor fills in all the other information
@@ -26,6 +26,9 @@ in the zone file by looking at the properties of the hosts it knows about.
 		& alias "example.museum"
 		& Docker.docked hosts "webserver"
 			`requres` backedup "/var/www"
+		
+		& alias "ns2.example.com"
+		& Dns.secondary hosts "example.com"
 """]]
 
 When it sees this host, Propellor adds its IP addresses to the example.com

blog update
diff --git a/blog/entry/propellor-driven_DNS_and_backups.mdwn b/blog/entry/propellor-driven_DNS_and_backups.mdwn
new file mode 100644
index 0000000..9e2f3ea
--- /dev/null
+++ b/blog/entry/propellor-driven_DNS_and_backups.mdwn
@@ -0,0 +1,101 @@
+Took a while to get here, but [[code/Propellor]] 0.4.0 can deploy DNS
+servers and I just had it deploy mine. Including generating DNS zone files.
+
+Configuration is dead simple, as far as DNS goes:
+
+[[!format haskell """
+		& Dns.secondary hosts "joeyh.name"
+                & Dns.primary hosts "example.com"
+                        ( Dns.mkSOA "ns1.example.com" 100
+                                [ NS (AbsDomain "ns1.example.com")
+                                , NS (AbsDomain "ns2.example.com")
+                                ]
+                        ) []
+"""]]
+
+The awesome thing is that propellor fills in all the other information
+in the zone file by looking at the properties of the hosts it knows about.
+
+[[!format haskell """
+	, host "blue.example.com"
+		& ipv4 "192.168.1.1"
+		& ipv6 "fe80::26fd:52ff:feea:2294"
+
+		& alias "example.com"
+		& alias "www.example.com"
+		& alias "example.museum"
+		& Docker.docked hosts "webserver"
+			`requres` backedup "/var/www"
+"""]]
+
+When it sees this host, Propellor adds its IP addresses to the example.com
+DNS zone file, for both its main hostname ("blue.example.com"), and also its
+relevant aliases. (The .museum alias would go into a different zone file.)
+
+Multiple hosts can define the same alias, and then you automaticlly get
+round-robin DNS.
+
+The web server part of of the blue.example.com config can be cut and
+pasted to another host in order to move its web server to the other host,
+including updating the DNS. That's really all there is to is, just cut,
+paste, and commit!
+
+I'm quite happy with how that worked out. And curious if Puppet etc
+have anything similar.
+
+----
+
+One tricky part of this was how to ensure that the serial number automtically
+updates when changes are made. The way this is handled is Propellor starts
+with a base serial number (100 in the example above), and then it adds to it
+the number of commits in its git repository. The zone file is only updated
+when something in it besides the serial number needs to change. 
+
+The result is nice small serial numbers that don't risk overflowing the
+(so 90's) 32 bit limit, and will be consistent even if the configuration
+had Propellor setting up multiple independent master DNS servers for the
+same domain.
+
+----
+
+Another recent feature in Propellor is that it can use Obnam
+to back up a directory. With the awesome feature that if
+the backed up directory is empty/missing,
+Propellor will automcatically *restore* it from the backup.
+
+Here's how the `backedup` property used in the example above
+might be implemented:
+
+[[!format haskell """
+backedup :: FilePath -> Property
+backedup dir = Obnam.backup dir daily
+	[ "--repository=sftp://rsync.example.com/~/webserver.obnam"
+	] Obnam.OnlyClient
+	`requires` Ssh.keyImported SshRsa "root"
+	`requires` Ssh.knownHost hosts "rsync.example.com" "root"
+	`requires` Gpg.keyImported "1B169BE1" "root"
+"""]]
+
+Notice that the `Ssh.knownHost` makes root trust the ssh host key
+belonging to rsync.example.com. So Propellor needs to be told what that
+host key is, like so:
+
+[[!format haskell """
+	, host "rsync.example.com"
+		& ipv4 "192.168.1.4"
+		& sshPubKey "ssh-rsa blahblahblah"
+"""]]
+
+Which of course ties back into the DNS and gets this hostname set in it.
+But also, the ssh public key is available for this host and visible to the
+DNS zone file generator, and that could also be set in the DNS, in a SSHFP
+record. I haven't gotten around to implementing that, but hope at some
+point to make Propellor support DNSSEC, and then this will all combine even
+more nicely.
+
+----
+
+By the way, Propellor is now up to 3 thousand lines of code
+(not including Utility library). In 20 days, as a 10% time side project.
+
+[[!meta title="propellor-driven DNS and backups"]]

foo
diff --git a/blog/entry/propellor_introspection_for_DNS.mdwn b/blog/entry/propellor_introspection_for_DNS.mdwn
index 1f7ad9e..a6077a6 100644
--- a/blog/entry/propellor_introspection_for_DNS.mdwn
+++ b/blog/entry/propellor_introspection_for_DNS.mdwn
@@ -63,7 +63,7 @@ and propellor will provision them, and update the zone file appropriately.
 
 Also, Chris Webber had suggested that Propellor be able to separate values
 from properties, so that eg, a web wizard could configure the values easily.
-I think this gets it of the way there. All that's left to do is two easy
+I think this gets it much of the way there. All that's left to do is two easy
 functions:
 
 [[!format haskell """

wording
diff --git a/blog/entry/propellor_introspection_for_DNS.mdwn b/blog/entry/propellor_introspection_for_DNS.mdwn
index 9faa61f..1f7ad9e 100644
--- a/blog/entry/propellor_introspection_for_DNS.mdwn
+++ b/blog/entry/propellor_introspection_for_DNS.mdwn
@@ -78,18 +78,18 @@ here's a containerized webserver that publishes a directory from
 the external host, as configured by JSON that it exports:
 
 [[!format haskell """
-	demo :: Host
-	demo = Docker.container "webserver" "joeyh/debian-unstable"
-		& Docker.publish "80:80"
-		& dir_to_publish "/home/mywebsite" -- dummy default
-		& Docker.volume (getAttr dir_to_publish ++":/var/www")
-		& Apt.serviceInstalledRunning "apache2"
-	
-	main = do
-		json <- readJSON "my.json"
-		let demo' = overrideAttrsFromJSON demo
-		writeJSON "my.json" (exportJSONAttrs demo')
-		defaultMain [demo']
+demo :: Host
+demo = Docker.container "webserver" "joeyh/debian-unstable"
+	& Docker.publish "80:80"
+	& dir_to_publish "/home/mywebsite" -- dummy default
+	& Docker.volume (getAttr dir_to_publish ++":/var/www")
+	& Apt.serviceInstalledRunning "apache2"
+
+main = do
+	json <- readJSON "my.json"
+	let demo' = overrideAttrsFromJSON demo
+	writeJSON "my.json" (exportJSONAttrs demo')
+	defaultMain [demo']
 """]]
 
 [[!meta title="propellor introspection for DNS"]]

wording
diff --git a/blog/entry/propellor_introspection_for_DNS.mdwn b/blog/entry/propellor_introspection_for_DNS.mdwn
index 09fcccb..9faa61f 100644
--- a/blog/entry/propellor_introspection_for_DNS.mdwn
+++ b/blog/entry/propellor_introspection_for_DNS.mdwn
@@ -79,16 +79,17 @@ the external host, as configured by JSON that it exports:
 
 [[!format haskell """
 	demo :: Host
-	demo = overrideAttrsFromJSON $
-		Docker.container "webserver" "joeyh/debian-unstable"
-			& Docker.publish "80:80"
-			& dir_to_publish "/home/mywebsite" -- dummy default
-			& Docker.volume (getAttr dir_to_publish ++":/var/www")
-			& Apt.serviceInstalledRunning "apache2"
+	demo = Docker.container "webserver" "joeyh/debian-unstable"
+		& Docker.publish "80:80"
+		& dir_to_publish "/home/mywebsite" -- dummy default
+		& Docker.volume (getAttr dir_to_publish ++":/var/www")
+		& Apt.serviceInstalledRunning "apache2"
 	
 	main = do
-		exportJSON "my.json" (exportJSONAttrs demo)
-		defaultMain [demo]
+		json <- readJSON "my.json"
+		let demo' = overrideAttrsFromJSON demo
+		writeJSON "my.json" (exportJSONAttrs demo')
+		defaultMain [demo']
 """]]
 
 [[!meta title="propellor introspection for DNS"]]

wording
diff --git a/blog/entry/propellor_introspection_for_DNS.mdwn b/blog/entry/propellor_introspection_for_DNS.mdwn
index 7982b49..09fcccb 100644
--- a/blog/entry/propellor_introspection_for_DNS.mdwn
+++ b/blog/entry/propellor_introspection_for_DNS.mdwn
@@ -47,7 +47,7 @@ of `hosts`! Tying the knot like this is a fun haskell laziness trick. :)
 Now I just need to write a little function to look over the hosts
 and generate a zone file from their hostname, cname, and address attributes:
 
-[[!format haselll """
+[[!format haskell """
 extractZoneFile :: Domain -> [Host] -> ZoneFile
 extractZoneFile = gen . map hostAttr
   where gen = -- TODO

wording
diff --git a/blog/entry/propellor_introspection_for_DNS.mdwn b/blog/entry/propellor_introspection_for_DNS.mdwn
index 0da523c..7982b49 100644
--- a/blog/entry/propellor_introspection_for_DNS.mdwn
+++ b/blog/entry/propellor_introspection_for_DNS.mdwn
@@ -1,6 +1,6 @@
 In just released Propellor 0.3.0, I've improved improved
 [[code/Propellor]]'s config file DSL significantly. Now properties can
-set attributes of a host, that can be looked up by its properties,
+set attributes of a host, that can be looked up by its other properties,
 using a Reader monad.
 
 This saves needing to repeat yourself:

blog update
diff --git a/blog/entry/propellor_introspection_for_DNS.mdwn b/blog/entry/propellor_introspection_for_DNS.mdwn
new file mode 100644
index 0000000..0da523c
--- /dev/null
+++ b/blog/entry/propellor_introspection_for_DNS.mdwn
@@ -0,0 +1,94 @@
+In just released Propellor 0.3.0, I've improved improved
+[[code/Propellor]]'s config file DSL significantly. Now properties can
+set attributes of a host, that can be looked up by its properties,
+using a Reader monad.
+
+This saves needing to repeat yourself:
+
+[[!format haskell """
+hosts = [ host "orca.kitenet.net"
+		& stdSourcesList Unstable
+		& Hostname.sane -- uses hostname from above
+"""]]
+
+And it simplifies docker setup, with no longer a need to differentiate between
+properties that configure docker vs properties of the container:
+
+[[!format haskell """
+	-- A generic webserver in a Docker container.
+	, Docker.container "webserver" "joeyh/debian-unstable"
+		& Docker.publish "80:80"
+		& Docker.volume "/var/www:/var/www"
+		& Apt.serviceInstalledRunning "apache2"
+"""]]
+
+But the really useful thing is, it allows automating DNS zone file
+creation, using attributes of hosts that are set and used alongside
+their other properties:
+
+[[!format haskell """
+hosts =
+	[ host "clam.kitenet.net"
+		& ipv4 "10.1.1.1"
+
+		& cname "openid.kitenet.net"
+		& Docker.docked hosts "openid-provider"
+
+		& cname "ancient.kitenet.net"
+		& Docker.docked hosts "ancient-kitenet"
+	, host "diatom.kitenet.net"
+		& Dns.primary "kitenet.net" hosts
+	]
+"""]]
+
+Notice that `hosts` is passed into `Dns.primary`, inside the definition
+of `hosts`! Tying the knot like this is a fun haskell laziness trick. :)
+
+Now I just need to write a little function to look over the hosts
+and generate a zone file from their hostname, cname, and address attributes:
+
+[[!format haselll """
+extractZoneFile :: Domain -> [Host] -> ZoneFile
+extractZoneFile = gen . map hostAttr
+  where gen = -- TODO
+"""]]
+
+The eventual plan is that the `cname` property won't be defined as a
+property of the host, but of the container running inside it.
+Then I'll be able to cut-n-paste move docker containers between hosts,
+or duplicate the same container onto several hosts to deal with load,
+and propellor will provision them, and update the zone file appropriately.
+
+----
+
+Also, Chris Webber had suggested that Propellor be able to separate values
+from properties, so that eg, a web wizard could configure the values easily.
+I think this gets it of the way there. All that's left to do is two easy
+functions:
+
+[[!format haskell """
+overrideAttrsFromJSON :: Host -> JSON -> Host
+
+exportJSONAttrs :: Host -> JSON
+"""]]
+
+With these, propellor's configuration could
+be adjusted at run time using JSON from a file or other source. For example,
+here's a containerized webserver that publishes a directory from 
+the external host, as configured by JSON that it exports:
+
+[[!format haskell """
+	demo :: Host
+	demo = overrideAttrsFromJSON $
+		Docker.container "webserver" "joeyh/debian-unstable"
+			& Docker.publish "80:80"
+			& dir_to_publish "/home/mywebsite" -- dummy default
+			& Docker.volume (getAttr dir_to_publish ++":/var/www")
+			& Apt.serviceInstalledRunning "apache2"
+	
+	main = do
+		exportJSON "my.json" (exportJSONAttrs demo)
+		defaultMain [demo]
+"""]]
+
+[[!meta title="propellor introspection for DNS"]]

wayback
diff --git a/blog/entry/kite.mdwn b/blog/entry/kite.mdwn
index b95df32..e777d9b 100644
--- a/blog/entry/kite.mdwn
+++ b/blog/entry/kite.mdwn
@@ -4,11 +4,13 @@ My server, Kite, is finishing its 20th year online.
 
 It started as kite.resnet.cornell.edu, a 486 under the desk in my dorm
 room. Early on, it bounced around the DNS -- kite.ithaca.ny.us,
-kite.ml.org, kite.preferred.com -- before landing on kite.kitenet.net. The
-hardware has changed too, from a succession of desktop machines, it
-eventually turned into a 2u rack-mount server in the CCCP co-op. And then
-it went virtual, and international, spending a brief time in Amsterdam,
-before relocating to England and the [kvm-hosting co-op](http://kvm-hosting.org/). 
+[kite.ml.org](http://web.archive.org/web/19961222095605/http://kite.ml.org/),
+[kite.preferred.com](http://web.archive.org/web/19970208005238/http://kite.preferred.com/)
+-- before landing on kite.kitenet.net. The hardware has
+changed too, from a succession of desktop machines, it eventually turned
+into a 2u rack-mount server in the CCCP co-op. And then it went virtual,
+and international, spending a brief time in Amsterdam, before relocating to
+England and the [kvm-hosting co-op](http://kvm-hosting.org/). 
 
 Through all this change, and no few reinstalls from scratch, it's had a
 single distinct personality. This is a multi-user unix system, of the old

fo
diff --git a/blog/entry/kite.mdwn b/blog/entry/kite.mdwn
index b91a7fa..b95df32 100644
--- a/blog/entry/kite.mdwn
+++ b/blog/entry/kite.mdwn
@@ -49,13 +49,14 @@ virtual abstract machine in a unknown computer in anther country.
 
 Now it seems that what will happen to Kite is that most of the important
 parts of it will split off into a constellation of specialized servers. The
-website, including the user sites, has mostly moved to branchable.com. The
-DNS server, git server and other crucial stuff is moving to various VPS
-instances and containers. (The exhibit above is just one more automatically
-deployed, soulless container..) A large part of Kite has always been about me
-playing with bleeding-edge stuff and installing random new toys; that has
-moved to a throwaway personal server at cloudatcost.com which might be gone
-tomorrow (or might keep running for free for years).
+website, including the user sites, has mostly moved to
+[branchable.com](https://www.branchable.com/). The DNS server, git server
+and other crucial stuff is moving to various VPS instances and containers.
+(The exhibit above is just one more automatically deployed, soulless
+container..) A large part of Kite has always been about me playing with
+bleeding-edge stuff and installing random new toys; that has moved to a
+throwaway personal server at cloudatcost.com which might be gone tomorrow
+(or might keep running for free for years).
 
 What it seems will be left is a shell box, with IMAP access to a mail
 server, and a web server for legacy `/~user/` sites, and a few tools that

fo
diff --git a/blog/entry/kite.mdwn b/blog/entry/kite.mdwn
index 2fb3a5a..b91a7fa 100644
--- a/blog/entry/kite.mdwn
+++ b/blog/entry/kite.mdwn
@@ -4,7 +4,7 @@ My server, Kite, is finishing its 20th year online.
 
 It started as kite.resnet.cornell.edu, a 486 under the desk in my dorm
 room. Early on, it bounced around the DNS -- kite.ithaca.ny.us,
-kite.ml.org, kite.preferred.com -- before landing on kitenet.net. The
+kite.ml.org, kite.preferred.com -- before landing on kite.kitenet.net. The
 hardware has changed too, from a succession of desktop machines, it
 eventually turned into a 2u rack-mount server in the CCCP co-op. And then
 it went virtual, and international, spending a brief time in Amsterdam,

blog update
diff --git a/blog/entry/kite.mdwn b/blog/entry/kite.mdwn
new file mode 100644
index 0000000..2fb3a5a
--- /dev/null
+++ b/blog/entry/kite.mdwn
@@ -0,0 +1,72 @@
+[[!meta title="Kite: a server's tale"]]
+
+My server, Kite, is finishing its 20th year online.
+
+It started as kite.resnet.cornell.edu, a 486 under the desk in my dorm
+room. Early on, it bounced around the DNS -- kite.ithaca.ny.us,
+kite.ml.org, kite.preferred.com -- before landing on kitenet.net. The
+hardware has changed too, from a succession of desktop machines, it
+eventually turned into a 2u rack-mount server in the CCCP co-op. And then
+it went virtual, and international, spending a brief time in Amsterdam,
+before relocating to England and the [kvm-hosting co-op](http://kvm-hosting.org/). 
+
+Through all this change, and no few reinstalls from scratch, it's had a
+single distinct personality. This is a multi-user unix system, of the old
+school, carefully (and not-so-carefully) configured and administered to
+perform a grab-bag of functions. Whatever the users need.
+
+I read the [olduse.net](http://olduse.net/) `hacknews` newsgroup, and I
+see, in their descriptions of their server in 1984, the prototype of Kite
+and all its ilk.
+
+It's consistently had a small group of users, a small subset of my family
+and friends. Not quite big enough to really turn into a community, and we
+`wall` and `talk` less than we once did.
+
+-----
+
+# Exhibit: [Kite as it appeared in the 90's](http://ancient.kitenet.net:1994/)
+
+[Intentionally partially broken, being able to read the cgi source code is
+half the fun.]
+
+<img src="http://ancient.kitenet.net:1994/gif/counter.gif"></img>
+
+Kite was an early server on the WWW, and
+[garnered mention](http://ancient.kitenet.net:1994/brag/) in books and
+print articles. Not because it did anything important, but because there
+were few enough interesting web sites that it slightly stood out.
+
+-----
+
+Many times over these 20 years I've wondered what will be the end of Kite's
+story. It seemed like I would either keep running it indefinitely, or
+perhaps lose interest. (Or funding -- it's eaten a *lot* of cash over the
+years, especially before the current days of $5/month VPS hosting.) But I
+failed to anticipate what seems to really be happening to it. Just as I didn't
+fathom, when kite was perched under my desk, that it would one day be some
+virtual abstract machine in a unknown computer in anther country.
+
+Now it seems that what will happen to Kite is that most of the important
+parts of it will split off into a constellation of specialized servers. The
+website, including the user sites, has mostly moved to branchable.com. The
+DNS server, git server and other crucial stuff is moving to various VPS
+instances and containers. (The exhibit above is just one more automatically
+deployed, soulless container..) A large part of Kite has always been about me
+playing with bleeding-edge stuff and installing random new toys; that has
+moved to a throwaway personal server at cloudatcost.com which might be gone
+tomorrow (or might keep running for free for years).
+
+What it seems will be left is a shell box, with IMAP access to a mail
+server, and a web server for legacy `/~user/` sites, and a few tools that
+my users need (including that `pine` program some of them are still stuck
+on.)
+
+Will it be worth calling that Kite?
+
+<a href="http://joeyh.name/"><img src="http://ancient.kitenet.net:1994/gif/kite.gif"></a>
+
+------
+
+[ Kite users: This transition needs to be done by December when the current
+host is scheduled to be retired. ]

grep
diff --git a/links/fun.mdwn b/links/fun.mdwn
index 9a4c82c..2ee6691 100644
--- a/links/fun.mdwn
+++ b/links/fun.mdwn
@@ -5,4 +5,5 @@
 [[languages]]  
 [[yurt]]  
 [[caving]]  
+[[grep]]  
 [[meta]]

Comment moderation
diff --git a/blog/entry/idea:_git_push_requests/comment_5_48bdd2410758292362e625b8905e0d1d._comment b/blog/entry/idea:_git_push_requests/comment_5_48bdd2410758292362e625b8905e0d1d._comment
new file mode 100644
index 0000000..6f78f1b
--- /dev/null
+++ b/blog/entry/idea:_git_push_requests/comment_5_48bdd2410758292362e625b8905e0d1d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://rjc.pip.verisignlabs.com.pip.verisignlabs.com/"
+ ip="87.213.42.234"
+ subject="git push request"
+ date="2013-08-30T05:38:49Z"
+ content="""
+suckless.org are already using this idea for updating their [web pages][0].
+
+[0]: http://suckless.org/wiki
+"""]]

typo
diff --git a/links/personal.mdwn b/links/personal.mdwn
index 6ad3beb..1c66d9d 100644
--- a/links/personal.mdwn
+++ b/links/personal.mdwn
@@ -6,4 +6,4 @@
 [[todo]]
 
 Funded in 2014 via  
-[campaign.joey.name](https://campaign.joeyh.name/)!
+[campaign.joeyh.name](https://campaign.joeyh.name/)!

Revert "lists"
This reverts commit 2bd804d3492ab0eaa839de6b0c8c7d80b5fac649.
diff --git a/index.mdwn b/index.mdwn
index 0412c63..59a79a9 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -9,9 +9,6 @@ html {
 	-o-background-size: cover;
 	background-size: cover;
 }
-li {
-        display: block;
-}
 .sidebar {
 	background: none;
 	border: none;
diff --git a/links/fun.mdwn b/links/fun.mdwn
index 6a74211..9a4c82c 100644
--- a/links/fun.mdwn
+++ b/links/fun.mdwn
@@ -1,8 +1,8 @@
 ### fun
 
-* [[Joey_Learns_to_Fly|learnstofly]]
-* [oldusenet](http://olduse.net/)
-* [[languages]]
-* [[yurt]]
-* [[caving]]
-* [[meta]]
+[[Joey_Learns_to_Fly|learnstofly]]  
+[oldusenet](http://olduse.net/)  
+[[languages]]  
+[[yurt]]  
+[[caving]]  
+[[meta]]
diff --git a/links/personal.mdwn b/links/personal.mdwn
index 61103a6..6ad3beb 100644
--- a/links/personal.mdwn
+++ b/links/personal.mdwn
@@ -1,9 +1,9 @@
 ### personal
 
-* [[blog]]
-* [[pics]]
-* [[contact_me|contact]]
-* [[todo]]
+[[blog]]  
+[[pics]]  
+[[contact_me|contact]]  
+[[todo]]
 
 Funded in 2014 via  
 [campaign.joey.name](https://campaign.joeyh.name/)!
diff --git a/links/technical.mdwn b/links/technical.mdwn
index df9ee68..2f568d0 100644
--- a/links/technical.mdwn
+++ b/links/technical.mdwn
@@ -1,9 +1,9 @@
 ### technical
 
-* [[code]]
-* [[vcshome]]
-* [[talks]]
-* [[screencasts]]
-* [[termcasts|termcast]]
-* [[rfcs|rfc]]
-* [[boxen]]
+[[code]]  
+[[vcshome]]  
+[[talks]]  
+[[screencasts]]  
+[[termcasts|termcast]]  
+[[rfcs|rfc]]  
+[[boxen]]  

Merge branch 'master' of ssh://joeyh.branchable.com
lists
diff --git a/links/personal.mdwn b/links/personal.mdwn
index a58bb79..6ad3beb 100644
--- a/links/personal.mdwn
+++ b/links/personal.mdwn
@@ -5,4 +5,5 @@
 [[contact_me|contact]]  
 [[todo]]
 
-Funded in 2014 via [campaign.joey.name](https://campaign.joeyh.name/)!
+Funded in 2014 via  
+[campaign.joey.name](https://campaign.joeyh.name/)!

lists
diff --git a/index.mdwn b/index.mdwn
index 59a79a9..0412c63 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -9,6 +9,9 @@ html {
 	-o-background-size: cover;
 	background-size: cover;
 }
+li {
+        display: block;
+}
 .sidebar {
 	background: none;
 	border: none;
diff --git a/links/fun.mdwn b/links/fun.mdwn
index 9a4c82c..6a74211 100644
--- a/links/fun.mdwn
+++ b/links/fun.mdwn
@@ -1,8 +1,8 @@
 ### fun
 
-[[Joey_Learns_to_Fly|learnstofly]]  
-[oldusenet](http://olduse.net/)  
-[[languages]]  
-[[yurt]]  
-[[caving]]  
-[[meta]]
+* [[Joey_Learns_to_Fly|learnstofly]]
+* [oldusenet](http://olduse.net/)
+* [[languages]]
+* [[yurt]]
+* [[caving]]
+* [[meta]]
diff --git a/links/personal.mdwn b/links/personal.mdwn
index a58bb79..4ec5ec1 100644
--- a/links/personal.mdwn
+++ b/links/personal.mdwn
@@ -1,8 +1,8 @@
 ### personal
 
-[[blog]]  
-[[pics]]  
-[[contact_me|contact]]  
-[[todo]]
+* [[blog]]
+* [[pics]]
+* [[contact_me|contact]]
+* [[todo]]
 
 Funded in 2014 via [campaign.joey.name](https://campaign.joeyh.name/)!
diff --git a/links/technical.mdwn b/links/technical.mdwn
index 2f568d0..df9ee68 100644
--- a/links/technical.mdwn
+++ b/links/technical.mdwn
@@ -1,9 +1,9 @@
 ### technical
 
-[[code]]  
-[[vcshome]]  
-[[talks]]  
-[[screencasts]]  
-[[termcasts|termcast]]  
-[[rfcs|rfc]]  
-[[boxen]]  
+* [[code]]
+* [[vcshome]]
+* [[talks]]
+* [[screencasts]]
+* [[termcasts|termcast]]
+* [[rfcs|rfc]]
+* [[boxen]]

foo
diff --git a/index.mdwn b/index.mdwn
index 4ab36cf..59a79a9 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -23,7 +23,7 @@ input#searchbox {
 	border-bottom: none;
 }
 #pagebody {
-	margin-left: 40%;
+	margin-left: 20%;
 }
 .archivepagedate {
 	font-size: 0.5em;

foo
diff --git a/index.mdwn b/index.mdwn
index 0b58c9e..4ab36cf 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -40,7 +40,7 @@ input#searchbox {
 </table>
 
 [[!sidebar content="""
-### recent [[bloggification]]
+### [[blog|blog]] posts
 [[!inline pages="blog/entry/* and !blog/entry/*/* and !link(blog/foo) and !link(unfinished)"
 show=5 feeds=no archive=yes]]
 """]]

foo
diff --git a/index.mdwn b/index.mdwn
index b2ec7b4..0b58c9e 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -40,7 +40,7 @@ input#searchbox {
 </table>
 
 [[!sidebar content="""
-### Recent [[blog]] posts:
+### recent [[bloggification]]
 [[!inline pages="blog/entry/* and !blog/entry/*/* and !link(blog/foo) and !link(unfinished)"
 show=5 feeds=no archive=yes]]
 """]]

foo
diff --git a/index.mdwn b/index.mdwn
index 22417ca..b2ec7b4 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -40,7 +40,7 @@ input#searchbox {
 </table>
 
 [[!sidebar content="""
-Recent [[blog]] posts:
+### Recent [[blog]] posts:
 [[!inline pages="blog/entry/* and !blog/entry/*/* and !link(blog/foo) and !link(unfinished)"
 show=5 feeds=no archive=yes]]
 """]]

foo
diff --git a/index.mdwn b/index.mdwn
index d809889..22417ca 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -31,31 +31,13 @@ input#searchbox {
 </style>
 </div>
 
-### personal
-
-* [[blog]]
-* [[pics]]
-* [[contact_information|contact]]
-* [[todo]]
-
-### technical
-
-* [[code]]
-* [[vcshome]]
-* [[talks]]
-* [[screencasts]]
-* [[termcasts|termcast]]
-* [[rfcs|rfc]]
-* [[boxen]]
-
-### fun
-
-* [[Joey_Learns_to_Fly|learnstofly]]
-* [oldusenet](http://olduse.net/)
-* [[languages]]
-* [[yurt]]
-* [[caving]]
-* [[meta]]
+<table>
+<tr>
+<td width="33%" valign=top>[[!inline feeds=no template=bare pages=links/personal]]</td>
+<td width="33%" valign=top>[[!inline feeds=no template=bare pages=links/technical]]</td>
+<td width="33%" valign=top>[[!inline feeds=no template=bare pages=links/fun]]</td>
+</tr>
+</table>
 
 [[!sidebar content="""
 Recent [[blog]] posts:
diff --git a/links/fun.mdwn b/links/fun.mdwn
index 6a74211..9a4c82c 100644
--- a/links/fun.mdwn
+++ b/links/fun.mdwn
@@ -1,8 +1,8 @@
 ### fun
 
-* [[Joey_Learns_to_Fly|learnstofly]]
-* [oldusenet](http://olduse.net/)
-* [[languages]]
-* [[yurt]]
-* [[caving]]
-* [[meta]]
+[[Joey_Learns_to_Fly|learnstofly]]  
+[oldusenet](http://olduse.net/)  
+[[languages]]  
+[[yurt]]  
+[[caving]]  
+[[meta]]
diff --git a/links/personal.mdwn b/links/personal.mdwn
index 439c3a8..a58bb79 100644
--- a/links/personal.mdwn
+++ b/links/personal.mdwn
@@ -1,7 +1,8 @@
 ### personal
 
-* [[blog]]
-* [[pics]]
-* [[contact_information|contact]]
-* [[todo]]
+[[blog]]  
+[[pics]]  
+[[contact_me|contact]]  
+[[todo]]
 
+Funded in 2014 via [campaign.joey.name](https://campaign.joeyh.name/)!
diff --git a/links/technical.mdwn b/links/technical.mdwn
index e2bb85a..2f568d0 100644
--- a/links/technical.mdwn
+++ b/links/technical.mdwn
@@ -1,10 +1,9 @@
 ### technical
 
-* [[code]]
-* [[vcshome]]
-* [[talks]]
-* [[screencasts]]
-* [[termcasts|termcast]]
-* [[rfcs|rfc]]
-* [[boxen]]
-
+[[code]]  
+[[vcshome]]  
+[[talks]]  
+[[screencasts]]  
+[[termcasts|termcast]]  
+[[rfcs|rfc]]  
+[[boxen]]  

foo
diff --git a/links/fun.mdwn b/links/fun.mdwn
new file mode 100644
index 0000000..6a74211
--- /dev/null
+++ b/links/fun.mdwn
@@ -0,0 +1,8 @@
+### fun
+
+* [[Joey_Learns_to_Fly|learnstofly]]
+* [oldusenet](http://olduse.net/)
+* [[languages]]
+* [[yurt]]
+* [[caving]]
+* [[meta]]
diff --git a/links/personal.mdwn b/links/personal.mdwn
new file mode 100644
index 0000000..439c3a8
--- /dev/null
+++ b/links/personal.mdwn
@@ -0,0 +1,7 @@
+### personal
+
+* [[blog]]
+* [[pics]]
+* [[contact_information|contact]]
+* [[todo]]
+
diff --git a/links/technical.mdwn b/links/technical.mdwn
new file mode 100644
index 0000000..e2bb85a
--- /dev/null
+++ b/links/technical.mdwn
@@ -0,0 +1,10 @@
+### technical
+
+* [[code]]
+* [[vcshome]]
+* [[talks]]
+* [[screencasts]]
+* [[termcasts|termcast]]
+* [[rfcs|rfc]]
+* [[boxen]]
+
diff --git a/templates/bare.tmpl b/templates/bare.tmpl
new file mode 100644
index 0000000..2d476b7
--- /dev/null
+++ b/templates/bare.tmpl
@@ -0,0 +1 @@
+<TMPL_VAR CONTENT>

foo
diff --git a/index.mdwn b/index.mdwn
index 504310f..d809889 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -61,9 +61,6 @@ input#searchbox {
 Recent [[blog]] posts:
 [[!inline pages="blog/entry/* and !blog/entry/*/* and !link(blog/foo) and !link(unfinished)"
 show=5 feeds=no archive=yes]]
-
-<a href="http://flattr.com/thing/39887/Joey-Hesss-blog" target="_blank">
-<img src="https://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>
 """]]
 
 [[!meta openid="http://kitenet.net/"

foo
diff --git a/index.mdwn b/index.mdwn
index b72d02d..504310f 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -25,6 +25,9 @@ input#searchbox {
 #pagebody {
 	margin-left: 40%;
 }
+.archivepagedate {
+	font-size: 0.5em;
+}
 </style>
 </div>
 

foo
diff --git a/index.mdwn b/index.mdwn
index a495428..b72d02d 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -17,8 +17,6 @@ input#searchbox {
 	display: none;
 }
 #pageinfo {
-	border: none;
-	float: right;
 	display: none;
 }
 .pageheader .actions ul {

foo
diff --git a/index.mdwn b/index.mdwn
index 3f328e0..a495428 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -14,7 +14,7 @@ html {
 	border: none;
 }
 input#searchbox {
-	background: none;
+	display: none;
 }
 #pageinfo {
 	border: none;

foo
diff --git a/joeykite.jpg b/joeykite.jpg
index 728947c..1aae3c7 100644
Binary files a/joeykite.jpg and b/joeykite.jpg differ

foo
diff --git a/joeykite.jpg b/joeykite.jpg
index b4761c3..728947c 100644
Binary files a/joeykite.jpg and b/joeykite.jpg differ

foo
diff --git a/index.mdwn b/index.mdwn
index 301c943..3f328e0 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -1,5 +1,6 @@
 [[!meta title="Joey Hess"]]
 
+<div>
 <style>
 html { 
 	background: url(joeykite.jpg) no-repeat center center fixed; 
@@ -27,6 +28,7 @@ input#searchbox {
 	margin-left: 40%;
 }
 </style>
+</div>
 
 ### personal
 

foo
diff --git a/index.mdwn b/index.mdwn
index d094bb2..301c943 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -1,6 +1,32 @@
 [[!meta title="Joey Hess"]]
 
-<img src="joeykite.jpg" align=center" alt="picture of Joey Hess"></a>
+<style>
+html { 
+	background: url(joeykite.jpg) no-repeat center center fixed; 
+	-webkit-background-size: cover;
+	-moz-background-size: cover;
+	-o-background-size: cover;
+	background-size: cover;
+}
+.sidebar {
+	background: none;
+	border: none;
+}
+input#searchbox {
+	background: none;
+}
+#pageinfo {
+	border: none;
+	float: right;
+	display: none;
+}
+.pageheader .actions ul {
+	border-bottom: none;
+}
+#pagebody {
+	margin-left: 40%;
+}
+</style>
 
 ### personal
 
diff --git a/joeykite.jpg b/joeykite.jpg
index 9554a46..b4761c3 100644
Binary files a/joeykite.jpg and b/joeykite.jpg differ

foo
diff --git a/index.mdwn b/index.mdwn
index ad3388b..d094bb2 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -1,5 +1,7 @@
 [[!meta title="Joey Hess"]]
 
+<img src="joeykite.jpg" align=center" alt="picture of Joey Hess"></a>
+
 ### personal
 
 * [[blog]]
diff --git a/joeykite.jpg b/joeykite.jpg
new file mode 100644
index 0000000..9554a46
Binary files /dev/null and b/joeykite.jpg differ

show more posts
diff --git a/index.mdwn b/index.mdwn
index 372a79f..ad3388b 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -29,7 +29,7 @@
 [[!sidebar content="""
 Recent [[blog]] posts:
 [[!inline pages="blog/entry/* and !blog/entry/*/* and !link(blog/foo) and !link(unfinished)"
-show=3 feeds=no archive=yes]]
+show=5 feeds=no archive=yes]]
 
 <a href="http://flattr.com/thing/39887/Joey-Hesss-blog" target="_blank">
 <img src="https://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>

openid provider changed
diff --git a/index.mdwn b/index.mdwn
index d2f83fe..372a79f 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -36,4 +36,4 @@ show=3 feeds=no archive=yes]]
 """]]
 
 [[!meta openid="http://kitenet.net/"
-server="http://kitenet.net/simpleid/"]]
+server="http://openid.kitenet.net:8081/simpleid/"]]

Added a comment
diff --git a/blog/entry/propellor/comment_3_fba841b0f6bc0d91d43a29d2f21dd690._comment b/blog/entry/propellor/comment_3_fba841b0f6bc0d91d43a29d2f21dd690._comment
new file mode 100644
index 0000000..2e99a4b
--- /dev/null
+++ b/blog/entry/propellor/comment_3_fba841b0f6bc0d91d43a29d2f21dd690._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.16"
+ subject="comment 3"
+ date="2014-04-05T22:03:46Z"
+ content="""
+> What kind of secret data are you copying to the hosts?
+
+That host's passwords, private keys, etc
+
+> Therefor I prefer a configuration management system that does not require SSH access to the controlled hosts
+
+Propellor can be run in this mode, with a cron job so it pulls changes into its git repository.
+"""]]

Added a comment: Ideas from cfengine
diff --git a/blog/entry/propellor/comment_2_ddfc143d862311efcb314162465f6736._comment b/blog/entry/propellor/comment_2_ddfc143d862311efcb314162465f6736._comment
new file mode 100644
index 0000000..1358c7f
--- /dev/null
+++ b/blog/entry/propellor/comment_2_ddfc143d862311efcb314162465f6736._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/thkoch2001#3d518"
+ nickname="thkoch2001"
+ subject="Ideas from cfengine"
+ date="2014-04-05T21:30:18Z"
+ content="""
+Hi Joey,
+
+I've started to learn cfengine3 recently. Its concepts seem to be very well thought out it's just a shame that the Debian packaging is lacking behind. But your approach is intriguing because you're using Git and Haskell. :-)
+
+In cfengine, everything is based on promises. A promise promises something and it knows, what needs to be done to eventually fulfill the promise. I very much like the approach of focusing on self-healing agents instead of external intervention to manipulate a machine. Therefor I prefer a configuration management system that does not require SSH access to the controlled hosts. In cfengine, an external process can only ever trigger a new evaluation of the promises and nothing else. Every cfengine managed machine runs a cf-serverd that has only two purposes: serve policies to other machines (that's done by git with propellor) and allow the promise evaluation to be triggered.
+
+I'm not sure, whether it's really a good idea to distribute secrets to managed hosts. What kind of secret data are you copying to the hosts?
+
+It's really time to finally learn Haskell...
+"""]]

Added a comment
diff --git a/blog/entry/propellor_type-safe_reversions/comment_3_4375eac18696eb2d53b8d383a9b849d6._comment b/blog/entry/propellor_type-safe_reversions/comment_3_4375eac18696eb2d53b8d383a9b849d6._comment
new file mode 100644
index 0000000..6c703a6
--- /dev/null
+++ b/blog/entry/propellor_type-safe_reversions/comment_3_4375eac18696eb2d53b8d383a9b849d6._comment
@@ -0,0 +1,56 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnqAh0do_lo96xyC7wSV1FkluTXsbhNrTA"
+ nickname="Anthony"
+ subject="comment 3"
+ date="2014-04-03T17:01:54Z"
+ content="""
+hmph, no \"reply to comment\" button? weeeaaak.
+
+So I just deleted a bunch of pseudo-haskell that demonstrated I've no idea what I'm talking about.
+
+Anyway, what you (I) want is:
+
+ - to be able to describe different aspects of the system (what distro, what packages, contents of files, user setup, shell snippets to run, whatever)
+ - to be able to split your configuration into modules
+ - to generate actions from a description that will set the system up according to the description
+
+You could \"type\" some of your descriptions into:
+
+ - distro (Debian unstable)
+ - distro configuration (debconf settings, installed debs, selected alternatives, system user ids...)
+ - package configuration (configure ldap, apache, pam, etc -- some bits might be systemd specific)
+ - local user configuration (populate /home, user account names/ids/shells, ...)
+ - local software (/usr/local/*, /opt/*)
+ - local content (/srv/*, /var/www, ...)
+
+You might want to be able to say \"There could be random stuff in /home\" as part of a description, if you don't want \"make this machine conform to this description\" to delete everything in /home/aj.bak, eg.
+
+I'm not sure how you'd build a good datastructure out of that -- you want to be able to configure lots of packages on a system, but you don't want to be able to define the system as running both Debian and Ubuntu (probably?). It might be okay to only validate that at runtime though?
+
+Actions would then be defined by changes in configuration. So you'd have to have functions to go from a description that says \"Oracle is installed in /opt\", to one that doesn't. Maybe something like:
+
+ matchConfig :: [Description] -> [Description] -> [Actions]
+ createAction :: Description -> [Action]
+ removeAction :: Description -> [Action]
+ configToAction :: Description -> Description -> [Description] -> ([Action], [Description])
+
+ matchConfig [] [] = []
+ matchConfig [] b = createAction (head b) : matchConfig [] (tail b)
+ matchConfig a [] = removeAction (head a) : matchConfig (tail a) []
+ matchConfig a b =
+    actions ++ (matchconfig (tail a) newb) where
+        (actions, newb) = configToAction (head a) (head b) (tail b)
+
+
+ createAction InstallOracle = ...
+ removeAction InstallOracle = ...
+
+ configToAction InstallOracle InstallOracle t = ([], t)
+ configToAction InstallOracle h [] = ([removeAction InstallOracle], [])
+ configToAction InstallOracle h t = 
+     (a, h:tt) where (a,tt) = configToAction InstallOracle (head t) (tail t)
+
+...
+
+I'm not sure I even know where I'm trying to go with this...
+"""]]

Added a comment
diff --git a/blog/entry/propellor_type-safe_reversions/comment_2_8c9116a99516c3be1a1ca9201f6d4d4c._comment b/blog/entry/propellor_type-safe_reversions/comment_2_8c9116a99516c3be1a1ca9201f6d4d4c._comment
new file mode 100644
index 0000000..70da9e0
--- /dev/null
+++ b/blog/entry/propellor_type-safe_reversions/comment_2_8c9116a99516c3be1a1ca9201f6d4d4c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.16"
+ subject="comment 2"
+ date="2014-04-03T15:01:12Z"
+ content="""
+@Anthony, these are good thoughts. I do see the Properties as being a description of a system. But one problem as it stands now is that since a Property includes an IO action which is a closure over any configuration, there is no way to serialize/deserialize Properties. Which is necessary for the kind of thing you are thinking of, and some ideas I have had too.
+
+Concrete suggestions for better types in this area would be appreciated. :)
+"""]]

Added a comment: properties versus actions
diff --git a/blog/entry/propellor_type-safe_reversions/comment_1_a17bcb34c294288e5ee3d74d475d9013._comment b/blog/entry/propellor_type-safe_reversions/comment_1_a17bcb34c294288e5ee3d74d475d9013._comment
new file mode 100644
index 0000000..2fb8d0a
--- /dev/null
+++ b/blog/entry/propellor_type-safe_reversions/comment_1_a17bcb34c294288e5ee3d74d475d9013._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnqAh0do_lo96xyC7wSV1FkluTXsbhNrTA"
+ nickname="Anthony"
+ subject="properties versus actions"
+ date="2014-04-03T06:10:18Z"
+ content="""
+Maybe you could distinguish between properties and actions? A property being a description of the system, and an action being a change you make to a description (which may then make a property true or false).
+
+I think maintaining a \"description of a system\" makes more sense long term. That's what I'd like to have checked into a git repo, for instance.
+
+A list of actions is what you'd need to bring up a system from nothing, or to upgrade/downgrade it (stable -> testing, webserver to not-a-webserver), of course.
+
+You could obviously generate a list of actions to take to convert from one description of a system to another.
+
+Being able to \"apply a description\" to an existing system could be done with those steps if you also had something that would generate a description from a running system. That would be a really cool feature to have for converting to \"propellor\", just run the \"create-description\" thing on your hosts, check them into git, and you can recreate your system just by hitting a button...
+"""]]

Added a comment
diff --git a/blog/entry/adding_docker_support_to_propellor/comment_4_baa5e1392cbdfe705d4cd7a37a5900ed._comment b/blog/entry/adding_docker_support_to_propellor/comment_4_baa5e1392cbdfe705d4cd7a37a5900ed._comment
new file mode 100644
index 0000000..aa7261c
--- /dev/null
+++ b/blog/entry/adding_docker_support_to_propellor/comment_4_baa5e1392cbdfe705d4cd7a37a5900ed._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.16"
+ subject="comment 4"
+ date="2014-04-02T17:14:07Z"
+ content="""
+@Luca, propellor --spin automatically commits and deploys the local git repo. For security, it makes a signed commit, and to ensure that it's pushing a signed commit, it lets an empty commit be made if there are no changes. So, those are me re-running propellor --spin, mostly during debugging a new feature.
+"""]]

update
diff --git a/blog/entry/propellor_type-safe_reversions.mdwn b/blog/entry/propellor_type-safe_reversions.mdwn
index 19c8b83..3fdaa15 100644
--- a/blog/entry/propellor_type-safe_reversions.mdwn
+++ b/blog/entry/propellor_type-safe_reversions.mdwn
@@ -6,9 +6,8 @@ For example, I had a system with a webserver container:
 
 	Docker.docked container hostname "webserver"
 
-I don't want a web server there any more. Rather than need to look
-up that the way to make sure that container isn't running is
-"Docker.unDocked" or something, wouldn't it be nice to be able to say:
+I don't want a web server there any more. Rather than having a separate
+property to stop it, wouldn't it be nice to be able to say:
 
 	revert (Docker.docked container hostname "webserver")
 
@@ -20,7 +19,7 @@ that cannot be reverted.
 For example, `Docker.garbageCollected` is a property that makes sure there
 are no unused docker images wasting disk space. It can't be reverted.
 Nor can my personal `standardSystem Unstable` property, which amoung other
-things *upgrades* the system to unstable..
+things *upgrades* the system to unstable and sets up my home directory..
 
 I found a way to make Propellor statically check if a property can be
 reverted at compile time. So `revert Docker.garbageCollected` will fail

blog update
diff --git a/blog/entry/propellor_type-safe_reversions.mdwn b/blog/entry/propellor_type-safe_reversions.mdwn
new file mode 100644
index 0000000..19c8b83
--- /dev/null
+++ b/blog/entry/propellor_type-safe_reversions.mdwn
@@ -0,0 +1,46 @@
+[[code/Propellor]] ensures that a list of properties about a system
+are satisfied. But requirements change, and so you might want to revert
+a property that had been set up before.
+
+For example, I had a system with a webserver container:
+
+	Docker.docked container hostname "webserver"
+
+I don't want a web server there any more. Rather than need to look
+up that the way to make sure that container isn't running is
+"Docker.unDocked" or something, wouldn't it be nice to be able to say:
+
+	revert (Docker.docked container hostname "webserver")
+
+I've now gotten this working. The really fun part is, some properies
+support reversion, but other properties certianly do not. Maybe the code to
+revert them is not worth writing, or maybe the property does something
+that cannot be reverted.
+
+For example, `Docker.garbageCollected` is a property that makes sure there
+are no unused docker images wasting disk space. It can't be reverted.
+Nor can my personal `standardSystem Unstable` property, which amoung other
+things *upgrades* the system to unstable..
+
+I found a way to make Propellor statically check if a property can be
+reverted at compile time. So `revert Docker.garbageCollected` will fail
+to type check!
+
+The tricky part about implementing this is that the user configures
+Propellor with a list of properties. But now there are two distinct
+types of properties, revertable ones and non-revertable ones.
+And Haskell does not support heterogeneous lists..
+
+My solution to this is a typeclass and some syntactic sugar operators.
+To build a list of properties, with individual elements that might be
+revertable, and others not:
+
+[[!format haskell """
+	props
+		& standardSystem Unstable
+		& revert (Docker.docked container hostname "webserver")
+		& Docker.docked container hostname "amd64-git-annex-builder"
+		& Docker.garbageCollected
+"""]]
+
+[[!meta title="propellor type-safe reversions"]]

Added a comment: Propellor spin
diff --git a/blog/entry/adding_docker_support_to_propellor/comment_3_5121cb1b2b28a54615365828c8382752._comment b/blog/entry/adding_docker_support_to_propellor/comment_3_5121cb1b2b28a54615365828c8382752._comment
new file mode 100644
index 0000000..d762a12
--- /dev/null
+++ b/blog/entry/adding_docker_support_to_propellor/comment_3_5121cb1b2b28a54615365828c8382752._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmJSBuZtee1bBrGeLnNRFaRoxAIpE9ywws"
+ nickname="Luca"
+ subject="Propellor spin"
+ date="2014-04-02T07:42:26Z"
+ content="""
+Hi, what's up with all the \"propellor spin\" empty commits in the git log?
+"""]]

Added a comment
diff --git a/blog/entry/adding_docker_support_to_propellor/comment_2_30a454ce4e78068b0237423d0f86415f._comment b/blog/entry/adding_docker_support_to_propellor/comment_2_30a454ce4e78068b0237423d0f86415f._comment
new file mode 100644
index 0000000..1afe2e2
--- /dev/null
+++ b/blog/entry/adding_docker_support_to_propellor/comment_2_30a454ce4e78068b0237423d0f86415f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.16"
+ subject="comment 2"
+ date="2014-04-01T19:09:54Z"
+ content="""
+Docker support is now fully working!
+"""]]

Added a comment: Docker clone in Haskell
diff --git a/blog/entry/adding_docker_support_to_propellor/comment_1_55cc9739d58c737b4dc21806994eddee._comment b/blog/entry/adding_docker_support_to_propellor/comment_1_55cc9739d58c737b4dc21806994eddee._comment
new file mode 100644
index 0000000..de09ea5
--- /dev/null
+++ b/blog/entry/adding_docker_support_to_propellor/comment_1_55cc9739d58c737b4dc21806994eddee._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/thkoch2001#3d518"
+ nickname="thkoch2001"
+ subject="Docker clone in Haskell"
+ date="2014-04-01T18:56:22Z"
+ content="""
+Since you love Haskell so much, maybe you're interested to evaluate [scrz](https://github.com/scrz/scrz)? Unfortunately I've still not had the opportunity to learn Haskell myself.
+"""]]

layout
diff --git a/blog/entry/adding_docker_support_to_propellor.mdwn b/blog/entry/adding_docker_support_to_propellor.mdwn
index bd7ae2f..5c353a8 100644
--- a/blog/entry/adding_docker_support_to_propellor.mdwn
+++ b/blog/entry/adding_docker_support_to_propellor.mdwn
@@ -21,9 +21,9 @@ container _ "webserver" = Just $ Docker.containerFromImage "joeyh/debian-unstabl
         [ Docker.publish "80:80"
         , Docker.volume "/var/www:/var/www"
         , Docker.inside
-		[ serviceRunning "apache2"
-                	`requires` Apt.installed ["apache2"]
-		]
+            [ serviceRunning "apache2"
+                `requires` Apt.installed ["apache2"]
+            ]
         ]
 """]]
 

foo
diff --git a/blog/entry/adding_docker_support_to_propellor.mdwn b/blog/entry/adding_docker_support_to_propellor.mdwn
index 3c3e6eb..bd7ae2f 100644
--- a/blog/entry/adding_docker_support_to_propellor.mdwn
+++ b/blog/entry/adding_docker_support_to_propellor.mdwn
@@ -1,6 +1,9 @@
-Propellor development is churning away! Now supports secure handling of
-private data like passwords (only the host that owns it can see it),
-and fully end-to-end secured deployment via gpg signed and verified commits.
+[[code/Propellor]] development is churning away! (And leaving no few puns
+in its wake..)
+
+Now it supports secure handling of private data like passwords (only the
+host that owns it can see it), and fully end-to-end secured deployment via
+gpg signed and verified commits.
 
 And, I've just gotten support for Docker to build. Probably not quite
 work, but it should only be a few bugs away at this point.

blog update
diff --git a/blog/entry/adding_docker_support_to_propellor.mdwn b/blog/entry/adding_docker_support_to_propellor.mdwn
new file mode 100644
index 0000000..3c3e6eb
--- /dev/null
+++ b/blog/entry/adding_docker_support_to_propellor.mdwn
@@ -0,0 +1,68 @@
+Propellor development is churning away! Now supports secure handling of
+private data like passwords (only the host that owns it can see it),
+and fully end-to-end secured deployment via gpg signed and verified commits.
+
+And, I've just gotten support for Docker to build. Probably not quite
+work, but it should only be a few bugs away at this point.
+
+Here's how to deploy a dockerized webserver with propellor:
+
+[[!format haskell """
+host hostname@"clam.kitenet.net" = Just
+	[ Docker.configured
+	, File.dirExists "/var/www"
+	, Docker.hasContainer hostname "webserver" container
+	]
+
+container _ "webserver" = Just $ Docker.containerFromImage "joeyh/debian-unstable"
+        [ Docker.publish "80:80"
+        , Docker.volume "/var/www:/var/www"
+        , Docker.inside
+		[ serviceRunning "apache2"
+                	`requires` Apt.installed ["apache2"]
+		]
+        ]
+"""]]
+
+Docker containers are set up using Properties too, just like regular
+hosts, but their Properties are run inside the container.
+
+That means that, if I change the web server port above, Propellor will
+notice the container config is out of date, and stop the container,
+commit an image based on it, and quickly use that to bring up a new
+container with the new configuration.
+
+If I change the web server to say, lighttpd, Propellor will run inside
+the container, and notice that it needs to install lighttpd to satisfy
+the new property, and so will update the container without needing to take
+it down.
+
+Adding all this behavior took only 253 lines of code, and none of it
+impacts the core of Propellor at all; it's all in
+Propellor.Property.Docker. (Well, I did need another hundred lines
+to write a daemon that runs inside the container and reads commands
+to run over a named pipe... Docker makes running ad-hoc commands inside a
+container a PITA.)
+
+So, I think that this vindicates the approach of making the configuration
+of Propellor be a list of Properties, which can be constructed by
+abitrarily interesting Haskell code. I didn't design Propellor to support
+containers, but it was easy to find a way to express them as shown above.
+
+Compare that with how Puppet supports Docker: <http://docs.docker.io/en/latest/use/puppet/>
+
+<pre>
+docker::run { 'helloworld':
+  image        => 'ubuntu',
+  command      => '/bin/sh -c "while true; do echo hello world; sleep 1; done"',
+  ports        => ['4444', '4555'],
+...
+</pre>
+
+All puppet manages is running the image and a simple static command
+inside it. All the complexities that puppet provides for configuring
+servers cannot easily be brought to bear inside the container, and
+a large reason for that is, I think, that its configuration file is just
+not expressive enough.
+
+[[!meta title="adding docker support to propellor"]]

Added a comment
diff --git a/blog/entry/propellor/comment_1_2014586c3ec07b4bc28437a1daa2d113._comment b/blog/entry/propellor/comment_1_2014586c3ec07b4bc28437a1daa2d113._comment
new file mode 100644
index 0000000..3c98603
--- /dev/null
+++ b/blog/entry/propellor/comment_1_2014586c3ec07b4bc28437a1daa2d113._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmQL54KL0heX7a0hVZudt6RGO444XAiTqU"
+ nickname="Jimmy"
+ subject="comment 1"
+ date="2014-03-31T20:50:27Z"
+ content="""
+heh, took a quick look. seems interesting to use haskell for this.
+"""]]