Recent changes to this wiki:

layout
diff --git a/meta.mdwn b/meta.mdwn
index d6301a29..ad2ac144 100644
--- a/meta.mdwn
+++ b/meta.mdwn
@@ -6,7 +6,7 @@ pages="*/Discussion"]] are Discussion pages.
 It has a [[license]], if you care about that sort of thing. 
 
 And yeah, it's a wiki, but only Joey can edit it directly. However, you can
-clone its git repo from <git://joeyh.branchable.com/> and make changes and
+clone its git repo from `git://joeyh.branchable.com/` and make changes and
 even send me patches!
 
 Broken links:

update
diff --git a/meta.mdwn b/meta.mdwn
index 0f04ea45..d6301a29 100644
--- a/meta.mdwn
+++ b/meta.mdwn
@@ -3,7 +3,11 @@ This wiki contains [[!pagecount pages="* and !*.* and !grep/* and
 !*/Discussion"]] pages are blog entries and [[!pagecount
 pages="*/Discussion"]] are Discussion pages.
 
-It has a [[license]], if you care about that sort of thing.
+It has a [[license]], if you care about that sort of thing. 
+
+And yeah, it's a wiki, but only Joey can edit it directly. However, you can
+clone its git repo from <git://joeyh.branchable.com/> and make changes and
+even send me patches!
 
 Broken links:
 

Added a comment: Great Idea!
diff --git a/blog/entry/12_to_24_volt_house_conversion/comment_2_f29c544770495515325c891a7379a7bf._comment b/blog/entry/12_to_24_volt_house_conversion/comment_2_f29c544770495515325c891a7379a7bf._comment
new file mode 100644
index 0000000..359bece
--- /dev/null
+++ b/blog/entry/12_to_24_volt_house_conversion/comment_2_f29c544770495515325c891a7379a7bf._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="macdanny@a72b4b40c458ead665c8c2a022d209508e1393d6"
+ nickname="macdanny"
+ avatar="http://cdn.libravatar.org/avatar/e5831ecad78c64463fca51fddc891aad"
+ subject="Great Idea!"
+ date="2017-08-23T07:29:29Z"
+ content="""
+Hey Joey, Thanks for the unintended push in the right direction. I've been following along for a little while now. I recently had the cooling fan in my UPS take a nose dive. Trouble is that the UPS is 24V and those little fans are costly (especially from the UPS manufacturer). It wasn't until reading this entry that it occurred to me. I have a pile of LM317 IC's I purchased years ago for a lighting project. I used one of them to build a small circuit that allowed me to use a 12 volt fan like this one ( <a href=\"https://www.12volt-travel.com/small-12-volt-fan-for-electronics-airflow-cooling-p-23647.html\">https://www.12volt-travel.com/small-12-volt-fan-for-electronics-airflow-cooling-p-23647.html</a> ) instead of a 24 volt fan. For R2 in the circuit I added a thermistor so the fan runs slower when the UPS is cooler, but speeds up when the UPS is charging and creating more heat. So far so good. Thanks again, Dan McEntire 
+"""]]

removed
diff --git a/blog/entry/12_to_24_volt_house_conversion/comment_2_de4bd6da79dbb324d2420373efa1c693._comment b/blog/entry/12_to_24_volt_house_conversion/comment_2_de4bd6da79dbb324d2420373efa1c693._comment
deleted file mode 100644
index 4aac8ec..0000000
--- a/blog/entry/12_to_24_volt_house_conversion/comment_2_de4bd6da79dbb324d2420373efa1c693._comment
+++ /dev/null
@@ -1,9 +0,0 @@
-[[!comment format=mdwn
- username="macdanny@a72b4b40c458ead665c8c2a022d209508e1393d6"
- nickname="macdanny"
- avatar="http://cdn.libravatar.org/avatar/e5831ecad78c64463fca51fddc891aad"
- subject="Great Idea!"
- date="2017-08-22T17:27:03Z"
- content="""
-Hey Joey, Thanks for the unintended push in the right direction. I've been following along for a little while now. I recently had the cooling fan in my UPS take a nose dive. Trouble is that the UPS is 24V and those little fans are costly (especially from the UPS manufacturer). It wasn't until reading this entry that it occurred to me. I have a pile of LM317 IC's I purchased years ago for a lighting project. I used one of them to build a small circuit that allowed me to use a 12 volt fan like this one ( https://www.12volt-travel.com/small-12-volt-fan-for-electronics-airflow-cooling-p-23647.html ) instead of a 24 volt fan. For R2 in the circuit I added a thermistor so the fan runs slower when the UPS is cooler, but speeds up when the UPS is charging and creating more heat. So far so good. Thanks again, Dan McEntire
-"""]]

Added a comment: Great Idea!
diff --git a/blog/entry/12_to_24_volt_house_conversion/comment_2_de4bd6da79dbb324d2420373efa1c693._comment b/blog/entry/12_to_24_volt_house_conversion/comment_2_de4bd6da79dbb324d2420373efa1c693._comment
new file mode 100644
index 0000000..4aac8ec
--- /dev/null
+++ b/blog/entry/12_to_24_volt_house_conversion/comment_2_de4bd6da79dbb324d2420373efa1c693._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="macdanny@a72b4b40c458ead665c8c2a022d209508e1393d6"
+ nickname="macdanny"
+ avatar="http://cdn.libravatar.org/avatar/e5831ecad78c64463fca51fddc891aad"
+ subject="Great Idea!"
+ date="2017-08-22T17:27:03Z"
+ content="""
+Hey Joey, Thanks for the unintended push in the right direction. I've been following along for a little while now. I recently had the cooling fan in my UPS take a nose dive. Trouble is that the UPS is 24V and those little fans are costly (especially from the UPS manufacturer). It wasn't until reading this entry that it occurred to me. I have a pile of LM317 IC's I purchased years ago for a lighting project. I used one of them to build a small circuit that allowed me to use a 12 volt fan like this one ( https://www.12volt-travel.com/small-12-volt-fan-for-electronics-airflow-cooling-p-23647.html ) instead of a 24 volt fan. For R2 in the circuit I added a thermistor so the fan runs slower when the UPS is cooler, but speeds up when the UPS is charging and creating more heat. So far so good. Thanks again, Dan McEntire
+"""]]

link img to video
diff --git a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
index f6fc714..9e4db70 100644
--- a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
+++ b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
@@ -14,7 +14,7 @@ and perform the installation. The whole demo took around 20 minutes,
 and ended with a standard Debian desktop installation.
 ([Video](http://meetings-archive.debian.net/pub/debian-meetings/2017/debconf17/life-after-debian.vp8.webm))
 
-[[!img pics/debconf/17/debconf17.png]]
+[[!img pics/debconf/17/debconf17.png link="http://meetings-archive.debian.net/pub/debian-meetings/2017/debconf17/life-after-debian.vp8.webm"]]
 
 The core idea is to reuse the same configuration management system 
 for several different purposes.

correction
diff --git a/talks.mdwn b/talks.mdwn
index 76b14c8..d0c2d0e 100644
--- a/talks.mdwn
+++ b/talks.mdwn
@@ -113,3 +113,5 @@ by others.
 * "Life After Debian"
   - [video](http://meetings-archive.debian.net/pub/debian-meetings/2017/debconf17/life-after-debian.vp8.webm)
   - [[slides|debconf-17-life-after-debian.pdf]]
+  - Correction: The other propellor developer in the audience of this talk,
+    who I referred to as "Simon", was actually Sean Whitton.

add pic and tag
diff --git a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
index a87bcfc..f6fc714 100644
--- a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
+++ b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
@@ -14,6 +14,8 @@ and perform the installation. The whole demo took around 20 minutes,
 and ended with a standard Debian desktop installation.
 ([Video](http://meetings-archive.debian.net/pub/debian-meetings/2017/debconf17/life-after-debian.vp8.webm))
 
+[[!img pics/debconf/17/debconf17.png]]
+
 The core idea is to reuse the same configuration management system 
 for several different purposes.
 
@@ -94,3 +96,5 @@ ideas encountered along the way:
   [[dependency yak shaving|devblog/yak_attack]], 
   [[devblog/high_bandwidth_propellor_hacking]]
   and [[finishing_touches|devblog/secret_project_its_aliiive]]
+
+[[!tag propellor]]
diff --git a/pics/debconf/17/debconf17.png b/pics/debconf/17/debconf17.png
new file mode 100644
index 0000000..5d37f4f
Binary files /dev/null and b/pics/debconf/17/debconf17.png differ

talk available; add slides
diff --git a/talks.mdwn b/talks.mdwn
index 6cfad6f..76b14c8 100644
--- a/talks.mdwn
+++ b/talks.mdwn
@@ -111,5 +111,5 @@ by others.
 ## DebConf 17, Montreal, Canada
 
 * "Life After Debian"
-  - August 8th, 6:00 pm
-  - [abstract](https://debconf17.debconf.org/talks/21/)
+  - [video](http://meetings-archive.debian.net/pub/debian-meetings/2017/debconf17/life-after-debian.vp8.webm)
+  - [[slides|debconf-17-life-after-debian.pdf]]
diff --git a/talks/debconf-17-life-after-debian.pdf b/talks/debconf-17-life-after-debian.pdf
new file mode 100644
index 0000000..d29019c
Binary files /dev/null and b/talks/debconf-17-life-after-debian.pdf differ

link to recording
diff --git a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
index c79268e..a87bcfc 100644
--- a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
+++ b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
@@ -12,6 +12,7 @@ from the audience to
 [play with its visual user interface](https://downloads.kitenet.net/videos/prototype_gamified_interface.webm) 
 and perform the installation. The whole demo took around 20 minutes,
 and ended with a standard Debian desktop installation.
+([Video](http://meetings-archive.debian.net/pub/debian-meetings/2017/debconf17/life-after-debian.vp8.webm))
 
 The core idea is to reuse the same configuration management system 
 for several different purposes.

expand
diff --git a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
index 12fef1c..c79268e 100644
--- a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
+++ b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
@@ -36,15 +36,17 @@ Once everything is handled by configuration management, all user interface
 requirements become just a matter of editing the configuration. Including:
 
 * A user interface that runs on the live system and gets whatever
-   input is needed to install to the target system. This is really just
-   a config editor underneath. I built a [[devblog/prototype_gamified_interface]]
-   that's as minimal as such an interface could get.
+  input is needed to install to the target system. This is really just
+  a config editor underneath. I built a [[devblog/prototype_gamified_interface]]
+  that's as minimal as such an interface could get.
 * With a regular text editor, of course. This is the equivilant of
-   preseeding in d-i, giving advanced users full control over the system
-   that gets built.
+  preseeding in d-i, giving advanced users full control over the system
+  that gets built. Unlike with preseeding, users have the full power of a
+  configuration management system, so can specify precisely the system they
+  want installed.
 * A separate user interface for customizing disk images, for arm
-   boards and similar use cases. This would run on a server,
-   or on the user's own laptop.
+  boards and similar use cases. This would run on a server,
+  or on the user's own laptop.
 
 That's the gist of it. Configuration management reused for installation
 and image building, and multiple editor interfaces to make it widely

bullets
diff --git a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
index 92fc4c3..12fef1c 100644
--- a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
+++ b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
@@ -35,14 +35,14 @@ of those will often benefit all the rest as well.
 Once everything is handled by configuration management, all user interface
 requirements become just a matter of editing the configuration. Including:
 
-1. A user interface that runs on the live system and gets whatever
+* A user interface that runs on the live system and gets whatever
    input is needed to install to the target system. This is really just
    a config editor underneath. I built a [[devblog/prototype_gamified_interface]]
    that's as minimal as such an interface could get.
-2. With a regular text editor, of course. This is the equivilant of
+* With a regular text editor, of course. This is the equivilant of
    preseeding in d-i, giving advanced users full control over the system
    that gets built.
-3. A separate user interface for customizing disk images, for arm
+* A separate user interface for customizing disk images, for arm
    boards and similar use cases. This would run on a server,
    or on the user's own laptop.
 

update
diff --git a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
index 5074973..92fc4c3 100644
--- a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
+++ b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
@@ -13,7 +13,7 @@ from the audience to
 and perform the installation. The whole demo took around 20 minutes,
 and ended with a standard Debian desktop installation.
 
-The idea is to reuse the same configuration management system 
+The core idea is to reuse the same configuration management system 
 for several different purposes.
 
 1. Building a bootable disk image that can be used as both a live system

final
diff --git a/blog/entry/building_a_Debian_installer_with_propellor.mdwn b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
deleted file mode 100644
index 9746dc0..0000000
--- a/blog/entry/building_a_Debian_installer_with_propellor.mdwn
+++ /dev/null
@@ -1,168 +0,0 @@
-Three years ago, I realized that [[code/propellor]] (my configuration
-management system that is configured using haskell) could be used as an
-installer for Debian (or other versions of Linux). In
-[[propellor_is_d-i_2.0]], I guessed it would take "a month and adding a few
-thousand lines of code". I've now taken that month, and written [that 1
-KLoC](https://git.joeyh.name/index.cgi/secret-project.git/), and I
-presented the result at DebConf yesterday.
-
-The idea is to reuse the same configuration management system 
-for several different purposes.
-
-1. Building a bootable disk image that can be used as both a live system
-   and as an installer.
-2. Running on that live system, to install the target system. Which can
-   just involve copying the live system to the target disk and then letting
-   the configuration management system make the necessary changes to get
-   from the live system configuration to the target system configuration.
-4. To support such things as headless arm boards, building customized
-   images tuned for the target board and use case, that can then
-   simply be copied to the board to install.
-5. Optionally, running on the installed system later, to futher customize
-   it. Starting from the same configuration that produced the installed
-   system in the first place.
-
-There's enourmous code reuse here, and improvements made for one
-will often benefit all the rest as well.
-
-Once everything is handled by configuration management, all user interface
-requirements become just a matter of editing the configuration. Including:
-
-1. A user interface that runs on the live system and gets whatever
-   input is needed to install to the target system. This is really just
-   a config editor underneath. I built a [[devblog/prototype_gamified_interface]]
-   that's as minimal as such an interface could get.
-2. With a regular text editor, of course. This is the equivilant of
-   preseeding in d-i, giving advanced users full control over the system
-   that gets built.
-3. A separate user interface for customizing disk images, for arm
-   boards and similar use cases. This would run on a server,
-   or on the user's own laptop.
-
-That's the gist of it. Configuration management reused for installation
-and image building, and multiple editor interfaces to make it widely
-usable.
-
-----
-
-Here's links to more details about what I built, and ideas encountered
-along the way.
-
-* In [[Functional_Reactive_Propellor]] I found a way to express the
-  commonalities and differences between the installer's configuration and
-  the target system's configuration. This lets the installer disk image
-  be copied to the target and the minimum work be done to convert it into
-  the desired target system.
-* In [[devblog/disk_partitioning_nitty_gritty]] I tackled configuring the partition
-  table of the target system. I extended a DSL propellor already used
-  for partitioning disk images.
-* In [[devblog/end_in_sight]] I found a way to make propellor
-  build disk images super fast, so a new 5 gb disk image can be ready in 30
-  seconds, a quarter of the time that it takes to write a 5 gb file with `dd`.
-* For completeness sake, I also [[devblogged|devblog]] about 
-  [[unfortunately needing a progress bar|devblog/secret_project_progress_bar]],
-  [[picking the disk to install to and installing grub|devblog/secret_project_close_but_no_cigar]],
-  [[yak shaving|devblog/yak_attack]], [[devblog/high_bandwidth_propellor_hacking]]
-  and [[finishing_touches|devblog/secret_project_its_aliiive]]
-
-----
-
-Finally, here's the propellor config file used to both build an
-installer image, and used in that installer to install the target system.
-
-First (after some `imports`) it tells propellor about two hosts, and
-runs `installerMain`, which displays the user interface when run in the
-installer.
-
-[[!format haskell """
-main :: IO ()
-main = installerMain hosts
-
-hosts :: [Host]
-hosts =
-        [ installer
-        , installer_builder
-        ]
-"""]]
-
-Then the configuration of the host that builds the installer image.
-
-[[!format haskell """
--- | This is not a complete Host definition; it can be used on any host
--- to build the installer disk images, by running, as root:
---      propellor installer.builder
-installer_builder :: Host
-installer_builder = host "installer.builder" $ props
-        & osDebian Unstable X86_64
-        & installerBuilt
-
--- | Build a disk image for the installer.
-installerBuilt :: RevertableProperty (HasInfo + DebianLike) Linux
-installerBuilt = imageBuilt "/srv/installer.img"
-        (hostChroot installer (Debootstrapped mempty))
-        MSDOS
-        [ partition EXT4 `mountedAt` "/"
-                `setFlag` BootFlag
-                `mountOpt` errorReadonly
-                `reservedSpacePercentage` 0
-                `addFreeSpace` MegaBytes 256
-        ]
-"""]]
-
-Then create a data type, so we can keep the installer and target configurations
-distinct, and derive both from a common `seed`.
-
-[[!format haskell """
-data Variety = Installer | Target
-        deriving (Eq)
-
-installer :: Host
-installer = seed `version` Installer
-
-target :: Host
-target = seed `version` Target
-"""]]
-
-And finally the seed from which it grows. Starting off with all the properties
-that the installer and target system have in common.
-
-[[!format haskell """
-seed :: Versioned Variety Host
-seed ver = host "debian.local" $ props
-        & osDebian Unstable X86_64
-        & Hostname.sane
-        & Apt.stdSourcesList
-        & Apt.installed ["linux-image-amd64"]
-        & Grub.installed PC
-        & XFCE.installed
-        & Apt.installed ["firefox"]
-        & "en_US.UTF-8" `Locale.selectedFor` ["LANG"]
-"""]]
-
-And then continuing with properties that differ between the installer
-and the target system.
-
-[[!format haskell """
-        & ver (   (== Installer) --> installerUser
-              <|> (== Target)    --> desktopUser (inputUserName userInput)
-              )
-        & ver (   (== Installer) --> autostartInstaller)
-        & ver (   (== Installer) --> targetInstalled target userInput parts)
-        & ver (   (== Target)    --> fstabLists userInput parts)
-        & ver (   (== Installer) --> targetBootable userInput)
-"""]]
-
-And finally, the partition table for the target system.
-
-[[!format haskell """
-parts = TargetPartTable MSDOS
-        [ partition EXT2 `mountedAt` "/boot"
-                `setFlag` BootFlag
-                `mountOpt` errorReadonly
-                `setSize` MegaBytes 512
-        , partition EXT4 `mountedAt` "/"
-                `mountOpt` errorReadonly
-                `useDiskSpace` RemainingSpace
-        , swapPartition (MegaBytes 1024)
-        ]
-"""]]
diff --git a/blog/entry/unifying_OS_installation_and_configuration_management.mdwn b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
new file mode 100644
index 0000000..5074973
--- /dev/null
+++ b/blog/entry/unifying_OS_installation_and_configuration_management.mdwn
@@ -0,0 +1,93 @@
+Three years ago, I realized that [[code/propellor]] (my configuration
+management system that is configured using haskell) could be used as an
+installer for Debian (or other versions of Linux). In
+[[propellor_is_d-i_2.0]], I guessed it would take "a month and adding a few
+thousand lines of code". 
+
+I've now taken that month, and written 
+[that code](https://git.joeyh.name/index.cgi/secret-project.git/), and I
+presented the result at DebConf yesterday. I demoed propellor building
+a live Debian installation image, and then handed it off to a volenteer
+from the audience to 
+[play with its visual user interface](https://downloads.kitenet.net/videos/prototype_gamified_interface.webm) 
+and perform the installation. The whole demo took around 20 minutes,
+and ended with a standard Debian desktop installation.
+
+The idea is to reuse the same configuration management system 
+for several different purposes.
+
+1. Building a bootable disk image that can be used as both a live system
+   and as an OS installer.

(Diff truncated)
layout
diff --git a/blog/entry/building_a_Debian_installer_with_propellor.mdwn b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
index bbda39c..9746dc0 100644
--- a/blog/entry/building_a_Debian_installer_with_propellor.mdwn
+++ b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
@@ -137,7 +137,7 @@ seed ver = host "debian.local" $ props
         & XFCE.installed
         & Apt.installed ["firefox"]
         & "en_US.UTF-8" `Locale.selectedFor` ["LANG"]
-""]]
+"""]]
 
 And then continuing with properties that differ between the installer
 and the target system.

layout
diff --git a/blog/entry/building_a_Debian_installer_with_propellor.mdwn b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
index 32d96b8..bbda39c 100644
--- a/blog/entry/building_a_Debian_installer_with_propellor.mdwn
+++ b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
@@ -112,7 +112,7 @@ installerBuilt = imageBuilt "/srv/installer.img"
 Then create a data type, so we can keep the installer and target configurations
 distinct, and derive both from a common `seed`.
 
-[[[!format haskell """
+[[!format haskell """
 data Variety = Installer | Target
         deriving (Eq)
 
@@ -126,7 +126,7 @@ target = seed `version` Target
 And finally the seed from which it grows. Starting off with all the properties
 that the installer and target system have in common.
 
-[[[!format haskell """
+[[!format haskell """
 seed :: Versioned Variety Host
 seed ver = host "debian.local" $ props
         & osDebian Unstable X86_64
@@ -142,7 +142,7 @@ seed ver = host "debian.local" $ props
 And then continuing with properties that differ between the installer
 and the target system.
 
-[[[!format haskell """
+[[!format haskell """
         & ver (   (== Installer) --> installerUser
               <|> (== Target)    --> desktopUser (inputUserName userInput)
               )
@@ -154,7 +154,7 @@ and the target system.
 
 And finally, the partition table for the target system.
 
-[[[!format haskell """
+[[!format haskell """
 parts = TargetPartTable MSDOS
         [ partition EXT2 `mountedAt` "/boot"
                 `setFlag` BootFlag

layout
diff --git a/blog/entry/building_a_Debian_installer_with_propellor.mdwn b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
index d596cd0..32d96b8 100644
--- a/blog/entry/building_a_Debian_installer_with_propellor.mdwn
+++ b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
@@ -87,7 +87,7 @@ hosts =
 
 Then the configuration of the host that builds the installer image.
 
-[[[!format haskell """
+[[!format haskell """
 -- | This is not a complete Host definition; it can be used on any host
 -- to build the installer disk images, by running, as root:
 --      propellor installer.builder

layout
diff --git a/blog/entry/building_a_Debian_installer_with_propellor.mdwn b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
index 9befcad..d596cd0 100644
--- a/blog/entry/building_a_Debian_installer_with_propellor.mdwn
+++ b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
@@ -54,8 +54,8 @@ along the way.
   be copied to the target and the minimum work be done to convert it into
   the desired target system.
 * In [[devblog/disk_partitioning_nitty_gritty]] I tackled configuring the partition
-  table of the target system. I extended the DSL used for 
-  configuring disk image partitioning.
+  table of the target system. I extended a DSL propellor already used
+  for partitioning disk images.
 * In [[devblog/end_in_sight]] I found a way to make propellor
   build disk images super fast, so a new 5 gb disk image can be ready in 30
   seconds, a quarter of the time that it takes to write a 5 gb file with `dd`.
@@ -74,7 +74,7 @@ First (after some `imports`) it tells propellor about two hosts, and
 runs `installerMain`, which displays the user interface when run in the
 installer.
 
-[[!language haskell """
+[[!format haskell """
 main :: IO ()
 main = installerMain hosts
 
@@ -87,7 +87,7 @@ hosts =
 
 Then the configuration of the host that builds the installer image.
 
-[[[!language haskell """
+[[[!format haskell """
 -- | This is not a complete Host definition; it can be used on any host
 -- to build the installer disk images, by running, as root:
 --      propellor installer.builder
@@ -112,7 +112,7 @@ installerBuilt = imageBuilt "/srv/installer.img"
 Then create a data type, so we can keep the installer and target configurations
 distinct, and derive both from a common `seed`.
 
-[[[!language haskell """
+[[[!format haskell """
 data Variety = Installer | Target
         deriving (Eq)
 
@@ -126,7 +126,7 @@ target = seed `version` Target
 And finally the seed from which it grows. Starting off with all the properties
 that the installer and target system have in common.
 
-[[[!language haskell """
+[[[!format haskell """
 seed :: Versioned Variety Host
 seed ver = host "debian.local" $ props
         & osDebian Unstable X86_64
@@ -142,7 +142,7 @@ seed ver = host "debian.local" $ props
 And then continuing with properties that differ between the installer
 and the target system.
 
-[[[!language haskell """
+[[[!format haskell """
         & ver (   (== Installer) --> installerUser
               <|> (== Target)    --> desktopUser (inputUserName userInput)
               )
@@ -154,7 +154,7 @@ and the target system.
 
 And finally, the partition table for the target system.
 
-[[[!language haskell """
+[[[!format haskell """
 parts = TargetPartTable MSDOS
         [ partition EXT2 `mountedAt` "/boot"
                 `setFlag` BootFlag

-link
diff --git a/blog/entry/building_a_Debian_installer_with_propellor.mdwn b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
index 3823d2f..9befcad 100644
--- a/blog/entry/building_a_Debian_installer_with_propellor.mdwn
+++ b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
@@ -48,7 +48,7 @@ usable.
 Here's links to more details about what I built, and ideas encountered
 along the way.
 
-* In [[devblog/Functional_Reactive_Propellor]] I found a way to express the
+* In [[Functional_Reactive_Propellor]] I found a way to express the
   commonalities and differences between the installer's configuration and
   the target system's configuration. This lets the installer disk image
   be copied to the target and the minimum work be done to convert it into

blog update
diff --git a/blog/entry/building_a_Debian_installer_with_propellor.mdwn b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
new file mode 100644
index 0000000..3823d2f
--- /dev/null
+++ b/blog/entry/building_a_Debian_installer_with_propellor.mdwn
@@ -0,0 +1,168 @@
+Three years ago, I realized that [[code/propellor]] (my configuration
+management system that is configured using haskell) could be used as an
+installer for Debian (or other versions of Linux). In
+[[propellor_is_d-i_2.0]], I guessed it would take "a month and adding a few
+thousand lines of code". I've now taken that month, and written [that 1
+KLoC](https://git.joeyh.name/index.cgi/secret-project.git/), and I
+presented the result at DebConf yesterday.
+
+The idea is to reuse the same configuration management system 
+for several different purposes.
+
+1. Building a bootable disk image that can be used as both a live system
+   and as an installer.
+2. Running on that live system, to install the target system. Which can
+   just involve copying the live system to the target disk and then letting
+   the configuration management system make the necessary changes to get
+   from the live system configuration to the target system configuration.
+4. To support such things as headless arm boards, building customized
+   images tuned for the target board and use case, that can then
+   simply be copied to the board to install.
+5. Optionally, running on the installed system later, to futher customize
+   it. Starting from the same configuration that produced the installed
+   system in the first place.
+
+There's enourmous code reuse here, and improvements made for one
+will often benefit all the rest as well.
+
+Once everything is handled by configuration management, all user interface
+requirements become just a matter of editing the configuration. Including:
+
+1. A user interface that runs on the live system and gets whatever
+   input is needed to install to the target system. This is really just
+   a config editor underneath. I built a [[devblog/prototype_gamified_interface]]
+   that's as minimal as such an interface could get.
+2. With a regular text editor, of course. This is the equivilant of
+   preseeding in d-i, giving advanced users full control over the system
+   that gets built.
+3. A separate user interface for customizing disk images, for arm
+   boards and similar use cases. This would run on a server,
+   or on the user's own laptop.
+
+That's the gist of it. Configuration management reused for installation
+and image building, and multiple editor interfaces to make it widely
+usable.
+
+----
+
+Here's links to more details about what I built, and ideas encountered
+along the way.
+
+* In [[devblog/Functional_Reactive_Propellor]] I found a way to express the
+  commonalities and differences between the installer's configuration and
+  the target system's configuration. This lets the installer disk image
+  be copied to the target and the minimum work be done to convert it into
+  the desired target system.
+* In [[devblog/disk_partitioning_nitty_gritty]] I tackled configuring the partition
+  table of the target system. I extended the DSL used for 
+  configuring disk image partitioning.
+* In [[devblog/end_in_sight]] I found a way to make propellor
+  build disk images super fast, so a new 5 gb disk image can be ready in 30
+  seconds, a quarter of the time that it takes to write a 5 gb file with `dd`.
+* For completeness sake, I also [[devblogged|devblog]] about 
+  [[unfortunately needing a progress bar|devblog/secret_project_progress_bar]],
+  [[picking the disk to install to and installing grub|devblog/secret_project_close_but_no_cigar]],
+  [[yak shaving|devblog/yak_attack]], [[devblog/high_bandwidth_propellor_hacking]]
+  and [[finishing_touches|devblog/secret_project_its_aliiive]]
+
+----
+
+Finally, here's the propellor config file used to both build an
+installer image, and used in that installer to install the target system.
+
+First (after some `imports`) it tells propellor about two hosts, and
+runs `installerMain`, which displays the user interface when run in the
+installer.
+
+[[!language haskell """
+main :: IO ()
+main = installerMain hosts
+
+hosts :: [Host]
+hosts =
+        [ installer
+        , installer_builder
+        ]
+"""]]
+
+Then the configuration of the host that builds the installer image.
+
+[[[!language haskell """
+-- | This is not a complete Host definition; it can be used on any host
+-- to build the installer disk images, by running, as root:
+--      propellor installer.builder
+installer_builder :: Host
+installer_builder = host "installer.builder" $ props
+        & osDebian Unstable X86_64
+        & installerBuilt
+
+-- | Build a disk image for the installer.
+installerBuilt :: RevertableProperty (HasInfo + DebianLike) Linux
+installerBuilt = imageBuilt "/srv/installer.img"
+        (hostChroot installer (Debootstrapped mempty))
+        MSDOS
+        [ partition EXT4 `mountedAt` "/"
+                `setFlag` BootFlag
+                `mountOpt` errorReadonly
+                `reservedSpacePercentage` 0
+                `addFreeSpace` MegaBytes 256
+        ]
+"""]]
+
+Then create a data type, so we can keep the installer and target configurations
+distinct, and derive both from a common `seed`.
+
+[[[!language haskell """
+data Variety = Installer | Target
+        deriving (Eq)
+
+installer :: Host
+installer = seed `version` Installer
+
+target :: Host
+target = seed `version` Target
+"""]]
+
+And finally the seed from which it grows. Starting off with all the properties
+that the installer and target system have in common.
+
+[[[!language haskell """
+seed :: Versioned Variety Host
+seed ver = host "debian.local" $ props
+        & osDebian Unstable X86_64
+        & Hostname.sane
+        & Apt.stdSourcesList
+        & Apt.installed ["linux-image-amd64"]
+        & Grub.installed PC
+        & XFCE.installed
+        & Apt.installed ["firefox"]
+        & "en_US.UTF-8" `Locale.selectedFor` ["LANG"]
+""]]
+
+And then continuing with properties that differ between the installer
+and the target system.
+
+[[[!language haskell """
+        & ver (   (== Installer) --> installerUser
+              <|> (== Target)    --> desktopUser (inputUserName userInput)
+              )
+        & ver (   (== Installer) --> autostartInstaller)
+        & ver (   (== Installer) --> targetInstalled target userInput parts)
+        & ver (   (== Target)    --> fstabLists userInput parts)
+        & ver (   (== Installer) --> targetBootable userInput)
+"""]]
+
+And finally, the partition table for the target system.
+
+[[[!language haskell """
+parts = TargetPartTable MSDOS
+        [ partition EXT2 `mountedAt` "/boot"
+                `setFlag` BootFlag
+                `mountOpt` errorReadonly
+                `setSize` MegaBytes 512
+        , partition EXT4 `mountedAt` "/"
+                `mountOpt` errorReadonly
+                `useDiskSpace` RemainingSpace
+        , swapPartition (MegaBytes 1024)
+        ]
+"""]]

Add overwrite and ftruncate from editing in place discussion
diff --git a/code/moreutils/discussion.mdwn b/code/moreutils/discussion.mdwn
index fbaffef..604a289 100644
--- a/code/moreutils/discussion.mdwn
+++ b/code/moreutils/discussion.mdwn
@@ -578,3 +578,8 @@ Running foo.py and then immediately exiting 'less' by pressing 'q' causes sponge
     error writing buffer to output file: Broken pipe
 
 Curiously, running bar.sh directly doesn't have this problem.  I'm not sure what Python is doing to the execution environment to cause this, but would you consider changing write_buff_out to suppress its warning spew if it's writing to stdout?
+
+## Miscellanious
+
+* [overwrite](https://unix.stackexchange.com/a/11074/176171)
+* [ftrunctate](https://unix.stackexchange.com/a/280277/176171)

blog
diff --git a/blog/entry/home_power_monitoring.mdwn b/blog/entry/home_power_monitoring.mdwn
new file mode 100644
index 0000000..af8ef30
--- /dev/null
+++ b/blog/entry/home_power_monitoring.mdwn
@@ -0,0 +1,22 @@
+For years I've recorded solar panel data by hand. Filled two notebooks
+with columns of figures. My new charge controller, an 
+[EPsolar Tracer-BN](http://www.epsolarpv.com/en/index.php/Product/pro_content/id/573/am_id/136),
+finally let me automate it.
+
+[[!img blog/pics/homepower.png caption="morning activity; by 8 am the sun is still behind the hill but, 
+16 watts are being produced, and by 11:30 am, the battery bank is full"]]
+
+You can explore my home power data here: <http://homepower.joeyh.name/>  
+(click and drag to zoom)
+
+The web interface loads the RRD files into a web browser
+using [javascriptRRD](http://javascriptrrd.sourceforge.net/).
+I wrote a [haskell program](https://git.joeyh.name/index.cgi/joey/homepower.git/tree/poller.hs)
+that drives the
+[epsolar-tracer python library](https://github.com/kasbert/epsolar-tracer)
+to poll for data, and stores it in RRD files. Could have used collectd or
+something, but the interface to the charge controller is currently
+a bit flakey and I have to be careful about retries and polling frequencies. 
+Also I wanted full control over how much data is stored in the RRD files.
+
+[Full source code](https://git.joeyh.name/index.cgi/joey/homepower.git/)
diff --git a/blog/pics/homepower.png b/blog/pics/homepower.png
new file mode 100644
index 0000000..5fa427e
Binary files /dev/null and b/blog/pics/homepower.png differ

typo
diff --git a/thanks.mdwn b/thanks.mdwn
index 0111ed0..c25d5e6 100644
--- a/thanks.mdwn
+++ b/thanks.mdwn
@@ -3,6 +3,6 @@ I do, a note is always the best way to make me happy, but here are some
 more tangible options:
 
 * paypal joey@kitenet.net
-* [support me on Patream](https://patreon.com/joeyh)
+* [support me on Patreon](https://patreon.com/joeyh)
 * [My Amazon wishlist](http://www.amazon.com/gp/registry/registry.html/104-5960215-8415137?ie=UTF8&type=wishlist&id=H9MGKNPCYVS2)
 * bitcoin address: <a href="bitcoin:[[!inline raw=yes pages=bitcoin]]">[[!inline raw=yes pages=bitcoin]]</a>

devblog
diff --git a/devblog/secret_project_progress_bar.mdwn b/devblog/secret_project_progress_bar.mdwn
new file mode 100644
index 0000000..7326d1d
--- /dev/null
+++ b/devblog/secret_project_progress_bar.mdwn
@@ -0,0 +1,12 @@
+One of my initial goals for secret-project was for it to not need to
+implement a progress bar.
+
+[[!img progressbar.png]]
+
+So, of course, today I found myself implementing a progress bar to finish
+up secret-project. As well as some other UI polishing, and fixing a couple
+of bugs in propellor that impacted it.
+
+Ok, I'm entirely done with secret-project now, except for an unveiling
+later this month. Looking back over the devblog, it took only
+around 14 days total to build it all. Feels longer, but not bad!

devblog
diff --git a/devblog/secret_project_progress_bar/progressbar.png b/devblog/secret_project_progress_bar/progressbar.png
new file mode 100644
index 0000000..417ce5e
Binary files /dev/null and b/devblog/secret_project_progress_bar/progressbar.png differ

devblog
diff --git a/devblog/secret_project_its_aliiive.mdwn b/devblog/secret_project_its_aliiive.mdwn
new file mode 100644
index 0000000..344dcc2
--- /dev/null
+++ b/devblog/secret_project_its_aliiive.mdwn
@@ -0,0 +1,14 @@
+After a rather interesting morning, the secret-project is doing exactly
+what I set out to accomplish! It's alllive!
+
+(I found a way to segfault the ghc runtime first.
+And then I also managed to crash firefox, and finally managed to crash and
+hard-hang rsync.)
+
+All that remains to be done now is to clean up the user interface.
+I made propellor's output be displayed in the web browser, but currently
+it contains ansi escape sequences which don't look good.
+
+This would probably be a bad time to implement a in-browser terminal
+emulator in haskell, and perhaps a good time to give propellor customizable
+output backends. I have 3 days left to completely finish this project.

devblog
diff --git a/devblog/secret_project_close_but_no_cigar.mdwn b/devblog/secret_project_close_but_no_cigar.mdwn
new file mode 100644
index 0000000..3df3e62
--- /dev/null
+++ b/devblog/secret_project_close_but_no_cigar.mdwn
@@ -0,0 +1,15 @@
+One last detour: Had to do more work than I really want to at this stage,
+to make the secret-project pick a good disk to use. Hardcoding a disk
+device was not working reliably enough even for a demo. Ended up with some
+fairly sophisticated heuristics to pick the right disk, taking disk size
+and media into account.
+
+Then finally got on with grub installation to the target disk. Installing
+grub to a disk from a chroot is a fiddley process hard to get right. But, I
+remembered writing similar code before; propellor installs grub to a disk
+image from a chroot. So I generalized that special-purpose code to something
+the secret-project can also use.
+
+It was a very rainy day, and rain fade on the satellite internet prevented
+me from testing it quickly. There were some dumb bugs. But at 11:30 pm,
+it Just Worked! Well, at least the target booted. /etc/fstab is not 100% right.

update
diff --git a/boxen/honeybee.mdwn b/boxen/honeybee.mdwn
index 1045a7a..2c3d604 100644
--- a/boxen/honeybee.mdwn
+++ b/boxen/honeybee.mdwn
@@ -1 +1 @@
-Cubietruck, at Anna's, used for git-annex arm autobuilder.
+Cubietruck, used as my home router and git-annex arm autobuilder.
diff --git a/talks.mdwn b/talks.mdwn
index 29ef7ac..6cfad6f 100644
--- a/talks.mdwn
+++ b/talks.mdwn
@@ -111,5 +111,5 @@ by others.
 ## DebConf 17, Montreal, Canada
 
 * "Life After Debian"
-  - August 10th, 3:30 pm
+  - August 8th, 6:00 pm
   - [abstract](https://debconf17.debconf.org/talks/21/)

devblog
diff --git a/devblog/end_in_sight.mdwn b/devblog/end_in_sight.mdwn
new file mode 100644
index 0000000..65747e7
--- /dev/null
+++ b/devblog/end_in_sight.mdwn
@@ -0,0 +1,25 @@
+Late Friday evening, I realized that the secret-project's user interface
+should be a specialized propellor config file editor. Eureka! With that in mind,
+I reworked how the UserInput value is passed from the UI to propellor;
+now there's a UserInput.hs module that starts out with an unconfigured
+value, and the UI rewrites that file. This has a lot of benefits, including
+being able to test it without going through the UI, and letting the UI be
+decoupled into a separate program.
+
+Also, sped up propellor's disk image building a *lot*. It already had some
+efficiency hacks, to reuse disk image files and rsync files to the disk
+image, but it was still repartitioning the disk image every time, and the
+whole raw disk image was being copied to create the vmdk file for
+VirtualBox. Now it only repartitions when something has changed, and the
+vmdk file references the disk image, which sped up the secret-project's 5
+gigabyte image build time from around 30 minutes to 30 seconds.
+
+With that procrastination^Wgroundwork complete, I was finally at the point of
+testing the secret-project running on the disk image. There were a few minor
+problems, but within an hour it was successfully partitioning, mounting,
+and populating the target disk.
+
+Still have to deal with boot loader installation and progress
+display, but the end of the secret-project is in sight.
+
+Today's work was sponsored by Trenton Cronholm on Patreon.

typ
diff --git a/home.mdwn b/home.mdwn
index 8d93cc2..2b8359c 100644
--- a/home.mdwn
+++ b/home.mdwn
@@ -7,5 +7,5 @@ Home since 2010 is...
 * No running water (hauled from two springs)
 * Total privacy (all land visible from house is mine)
 * Pretty damn isolated
-* Dialup and satelite internet
+* Dialup and satellite internet
 * Where the heart is

format
diff --git a/links/personal.mdwn b/links/personal.mdwn
index 599954d..c3b0a37 100644
--- a/links/personal.mdwn
+++ b/links/personal.mdwn
@@ -2,7 +2,7 @@
 
 [[blog]]  
 [[pics]]  
-[[home]]
+[[home]]  
 [[contact_me|contact]]  
 [[GPG key|contact]]  
 [[todo]]

home
diff --git a/home.mdwn b/home.mdwn
new file mode 100644
index 0000000..8d93cc2
--- /dev/null
+++ b/home.mdwn
@@ -0,0 +1,11 @@
+Home since 2010 is...
+
+* Offgrid
+* [[blog/Solar]] powered
+* Earth sheltered (dug 8 feet into hillside)
+* Sun and wood heated
+* No running water (hauled from two springs)
+* Total privacy (all land visible from house is mine)
+* Pretty damn isolated
+* Dialup and satelite internet
+* Where the heart is
diff --git a/links/personal.mdwn b/links/personal.mdwn
index e47b4c5..599954d 100644
--- a/links/personal.mdwn
+++ b/links/personal.mdwn
@@ -2,6 +2,7 @@
 
 [[blog]]  
 [[pics]]  
+[[home]]
 [[contact_me|contact]]  
 [[GPG key|contact]]  
 [[todo]]

talk
diff --git a/talks.mdwn b/talks.mdwn
index 47c5414..29ef7ac 100644
--- a/talks.mdwn
+++ b/talks.mdwn
@@ -107,3 +107,9 @@ by others.
 * "securely backing up gpg private keys.. to the cloud‽"
   - [video](https://media.libreplanet.org/u/libreplanet/m/securely-backing-up-gpg-private-keys-to-the-cloud/)
   - [[slides|keysafe-libreplanet.pdf]]
+
+## DebConf 17, Montreal, Canada
+
+* "Life After Debian"
+  - August 10th, 3:30 pm
+  - [abstract](https://debconf17.debconf.org/talks/21/)

foo
diff --git a/devblog/disk_partitioning_nitty_gritty.mdwn b/devblog/disk_partitioning_nitty_gritty.mdwn
new file mode 100644
index 0000000..6150ecc
--- /dev/null
+++ b/devblog/disk_partitioning_nitty_gritty.mdwn
@@ -0,0 +1,30 @@
+The secret-project can probably partition disks now. I have not tried it
+yet.
+
+I generalized propellor's PartSpec DSL, which had been used for only
+auto-fitting disk images to chroot sizes, to also support things like
+partitions that use some percentage of the disk.
+
+A sample partition table using that, that gives `/` and `/srv` each 20% of
+the disk, has a couple of fixed size partitions, and uses the rest for `/home`:
+
+	[ partition EXT2 `mountedAt` "/boot"
+		`setFlag` BootFlag
+		`setSize` MegaBytes 512
+	, partition EXT4 `mountedAt` "/"
+		`useDiskSpace` (Percent 20)
+	, partition EXT4 `mountedAt` "/srv"
+		`useDiskSpace` (Percent 20)
+	, partition EXT4 `mountedAt` "/home"
+		`useDiskSpace` RemainingSpace
+	, swapPartition (MegaBytes 1024)
+        ]
+
+It would probably be good to extend that with a combinator that sets
+a minimum allows size, so eg `/` can be made no smaller than 4 GB.
+The implementation should make it simple enough to add such combinators.
+
+I thought about reusing the disk image auto-fitting code, so the 
+target's `/` would start at the size of the installer's `/`.
+May yet do that; it would make some sense when the target and
+installer are fairly similar systems.

devblog
diff --git a/devblog/a_plan_comes_together.mdwn b/devblog/a_plan_comes_together.mdwn
new file mode 100644
index 0000000..1ba7621
--- /dev/null
+++ b/devblog/a_plan_comes_together.mdwn
@@ -0,0 +1,10 @@
+After building the neato Host versioning described in
+[[blog/entry/Functional_Reactive_Propellor]] this weekend,
+I was able to clean up secret-project's config file significantly
+It's feeling close to the final version now.
+
+At this point, the disk image it builds is almost capable of installing the
+target system, and will try to do so when the user tells it to. But,
+choosing and partitioning of the target system disk is not implemented yet,
+so it installs to a chroot which will fail due to lack of disk space there.
+So, I have not actually tested it yet.

correct spelling mistakes
diff --git a/blog/entry/Functional_Reactive_Propellor.mdwn b/blog/entry/Functional_Reactive_Propellor.mdwn
index 40abb13..2f491f7 100644
--- a/blog/entry/Functional_Reactive_Propellor.mdwn
+++ b/blog/entry/Functional_Reactive_Propellor.mdwn
@@ -18,7 +18,7 @@ I wrote this code, and it made me super happy!
 		      )
 		& ver (   (== Installer) --> autostartInstaller )
 
-This is doing so much in so little space and with so luttle fuss! It's
+This is doing so much in so little space and with so little fuss! It's
 completely defining two different versions of a `Host`. One version is the
 `Installer`, which in turn installs the `Target`. The code above provides
 all the information that [[code/propellor]] needs to  *convert* a copy of
@@ -42,7 +42,7 @@ out of git. But then I ran into the situation where I needed these two
 closely related hosts to be defined in a single file, and it all fell
 into place.
 
-The basic idea is that propellor first reverts all the revertable
+The basic idea is that propellor first reverts all the revertible
 properties for other versions. Then it ensures the property for the current
 version.
 

link
diff --git a/blog/entry/Functional_Reactive_Propellor.mdwn b/blog/entry/Functional_Reactive_Propellor.mdwn
index bb04fc3..40abb13 100644
--- a/blog/entry/Functional_Reactive_Propellor.mdwn
+++ b/blog/entry/Functional_Reactive_Propellor.mdwn
@@ -72,6 +72,8 @@ Notice that I've embedded a small DSL for versioning into the propellor
 config file syntax. While implementing versioning took all day,
 that part was super easy; Haskell config files win again!
 
+[API documentation for this feature](http://hackage.haskell.org/package/propellor/docs/Propellor-Property-Versioned.html)
+
 PS: Not really FRP, probably. But time-varying in a FRP-like way.
 
 ---

foo
diff --git a/blog/entry/I_am_ArchiveTeam.mdwn b/blog/entry/I_am_ArchiveTeam.mdwn
index 0476af8..a76dae0 100644
--- a/blog/entry/I_am_ArchiveTeam.mdwn
+++ b/blog/entry/I_am_ArchiveTeam.mdwn
@@ -12,7 +12,7 @@ It's even been the subject of
 [serious academic study as outlined in this talk](http://cdn.media.ccc.de/congress/2014/h264-hd/31c3-6373-en-de-The_Only_Thing_We_Know_About_Cyberspace_Is_That_Its_640x480_hd.mp4),
 which is pretty awesome.
 
-<img src="https://pbs.twimg.com/media/CAMZihSVAAEHyAa.jpg:small" alt="Jason Scott in full stage regalia">
+[[pics/sketchcow.jpeg]]
 
 I'm happy to let this guy be the public face of ArchiveTeam in
 internet meme-land. It's a 0.1% project for me, and has grown into a
diff --git a/blog/pics/sketchcow.jpeg b/blog/pics/sketchcow.jpeg
new file mode 100644
index 0000000..e625112
Binary files /dev/null and b/blog/pics/sketchcow.jpeg differ

blog
diff --git a/blog/entry/Functional_Reactive_Propellor.mdwn b/blog/entry/Functional_Reactive_Propellor.mdwn
new file mode 100644
index 0000000..bb04fc3
--- /dev/null
+++ b/blog/entry/Functional_Reactive_Propellor.mdwn
@@ -0,0 +1,82 @@
+I wrote this code, and it made me super happy!
+
+	data Variety = Installer | Target
+		deriving (Eq)
+
+	seed :: UserInput -> Versioned Variety Host
+	seed userinput ver = host "foo"
+		& ver (   (== Installer) --> hostname "installer"
+		      <|> (== Target)    --> hostname (inputHostname userinput)
+		      )
+		& osDebian Unstable X86_64
+		& Apt.stdSourcesList
+		& Apt.installed ["linux-image-amd64"]
+		& Grub.installed PC
+		& XFCE.installed
+		& ver (   (== Installer) --> desktopUser defaultUser
+		      <|> (== Target)    --> desktopUser (inputUsername userinput)
+		      )
+		& ver (   (== Installer) --> autostartInstaller )
+
+This is doing so much in so little space and with so luttle fuss! It's
+completely defining two different versions of a `Host`. One version is the
+`Installer`, which in turn installs the `Target`. The code above provides
+all the information that [[code/propellor]] needs to  *convert* a copy of
+the `Installer` into the `Target`, which it can do very efficiently. For
+example, it knows that the default user account should be deleted, and a
+new user account created based on the user's input of their name.
+
+The germ of this idea comes from a short presentation I made about
+propellor in Portland several years ago. I was describing
+`RevertableProperty`, and Joachim Breitner pointed out that to use it, the
+user essentially has to keep track of the evolution of their `Host` in
+their head. It would be better for propellor to know what past versions
+looked like, so it can know when a `RevertableProperty` needs to be
+reverted.
+
+I didn't see a way to address the objection for years. I was hung up
+on the problem that propellor's properties can't be compared for equality,
+because functions can't be compared for equality (generally). And on the
+problem that it would be hard for propellor to pull old versions of a `Host`
+out of git. But then I ran into the situation where I needed these two
+closely related hosts to be defined in a single file, and it all fell
+into place.
+
+The basic idea is that propellor first reverts all the revertable
+properties for other versions. Then it ensures the property for the current
+version.
+
+Another use for it would be if you wanted to be able to roll back changes
+to a Host. For example:
+
+	foos :: Versioned Int Host
+	foos ver = host "foo"
+		& hostname "foo.example.com"
+		& ver (   (== 1) --> Apache.modEnabled "mpm_worker"
+		      <|> (>= 2) --> Apache.modEnabled "mpm_event"
+		      )
+		& ver ( (>= 3)   --> Apt.unattendedUpgrades )
+
+	foo :: Host
+	foo = foos `version` (4 :: Int)
+
+Versioned properties can also be defined:
+
+	foobar :: Versioned Int -> RevertableProperty DebianLike DebianLike
+	foobar ver =
+		ver (   (== 1) --> (Apt.installed "foo" <!> Apt.removed "foo")
+		    <|> (== 2) --> (Apt.installed "bar" <!> Apt.removed "bar")
+		    )
+
+Notice that I've embedded a small DSL for versioning into the propellor
+config file syntax. While implementing versioning took all day,
+that part was super easy; Haskell config files win again!
+
+PS: Not really FRP, probably. But time-varying in a FRP-like way.
+
+---
+
+Development of this was sponsored by Jake Vosloo on
+[Patreon](https://patreon.com/joeyh/).
+
+[[!tag propellor]]

typo
diff --git a/devblog/yak_attack.mdwn b/devblog/yak_attack.mdwn
index 1458313..62ddb9f 100644
--- a/devblog/yak_attack.mdwn
+++ b/devblog/yak_attack.mdwn
@@ -8,7 +8,7 @@ another approach, but finally gave in, and taught propellor how to build
 itself with stack. There was an open todo about that, with a hacky
 implementation by Arnaud Bailly, which I cleaned up.
 
-Then the yak shaving continued as I revisited a tricky intermittend
+Then the yak shaving continued as I revisited a tricky intermittent
 propellor bug. Think I've finally squashed that.
 
 Finally, got back to where I left off last week, and at last here's a

devblog
diff --git a/devblog/yak_attack.mdwn b/devblog/yak_attack.mdwn
new file mode 100644
index 0000000..1458313
--- /dev/null
+++ b/devblog/yak_attack.mdwn
@@ -0,0 +1,26 @@
+Integrating propellor and secret-project stalled out last week.
+The problem was that secret-project can only be built with stack right now
+(until my patch to threepenny-gui to fix drag and drop handling gets
+accepted), but propellor did not support building itself with stack.
+
+I didn't want to get sucked into yak shaving on that, and tried to find
+another approach, but finally gave in, and taught propellor how to build
+itself with stack. There was an open todo about that, with a hacky
+implementation by Arnaud Bailly, which I cleaned up.
+
+Then the yak shaving continued as I revisited a tricky intermittend
+propellor bug. Think I've finally squashed that.
+
+Finally, got back to where I left off last week, and at last here's a
+result! This is a disk image that was built entirely from a propellor
+config file, that contains a working propellor installation, and that
+starts up secret-project on boot.
+
+[[!img aliiiive.png]]
+
+Now to make this secret-project actually do something more than looking
+pretty..
+
+----
+
+Today's work was sponsored by Trenton Cronholm on Patreon.
diff --git a/devblog/yak_attack/aliiiive.png b/devblog/yak_attack/aliiiive.png
new file mode 100644
index 0000000..a40f958
Binary files /dev/null and b/devblog/yak_attack/aliiiive.png differ

update
diff --git a/blog/entry/bonus_project.mdwn b/blog/entry/bonus_project.mdwn
index 893d234..a021d95 100644
--- a/blog/entry/bonus_project.mdwn
+++ b/blog/entry/bonus_project.mdwn
@@ -18,3 +18,6 @@ After finishing all that, it was time to
 while enjoying this.
 
 <video controls width=705 src="https://joeyh.name/blog/pics/river.webm">
+
+(Followed by taking delivery of a dumptruck full of gravel -- 23 tons --
+which it turns out was enough for only half of my driveway..)

fix
diff --git a/blog/entry/bonus_project.mdwn b/blog/entry/bonus_project.mdwn
index 41974aa..893d234 100644
--- a/blog/entry/bonus_project.mdwn
+++ b/blog/entry/bonus_project.mdwn
@@ -17,4 +17,4 @@ After finishing all that, it was time to
 [think about this](https://git-annex.branchable.com/design/exporting_trees_to_special_remotes/)
 while enjoying this.
 
-<video controls width=705 src="https://joeyh.name/blog/pics/blog/pics/river.webm">
+<video controls width=705 src="https://joeyh.name/blog/pics/river.webm">

fix
diff --git a/blog/entry/bonus_project.mdwn b/blog/entry/bonus_project.mdwn
index 915d388..41974aa 100644
--- a/blog/entry/bonus_project.mdwn
+++ b/blog/entry/bonus_project.mdwn
@@ -11,7 +11,7 @@ protect the plywood.
 Bonus bonus project to use up paint. (Argh, now I want to increase the size
 of the overflowing grape arbor. Once you start on this kind of stuff..)
 
-[[!img retainingwall.jpg]]
+[[!img pics/retainingwall.jpg]]
 
 After finishing all that, it was time to
 [think about this](https://git-annex.branchable.com/design/exporting_trees_to_special_remotes/)

fix
diff --git a/blog/entry/bonus_project.mdwn b/blog/entry/bonus_project.mdwn
index 30f8e24..915d388 100644
--- a/blog/entry/bonus_project.mdwn
+++ b/blog/entry/bonus_project.mdwn
@@ -1,7 +1,7 @@
 Little bonus project after the solar upgrade was replacing the battery
 box's rotted roof, down to the cinderblock walls.
 
-[[!img src="pics/batterybox.jpg"]]
+[[!img pics/batterybox.jpg]]
 
 Except for a piece of plywood, used all scrap lumber for this project, and
 also scavenged a great set of hinges from a discarded cabinet. I hope the
@@ -11,7 +11,7 @@ protect the plywood.
 Bonus bonus project to use up paint. (Argh, now I want to increase the size
 of the overflowing grape arbor. Once you start on this kind of stuff..)
 
-[[!img src="retainingwall.jpg"]]
+[[!img retainingwall.jpg]]
 
 After finishing all that, it was time to
 [think about this](https://git-annex.branchable.com/design/exporting_trees_to_special_remotes/)

blog update
diff --git a/blog/entry/bonus_project.mdwn b/blog/entry/bonus_project.mdwn
new file mode 100644
index 0000000..30f8e24
--- /dev/null
+++ b/blog/entry/bonus_project.mdwn
@@ -0,0 +1,20 @@
+Little bonus project after the solar upgrade was replacing the battery
+box's rotted roof, down to the cinderblock walls.
+
+[[!img src="pics/batterybox.jpg"]]
+
+Except for a piece of plywood, used all scrap lumber for this project, and
+also scavenged a great set of hinges from a discarded cabinet. I hope the
+paint on all sides and an inch of shingle overhang will be enough to
+protect the plywood.
+
+Bonus bonus project to use up paint. (Argh, now I want to increase the size
+of the overflowing grape arbor. Once you start on this kind of stuff..)
+
+[[!img src="retainingwall.jpg"]]
+
+After finishing all that, it was time to
+[think about this](https://git-annex.branchable.com/design/exporting_trees_to_special_remotes/)
+while enjoying this.
+
+<video controls width=705 src="https://joeyh.name/blog/pics/blog/pics/river.webm">
diff --git a/blog/pics/batterybox.jpg b/blog/pics/batterybox.jpg
new file mode 100644
index 0000000..ace344e
Binary files /dev/null and b/blog/pics/batterybox.jpg differ
diff --git a/blog/pics/retainingwall.jpg b/blog/pics/retainingwall.jpg
new file mode 100644
index 0000000..680ea26
Binary files /dev/null and b/blog/pics/retainingwall.jpg differ
diff --git a/blog/pics/river.webm b/blog/pics/river.webm
new file mode 100644
index 0000000..6deec43
Binary files /dev/null and b/blog/pics/river.webm differ

poll vote (I haven't tried it, but want to)
diff --git a/code/kaxxt/feedback.mdwn b/code/kaxxt/feedback.mdwn
index 51feb3e..1195c7e 100644
--- a/code/kaxxt/feedback.mdwn
+++ b/code/kaxxt/feedback.mdwn
@@ -1,4 +1,4 @@
 Whatdayathink? Please vote in the poll, or post your
 experiences/questions to [[/code/Kaxxt/Discussion]].
 
-[[!poll 4 "I tried it, liked it." 0 "I tried it, needs work." 10 "I haven't tried it, but want to" 2 "I don't plan to try it"]]
+[[!poll 4 "I tried it, liked it." 0 "I tried it, needs work." 11 "I haven't tried it, but want to" 2 "I don't plan to try it"]]

poll vote (I haven't tried it, but want to)
diff --git a/code/kaxxt/feedback.mdwn b/code/kaxxt/feedback.mdwn
index 4cbcfba..51feb3e 100644
--- a/code/kaxxt/feedback.mdwn
+++ b/code/kaxxt/feedback.mdwn
@@ -1,4 +1,4 @@
 Whatdayathink? Please vote in the poll, or post your
 experiences/questions to [[/code/Kaxxt/Discussion]].
 
-[[!poll 4 "I tried it, liked it." 0 "I tried it, needs work." 9 "I haven't tried it, but want to" 2 "I don't plan to try it"]]
+[[!poll 4 "I tried it, liked it." 0 "I tried it, needs work." 10 "I haven't tried it, but want to" 2 "I don't plan to try it"]]

devblog
diff --git a/devblog/mashup.mdwn b/devblog/mashup.mdwn
new file mode 100644
index 0000000..25e7388
--- /dev/null
+++ b/devblog/mashup.mdwn
@@ -0,0 +1,17 @@
+This was a one step forward, one step back kind of day, as I moved the
+working stuff from yesterday out of my personal propellor config file and
+into the secret-project repository, and stumbled over some issues while
+doing so.
+
+But, I had a crucial idea last night. When propellor is used to build an
+installer image, the installer does not need to bootstrap the target system
+from scratch. It can just copy the installer to the target system, and then
+run propellor there, with a configuration that reverts any properties that
+the installer had but the installed system should not. This will be a
+lot faster and avoid duplicate downloads.
+
+That's similar to how d-i's live-installer works, but simpler, since
+with propellor there's a short list of all the properties that the
+installer has, and propellor knows if a property can be reverted or not.
+
+Today's work was sponsored by Riku Voipio.

link to better blog post
diff --git a/devblog/high_bandwidth_propellor_hacking.mdwn b/devblog/high_bandwidth_propellor_hacking.mdwn
index 7732336..9df8bf7 100644
--- a/devblog/high_bandwidth_propellor_hacking.mdwn
+++ b/devblog/high_bandwidth_propellor_hacking.mdwn
@@ -44,7 +44,7 @@ propellor stuff from home all day, for the first time!
 Up until now, all propellor features involving disk images were
 either tested remotely, or developed while I was away from home.
 It's a cloudy, rainy day; the 
-[[solar_upgrade|blog/entry/DIY_solar_upgrade_complete-ish]]
+[[solar_upgrade|blog/entry/DIY_professional_grade_solar_panel_installation]]
 and [[satellite_internet|blog/entry/end_of_an_era]] paid off.
 
 ----

rename
diff --git a/devblog/high_bandwidth_propellor_hacking.mdwn b/devblog/high_bandwidth_propellor_hacking.mdwn
new file mode 100644
index 0000000..7732336
--- /dev/null
+++ b/devblog/high_bandwidth_propellor_hacking.mdwn
@@ -0,0 +1,52 @@
+Doing a bunch of work on propellor this week. Some bug fixes and
+improvements to disk image building. Also some properties involving the
+XFCE desktop environment.
+
+Putting it all together, I have 28 lines of propellor config file that
+generates a disk image that boots to a XFCE desktop and also
+has propellor installed. I wonder where it will go from here? ;-)
+
+[[!format haskell """
+darkstar :: Host
+darkstar = host "darkstar.kitenet.net" $ props
+	...
+        & imageBuilt "/srv/propellor-disk.img"
+                (Chroot.hostChroot demo (Chroot.Debootstrapped mempty))
+                MSDOS (grubBooted PC)
+                [ partition EXT2 `mountedAt` "/boot"
+                        `setFlag` BootFlag
+                , partition EXT4 `mountedAt` "/"
+                        `mountOpt` errorReadonly
+                        `addFreeSpace` MegaBytes 256
+                , swapPartition (MegaBytes 256)
+                ]
+
+demo :: Host
+demo = host "demo" $ props
+        & osDebian Unstable X86_64
+        & Apt.installed ["linux-image-amd64"]
+        & bootstrappedFrom GitRepoOutsideChroot
+        & User.accountFor user
+        & root `User.hasInsecurePassword` "debian"
+        & user `User.hasInsecurePassword` "debian"
+        & XFCE.installedMin
+        & XFCE.networkManager
+        & XFCE.defaultPanelFor user File.OverwriteExisting
+        & LightDM.autoLogin user
+        & Apt.installed ["firefox"]
+  where
+        user = User "user"
+        root = User "root"
+"""]]
+
+Indcidentially, I have power and bandwidth to work on this kind of
+propellor stuff from home all day, for the first time! 
+Up until now, all propellor features involving disk images were
+either tested remotely, or developed while I was away from home.
+It's a cloudy, rainy day; the 
+[[solar_upgrade|blog/entry/DIY_solar_upgrade_complete-ish]]
+and [[satellite_internet|blog/entry/end_of_an_era]] paid off.
+
+----
+
+Today's work was sponsored by Riku Voipio.
diff --git a/devblog/propellor_hacking.mdwn b/devblog/propellor_hacking.mdwn
deleted file mode 100644
index 7732336..0000000
--- a/devblog/propellor_hacking.mdwn
+++ /dev/null
@@ -1,52 +0,0 @@
-Doing a bunch of work on propellor this week. Some bug fixes and
-improvements to disk image building. Also some properties involving the
-XFCE desktop environment.
-
-Putting it all together, I have 28 lines of propellor config file that
-generates a disk image that boots to a XFCE desktop and also
-has propellor installed. I wonder where it will go from here? ;-)
-
-[[!format haskell """
-darkstar :: Host
-darkstar = host "darkstar.kitenet.net" $ props
-	...
-        & imageBuilt "/srv/propellor-disk.img"
-                (Chroot.hostChroot demo (Chroot.Debootstrapped mempty))
-                MSDOS (grubBooted PC)
-                [ partition EXT2 `mountedAt` "/boot"
-                        `setFlag` BootFlag
-                , partition EXT4 `mountedAt` "/"
-                        `mountOpt` errorReadonly
-                        `addFreeSpace` MegaBytes 256
-                , swapPartition (MegaBytes 256)
-                ]
-
-demo :: Host
-demo = host "demo" $ props
-        & osDebian Unstable X86_64
-        & Apt.installed ["linux-image-amd64"]
-        & bootstrappedFrom GitRepoOutsideChroot
-        & User.accountFor user
-        & root `User.hasInsecurePassword` "debian"
-        & user `User.hasInsecurePassword` "debian"
-        & XFCE.installedMin
-        & XFCE.networkManager
-        & XFCE.defaultPanelFor user File.OverwriteExisting
-        & LightDM.autoLogin user
-        & Apt.installed ["firefox"]
-  where
-        user = User "user"
-        root = User "root"
-"""]]
-
-Indcidentially, I have power and bandwidth to work on this kind of
-propellor stuff from home all day, for the first time! 
-Up until now, all propellor features involving disk images were
-either tested remotely, or developed while I was away from home.
-It's a cloudy, rainy day; the 
-[[solar_upgrade|blog/entry/DIY_solar_upgrade_complete-ish]]
-and [[satellite_internet|blog/entry/end_of_an_era]] paid off.
-
-----
-
-Today's work was sponsored by Riku Voipio.

devblog
diff --git a/devblog/propellor_hacking.mdwn b/devblog/propellor_hacking.mdwn
new file mode 100644
index 0000000..7732336
--- /dev/null
+++ b/devblog/propellor_hacking.mdwn
@@ -0,0 +1,52 @@
+Doing a bunch of work on propellor this week. Some bug fixes and
+improvements to disk image building. Also some properties involving the
+XFCE desktop environment.
+
+Putting it all together, I have 28 lines of propellor config file that
+generates a disk image that boots to a XFCE desktop and also
+has propellor installed. I wonder where it will go from here? ;-)
+
+[[!format haskell """
+darkstar :: Host
+darkstar = host "darkstar.kitenet.net" $ props
+	...
+        & imageBuilt "/srv/propellor-disk.img"
+                (Chroot.hostChroot demo (Chroot.Debootstrapped mempty))
+                MSDOS (grubBooted PC)
+                [ partition EXT2 `mountedAt` "/boot"
+                        `setFlag` BootFlag
+                , partition EXT4 `mountedAt` "/"
+                        `mountOpt` errorReadonly
+                        `addFreeSpace` MegaBytes 256
+                , swapPartition (MegaBytes 256)
+                ]
+
+demo :: Host
+demo = host "demo" $ props
+        & osDebian Unstable X86_64
+        & Apt.installed ["linux-image-amd64"]
+        & bootstrappedFrom GitRepoOutsideChroot
+        & User.accountFor user
+        & root `User.hasInsecurePassword` "debian"
+        & user `User.hasInsecurePassword` "debian"
+        & XFCE.installedMin
+        & XFCE.networkManager
+        & XFCE.defaultPanelFor user File.OverwriteExisting
+        & LightDM.autoLogin user
+        & Apt.installed ["firefox"]
+  where
+        user = User "user"
+        root = User "root"
+"""]]
+
+Indcidentially, I have power and bandwidth to work on this kind of
+propellor stuff from home all day, for the first time! 
+Up until now, all propellor features involving disk images were
+either tested remotely, or developed while I was away from home.
+It's a cloudy, rainy day; the 
+[[solar_upgrade|blog/entry/DIY_solar_upgrade_complete-ish]]
+and [[satellite_internet|blog/entry/end_of_an_era]] paid off.
+
+----
+
+Today's work was sponsored by Riku Voipio.

Added a comment: Nice Work
diff --git a/blog/entry/12_to_24_volt_house_conversion/comment_1_0a33f98564ffab61375d25b98e1c28a8._comment b/blog/entry/12_to_24_volt_house_conversion/comment_1_0a33f98564ffab61375d25b98e1c28a8._comment
new file mode 100644
index 0000000..d492332
--- /dev/null
+++ b/blog/entry/12_to_24_volt_house_conversion/comment_1_0a33f98564ffab61375d25b98e1c28a8._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="A.Steinel@03364ce01487b6885ca91d9dad3c972f961e61a6"
+ nickname="A.Steinel"
+ avatar="http://cdn.libravatar.org/avatar/762306680c167ef96cb280f4fade89a2"
+ subject="Nice Work"
+ date="2017-06-29T20:18:52Z"
+ content="""
+Hi Joey,
+
+I read your blog for a few month now and it is great to see what you accomplished with your cabin.  Keep expanding and blogging about it.
+
+Greetings from Germany,
+Andreas
+"""]]

format
diff --git a/blog/entry/12_to_24_volt_house_conversion.mdwn b/blog/entry/12_to_24_volt_house_conversion.mdwn
index b0bdfcb..8829a99 100644
--- a/blog/entry/12_to_24_volt_house_conversion.mdwn
+++ b/blog/entry/12_to_24_volt_house_conversion.mdwn
@@ -9,7 +9,7 @@ I did not find a lot of references online for converting a whole house's
 voltage from 12V to 24V.
 
 To prepare, I first checked that all the fuses and breakers were rated for
-> 24 volts. (Actually, > 30 volts because it will be 26 volts or so when
+&gt; 24 volts. (Actually, &gt; 30 volts because it will be 26 volts or so when
 charging.) Also, I checked for any shady wiring, and verified that all the
 wires I could see in the attic and wiring closet were reasonably sized
 (10AWG) and in good shape.

blog update
diff --git a/blog/entry/12_to_24_volt_house_conversion.mdwn b/blog/entry/12_to_24_volt_house_conversion.mdwn
new file mode 100644
index 0000000..b0bdfcb
--- /dev/null
+++ b/blog/entry/12_to_24_volt_house_conversion.mdwn
@@ -0,0 +1,75 @@
+Upgrading my solar panels involved switching the house from 12 volts to 24
+volts. No reasonably priced charge controllers can handle 1 KW of PV at 12
+volts.
+
+There might not be a lot of people who need to do this; entirely 12 volt
+offgrid houses are not super common, and most upgrades these days probably
+involve rooftop microinverters and so would involve a switch from DC to AC.
+I did not find a lot of references online for converting a whole house's
+voltage from 12V to 24V.
+
+To prepare, I first checked that all the fuses and breakers were rated for
+> 24 volts. (Actually, > 30 volts because it will be 26 volts or so when
+charging.) Also, I checked for any shady wiring, and verified that all the
+wires I could see in the attic and wiring closet were reasonably sized
+(10AWG) and in good shape.
+
+Then I:
+
+1. Turned off every light, unplugged every plug, 
+   pulled every fuse and flipped every breaker.
+2. Rewired the battery bank from 12V to 24V.
+3. Connected the battery bank to the new charge controller.
+4. Engaged the main breaker, and waited for anything strange.
+5. Screwed in one fuse at a time.
+
+## lighting
+
+The house used all fluorescent lights, and they have ballasts rated for
+only 12V. While they work at 24V, they might blow out sooner or overheat.
+In fact one died this evening, and while it was flickering before, I
+suspect the 24V did it in. It makes sense to replace them with more
+efficient LED lights anyway. I found some 12-24V DC LED lights for regular
+screw-in (edison) light fixtures. Does not seem very common; Amazon only
+had a few models and they shipped from China.
+
+Also, I ordered a 15 foot long, 300 LED strip light, which runs on 24V DC
+and has an adhesive backing. Great stuff -- it can be cut to different
+lengths and stuck anywhere. I installed some underneath the cook stove hood
+and the kitchen cabinets, which didn't have lights before.
+
+Similar LED strips are used in some desktop lamps. My lamp 
+was 12V only (barely lit at 24V), but I was able to replace its LED
+strip, upgrading it to 24V and three times as bright.
+
+(Christmas lights are another option; many LED christmas lights run on
+24V.)
+
+## appliances
+
+My Lenovo laptop's power supply that I use in the house is a vehicle DC-DC
+converter, and is rated for 12-24V. It seems to be running fine at 26V,
+did not get warm even when charging the laptop up from empty.
+
+I'm using buck converters to run various USB powered 
+(5V) ARM boxes such as my sheevaplug. They're quarter sized, so fit
+anywhere, and are very efficient.
+
+My satellite internet receiver is running with a large buck converter,
+feeding 12V to an inverter, feeding to a 30V DC power supply. That triple
+conversion is inneficient, but it works for now.
+
+The ceiling fan runs on 24V, and does not seem to run much faster than on
+12V. It may be rated for 12-24V. Can't seem to find any info about it.
+
+The radio is a 12V car radio. I used a
+[LM317](https://en.wikipedia.org/wiki/LM317) to run it on 24V, to avoid
+the RF interference a buck converter would have produced. This is a very
+inneficient conversion; half of the power is wasted as heat. But
+since I can stream internet radio all day now via satellite,
+I'll not use the FM radio very often.
+
+Fridge... still running on propane for now, but I have an idea for a way to
+build a cold storage battery that will use excess power from the PV array,
+and keep a fridge at a constant 34 degrees F. Next home improvement project
+in the queue.

blog update
diff --git a/blog/entry/DIY_solar_upgrade_complete-ish.mdwn b/blog/entry/DIY_solar_upgrade_complete-ish.mdwn
new file mode 100644
index 0000000..5ab84cb
--- /dev/null
+++ b/blog/entry/DIY_solar_upgrade_complete-ish.mdwn
@@ -0,0 +1,14 @@
+Success! I received the Tracer4215BN charge controller where UPS
+accidentially-on-purpose delivered it to a neighbor, and got it connected
+up, and the battery bank rewired to 24V in a couple hours.
+
+[[!img pics/solar_upgrade/chargecontroller.jpg alt="charge controller
+reading 66.1V at 3.4 amps on panels, charging battery at 29.0V at 7.6A"]]
+
+Here it's charging the batteries at 220 watts, and that picture was taken
+at 5 pm, when the light hits the panels at nearly a 90 degree angle.
+Compare with the old panels, where the maximum I ever recorded at high noon
+was 90 watts. I've made more power since 4:30 pm than I used to be able to
+make in a day! \o/
+
+[[!tag solar DIY]]
diff --git a/blog/pics/solar_upgrade/chargecontroller.jpg b/blog/pics/solar_upgrade/chargecontroller.jpg
new file mode 100644
index 0000000..3d71d29
Binary files /dev/null and b/blog/pics/solar_upgrade/chargecontroller.jpg differ

Added a comment: How will this change things for you?
diff --git a/blog/entry/PV_array_is_hot/comment_1_682cf477f9b03b898983f6a2db63abdb._comment b/blog/entry/PV_array_is_hot/comment_1_682cf477f9b03b898983f6a2db63abdb._comment
new file mode 100644
index 0000000..965ab36
--- /dev/null
+++ b/blog/entry/PV_array_is_hot/comment_1_682cf477f9b03b898983f6a2db63abdb._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="danny@0634b3dbfcf01f496a662052eda825ecce9a9a5d"
+ nickname="danny"
+ avatar="http://cdn.libravatar.org/avatar/6695befc063187009fce565f64ef88b2"
+ subject="How will this change things for you?"
+ date="2017-06-26T06:46:10Z"
+ content="""
+Congratulations! I'm interested in what all this new power will transform (no pun intended) your work and life habits!
+"""]]

correction
diff --git a/blog/entry/PV_array_is_hot.mdwn b/blog/entry/PV_array_is_hot.mdwn
index e3350b5..65458fb 100644
--- a/blog/entry/PV_array_is_hot.mdwn
+++ b/blog/entry/PV_array_is_hot.mdwn
@@ -7,9 +7,12 @@ than what I'm used to.
 
 [[!img pics/solar_upgrade/combinerwiring.jpg alt="PV combiner box wiring"]]
 
-And the new PV array is hot! This should read close to 112 V at solar noon;
-so for 4 pm, 66.8 V seems reasonable.
+And the new PV array is hot!
 
 [[!img pics/solar_upgrade/pvhot.jpg alt="multimeter reading 66.8 DVC"]]
 
+Update: The panels have an open circuit voltage of 35.89 and are in strings
+of 2, so I'd expect to see 71.78 V with only my multimeter connected. So
+I'm losing 0.07 volts to wiring, which is less than I designed for.
+
 [[!tag DIY solar]]

blog update
diff --git a/blog/entry/PV_array_is_hot.mdwn b/blog/entry/PV_array_is_hot.mdwn
new file mode 100644
index 0000000..e3350b5
--- /dev/null
+++ b/blog/entry/PV_array_is_hot.mdwn
@@ -0,0 +1,15 @@
+Only took a couple hours to wire up and mount the combiner box.
+
+[[!img pics/solar_upgrade/combinerbox.jpg alt="PV combiner box with breakers"]]
+
+Something about larger wiring like this is enjoyable. So much less fiddly
+than what I'm used to.
+
+[[!img pics/solar_upgrade/combinerwiring.jpg alt="PV combiner box wiring"]]
+
+And the new PV array is hot! This should read close to 112 V at solar noon;
+so for 4 pm, 66.8 V seems reasonable.
+
+[[!img pics/solar_upgrade/pvhot.jpg alt="multimeter reading 66.8 DVC"]]
+
+[[!tag DIY solar]]
diff --git a/blog/entry/advogato/advogato_20-2000-04-11-00-00/comment_1_bbd9e146d640f0fc8ac26259ea957c7c._comment b/blog/entry/advogato/advogato_20-2000-04-11-00-00/comment_1_bbd9e146d640f0fc8ac26259ea957c7c._comment
deleted file mode 100644
index 052f316..0000000
--- a/blog/entry/advogato/advogato_20-2000-04-11-00-00/comment_1_bbd9e146d640f0fc8ac26259ea957c7c._comment
+++ /dev/null
@@ -1,8 +0,0 @@
-[[!comment format=mdwn
- username="https://www.google.com/accounts/o8/id?id=AItOawnF6mfrWFMdvdSEJFcmYpl2sxVJnF0-qbE"
- nickname="Ravi"
- subject="wishom teeth pain"
- date="2011-08-17T18:56:13Z"
- content="""
-wisdom teeth give many problem if it doesnt comes out properly. so it is better to removal of <a href=\"http://ewisdomteethpain.com/\">wisdom teeth</a>. there is a little surgery that will be done with in 2 hours.
-"""]]
diff --git a/blog/pics/solar_upgrade/combinerbox.jpg b/blog/pics/solar_upgrade/combinerbox.jpg
new file mode 100644
index 0000000..295d7d0
Binary files /dev/null and b/blog/pics/solar_upgrade/combinerbox.jpg differ
diff --git a/blog/pics/solar_upgrade/combinerwiring.jpg b/blog/pics/solar_upgrade/combinerwiring.jpg
new file mode 100644
index 0000000..361cc53
Binary files /dev/null and b/blog/pics/solar_upgrade/combinerwiring.jpg differ
diff --git a/blog/pics/solar_upgrade/pvhot.jpg b/blog/pics/solar_upgrade/pvhot.jpg
new file mode 100644
index 0000000..11cba45
Binary files /dev/null and b/blog/pics/solar_upgrade/pvhot.jpg differ

blog update
diff --git a/blog/entry/DIY_professional_grade_solar_panel_installation.mdwn b/blog/entry/DIY_professional_grade_solar_panel_installation.mdwn
new file mode 100644
index 0000000..08494ac
--- /dev/null
+++ b/blog/entry/DIY_professional_grade_solar_panel_installation.mdwn
@@ -0,0 +1,78 @@
+I've installed 1 kilowatt of solar panels on my roof, using professional
+grade eqipment. The four panels are Astronergy 260 watt panels, and they're
+mounted on IronRidge XR100 rails. Did it all myself, without help.
+
+[[!img pics/solar_upgrade/housepanels.jpg alt="house with 4 solar panels on roof"]]
+
+I had three goals for this install:
+
+1. Cheap but sturdy. Total cost will be under $2500. It would probably cost
+   at least twice as much to get a professional install, and the pros might
+   not even want to do such a small install.
+2. Learn the roof mount system. I want to be able to add more panels, remove
+   panels when working on the roof, and understand everything.
+3. Make every day a sunny day. With my current solar panels, I get around
+   10x as much power on a sunny day as a cloudy day, and I have plenty of
+   power on sunny days. So 10x the PV capacity should be a good amount of
+   power all the time.
+
+My main concerns were, would I be able to find the rafters when installing
+the rails, and would the 5x3 foot panels be too unweildly to get up on the
+roof by myself.
+
+I was able to find the rafters, without needing a stud finder, after I
+removed the roof's vent caps, which exposed the rafters. The shingles were
+on straight enough that I could follow the lines down and drilled into the
+rafter on the first try every time. And I got the rails on spaced well and
+straight, although I could have spaced the FlashFeet out better (oops).
+
+My drill ran out of juice half-way, and I had to hack it to recharge on
+solar power, but that's another story. Between the learning curve, a lot of
+careful measurement, not the greatest shoes for roofing, and waiting for
+recharging, it took two days to get the 8 FlashFeet installed and the rails
+mounted.
+
+Taking a break from that and swimming in the river, I realized I should
+have been wearing my water shoes on the roof all along. Super soft and
+nubbly, they make me feel like a gecko up there! After recovering from an
+(unrelated) achilles tendon strain, I got the panels installed today.
+
+Turns out they're not hard to handle on the roof by myself. Getting them up
+a ladder to the roof by yourself would normally be another story, but my
+house has a 2 foot step up from the back retaining wall to the roof, and
+even has a handy grip beam as you step up.
+
+[[!img pics/solar_upgrade/stepup.jpg alt="roof next to the ground with a couple of cinderblock steps"]]
+
+The last gotcha, which I luckily anticipated, is that panels will slide
+down off the rails before you can get them bolted down. This is where a
+second pair of hands would have been most useful. But, I macguyvered a
+solution, attaching temporary clamps before bringing a panel up, that
+stopped it sliding down while I was attaching it.
+
+[[!img pics/solar_upgrade/clamp.jpg alt="clamp temporarily attached to side of panel"]]
+
+I also finished the outside wiring today. Including the one hack of this
+install so far. Since the local hardware store didn't have a suitable
+conduit to bring the cables off the roof, I cobbled one together from pipe,
+with foam inserts to prevent chafing.
+
+[[!img pics/solar_upgrade/conduit.jpg alt="some pipe with 5 wires running
+through it, attached to the side of the roof"]]
+
+While I have 1 kilowatt of power on my roof now, I won't be able to use it
+until next week. After ordering the upgrade, I realized that my old PWM
+charge controller would be able to handle less than half the power, and to
+get even that I would have needed to mount the fuse box near the top of the
+roof and run down a large and expensive low-voltage high-amperage cable,
+around OO AWG size. Instead, I'll be upgrading to a MPPT controller, and
+running a single 150 volt cable to it.
+
+Then, since the MPPT controller can only handle 1 kilowatt when it's
+converting to 24 volts, not 12 volts, I'm gonna have to convert the
+entire house over from 12V DC to 24V DC, including changing all the light
+fixtures and rewiring the battery bank...
+
+[[!img pics/solar_upgrade/panelsside.jpg]]
+
+[[!tag solar diy]]

add
diff --git a/blog/pics/solar_upgrade/clamp.jpg b/blog/pics/solar_upgrade/clamp.jpg
new file mode 100644
index 0000000..c3f98d7
Binary files /dev/null and b/blog/pics/solar_upgrade/clamp.jpg differ
diff --git a/blog/pics/solar_upgrade/conduit.jpg b/blog/pics/solar_upgrade/conduit.jpg
new file mode 100644
index 0000000..04bc14a
Binary files /dev/null and b/blog/pics/solar_upgrade/conduit.jpg differ
diff --git a/blog/pics/solar_upgrade/housepanels.jpg b/blog/pics/solar_upgrade/housepanels.jpg
new file mode 100644
index 0000000..e312525
Binary files /dev/null and b/blog/pics/solar_upgrade/housepanels.jpg differ
diff --git a/blog/pics/solar_upgrade/panelsside.jpg b/blog/pics/solar_upgrade/panelsside.jpg
new file mode 100644
index 0000000..33c7292
Binary files /dev/null and b/blog/pics/solar_upgrade/panelsside.jpg differ
diff --git a/blog/pics/solar_upgrade/stepup.jpg b/blog/pics/solar_upgrade/stepup.jpg
new file mode 100644
index 0000000..99813ce
Binary files /dev/null and b/blog/pics/solar_upgrade/stepup.jpg differ

alt
diff --git a/blog/entry/not_tabletop_solar.mdwn b/blog/entry/not_tabletop_solar.mdwn
index 78e4f04..52890d0 100644
--- a/blog/entry/not_tabletop_solar.mdwn
+++ b/blog/entry/not_tabletop_solar.mdwn
@@ -1,4 +1,4 @@
 Borrowed a pickup truck today to fetch my new solar panels. This is 1
 kilowatt of power on my picnic table.
 
-[[!img pics/solarpanelstable.jpg caption="solar panels on picnic table"]]
+[[!img pics/solarpanelstable.jpg alt="solar panels on picnic table"]]

link
diff --git a/blog/entry/not_tabletop_solar.mdwn b/blog/entry/not_tabletop_solar.mdwn
index 6fae30a..78e4f04 100644
--- a/blog/entry/not_tabletop_solar.mdwn
+++ b/blog/entry/not_tabletop_solar.mdwn
@@ -1,4 +1,4 @@
 Borrowed a pickup truck today to fetch my new solar panels. This is 1
 kilowatt of power on my picnic table.
 
-[[!img solarpanelstable.jpg caption="solar panels on picnic table"]]
+[[!img pics/solarpanelstable.jpg caption="solar panels on picnic table"]]

blog update
diff --git a/blog/entry/not_tabletop_solar.mdwn b/blog/entry/not_tabletop_solar.mdwn
new file mode 100644
index 0000000..6fae30a
--- /dev/null
+++ b/blog/entry/not_tabletop_solar.mdwn
@@ -0,0 +1,4 @@
+Borrowed a pickup truck today to fetch my new solar panels. This is 1
+kilowatt of power on my picnic table.
+
+[[!img solarpanelstable.jpg caption="solar panels on picnic table"]]
diff --git a/blog/pics/solarpanelstable.jpg b/blog/pics/solarpanelstable.jpg
new file mode 100644
index 0000000..e253ee6
Binary files /dev/null and b/blog/pics/solarpanelstable.jpg differ

hmm
diff --git a/devblog/prototype_gamified_interface.mdwn b/devblog/prototype_gamified_interface.mdwn
index a6ec5f7..19d83e2 100644
--- a/devblog/prototype_gamified_interface.mdwn
+++ b/devblog/prototype_gamified_interface.mdwn
@@ -6,9 +6,10 @@ What is this strange thing? It's a prototype, thrown together with
 open clip art in a long weekend. It's an exploration how far an interface
 can diverge from the traditional and still work. And it's a mini-game.
 
-Watch the video, and at the end, try to anwser these questions:
+Watch the video, and at the end, try to answer these questions:
 
-What will you do then? What happens next?
+* What will you do then?
+* What happens next?
 
 Spoilers below...
 

hmm
diff --git a/devblog/prototype_gamified_interface.mdwn b/devblog/prototype_gamified_interface.mdwn
index 71ef759..a6ec5f7 100644
--- a/devblog/prototype_gamified_interface.mdwn
+++ b/devblog/prototype_gamified_interface.mdwn
@@ -6,8 +6,7 @@ What is this strange thing? It's a prototype, thrown together with
 open clip art in a long weekend. It's an exploration how far an interface
 can diverge from the traditional and still work. And it's a mini-game.
 
-As the user interacts with the game, the clutter of objects get knocked off
-the tree, and fall offscreen.
+Watch the video, and at the end, try to anwser these questions:
 
 What will you do then? What happens next?
 

hmm
diff --git a/devblog/prototype_gamified_interface.mdwn b/devblog/prototype_gamified_interface.mdwn
index 8b7d80c..71ef759 100644
--- a/devblog/prototype_gamified_interface.mdwn
+++ b/devblog/prototype_gamified_interface.mdwn
@@ -9,10 +9,12 @@ can diverge from the traditional and still work. And it's a mini-game.
 As the user interacts with the game, the clutter of objects get knocked off
 the tree, and fall offscreen.
 
-What will you do then? What happens next? [[!img middle.png]]
+What will you do then? What happens next?
 
 Spoilers below...
 
+[[!img middle.png]]
+
 What I hope you might have answered to those questions, after watching the
 video, is something like this:
 

hmm
diff --git a/devblog/prototype_gamified_interface.mdwn b/devblog/prototype_gamified_interface.mdwn
index e2e7708..8b7d80c 100644
--- a/devblog/prototype_gamified_interface.mdwn
+++ b/devblog/prototype_gamified_interface.mdwn
@@ -7,18 +7,12 @@ open clip art in a long weekend. It's an exploration how far an interface
 can diverge from the traditional and still work. And it's a mini-game.
 
 As the user interacts with the game, the clutter of objects get knocked off
-the tree, and fall offscreen. Leaving eventually this:
+the tree, and fall offscreen.
 
-[[!img middle.png]]
-
-What will you do then? What happens next?
+What will you do then? What happens next? [[!img middle.png]]
 
 Spoilers below...
 
-<div height=200></div>
-
-[[!img middle.png]]
-
 What I hope you might have answered to those questions, after watching the
 video, is something like this:
 

hmm
diff --git a/devblog/prototype_gamified_interface.mdwn b/devblog/prototype_gamified_interface.mdwn
index 763f6ce..e2e7708 100644
--- a/devblog/prototype_gamified_interface.mdwn
+++ b/devblog/prototype_gamified_interface.mdwn
@@ -9,72 +9,13 @@ can diverge from the traditional and still work. And it's a mini-game.
 As the user interacts with the game, the clutter of objects get knocked off
 the tree, and fall offscreen. Leaving eventually this:
 
+[[!img middle.png]]
+
 What will you do then? What happens next?
 
 Spoilers below...
 
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
-<p>
+<div height=200></div>
 
 [[!img middle.png]]
 

use webm not mp4
diff --git a/devblog/prototype_gamified_interface.mdwn b/devblog/prototype_gamified_interface.mdwn
index 361aae9..763f6ce 100644
--- a/devblog/prototype_gamified_interface.mdwn
+++ b/devblog/prototype_gamified_interface.mdwn
@@ -1,6 +1,6 @@
 And now for something completely different..
 
-<video controls src="https://downloads.kitenet.net/videos/prototype_gamified_interface.mp4" poster="https://joeyh.name/devblog/prototype_gamified_interface/start.png"></video>
+<video controls src="https://downloads.kitenet.net/videos/prototype_gamified_interface.webm" poster="https://joeyh.name/devblog/prototype_gamified_interface/start.png"></video>
 
 What is this strange thing? It's a prototype, thrown together with
 open clip art in a long weekend. It's an exploration how far an interface

devblog
diff --git a/devblog/prototype_gamified_interface.mdwn b/devblog/prototype_gamified_interface.mdwn
new file mode 100644
index 0000000..361aae9
--- /dev/null
+++ b/devblog/prototype_gamified_interface.mdwn
@@ -0,0 +1,139 @@
+And now for something completely different..
+
+<video controls src="https://downloads.kitenet.net/videos/prototype_gamified_interface.mp4" poster="https://joeyh.name/devblog/prototype_gamified_interface/start.png"></video>
+
+What is this strange thing? It's a prototype, thrown together with
+open clip art in a long weekend. It's an exploration how far an interface
+can diverge from the traditional and still work. And it's a mini-game.
+
+As the user interacts with the game, the clutter of objects get knocked off
+the tree, and fall offscreen. Leaving eventually this:
+
+What will you do then? What happens next?
+
+Spoilers below...
+
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+<p>
+
+[[!img middle.png]]
+
+What I hope you might have answered to those questions, after watching the
+video, is something like this:
+
+* What will you do then?  
+  I'll move the egg into the brain-tree.  
+* What happens next?  
+  It will throw away the junk I had installed and replace it with what's in the egg.
+
+The interface I'm diverging from is this kind of thing:
+
+<img src="https://imgs.xkcd.com/comics/permanence.png">
+
+My key design points are these:
+
+* **Avoid words entirely**  
+
+  One of my takeaways from the Debian installer project is that it's
+  important to make the interface support non-English users, but
+  maintaining translations massively slows down development. 
+  I want an interface that can be quickly iterated on or thrown away.
+  
+* **Massively simplify**
+
+  In the Debian installer, we never managed to get rid of as many questions
+  as we wanted to. I'm starting from the other end, and only putting in the
+  absolute most essential questions.
+
+  1. Do you want to delete everything that is on this computer?
+  2. What's the hostname?
+  3. What account to make?
+  4. What password to use?
+  
+  I hope to stop at the first that I've implemented so far. It should be
+  possible to make the hostname easy to change after installation, and for an
+  end user installation, the username doesh't matter much, and the password
+  generally adds little or no security (and desktop environments should make
+  it easy to add a password later).
+
+* **Don't target all the users**
+
+  Trying to target all users constrained the Debian installer in weird ways 
+  while complicating it massively.
+
+  This if not for installing a server or an embedded system.
+  This interface is targeting end users who want a working desktop system 
+  with minimum fuss, and are capable of seeing and dragging.
+  There can be other interfaces for other users.
+
+* **Make it fun**  
+
+  Fun to use, and also fun to develop.
+
+  I'm using [threepenny-gui](http://hackage.haskell.org/package/threepenny-gui)
+  to build the insterface. This lets [Haskell code be written that directly
+  manipulates the web browser's DOM](https://git.joeyh.name/index.cgi/secret-project.git/tree/test.hs).
+  I'm having a lot of fun with that and can already think of other projects
+  I can use threepenny-gui with!
+
+Previously: [[blog/entry/propellor_is_d-i_2.0]]
diff --git a/devblog/prototype_gamified_interface/middle.png b/devblog/prototype_gamified_interface/middle.png
new file mode 100644
index 0000000..359c609
Binary files /dev/null and b/devblog/prototype_gamified_interface/middle.png differ
diff --git a/devblog/prototype_gamified_interface/start.png b/devblog/prototype_gamified_interface/start.png
new file mode 100644
index 0000000..c9802ca
Binary files /dev/null and b/devblog/prototype_gamified_interface/start.png differ

devblog
diff --git a/devblog/debug_me_keyrings.mdwn b/devblog/debug_me_keyrings.mdwn
new file mode 100644
index 0000000..1b9aabc
--- /dev/null
+++ b/devblog/debug_me_keyrings.mdwn
@@ -0,0 +1,19 @@
+Releasing debug-me 1.20170520 today with a major improvement.
+
+Now it will look for the gpg key of the developer in keyring
+files in `/usr/share/debug-me/keyring/`, and tell the user which project(s)
+the developer is known to be a member of. So, for example, Debian
+developers who connect to debug-me sessions of Debian users will be
+identified as a Debian developer. And when I connect to a debug-me user's
+session, debug-me will tell them that I'm the developer of debug-me.
+
+This should help the user decide when to trust a developer to connect to
+their debug-me session. If they develop software that you're using, you
+already necessarily trust them and letting them debug your machine is not 
+a stretch, as long as it's securely logged. 
+
+Thanks to Sean Whitton for the idea of checking the Debian keyring, which
+I've generalized to this.
+
+Also, debug-me is now just an apt-get away for Debian unstable users,
+and I think it may end up in the next Debian release.

format
diff --git a/blog/entry/announcing_debug-me.mdwn b/blog/entry/announcing_debug-me.mdwn
index 6e3dd6b..c982da0 100644
--- a/blog/entry/announcing_debug-me.mdwn
+++ b/blog/entry/announcing_debug-me.mdwn
@@ -1,17 +1,15 @@
 Today I'm excited to release [debug-me](https://debug-me.branchable.com/),
 a program for secure remote debugging.
 
-<blockquote>
-Debugging a problem over email/irc/BTS is slow, tedious, and hard. The developer
-needs to see your problem to understand it. Debug-me aims to make debugging
-fast, fun, and easy, by letting the developer access your computer remotely,
-so they can immediately see and interact with the problem. Making your
-problem their problem gets it fixed fast.
-
-debug-me session is logged and signed with the developer's GnuPG
-key, producing a chain of evidence of what they saw and what they did.
-So the developer's good reputation is leveraged to make debug-me secure.
-</blockquote>
+> Debugging a problem over email/irc/BTS is slow, tedious, and hard. The developer
+> needs to see your problem to understand it. Debug-me aims to make debugging
+> fast, fun, and easy, by letting the developer access your computer remotely,
+> so they can immediately see and interact with the problem. Making your
+> problem their problem gets it fixed fast.
+> 
+> debug-me session is logged and signed with the developer's GnuPG
+> key, producing a chain of evidence of what they saw and what they did.
+> So the developer's good reputation is leveraged to make debug-me secure.
 
 I've recorded a [short screencast demoing debug-me](https://downloads.kitenet.net/videos/debug-me/debug-me-demo.webm).
 

devblog
diff --git a/blog/entry/announcing_debug-me.mdwn b/blog/entry/announcing_debug-me.mdwn
new file mode 100644
index 0000000..6e3dd6b
--- /dev/null
+++ b/blog/entry/announcing_debug-me.mdwn
@@ -0,0 +1,40 @@
+Today I'm excited to release [debug-me](https://debug-me.branchable.com/),
+a program for secure remote debugging.
+
+<blockquote>
+Debugging a problem over email/irc/BTS is slow, tedious, and hard. The developer
+needs to see your problem to understand it. Debug-me aims to make debugging
+fast, fun, and easy, by letting the developer access your computer remotely,
+so they can immediately see and interact with the problem. Making your
+problem their problem gets it fixed fast.
+
+debug-me session is logged and signed with the developer's GnuPG
+key, producing a chain of evidence of what they saw and what they did.
+So the developer's good reputation is leveraged to make debug-me secure.
+</blockquote>
+
+I've recorded a [short screencast demoing debug-me](https://downloads.kitenet.net/videos/debug-me/debug-me-demo.webm).
+
+<video controls width=400 title="debug-me demo" src="https://downloads.kitenet.net/videos/debug-me/debug-me-demo.webm"></video>
+
+And here's a [screencast about debug-me's chain of evidence](https://downloads.kitenet.net/videos/debug-me/debug-me-logs.webm).
+
+<video controls width=400 title="debug-me logs" src="https://downloads.kitenet.net/videos/debug-me/debug-me-logs.webm"></video>
+
+The idea for debug-me came from [[Re:_Debugging_over_email]], and then my
+[Patreon](https://www.patreon.com/joeyh) supporters picked debug-me in a
+poll as a project I should work on. It's been a fun month, designing the
+evidence chain, building a custom efficient protocol with space saving
+hacks, using websockets and protocol buffers and ed25519 for the first
+time, and messing around with low-level tty details. The details of
+debug-me's development are in my [[devblog]].
+
+Anyway, I hope debug-me makes debugging less of a tedious back and forth,
+at least some of the time.
+
+PS: Since debug-me's protocol lets multiple people view the same shell
+session, and optionally interact with it, there could be uses for it beyond
+debugging, including live screencasting, pair programming, etc.
+
+PPS: There needs to be a debug-me server not run by me, so someone
+please [run one](https://debug-me.branchable.com/servers/)..
diff --git a/devblog/debug_me_released.mdwn b/devblog/debug_me_released.mdwn
new file mode 100644
index 0000000..af34c17
--- /dev/null
+++ b/devblog/debug_me_released.mdwn
@@ -0,0 +1,15 @@
+debug-me is released! <https://debug-me.branchable.com/>
+
+I made one last protocol compatability breaking change before the release.
+Realized that while the websocket framing protocol has a version number,
+the higher-level protocol does not, which would made extending it very hard
+later. So, added in a protocol verison number.
+
+The release includes a tarball that should let debug-me run on most linux
+systems. I adapted the code from git-annex for
+[[blog/entry/completely_linux_distribution-independent_packaging]]. That
+added 300 lines of code to debug-me's source tree, which is suboptimal. But
+all the options in the Linux app packaging space are suboptimal. Flatpak
+and snappy would both be ok -- if the other one didn't exist and they
+were were installed everywhere. Appimage needs the program to be built against
+an older version of libraries.

devblog
diff --git a/devblog/debug_me_screencast_recording_and_server.mdwn b/devblog/debug_me_screencast_recording_and_server.mdwn
new file mode 100644
index 0000000..3c2d45b
--- /dev/null
+++ b/devblog/debug_me_screencast_recording_and_server.mdwn
@@ -0,0 +1,31 @@
+Recorded a 7 minute screencast demoing debug-me, and another 3 minute
+screencast talking about its log files. That took around 5 hours of work
+actually, between finding a screencast program that works well (I used
+kazam), writing the "script", and setting the scenes for the user and
+developer desktops shown in the screencast.
+
+While recording, I found a bug in debug-me. The gpg key was not available
+when it tried to verify it. I thought that I had seen gpg --verify
+--keyserver download a key from a keyserver and use it to verify but seems
+I was mistaken. So I changed the debug-me protocol to include the gpg
+public key, so it does not need to rely on accessing a keyserver.
+
+Also deployed a debug-me server, <http://debug-me.joeyh.name:8081/>. It's
+not ideal for me to be running the debug-me server, because when me and a
+user are using that server with debug-me, I could use my control of the
+server to prevent the debug-me log being emailed to them, and also delete
+their local copy of the log. 
+
+I have a plan to 
+<https://debug-me.branchable.com/todo/send_to_multiple_servers/>
+that will avoid that problem but it needs a debug-me server run by someone
+else. Perhaps that will happen once I release debug-me; for now the single
+debug-me server will have to do.
+
+Finally, made `debug-me --verify log` check all the signatures and hashes
+in the log file, and display the gpg keys of the participants in the
+debug-me session.
+
+Today's work was sponsored by Jake Vosloo on Patreon.
+
+(Also, Sean Whitton has stepped up to get debug-me into Debian!)

correct spelling mistakes
diff --git a/devblog/debug_me_one_last_big_change.mdwn b/devblog/debug_me_one_last_big_change.mdwn
index c8f2fcc..51fa0c0 100644
--- a/devblog/debug_me_one_last_big_change.mdwn
+++ b/devblog/debug_me_one_last_big_change.mdwn
@@ -5,7 +5,7 @@ the order of two entered values could be ambiguous.
 And also, it makes for nicer graphs! In this one, I typed "qwertyuiop" with
 high network lag, and you can see that the "r" didn't echo
 back until "t" "y" "u" had been entered. Then the two
-divered states merged back together when "i" was entered
+diverged states merged back together when "i" was entered
 chaining back to the last seen "r" and last entered "u".
 
 [[debug-me.png]]
@@ -14,7 +14,7 @@ chaining back to the last seen "r" and last entered "u".
 [[debug_me_first_stage_complete]].)
 
 Having debug-me generate these graphs has turned out to be a very good
-idea. Makes analizing problems much easier.
+idea. Makes analyzing problems much easier.
 
 ----
 

update
diff --git a/devblog/debug_me_one_last_big_change.mdwn b/devblog/debug_me_one_last_big_change.mdwn
index 1a450ce..c8f2fcc 100644
--- a/devblog/debug_me_one_last_big_change.mdwn
+++ b/devblog/debug_me_one_last_big_change.mdwn
@@ -13,6 +13,9 @@ chaining back to the last seen "r" and last entered "u".
 (Compare with the graph of the same kind of activity back in
 [[debug_me_first_stage_complete]].)
 
+Having debug-me generate these graphs has turned out to be a very good
+idea. Makes analizing problems much easier.
+
 ----
 
 Also made `/quit` in the control window quit the debug-me session.

devblog
diff --git a/devblog/debug_me_one_last_big_change.mdwn b/devblog/debug_me_one_last_big_change.mdwn
new file mode 100644
index 0000000..1a450ce
--- /dev/null
+++ b/devblog/debug_me_one_last_big_change.mdwn
@@ -0,0 +1,28 @@
+Added an additional hash chain of entered values to the debug-me data
+types. This fixes the known problem with debug-me's proof chains, that
+the order of two entered values could be ambiguous.
+
+And also, it makes for nicer graphs! In this one, I typed "qwertyuiop" with
+high network lag, and you can see that the "r" didn't echo
+back until "t" "y" "u" had been entered. Then the two
+divered states merged back together when "i" was entered
+chaining back to the last seen "r" and last entered "u".
+
+[[debug-me.png]]
+
+(Compare with the graph of the same kind of activity back in
+[[debug_me_first_stage_complete]].)
+
+----
+
+Also made `/quit` in the control window quit the debug-me session.
+I want to also let the user pause and resume entry in the session, but
+it seems that could lead to more ambiguity problems in the proof chain,
+so I'll have to think that over carefully.
+
+debug-me seems ready for release now, except it needs some servers,
+and some packages, and a screencast showing how it works.
+
+----
+
+Today's work was sponsored by Trenton Cronholm on Patreon.

devblog
diff --git a/devblog/debug_me_one_last_big_change/debug-me.png b/devblog/debug_me_one_last_big_change/debug-me.png
new file mode 100644
index 0000000..0212a17
Binary files /dev/null and b/devblog/debug_me_one_last_big_change/debug-me.png differ

point to debug-me website
diff --git a/code.mdwn b/code.mdwn
index 2aa5ac7..104c3e3 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -6,6 +6,7 @@ occasionally basic websites about my software.
 The stuff that's swapped into my local cache at the moment.
 
 [[git-annex]]
+[[debug-me]]
 [[propellor]]
 [[keysafe]]
 [[concurrent-output]]
diff --git a/code/debug-me.mdwn b/code/debug-me.mdwn
index dbe9209..f448552 100644
--- a/code/debug-me.mdwn
+++ b/code/debug-me.mdwn
@@ -1,171 +1,7 @@
-A not yet implemented idea from [[blog/entry/Re:_Debugging_over_email]]:
+secure remote debugging with gpg signed proof chain.
 
-> I've noticed that once I am in a position to run some commands in the
-> environment that has the problem, it seems to be much easier to solve
-> it than when I'm trying to get the user to debug it remotely. This must
-> be partly psychological?
-> 
-> Partly, I think that the feeling of being at a remove from the system,
-> makes it harder to think of what to do. And then there are the times where
-> the user pastes some output of running some commands and I mentally skip
-> right over an important part of it. Because I didn't think to run one of
-> the commands myself.
+<https://debug-me.branchable.com>
 
-`debug-me` lets a developer access your shell remotely, to debug a problem,
-avoiding a tedious back-and-forth by email. When you start `debug-me`, it
-starts a shell, and generates an URL which you can give to the developer
-(or developers) to connect them to the session.
+Initial idea: [[blog/entry/Re:_Debugging_over_email]]  
 
-It's not normally a good idea to let someone run commands in a shell on
-your computer. To make this as safe as possible, `debug-me` uses the
-GPG web of trust. Everything the developer sends to `debug-me` is signed
-with their GPG key, in a way that produces a GPG signed proof of what the
-developer saw, and what they did in the `debug-me` session.
-If the developer does something Evil, you have the neccessary proof
-to adjust their reputation.
-
-### design
-
-#### client-server
-
-This needs to be client-server, because a end user's machine is probably
-buried behind NAT. 
-
-It should use HTTPS, because of stupid firewalls. Will need to
-use some form of long polling to get multiple messages promptly in
-both directions.
-
-The user's client picks which server to use, connects, and
-gets an URL, which developers' clients can connect to in order to enter
-the session. Sharing that URL should be the only way for anyone to view
-the session (other than the person running the HTTP server).
-
-Multiple clients can be connected, and all send inputs. The user's
-client will only accept inputs GPG signed with keys that the user
-has granted access.
-
-When a new client connects, the whole session is sent to it, so it
-gets caught up and can start adding inputs to the chain.
-
-Other clients can connect and only record the session. This allows a user
-to run `debug-me` on another computer, to record the developer activity proof
-there. This way a very Evil developer can't delete the user's only copy of
-the proof of their Evil.
-
-The server can also record the session. This doesn't help preserve proof 
-if the developer is running the server. But if there are multiple servers
-run by different people, the user's client could send the session to
-several of them to get it recorded.
-
-#### proof
-
-The developer activity proof takes the form of a chain of outputs and inputs.
-In other words, what the developer was shown, and what they did in response,
-and so on. Each input is GPG signed and includes the SHA256 hash of a
-previous output or input.
-
-A `debug-me` session starts by generating an initial output.
-Probably this is a shell prompt. (To prevent replay attacks
-of debug-me sessions it should also include a timestamp and/or a random token.)
-
-The developer enters a command, and their client hashes the last seen
-output and includes that in a GPG signed message with the command. The
-ouput of the command then arrives, and is hashed and included in the next
-GPG signed input message, and so on.
-
-There are two kinds of inputs: Synchronous and asynchronous.
-
-A synchronous input must include the hash of the output that it was made
-in response to, and will only be accepted by the user's client when that
-output is the last one that was sent. This way it's always clear what
-the state of the debug-me session was when the developer saw the output
-and entered a given input.
-
-An asynchronous input must include the hash of the previous input.
-Asynchronous inputs are only used for sending signals, eg ctrl-c, not for
-sending keystrokes. This allows interruption of a running command at any
-time, without needing to catch up to its most recent output. (Especially
-useful if a buggy program is printing out a lot of output.)
-
-It might seem like a good idea for a client to resend a rejected input,
-rebasing it on top of the new output. But, if a client did this, its user
-would have plausible deniability about what they intended that input to do.
-Perhaps they were not sending Y in response to "delete disk?", but to a
-previous question. So, inputs should not be resent. To prevent that,
-no message is sent to indicate when an input is rejected.
-
-Synchronous input interacts badly with terminal echo, because sending an
-input causes an echo output, and if that output has not been received by the
-time the next letter is input, the next input sent will be rejected. To
-deal with this, an input can include an echo block. If the echo block has
-the same content as the sum of outputs sent since the output that the input
-is in response to, then the input will be accepted.
-
-For example:
-
-	1. output "prompt>"
-	2. input "t" (previous: 1)
-	3. output "t" (previous: 2)
-	4. input "o" (previous: 1, echo: "t") -- valid because "t" = 3
-	5. output "o" (previous: 4)
-	6. input "p" (previous: 1, echo: "to") -- valid because "to" = 3+5
-	7. output: "p" (previous: 6)
-
-This should be sufficient for shell access, and for using some editors.
-However, editors like vim that update a cursor position indicator as
-text is added will often have inputs rejected. debug-me could optionally
-beep or flash the screen when an input has been rejected.
-
-##### proof truncation
-
-A proof can be truncated at any point in the chain and still be a valid
-proof of what happened in the session up to that point.
-
-One use case for this is that a developer might run a command to display
-known sensitive data (eg `.ssh/id_rsa`).
-
-An interface to truncate a proof could also upload the truncated version of
-it to a server. There would need to be a way for the user to to remove the
-full proof from the server.
-
-#### interface
-
-Interface is as close to a ssh session as possible.
-
-The user can input stuff, just as well as the developer.
-
-It can be important to match terminal sizes, to make sure the developer
-is seeing same thing as the user. `debug-me` can assist with this by
-drawing a box and having the developer resize their terminal to enclose it,
-when the terminal sizes vary.
-
-It would be possible to have the user manually vet inputs and outputs,
-rather than generating a GPG signed proof of the developer's activity.
-But, this would significantly complicate things, by needing to display
-on the user's terminal what inputs and outputs remain to be vetted.
-The complication of implementing that does not seem worth it.
-Especially because manual vetting would introduce lag.
-
-It might be nice to have an integrated chat, but again this complicates
-the terminal handing significantly. User and developer can just as well
-chat on IRC anyway. Or run `screen` within `debug-me` and use one window
-to chat in.
-
-#### installation
-
-For `debug-me` to be most useful, it will need to be included in major
-distributions. It should also be as easy as possible to install manually.
-
-It may be helpful for programs to bundle `debug-me`, at least
-until the standalone `debug-me` is widely available. For example, I can
-imagine including it in the standalone git-annex bundles.
-
-#### other uses
-
-Something like this could be used in a few other ways than debugging:
-
-* Let anyone connect in watch-only mode. Could be used for
-  broadcasting both debugging sessions and other activity.
-* Moderated mode where N people connect and M of them need to approve
-  an action before it's accepted. Could be used to add security, or for
-  pair programming where both in the pair need to agree what to do.
+Initial design thoughts: [[initial_design]]
diff --git a/code/debug-me/initial_design.mdwn b/code/debug-me/initial_design.mdwn
new file mode 100644
index 0000000..dbe9209
--- /dev/null
+++ b/code/debug-me/initial_design.mdwn
@@ -0,0 +1,171 @@
+A not yet implemented idea from [[blog/entry/Re:_Debugging_over_email]]:
+

(Diff truncated)
add gpg key
diff --git a/links/personal.mdwn b/links/personal.mdwn
index bef4558..e47b4c5 100644
--- a/links/personal.mdwn
+++ b/links/personal.mdwn
@@ -3,4 +3,5 @@
 [[blog]]  
 [[pics]]  
 [[contact_me|contact]]  
+[[GPG key|contact]]  
 [[todo]]

devblog
diff --git a/devblog/debug_me_final_polishing.mdwn b/devblog/debug_me_final_polishing.mdwn
new file mode 100644
index 0000000..2506f9f
--- /dev/null
+++ b/devblog/debug_me_final_polishing.mdwn
@@ -0,0 +1,14 @@
+Fixed a tricky race condition that I think was responsible for some
+recent instability seen in debug-me when connecting to a session.
+It's a bit hard to tell because it caused at least 3 different types
+of crashes, and it was a race condition.
+
+Made debug-me prompt for the user's email address when it starts up, and
+then the server will email the session log to the user at the end. There
+are two reasons to do this. First, it guards against the developer
+connecting to the session, doing something bad, and deleting the user's
+local log file to cover their tracks. Second, it means the server doesn't
+have to retain old log files, which could be abused to store other data on
+servers.
+
+Also put together a basic web site, <https://debug-me.branchable.com/>.

update
diff --git a/devblog/debug_me_gpg_key_verification.mdwn b/devblog/debug_me_gpg_key_verification.mdwn
index cf8c951..71fd465 100644
--- a/devblog/debug_me_gpg_key_verification.mdwn
+++ b/devblog/debug_me_gpg_key_verification.mdwn
@@ -50,3 +50,12 @@ because wotsap still has to download the WoT database. (Also,
 the version of wotsap in debian is [outdated and insecure](http://bugs.debian.org/800134))
 The decentralized way is for the user do some key signing, get into the WoT,
 and then gpg can tell them if the key is trusted itself.
+
+----
+
+debug-me is now nearly feature-complete!
+
+It has some bugs, and a known problem with the evidence chain that
+needs to be fixed. And, I want to make debug-me servers email logs
+back to users, which will change the websockets protocol, so ought to be
+done before making any release.

devblog
diff --git a/devblog/debug_me_gpg_key_verification.mdwn b/devblog/debug_me_gpg_key_verification.mdwn
new file mode 100644
index 0000000..cf8c951
--- /dev/null
+++ b/devblog/debug_me_gpg_key_verification.mdwn
@@ -0,0 +1,52 @@
+Working on making debug-me verify the developer's gpg key.
+Here's what the user sees when I connect to them:
+
+	** debug-me session control and chat window
+	Someone wants to connect to this debug-me session.
+	Checking their Gnupg signature ...
+	gpg: Signature made Sat Apr 29 14:31:37 2017 JEST
+	gpg:                using RSA key 28A500C35207EAB72F6C0F25DB12DB0FF05F8F38
+	gpg: Good signature from "Joey Hess <joeyh@joeyh.name>" [unknown]
+	gpg:                 aka "Joey Hess <id@joeyh.name>" [unknown]
+	gpg:                 aka "Joey Hess <joey@kitenet.net>" [unknown]
+	gpg: WARNING: This key is not certified with a trusted signature!
+	gpg:          There is no indication that the signature belongs to the owner.
+	Checking the Gnupg web of trust ...
+	Joey Hess's identity has been verified by as many as 111 people, including:
+	Martin Michlmayr, Kurt Gramlich, Luca Capello, Christian Perrier, Axel Beckert,
+	Stefano Zacchiroli, Gerfried Fuchs, Eduard Bloch, Anibal Monsalve Salazar
+	
+	Joey Hess is probably a real person.
+	
+	Let them connect to the debug-me session and run commands? [y/n] 
+
+And here's what the user sees when a fake person connects:
+
+	** debug-me session control and chat window
+	Someone wants to connect to this debug-me session.
+	Checking their Gnupg signature ...
+	gpg: Signature made Sat Apr 29 14:47:29 2017 JEST
+	gpg:                using RSA key
+	gpg: Good signature from "John Doe" [unknown]
+	gpg: WARNING: This key is not certified with a trusted signature!
+	gpg:          There is no indication that the signature belongs to the owner.
+	Primary key fingerprint: B2CF F6EF 2F01 96B1 CD2C  5A03 16A1 2F05 4447 4791
+	Checking the Gnupg web of trust ...
+
+	Their identity cannot be verified!
+
+	Let them connect to the debug-me session and run commands? [y/n] 
+
+The debug-me user is likely not be connected to the gpg web of trust,
+so debug-me will download the developer's key from a keyserver,
+and uses the <https://pgp.cs.uu.nl/> service to check if the developer's
+key is in the strong set of the web of trust. It prints out the best-connected
+people who have signed the developer's key, since the user might recognise some
+of those names.
+
+While relying on a server to determine if the developer is in the strong set is
+not ideal, it would be no better to have debug-me depend on wotsap,
+because wotsap still has to download the WoT database. (Also,
+the version of wotsap in debian is [outdated and insecure](http://bugs.debian.org/800134))
+The decentralized way is for the user do some key signing, get into the WoT,
+and then gpg can tell them if the key is trusted itself.

devblog
diff --git a/devblog/debug_me_control_window.mdwn b/devblog/debug_me_control_window.mdwn
new file mode 100644
index 0000000..940c6c7
--- /dev/null
+++ b/devblog/debug_me_control_window.mdwn
@@ -0,0 +1,44 @@
+I've been trying to write a good description of debug-me, and here's
+what I've got so far:
+
+Short description: "secure remote debugging"
+
+Long description:
+
+> Debugging a problem over email is slow, tedious, and hard. The developer
+> needs to see the your problem to understand it. Debug-me aims to make
+> debugging fast, fun, and easy, by letting the developer access your
+> computer remotely, so they can immediately see and interact with the
+> problem. Making your problem their problem gets it fixed fast.
+> 
+> A debug-me session is logged and signed with the developer's Gnupg
+> key, producing a chain of evidence of what they saw and what they did.
+> So the developer's good reputation is leveraged to make debug-me secure.
+> 
+> When you start debug-me without any options, it will connect to a debug-me
+> server, and print out an url that you can give to the developer to get
+> them connected to you. Then debug-me will show you their Gnupg key and who
+> has signed it. If the developer has a good reputation, you can proceed
+> to let them type into your console in a debug-me session. Once the
+> session is done, the debug-me server will email you the signed
+> evidence of what the developer did in the session.
+> 
+> If the developer did do something bad, you'd have proof that they cannot
+> be trusted, which you can share with the world. Knowing that is the case
+> will keep most developers honest.
+
+I think that's pretty good, and would like to know your thoughts, reader,
+as a prospective debug-me user.
+
+----
+
+Most of today was spent making `debug-me --control` communicate over a socket
+with the main debug-me process. That is run in a separate window,
+which is the debug-me session control and chat window. Things typed there
+can be seen by the other people involved in a debug-me session. And, the gnupg
+key prompting stuff will be done in that window eventually.
+
+Screenshot of the first time that worked. The "user" is on the left and the
+"developer" is on the right.
+
+[[screenshot.png]]
diff --git a/devblog/debug_me_control_window/screenshot.png b/devblog/debug_me_control_window/screenshot.png
new file mode 100644
index 0000000..01d425c
Binary files /dev/null and b/devblog/debug_me_control_window/screenshot.png differ

add
diff --git a/blog/entry/Exede_Surfbeam_2.mdwn b/blog/entry/Exede_Surfbeam_2.mdwn
new file mode 100644
index 0000000..809e639
--- /dev/null
+++ b/blog/entry/Exede_Surfbeam_2.mdwn
@@ -0,0 +1,108 @@
+My new satellite internet connection is from Exede, connecting to the
+ViaSat 1 bird in geosync orbit.  A few technical details that I've observed
+follow.
+
+## antagonistic by design
+
+The "Surfbeam 2 wifi modem" is a closed proprietary system. That is important
+because it's part of Exede's bandwidth management system. The Surfbeam tracks
+data use and sends it periodically to Exede. When a user has gone over
+their monthly priority data, Exede then throttles the bandwidth in various
+ways -- this throttling seems to be implemented, at least partially on the
+Surfbeam itself. (Perhaps by setting QoS flags?)
+
+So, if a user could hack their Surfbeam, they could probably bypass the
+bandwidth caps, or at least some of them. Perhaps Exede would notice
+eventually. Of course, doing so would surely violate the Exede TOS. If
+you're renting the modem, like I am, hacking a device you don't own might
+also subject you to criminal penalties. Needless to say, I don't plan to
+hack the SurfBeam. But
+[it's been hacked before](https://www.youtube.com/watch?v=7QTVi9CPQDw).
+
+So, this is a device that lives in people's homes and is
+antagonistic to them by design.
+
+## weird data throttling
+
+The way the Surfbeam reports data use back to Exede periodically and gets
+throttling configured has some odd effects sometimes. For example, the
+Surfbeam can be in throttled state left-over from the previous billing
+month. When a new billing month begins, it can remain throttled for
+some time (up to multiple hours) until it sends an update to Exede and
+they un-throttle it. Data downloaded at that time might still be counted as
+priority data even though it was throttled. I've seen some good indications
+of that happening, but am not sure yet.
+
+But, I've decided that the throttling doesn't matter for me. Why? ViaSat 1
+has many spot beams, and the working-class beam I'm in (most of it is in
+eastern Kentucky) does not seem to get a lot of use between 7 am and 4:30 pm
+weekdays. Even when throttled, I often get 300 kb/s - 1 mb/s speeds
+during the day, which is not a lot worse than the ~2.5 mb/s peak when
+unthrottled. And that's the time when I want to use broadband -- when the sun
+is shining and I'm at home at work/play. I'm probably going to switch to a
+cheaper plan with less priority data, because the priority data is not
+buying me much. This is a *big* change from the old FAP which rendered
+the satellite no faster than dialup.
+
+## a whole network in there
+
+Looking at the ports open on the Surfbeam, some very strange things
+turned up. First, there are not one, not two, but **three** separate IPs
+used by the device, and there are at least two and perhaps three distinct
+computers involved. There are a lot of flickering LEDs **inside**
+the box; a whole network in there.
+
+192.168.100.1 is the satellite controller. It's a Linux box, fingerprinted
+as kernel 3.10 or so (so full of security holes presumably), and it's running 
+thttpd/2.25b (doesn't seem to have any known holes). 
+It seems to have ssh and snmp, but with some port filtering that
+prevents access. (Note that the above exploit video confirms
+that snmp is running.) Some machine parsable data is exposed at
+<http://192.168.100.1/index.cgi?page=modemStatusData> and
+<http://192.168.100.1/index.cgi?page=triaStatusData>. (See
+([SurfStat program](https://github.com/blachniet/SurfStat/))
+
+192.168.1.1 is the wifi router. It has a dns server, an icslap proxy, and
+nmap thinks it's Linux 3.x with Synology DiskStation Manager (probably the
+latter is a false positive?) It has its own separate web server for
+configuration, which is not thttpd. I'm fairly sure this is a separate
+processor from the other IP address.
+
+192.168.100.2 responds to ICMP, but has no open ports at all. However, it
+seems to have filtered ssh, telnet, msrpc, microsoft-ds, and port 8090
+(probably http), so perhaps it's running all that stuff. This one
+is definitely a separate processor, located in the Satellite dish's
+TRIA (transmit receive integrated assembly). Verified by disconnecting the
+dish's coax cable and being unable to ping it.
+
+## lack of source code for GPLed software
+
+Exede did not provide anything to me about the GPL licensed source code on
+the Surfbeam 2. I'm not sure if they're legally required to do so in my
+case, since they're renting it to me?
+
+But, they do let you buy the device too, so it's interesting that nothing
+mentions the licenses of its software and where to get the source code.
+I'll try to buy it and ask for the source code eventually.
+
+## power use
+
+The Surfbeam pulls as much power as two beefy laptops, but it is beaming
+signals thousands of miles into space, so I give it a bit of a pass.
+I want to find a way to power it from DC power, but have not had any
+success with that so far, so am wasting more power to run it on an
+inverter.
+
+Its power supply is rated at 30v and 2.5 amps. Interestingly, I've seen a
+photo of another Surfbeam power supply that only pulls 1.5 amps. This and
+a different case with fewer (external) LEDs makes me think perhaps the
+installer stuck me with an old and less efficient version. Maybe they
+integrated some of those processors into a single board in a new version
+and perhaps made it waste less power as heat. Mine gets pretty warm.
+
+I'm currently only able to run it approximately one hour per hour of sun
+collected by the house. Still on dialup the rest of the time. With the
+ability to get on broadband when dialup is being painful, being on dialup
+the rest of the time is perfectly ok. Of course it helps that with tools
+like [[code/git-annex]], I'm very well tuned to popping up onto broadband
+briefly and making it count.

devbog
diff --git a/devblog/debug_me_finalizing_wire_format.mdwn b/devblog/debug_me_finalizing_wire_format.mdwn
new file mode 100644
index 0000000..98780d4
--- /dev/null
+++ b/devblog/debug_me_finalizing_wire_format.mdwn
@@ -0,0 +1,19 @@
+Went ahead and made debug-me use protocol buffers for its wire protocol.
+There's a nice haskell library for this that doesn't depend on anything
+else, and can generate them directly from data types, but I had to write a
+shim between the protobuf style data types and debug-me's internal
+data types. Took 250 lines of quite tedious code.
+
+Then I finally implemented the trick I thought of to leave out the previous
+hash from debug-me messages on the wire, while still including
+cryptograhically secure proof of what the previous hash was. That reduced
+the overhead of a debug-me message from 168 bytes to 74 bytes!
+
+I doubt debug-me's wire format will see any more major changes.
+
+How does debug-me compare with ssh? I tried some experiments, and
+typing a character in ssh sends 180 bytes over the wire, while doing the
+same in debug-me sends 326 bytes. The extra overhead must be due to using
+websockets, I guess. At least debug-me is in the same ballpark as ssh.
+
+Today's work was sponsored by Riku Voipio.

devblog
diff --git a/devblog/debug_me_polishing.mdwn b/devblog/debug_me_polishing.mdwn
new file mode 100644
index 0000000..d3f9495
--- /dev/null
+++ b/devblog/debug_me_polishing.mdwn
@@ -0,0 +1,30 @@
+Working on polishing up debug-me's features to not just work, but work
+well.
+
+On Monday, I spent much longer than expected on the problem that when a
+debug-me session ended, clients attached to it did not shut down.
+The session shutdown turned out to have worked by accident in one case,
+but it was lacking a proper implementation, and juggling all the threads
+and channels and websockets to get everything to shut down cleanly was
+nontrivial.
+
+Today, I fixed a bug that made `debug-me --download` fail while downloading a
+session, because the server didn't relay messages from developers, and so
+the proof chain was invalid. After making the server relay those messages,
+and handling them, that was fixed -- and I got a great feature for free:
+Multiple developers can connect to a debug-me session and all interact with
+it at the same time!
+
+Also, added timing information to debug-me messages. While time is relative
+and so it can't be proved how long the time was between messages in the
+debug-me proof chain, including that information lets `debug-me --download`
+download a session and then `debug-me --replay` can replay the log file
+with realistic pauses.
+
+Started on gpg signing and signature verification, but that has a user
+interface problem. If the developer connects after the debug-me session has
+started, prompting the user on the same terminal that is displaying the
+session would not be good. This is where it'd be good to have a library for
+[[blog/entry/multi-terminal_applications]]. Perhaps I should go build a
+prototype of that. Of perhaps I'll make debug-me wait for one developer to
+connect and prompt the user before starting the session.

introduce kaitai
diff --git a/devblog/debug_me_websockets/discussion.mdwn b/devblog/debug_me_websockets/discussion.mdwn
new file mode 100644
index 0000000..5e2c3f6
--- /dev/null
+++ b/devblog/debug_me_websockets/discussion.mdwn
@@ -0,0 +1,3 @@
+re. protobufs - i think that would be an improvement: it seems like a good idea to decouple language-specific data structures from the protocol, if only to make debugging easier, but it seems like a good idea also to allow for better extensibility (e.g. writing different client/servers implementations)...
+
+An interesting approach I have found is the language-neutral [kaitai.io](http://kaitai.io/) specification system. it's a YAML-like metadata description language that translates into multiple languages like Java, Python, PHP, Ruby, C++ but, unfortunately, not Haskell just yet. I find it an interesting alternative to protobufs because you are not bound by a certain data format - you can just write your own binary language (or port existing ones) by specifying its metadata clearly... --[[anarcat]]

update
diff --git a/devblog/debug_me_client-server_working.mdwn b/devblog/debug_me_client-server_working.mdwn
index 9cc0a96..b0bd508 100644
--- a/devblog/debug_me_client-server_working.mdwn
+++ b/devblog/debug_me_client-server_working.mdwn
@@ -1,5 +1,12 @@
 Got debug-me fully working over the network today. It's allllive!
 
+Hardest thing today was when a developer connects and the server needs to
+send them the backlog of the session before they start seeing current
+activity. Potentially full of races. My implementation avoids race
+conditions, but might cause other connected developers to see a stall in
+activity at that point. A stall-free version is certianly doable, but this
+is good enough for now.
+
 There are quite a few bugs to fix. Including a security hole in the proof
 chain design, that I realized it had when thinking about what happens whith
 multiple people are connected to a debug-me session who are all typing at

devblog
diff --git a/devblog/debug_me_client-server_working.mdwn b/devblog/debug_me_client-server_working.mdwn
new file mode 100644
index 0000000..9cc0a96
--- /dev/null
+++ b/devblog/debug_me_client-server_working.mdwn
@@ -0,0 +1,14 @@
+Got debug-me fully working over the network today. It's allllive!
+
+There are quite a few bugs to fix. Including a security hole in the proof
+chain design, that I realized it had when thinking about what happens whith
+multiple people are connected to a debug-me session who are all typing at
+once.
+
+(There have actually been 3 security holes spotted over the past day; the
+one above, a lacking sanitization of session IDs, and a bug in the server
+that let a developer truncate logs.)
+
+So I need to spend several mode days bugfixing, and also make it only allow
+connections signed by trusted gpg keys. Still, an initial release does not
+seem far off now.

update
diff --git a/code/debug-me.mdwn b/code/debug-me.mdwn
index 882aec0..dbe9209 100644
--- a/code/debug-me.mdwn
+++ b/code/debug-me.mdwn
@@ -24,12 +24,6 @@ developer saw, and what they did in the `debug-me` session.
 If the developer does something Evil, you have the neccessary proof
 to adjust their reputation.
 
-As well as checking the GPG web of trust, `debug-me` can clone the git
-repository of the program that it's being used to debug, and check for GPG
-signed git tags and commits made using the developer's key. This helps you
-tell if the person connecting to `debug-me` is a developer of the program
-being debugged.
-
 ### design
 
 #### client-server
diff --git a/devblog/debug_me_websockets.mdwn b/devblog/debug_me_websockets.mdwn
index c9e7ce6..fd67d81 100644
--- a/devblog/debug_me_websockets.mdwn
+++ b/devblog/debug_me_websockets.mdwn
@@ -10,3 +10,11 @@ protocol buffers to make it less of a haskell-specific wire format.
 Currently, the client and server basically work; the client can negotiate
 a protocol version with the server and send messages to it, which the
 server logs.
+
+----
+
+Also, added two additional modes to debug-me. `debug-me --download url` will
+download a debug-me log file. If that session is still running, it keeps
+downloading until it's gotten the whole session. `debug-me --watch url`
+connects to a debug-me session, and displays it in non-interactive mode.
+These were really easy to implement, reusing existing code.

devblog
diff --git a/devblog/debug_me_websockets.mdwn b/devblog/debug_me_websockets.mdwn
new file mode 100644
index 0000000..c9e7ce6
--- /dev/null
+++ b/devblog/debug_me_websockets.mdwn
@@ -0,0 +1,12 @@
+Worked today on making debug-me run as a client/server, communicating using
+websockets.
+
+I decided to use the "binary" library to get an efficient serialization of
+debug-me's messages to send over the websockets, rather than using JSON.
+A typicaly JSON message was 341 bytes, and this only uses 165 bytes, which
+is fairly close to the actual data size of ~129 bytes. I may later use
+protocol buffers to make it less of a haskell-specific wire format.
+
+Currently, the client and server basically work; the client can negotiate
+a protocol version with the server and send messages to it, which the
+server logs.

update
diff --git a/blog/entry/propelling_containers.mdwn b/blog/entry/propelling_containers.mdwn
index 170f568..086a6ed 100644
--- a/blog/entry/propelling_containers.mdwn
+++ b/blog/entry/propelling_containers.mdwn
@@ -139,4 +139,11 @@ infinitelyNestedContainer = Systemd.container "evil-systemd"
 Strongly typed purely functional container deployment can only protect us
 against a certian subset of all badly thought out systems. ;)
 
+----
+
+Note that the above was written in 2014 and some syntatix details have
+changed. See the documentation for Propellor.Property.Chroot,
+Propellor.Property.Debootstrap,  Propellor.Property.Docker,
+Propellor.Property.Systemd for current examples.
+
 [[!meta title="propelling containers"]]

devblog
diff --git a/devblog/debug_me_signatures.mdwn b/devblog/debug_me_signatures.mdwn
new file mode 100644
index 0000000..640d8a6
--- /dev/null
+++ b/devblog/debug_me_signatures.mdwn
@@ -0,0 +1,23 @@
+Added signatures to the debug-me protocol today. All messages are signed
+using a ed25519 session key, and the protocol negotiates these keys.
+
+Here's a dump of a debug-me session, including session key exchange:
+
+	{"ControlMessage":{"control":{"SessionKey":[{"b64":"it8RIgswI8IZGjjQ+/INPjGYPAcGCwN9WmGZNlMFoX0="},null]},"controlSignature":{"Ed25519Signature":{"b64":"v80m5vQbgw87o88+oApg0syUk/vg88t14nIfXzahwAqEes/mqY4WWFIbMR46WcsEKP2fwfXQEN5/nc6UOagBCQ=="}}}}
+	{"ActivityMessage":{"prevActivity":null,"activitySignature":{"Ed25519Signature":{"b64":"HNPk/8QF7iVtsI+hHuO1+J9CFnIgsSrqr1ITQ2eQ4VM7rRPG7i07eKKpv/iUwPP4OdloSmoHLWZeMXZNvqnCBQ=="}},"activity":{"seenData":{"v":">>> debug-me session starting\r\n"}}}}
+	{"ActivityMessage":{"prevActivity":{"hashValue":{"v":"63d31b25ca262d7e9fc5169d137f61ecef20fb65c23c493b1910443d7a5514e4"},"hashMethod":"SHA256"},"activitySignature":{"Ed25519Signature":{"b64":"+E0N7j9MwWgFp+LwdzNyByA5W6UELh6JFxVCU7+ByuhcerVO/SC2ZJJJMq8xqEXSc9rMNKVaAT3Z6JmidF+XAw=="}},"activity":{"seenData":{"v":"$ "}}}}
+	{"ControlMessage":{"control":{"SessionKey":[{"b64":"dlaIEkybI5j3M/WU97RjcAAr0XsOQQ89ffZULVR82pw="},null]},"controlSignature":{"Ed25519Signature":{"b64":"hlyf7SZ5ZyDrELuTD3ZfPCWCBcFcfG9LP7Zuy+roXwlkFAv2VtpYrFAAcnWSvhloTmYIfqo5LWakITPI0ITtAQ=="}}}}
+	{"ControlMessage":{"control":{"SessionKeyAccepted":[{"b64":"dlaIEkybI5j3M/WU97RjcAAr0XsOQQ89ffZULVR82pw="},null]},"controlSignature":{"Ed25519Signature":{"b64":"kJ7AdhBgoiYfsXOM//4mcMcU5sL0oyqulKQHUPFo2aYYPJnu5rKUHlfNsfQbGDDrdsl9SocZaacUpm+FoiDCCg=="}}}}
+	{"ActivityMessage":{"prevActivity":{"hashValue":{"v":"2250d8b902683053b3faf5bdbe3cfa27517d4ede220e4a24c8887ef42ab506e0"},"hashMethod":"SHA256"},"activitySignature":{"Ed25519Signature":{"b64":"hlF7oFhFealsf8+9R0Wj+vzfb3rBJyQjUyy7V0+n3zRLl5EY88XKQzTuhYb/li+WoH/QNjugcRLEBjfSXCKJBQ=="}},"activity":{"echoData":{"v":""},"enteredData":{"v":"l"}}}}
+
+Ed25519 signatures add 64 bytes overhead to each message, on top of the
+64 bytes for the hash pointer to the previous message. But, last night I
+thought of a cunning plan to remove that hash pointer from the wire
+protocol, while still generating a provable hash chain. Just leave it out
+of the serialized message, but include it in the data that's signed.
+debug-me will then just need to try the hashes of recent messages until
+it finds one for which the signature verifies, and then it will know
+what the hash pointer is supposed to point to, without it ever having been
+sent over the wire! Will implement this trick eventually.
+
+Next though, I need to make debug-me communicate over the network.

add news item for moreutils 0.61
diff --git a/code/moreutils/news/version_0.56.mdwn b/code/moreutils/news/version_0.56.mdwn
deleted file mode 100644
index 5451197..0000000
--- a/code/moreutils/news/version_0.56.mdwn
+++ /dev/null
@@ -1,7 +0,0 @@
-moreutils 0.56 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * ifdata: Fix error messages when a non-existent network interface
-     is queried. Closes: #[386754](http://bugs.debian.org/386754) Thanks, Nicolas Schier
-   * errno.docbook: Fix typo. Closes: #[749399](http://bugs.debian.org/749399)
-   * vidir: Create missing target directories. Closes: #[728688](http://bugs.debian.org/728688)
-     Thanks, Nicolas Schier"""]]
\ No newline at end of file
diff --git a/code/moreutils/news/version_0.61.mdwn b/code/moreutils/news/version_0.61.mdwn
new file mode 100644
index 0000000..56e22de
--- /dev/null
+++ b/code/moreutils/news/version_0.61.mdwn
@@ -0,0 +1,4 @@
+moreutils 0.61 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * chronic: Flush output more often to better preserve stdout,err ordering.
+     Thanks, Miroslav Šustek"""]]
\ No newline at end of file

typo
diff --git a/devblog/debug_me_first_stage_complete.mdwn b/devblog/debug_me_first_stage_complete.mdwn
index 42ce096..bca2f58 100644
--- a/devblog/debug_me_first_stage_complete.mdwn
+++ b/devblog/debug_me_first_stage_complete.mdwn
@@ -9,7 +9,7 @@ actual networked debug-me is done now. I only have to add signing,
 verification of gpg key trust, and http client-server to finish debug-me.
 
 (Also, I made `debug-me --replay debug-me.log` replay the log with
-realistic delays, like [[code/scriptreply]] or `ttyplay`. Only took a page
+realistic delays, like [[code/scriptreplay]] or `ttyplay`. Only took a page
 of code to add that feature.)
 
 ----

devblog
diff --git a/devblog/debug_me_first_stage_complete.mdwn b/devblog/debug_me_first_stage_complete.mdwn
new file mode 100644
index 0000000..42ce096
--- /dev/null
+++ b/devblog/debug_me_first_stage_complete.mdwn
@@ -0,0 +1,40 @@
+Solved that bug I was stuck on yesterday. I had been looking in the code
+for the developer side for a bug, but that side was fine; the bug was
+excessive backlog trimming on the user side.
+
+Now I'm fairly happy with how debug-me's activity chains look,
+and the first stage of developing debug-me is complete. It still doesn't do
+anything more than the `script` command, but all the groundwork for the
+actual networked debug-me is done now. I only have to add signing,
+verification of gpg key trust, and http client-server to finish debug-me.
+
+(Also, I made `debug-me --replay debug-me.log` replay the log with
+realistic delays, like [[code/scriptreply]] or `ttyplay`. Only took a page
+of code to add that feature.)
+
+----
+
+I'm only "fairly happy" with the activity chains because there is a
+weird edge case.. At high latency, when typing "qwertyuiop", this
+happens:
+
+[[debug-me.log.png]]
+
+That looks weird, and is somewhat hard to follow in graph form, but
+it's "correct" as far as debug-me's rules for activity chains go.
+Due to the lag, the chain forks:
+
+* It sends "wer" before the "q" echos back
+* It replies to the "q" echo with tyuio" before
+  the "w" echos back.
+* It replies to the "w" echo with "p"
+* Finally, all the delayed echos come in, and it sends
+  a carriage return, resulting in the command being run.
+
+I'd be happier if the forked chain explicitly merged back together,
+but to do that and add any provable information, the developer would have
+to wait for all the echos to arrive before sending the carriage return,
+or something like that, which would make type-ahead worse. So I think I'll
+leave it like this. Most of the time, latency is not so high, and so this
+kind of forking doesn't happen much or is much simpler to understand when
+it does happen.
diff --git a/devblog/debug_me_first_stage_complete/debug-me.log.png b/devblog/debug_me_first_stage_complete/debug-me.log.png
new file mode 100644
index 0000000..68a11ec
Binary files /dev/null and b/devblog/debug_me_first_stage_complete/debug-me.log.png differ

devblog
diff --git a/devblog/debug_me_chain_issues.mdwn b/devblog/debug_me_chain_issues.mdwn
new file mode 100644
index 0000000..5d6b80f
--- /dev/null
+++ b/devblog/debug_me_chain_issues.mdwn
@@ -0,0 +1,18 @@
+Working on getting the debug-me proof chain to be the right shape,
+and be checked at all points for valididity. This graph of a session
+shows today'ss progress, but also a bug.
+
+[[debug-me.log.png]]
+
+At the top, everything is synchronous while "ls" is entered and echoed back. 
+Then, things go asynchronous when " -la" is entered, and
+the expected echos (in brackets) match up with what really gets
+echoed, so that input is also accepted.
+
+Finally, the bit in red where "|" is entered is a bug
+on the developer side, and it gets (correctly) rejected
+on the user side due to having forked the proof chain. Currently stuck on
+this bug.
+
+The code for this, especially on the developer side, is rather hairy,
+I wonder if I am missing a way to simplify it.
diff --git a/devblog/debug_me_chain_issues/debug-me.log.png b/devblog/debug_me_chain_issues/debug-me.log.png
new file mode 100644
index 0000000..f9ef5de
Binary files /dev/null and b/devblog/debug_me_chain_issues/debug-me.log.png differ