Recent changes to this wiki:

commen
diff --git a/doc/forum/build_propellor_binary/comment_4_d5bf3e9f7a7e01fd6b55b2e761c8cc2e._comment b/doc/forum/build_propellor_binary/comment_4_d5bf3e9f7a7e01fd6b55b2e761c8cc2e._comment
new file mode 100644
index 00000000..eff55db0
--- /dev/null
+++ b/doc/forum/build_propellor_binary/comment_4_d5bf3e9f7a7e01fd6b55b2e761c8cc2e._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2019-04-22T17:14:20Z"
+ content="""
+I've fixed the build of origin/precompiled 
+"""]]

Added a comment
diff --git a/doc/forum/Getting_Info_from_containers/comment_4_db1a195688aa23e99b0aca9e776fd4ac._comment b/doc/forum/Getting_Info_from_containers/comment_4_db1a195688aa23e99b0aca9e776fd4ac._comment
new file mode 100644
index 00000000..f6d33302
--- /dev/null
+++ b/doc/forum/Getting_Info_from_containers/comment_4_db1a195688aa23e99b0aca9e776fd4ac._comment
@@ -0,0 +1,41 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="comment 4"
+ date="2019-04-20T21:54:16Z"
+ content="""
+After thinking about it, it would be nicer if an Host could give information about
+several of its children, that would be a larger change, but having the wrapper
+would then be useless and propellor would be able to find containers
+automatically.
+
+As a container is created by a property, a container Host could be included in
+Info of a Host. If an entry is to be propagated, then it is added as an entry
+of the host, else it is kept as an entry of the container.
+
+When looking up a host, we have to search for one Host of a [Host] list, but
+also for any Host listed in the containersInfo of all the listed Host.
+
+Not sure this is clear, here is a example to try to make it clearer:
+
+    hard_node :: Host
+        hostName = \"hard-node.example.org\"
+        hostProperties = ...
+        hostInfo =
+            [ a HostKeyInfo for riva
+            , a DnsInfoUnpropagated for riva
+            , a DnsInfoPropagated from container-web
+            , a ContainersInfo =
+                [ container_web :: Host
+                    hostName = \"container-web\"
+                    hostProperties = ...
+                    hostInfo =
+                        [ a HostKeyInfo for container-web
+                        , a DnsInfoUnpropagated for container-web
+                        ]
+                , container_git :: Host
+                    ...
+                ]
+            ]
+
+"""]]

Added a comment
diff --git a/doc/forum/build_propellor_binary/comment_3_5fa856434db0d285874ac3f468ab792e._comment b/doc/forum/build_propellor_binary/comment_3_5fa856434db0d285874ac3f468ab792e._comment
new file mode 100644
index 00000000..5173511c
--- /dev/null
+++ b/doc/forum/build_propellor_binary/comment_3_5fa856434db0d285874ac3f468ab792e._comment
@@ -0,0 +1,38 @@
+[[!comment format=mdwn
+ username="desired.mta@88576fa3c90538abed47d3f0aa48d00bcc903b23"
+ nickname="desired.mta"
+ avatar="http://cdn.libravatar.org/avatar/d93af7ba58088a39d04c7da13fc176ee"
+ subject="comment 3"
+ date="2019-04-20T09:10:52Z"
+ content="""
+Thanks for your responses! I wasn't aware there was prior work done on this.
+
+`origin/precompiled` did not build for me. But when I merged master into it, and patching around a trivial merge conflict, I got this:
+
+```
+[ 58 of 182] Compiling Propellor.Property ( src/Propellor/Property.hs, dist/build/Propellor/Property.o )
+
+src/Propellor/Property.hs:364:13: error:
+    * Could not deduce (Monoid (Property (MetaTypes t)))
+        arising from a use of `mempty'
+      from the context: SingI t
+        bound by the type signature for:
+                   doNothing :: forall k (t :: k). SingI t => Property (MetaTypes t)
+        at src/Propellor/Property.hs:363:1-46
+    * In the expression: mempty
+      In an equation for `doNothing': doNothing = mempty
+    |
+364 | doNothing = mempty
+    |             ^^^^^^
+```
+
+Unfortunately, I am not versed enough in Haskell to understand the error.
+
+
+```
+$ ghc --version
+The Glorious Glasgow Haskell Compilation System, version 8.4.4
+```
+
+Here is my merged fork (based on 38b4da93 and origin/precompiled at 7d550c75): if you can `make` it: [github.com/motiejus/propellor](https://github.com/motiejus/propellor), and tell me how to fix the above error, I would try to test it functionally further.
+"""]]

Added a comment: patches submitted
diff --git a/doc/todo/Debootstrap_module_should_respect_a_configured_Apt.proxy/comment_9_9d1cf538e0b1f560bac9b031b892a68c._comment b/doc/todo/Debootstrap_module_should_respect_a_configured_Apt.proxy/comment_9_9d1cf538e0b1f560bac9b031b892a68c._comment
new file mode 100644
index 00000000..75f6afd5
--- /dev/null
+++ b/doc/todo/Debootstrap_module_should_respect_a_configured_Apt.proxy/comment_9_9d1cf538e0b1f560bac9b031b892a68c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="patches submitted"
+ date="2019-04-18T20:58:35Z"
+ content="""
+I've just mailed patches addressing this to Joey.
+"""]]

comment
diff --git a/doc/forum/build_propellor_binary/comment_2_c650673606f798100be5ff1157742f54._comment b/doc/forum/build_propellor_binary/comment_2_c650673606f798100be5ff1157742f54._comment
new file mode 100644
index 00000000..94fdcb68
--- /dev/null
+++ b/doc/forum/build_propellor_binary/comment_2_c650673606f798100be5ff1157742f54._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2019-04-16T18:26:11Z"
+ content="""
+Yeah, if someone wants to check out origin/precompiled and test if it
+works, it may well be in a mergeable state. However, it doesn't deal with
+cross compilation to arm or anything like that.
+
+Anyway, once you've built a propellor binary, all it takes to run it on
+some remote host is "sudo ./propellor" (perhaps passing the hostname
+to run for if the current hostname is not one that propellor recognises). 
+
+But it expects to be run in a clone of the git repository, I don't know
+what will fail if it's run without that clone. Probably best to clone the
+git repo to /usr/local/propellor and run it in there.
+
+And if any of your properties rely on private data
+it won't be able to access that and they'll fail.
+"""]]

comment
diff --git a/doc/forum/Getting_Info_from_containers/comment_2_52ab9e8d56cf7b04be644293f6a30404._comment b/doc/forum/Getting_Info_from_containers/comment_2_52ab9e8d56cf7b04be644293f6a30404._comment
new file mode 100644
index 00000000..bfb1a754
--- /dev/null
+++ b/doc/forum/Getting_Info_from_containers/comment_2_52ab9e8d56cf7b04be644293f6a30404._comment
@@ -0,0 +1,30 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2019-04-16T18:18:55Z"
+ content="""
+Sure, look at how `Container` is defined:
+
+	data Container = Container MachineName Chroot.Chroot Host
+
+Getting a Host out of that is easy. :)
+
+	getContainerHost (Container _ _ h) = h
+
+(Has to be put inside the Systemd module as it does not export the
+Container constructor.)
+
+That's specific to systemd containers, other container systems
+have different data types. Here's the one from the Docker module:
+
+	data Container = Container Image Host
+
+If you wanted to you could even make a type class that these and other
+containers are part of, with a method to extract the Host. I would be happy
+to merge such a patch.
+
+And yeah, this seems like a good way around wanting to get otherwise
+unpropigated info out of containers. It's worth noting that the Host
+inside a systemd Container has as its hostname the MachineName used
+for the container.
+"""]]

Added a comment
diff --git a/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory/comment_2_c8e1c42e5fb36c2f0a69436b1a467a60._comment b/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory/comment_2_c8e1c42e5fb36c2f0a69436b1a467a60._comment
new file mode 100644
index 00000000..e609c981
--- /dev/null
+++ b/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory/comment_2_c8e1c42e5fb36c2f0a69436b1a467a60._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="comment 2"
+ date="2019-04-16T17:27:21Z"
+ content="""
+Great, thanks!
+"""]]

Added a comment: containerToHost?
diff --git a/doc/forum/Getting_Info_from_containers/comment_2_347f67e1be11f69fab571d8f9e7612b5._comment b/doc/forum/Getting_Info_from_containers/comment_2_347f67e1be11f69fab571d8f9e7612b5._comment
new file mode 100644
index 00000000..5db271fd
--- /dev/null
+++ b/doc/forum/Getting_Info_from_containers/comment_2_347f67e1be11f69fab571d8f9e7612b5._comment
@@ -0,0 +1,28 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="containerToHost?"
+ date="2019-04-16T17:23:16Z"
+ content="""
+Would it be possible to add a `containerToHost` wrapper that takes a container
+and returns a host?
+
+It would be something like this:
+
+	hosts :: [Host]
+	hosts =
+		[ myHost
+		, myContainerHost
+		]
+
+	myHost = host \"myhost.mydomain\" $ props
+		& ...
+		& myContainerSpawn myContainer
+
+	myContainer :: Systemd.Container
+	myContainer = Systemd.debContainer \"mycontainer\" $ props
+		& ...
+
+	myContainerHost = containerToHost \"mycontainer.mydomain\" myContainer
+
+"""]]

Ssh.userKeys, Ssh.userKeyAt: Create .ssh directory when it does not yet exist.
* Ssh.userKeys, Ssh.userKeyAt: Create .ssh directory when it does not yet
exist.
* Ssh.userKeyAt: When a relative filepath is provided, it's put inside
the user's .ssh directory.
diff --git a/debian/changelog b/debian/changelog
index dd8f8fd2..b7dafc8c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -10,6 +10,10 @@ propellor (5.8.0) UNRELEASED; urgency=medium
     since it's namespaced.
   * Add User.ownsWithPrimaryGroup
     Thanks, Sean Whitton
+  * Ssh.userKeys, Ssh.userKeyAt: Create .ssh directory when it does not yet
+    exist.
+  * Ssh.userKeyAt: When a relative filepath is provided, it's put inside
+    the user's .ssh directory.
 
  -- Joey Hess <id@joeyh.name>  Mon, 08 Apr 2019 11:09:04 -0400
 
diff --git a/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory.mdwn b/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory.mdwn
index 0c333c0c..d61c809d 100644
--- a/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory.mdwn
+++ b/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory.mdwn
@@ -1,5 +1,10 @@
 Hello,
 
-Maybe this should not create the directory as the given path is absolute, but unless my understanding is wrong, `Ssh.userKeys` does not create the directory either.
+Maybe this should not create the directory as the given path is absolute,
+but unless my understanding is wrong, `Ssh.userKeys` does not create the
+directory either.
 
-Could there be a `Ssh.userKeyNamed` for example which would prepend `$HOME/.ssh` to the given name?
+Could there be a `Ssh.userKeyNamed` for example which would prepend
+`$HOME/.ssh` to the given name? 
+
+> [[done]] --[[Joey]]
diff --git a/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory/comment_1_5883054e256c5970c425108bca106b58._comment b/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory/comment_1_5883054e256c5970c425108bca106b58._comment
new file mode 100644
index 00000000..fc26779e
--- /dev/null
+++ b/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory/comment_1_5883054e256c5970c425108bca106b58._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-04-16T15:12:20Z"
+ content="""
+Well spotted, I've fixed it to create the directory.
+
+userKeyAt's documentation doesn't actually specify that the filepath
+provided can't be relative, and if it were relative, it seems to make sense
+for it to be relative to the usual .ssh directory. Done so.
+"""]]
diff --git a/src/Propellor/Property/Ssh.hs b/src/Propellor/Property/Ssh.hs
index 59698ec0..ca20e68c 100644
--- a/src/Propellor/Property/Ssh.hs
+++ b/src/Propellor/Property/Ssh.hs
@@ -279,9 +279,12 @@ userKeys user@(User name) context ks = combineProperties desc $ toProps $
 -- | Sets up a user with the specified pubic key, and a private
 -- key from the privdata.
 --
--- A file can be specified to write the key to somewhere other than
+-- A FilePath can be specified to write the key to somewhere other than
 -- the default locations. Allows a user to have multiple keys for
 -- different roles.
+--
+-- When the FilePath is relative, is put inside the User's 
+-- ~/.ssh/ directory.
 userKeyAt :: IsContext c => Maybe FilePath -> User -> c -> (SshKeyType, PubKeyText) -> Property (HasInfo + UnixLike)
 userKeyAt dest user@(User u) context (keytype, pubkeytext) =
 	combineProperties desc $ props
@@ -306,14 +309,18 @@ userKeyAt dest user@(User u) context (keytype, pubkeytext) =
 	installprop writer ext key = do
 		f <- liftIO $ keyfile ext
 		return $ combineProperties desc $ props
+			& File.dirExists (takeDirectory f)
 			& writer f (keyFileContent key)
 			& File.ownerGroup f user (userGroup user)
 			& File.ownerGroup (takeDirectory f) user (userGroup user)
 	keyfile ext = case dest of
-		Nothing -> do
-			home <- homeDirectory <$> getUserEntryForName u
-			return $ home </> ".ssh" </> "id_" ++ fromKeyType keytype ++ ext
-		Just f -> return $ f ++ ext
+		Nothing -> relhomessh $ "id_" ++ fromKeyType keytype ++ ext
+		Just f
+			| isRelative f -> relhomessh (f ++ ext)
+			| otherwise -> return (f ++ ext)
+	relhomessh f = do
+		home <- homeDirectory <$> getUserEntryForName u
+		return $ home </> ".ssh" </> f
 
 fromKeyType :: SshKeyType -> String
 fromKeyType SshRsa = "rsa"

comment
diff --git a/doc/forum/Getting_Info_from_containers/comment_1_2e6f117f7a3ba93f61695aea08a928b4._comment b/doc/forum/Getting_Info_from_containers/comment_1_2e6f117f7a3ba93f61695aea08a928b4._comment
new file mode 100644
index 00000000..87895d4a
--- /dev/null
+++ b/doc/forum/Getting_Info_from_containers/comment_1_2e6f117f7a3ba93f61695aea08a928b4._comment
@@ -0,0 +1,32 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-04-16T14:35:26Z"
+ content="""
+Info can propagate out of containers, but then it becomes Info of the Host
+that the container is part of. The IsInfo type class has a propagateInfo
+that controls whether a value of that type propagates from container to
+host.
+
+The ssh HostKeyInfo has a propagateInfo that prevents propagation.
+This makes sense with the current data structure because the ssh host key
+inside the container does not replace the host key used outside. The data
+structures would need to be changed in some way to support propagation.
+I guess HostKeyInfo could be changed to a map from hostname to what it
+contains now.
+
+There would be follow-on changes needed, eg Dns.genSSHFP adds the ssh host
+key to a dns record, and I think it would only make sense for that to add
+the host's ssh key, not one for each container.
+
+WRT the name of a systemd container, it's not a hostname, but a systemd
+machine name. Propellor does not currently track the hostname of a
+container as Info (and the Info system is actually not used for hostnames
+since the hostname is part of each Host). The closest thing available
+currently is Propellor.Info.alias which can be used in a container to add
+an CNAME to the Host that contains it.
+
+Anyway, changing the name of a systemd container would indeed build a new
+container. I'd probably revert the current property (so it deletes the
+current container) and add a new property with the new name.
+"""]]

Added a comment
diff --git a/doc/forum/need_help_to_write_a_property_of_a_generic_kind/comment_2_2a9edee1c4f8ca02197094f1e988ef94._comment b/doc/forum/need_help_to_write_a_property_of_a_generic_kind/comment_2_2a9edee1c4f8ca02197094f1e988ef94._comment
new file mode 100644
index 00000000..ea8dada9
--- /dev/null
+++ b/doc/forum/need_help_to_write_a_property_of_a_generic_kind/comment_2_2a9edee1c4f8ca02197094f1e988ef94._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="comment 2"
+ date="2019-04-14T20:44:31Z"
+ content="""
+Thanks for the analysis.
+
+My `withPassword` parameter can actually have two different types, depending
+on whether it gets password from privdata or not.
+
+Most of my problems when writing complex properties are due to the Property
+kind, may be I should write simpler properties :)
+
+"""]]

Getting Info from containers
diff --git a/doc/forum/Getting_Info_from_containers.mdwn b/doc/forum/Getting_Info_from_containers.mdwn
new file mode 100644
index 00000000..dc4868ab
--- /dev/null
+++ b/doc/forum/Getting_Info_from_containers.mdwn
@@ -0,0 +1,17 @@
+Hello,
+
+I am using propellor mostly with Systemd containers. I have a problem when
+trying to use `Ssh.knownHost`, as the host to be known is not a host, but a
+container.
+
+Is this supposed to work? Are containers accessible like the other hosts with
+the info system?
+
+Also, I used short names for my containers, like:
+
+    vzWeb2 :: Systemd.Container
+    vzWeb2 = Systemd.debContainer "vz-web2" $ props
+
+but now I realize that I should have used a fqdn so that properties like
+`Hostname.sane` could find the domain name. But changing this implies that the
+container will be rebuilt, right?

Added a comment
diff --git a/doc/forum/build_propellor_binary/comment_1_12ab0dd45ddd67790f3539fe71c20f00._comment b/doc/forum/build_propellor_binary/comment_1_12ab0dd45ddd67790f3539fe71c20f00._comment
new file mode 100644
index 00000000..28402039
--- /dev/null
+++ b/doc/forum/build_propellor_binary/comment_1_12ab0dd45ddd67790f3539fe71c20f00._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="comment 1"
+ date="2019-04-14T20:25:12Z"
+ content="""
+There is a pending task about this, see [[todo/spin_without_remote_compilation]].
+"""]]

creating Ssh.userKeyAt should create the .ssh directory
diff --git a/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory.mdwn b/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory.mdwn
new file mode 100644
index 00000000..0c333c0c
--- /dev/null
+++ b/doc/todo/Ssh.userKeyAt_should_create_the_.ssh_directory.mdwn
@@ -0,0 +1,5 @@
+Hello,
+
+Maybe this should not create the directory as the given path is absolute, but unless my understanding is wrong, `Ssh.userKeys` does not create the directory either.
+
+Could there be a `Ssh.userKeyNamed` for example which would prepend `$HOME/.ssh` to the given name?

Added a comment: Tested Hostname in a systemd container
diff --git a/doc/todo/Hostname_is_not_set_in_a_systemd_container/comment_2_4328fcf8e0f65e2affe7841755a1fbe1._comment b/doc/todo/Hostname_is_not_set_in_a_systemd_container/comment_2_4328fcf8e0f65e2affe7841755a1fbe1._comment
new file mode 100644
index 00000000..01e178ef
--- /dev/null
+++ b/doc/todo/Hostname_is_not_set_in_a_systemd_container/comment_2_4328fcf8e0f65e2affe7841755a1fbe1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="Tested Hostname in a systemd container"
+ date="2019-04-11T18:33:40Z"
+ content="""
+I just tested it, it works, thanks!
+"""]]

diff --git a/doc/forum/build_propellor_binary.mdwn b/doc/forum/build_propellor_binary.mdwn
new file mode 100644
index 00000000..e8f6e771
--- /dev/null
+++ b/doc/forum/build_propellor_binary.mdwn
@@ -0,0 +1,13 @@
+Hi,
+
+I'd like to run propellor differently:
+
+- create a static binary from `config.hs`.
+- upload it to the target machine (which can be ARM, do not have GHC, et al).
+- run it.
+
+Propellor would build the binary if I ask it to with `propellor --build`; not static yet, but I think I can figure it out.
+
+How would I run a propellor binary on the local host, without trying to connect anywhere? I would be grateful if you could suggest an approach.
+
+Thank you!

change from inChroot to granular container capabilities info
* Removed inChroot, instead use hasContainerCapability FilesystemContained.
(API change)
* Hostname: Properties that used to not do anything in a systemd or
docker container will now change the container's hostname,
since it's namespaced.
More container capabilities can easily be added later, to fine grain
control what properties will run in different kinds of containers.
This changed CmdLine's Read instance, which should be ok, because propellor
inside the container is always updated at the same time as propellor
outside, so when it chains into the chroot, it will know to expect the
capability list.
Docker was not setting InChroot before, but now sets both container
capabilities, so chroot setting will also work in it. Note that,
things that used to check inChroot before would not work in docker, but
things that check FilesystemContained now will. It may be that some of
those properties don't really work properly in docker.
And, Grub.installed used to run grub-mkconfig in a docker container before,
I doubt that made sense (was it even safe?); it doesn't do it now.
This commit was sponsored by Trenton Cronholm on Patreon.
diff --git a/debian/changelog b/debian/changelog
index 988c3641..1d46fb53 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,13 @@
-propellor (5.7.1) UNRELEASED; urgency=medium
+propellor (5.8.0) UNRELEASED; urgency=medium
 
   * Fix bug in File.containsShellSetting that replaced whole shell conffile
     content with the setting if the file did not previously contain a line
     setting the key to some value.
+  * Removed inChroot, instead use hasContainerCapability FilesystemContained.
+    (API change)
+  * Hostname: Properties that used to not do anything in a systemd or
+    docker container will now change the container's hostname,
+    since it's namespaced.
 
  -- Joey Hess <id@joeyh.name>  Mon, 08 Apr 2019 11:09:04 -0400
 
diff --git a/doc/todo/Hostname_is_not_set_in_a_systemd_container.mdwn b/doc/todo/Hostname_is_not_set_in_a_systemd_container.mdwn
index e88dcac6..6b6db329 100644
--- a/doc/todo/Hostname_is_not_set_in_a_systemd_container.mdwn
+++ b/doc/todo/Hostname_is_not_set_in_a_systemd_container.mdwn
@@ -8,3 +8,5 @@ Note: I use `Systemd.containerCfg "network-bridge=br0"`, so the container has
 a different network stack.
 
 I suppose that the `check (not <$> inChroot)` might be the problem here.
+
+> [[fixed|done]]
diff --git a/doc/todo/Hostname_is_not_set_in_a_systemd_container/comment_1_239bf5057bb5a5f632523bf9ba2a71de._comment b/doc/todo/Hostname_is_not_set_in_a_systemd_container/comment_1_239bf5057bb5a5f632523bf9ba2a71de._comment
new file mode 100644
index 00000000..7da0cf12
--- /dev/null
+++ b/doc/todo/Hostname_is_not_set_in_a_systemd_container/comment_1_239bf5057bb5a5f632523bf9ba2a71de._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-04-08T15:37:45Z"
+ content="""
+I've fixed this by switching to a more granular data structure for
+describing the capabilities of a container.
+
+Didn't test it, but I think it will work..
+"""]]
diff --git a/src/Propellor/CmdLine.hs b/src/Propellor/CmdLine.hs
index bd01b34c..31e45da1 100644
--- a/src/Propellor/CmdLine.hs
+++ b/src/Propellor/CmdLine.hs
@@ -129,7 +129,7 @@ defaultMain hostlist = withConcurrentOutput $ do
 	go _ ListFields = listPrivDataFields hostlist
 	go _ (AddKey keyid) = addKey keyid
 	go _ (RmKey keyid) = rmKey keyid
-	go _ c@(ChrootChain _ _ _ _) = Chroot.chain hostlist c
+	go _ c@(ChrootChain _ _ _ _ _) = Chroot.chain hostlist c
 	go _ (DockerChain hn cid) = Docker.chain hostlist hn cid
 	go _ (DockerInit hn) = Docker.init hn
 	go _ (GitPush fin fout) = gitPushHelper fin fout
diff --git a/src/Propellor/Info.hs b/src/Propellor/Info.hs
index ba73b449..01a53ad5 100644
--- a/src/Propellor/Info.hs
+++ b/src/Propellor/Info.hs
@@ -11,6 +11,7 @@ module Propellor.Info (
 	pureInfoProperty',
 	askInfo,
 	getOS,
+	hasContainerCapability,
 	ipv4,
 	ipv6,
 	alias,
@@ -26,6 +27,7 @@ module Propellor.Info (
 import Propellor.Types
 import Propellor.Types.Info
 import Propellor.Types.MetaTypes
+import Propellor.Types.Container
 
 import "mtl" Control.Monad.Reader
 import qualified Data.Set as S
@@ -75,6 +77,11 @@ pureInfoProperty' desc i = setInfoProperty p i
 askInfo :: (IsInfo v) => Propellor v
 askInfo = asks (fromInfo . hostInfo)
 
+-- | Checks if a ContainerCapability is set in the current Info.
+hasContainerCapability :: ContainerCapability -> Propellor Bool
+hasContainerCapability c = elem c
+	<$> (askInfo ::  Propellor [ContainerCapability])
+
 -- | Specifies that a host's operating system is Debian,
 -- and further indicates the suite and architecture.
 -- 
diff --git a/src/Propellor/Property/Bootstrap.hs b/src/Propellor/Property/Bootstrap.hs
index 6bbb4512..35df08e0 100644
--- a/src/Propellor/Property/Bootstrap.hs
+++ b/src/Propellor/Property/Bootstrap.hs
@@ -13,6 +13,7 @@ module Propellor.Property.Bootstrap (
 import Propellor.Base
 import Propellor.Bootstrap
 import Propellor.Types.Info
+import Propellor.Types.Container
 import Propellor.Property.Chroot
 import Propellor.PrivData.Paths
 
@@ -58,7 +59,7 @@ data RepoSource
 -- All build dependencies are installed, using distribution packages
 -- or falling back to using cabal or stack.
 bootstrappedFrom :: RepoSource -> Property Linux
-bootstrappedFrom reposource = check inChroot $
+bootstrappedFrom reposource = check (hasContainerCapability FilesystemContained) $
 	go `requires` clonedFrom reposource
   where
 	go :: Property Linux
@@ -133,7 +134,7 @@ clonedFrom reposource = case reposource of
 			liftIO $ B.writeFile gitconfig cfg
 		return MadeChange
 
-	needclone = (inChroot <&&> truelocaldirisempty)
+	needclone = (hasContainerCapability FilesystemContained <&&> truelocaldirisempty)
 		<||> (liftIO (not <$> doesDirectoryExist localdir))
 	
 	truelocaldirisempty = exposeTrueLocaldir $ const $
diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs
index 5d29538c..48d96dcf 100644
--- a/src/Propellor/Property/Chroot.hs
+++ b/src/Propellor/Property/Chroot.hs
@@ -9,7 +9,6 @@ module Propellor.Property.Chroot (
 	ChrootBootstrapper(..),
 	Debootstrapped(..),
 	ChrootTarball(..),
-	inChroot,
 	exposeTrueLocaldir,
 	-- * Internal use
 	provisioned',
@@ -23,6 +22,7 @@ import Propellor.Base
 import Propellor.Container
 import Propellor.Types.CmdLine
 import Propellor.Types.Chroot
+import Propellor.Types.Container
 import Propellor.Types.Info
 import Propellor.Types.Core
 import Propellor.Property.Chroot.Util
@@ -127,19 +127,20 @@ bootstrapped bootstrapper location ps = c
 -- is first unmounted. Note that it does not ensure that any processes
 -- that might be running inside the chroot are stopped.
 provisioned :: Chroot -> RevertableProperty (HasInfo + Linux) Linux
-provisioned c = provisioned' c False
+provisioned c = provisioned' c False [FilesystemContained]
 
 provisioned'
 	:: Chroot
 	-> Bool
+	-> [ContainerCapability]
 	-> RevertableProperty (HasInfo + Linux) Linux
-provisioned' c@(Chroot loc bootstrapper infopropigator _) systemdonly =
+provisioned' c@(Chroot loc bootstrapper infopropigator _) systemdonly caps =
 	(infopropigator c normalContainerInfo $ setup `describe` chrootDesc c "exists")
 		<!>
 	(teardown `describe` chrootDesc c "removed")
   where
 	setup :: Property Linux
-	setup = propellChroot c (inChrootProcess (not systemdonly) c) systemdonly
+	setup = propellChroot c (inChrootProcess (not systemdonly) c) systemdonly caps
 		`requires` built
 
 	built = case buildchroot bootstrapper (chrootSystem c) loc of
@@ -165,8 +166,8 @@ chrootInfo (Chroot loc _ _ h) = mempty `addInfo`
 	mempty { _chroots = M.singleton loc h }
 
 -- | Propellor is run inside the chroot to provision it.
-propellChroot :: Chroot -> ([String] -> IO (CreateProcess, IO ())) -> Bool -> Property UnixLike
-propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "provisioned") $ do
+propellChroot :: Chroot -> ([String] -> IO (CreateProcess, IO ())) -> Bool -> [ContainerCapability] -> Property UnixLike
+propellChroot c@(Chroot loc _ _ _) mkproc systemdonly caps = property (chrootDesc c "provisioned") $ do
 	let d = localdir </> shimdir c
 	let me = localdir </> "propellor"
 	shim <- liftIO $ Shim.setup me Nothing d
@@ -188,7 +189,7 @@ propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "
 
 	chainprovision shim = do
 		parenthost <- asks hostName
-		cmd <- liftIO $ toChain parenthost c systemdonly
+		cmd <- liftIO $ toChain parenthost c systemdonly caps
 		pe <- liftIO standardPathEnv
 		(p, cleanup) <- liftIO $ mkproc
 			[ shim
@@ -199,13 +200,13 @@ propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "
 		liftIO cleanup
 		return r
 
-toChain :: HostName -> Chroot -> Bool -> IO CmdLine
-toChain parenthost (Chroot loc _ _ _) systemdonly = do
+toChain :: HostName -> Chroot -> Bool -> [ContainerCapability] -> IO CmdLine
+toChain parenthost (Chroot loc _ _ _) systemdonly caps = do
 	onconsole <- isConsole <$> getMessageHandle
-	return $ ChrootChain parenthost loc systemdonly onconsole
+	return $ ChrootChain parenthost loc systemdonly onconsole caps
 
 chain :: [Host] -> CmdLine -> IO ()
-chain hostlist (ChrootChain hn loc systemdonly onconsole) =
+chain hostlist (ChrootChain hn loc systemdonly onconsole caps) =
 	case findHostNoAlias hostlist hn of

(Diff truncated)
Hostname is not set in a systemd container
diff --git a/doc/todo/Hostname_is_not_set_in_a_systemd_container.mdwn b/doc/todo/Hostname_is_not_set_in_a_systemd_container.mdwn
new file mode 100644
index 00000000..e88dcac6
--- /dev/null
+++ b/doc/todo/Hostname_is_not_set_in_a_systemd_container.mdwn
@@ -0,0 +1,10 @@
+Hello,
+
+I use propellor to deploy systemd containers. I have a problem with
+`Hostname.setTo`, it sets the hostname in `/etc/hostname`, but the container
+hostname is not set until I restart the container.
+
+Note: I use `Systemd.containerCfg "network-bridge=br0"`, so the container has
+a different network stack.
+
+I suppose that the `check (not <$> inChroot)` might be the problem here.

Added a comment
diff --git a/doc/forum/How_can_File.mode_be_used_in_config.hs___63__/comment_2_214c8c06bffb879b8277323bb96ce7fc._comment b/doc/forum/How_can_File.mode_be_used_in_config.hs___63__/comment_2_214c8c06bffb879b8277323bb96ce7fc._comment
new file mode 100644
index 00000000..d887f281
--- /dev/null
+++ b/doc/forum/How_can_File.mode_be_used_in_config.hs___63__/comment_2_214c8c06bffb879b8277323bb96ce7fc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="comment 2"
+ date="2019-04-07T14:05:06Z"
+ content="""
+OK, thanks.
+"""]]

add news item for propellor 5.7.0
diff --git a/doc/news/version_5.4.0.mdwn b/doc/news/version_5.4.0.mdwn
deleted file mode 100644
index e63f8c6c..00000000
--- a/doc/news/version_5.4.0.mdwn
+++ /dev/null
@@ -1,13 +0,0 @@
-propellor 5.4.0 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * [ Sean Whitton ]
-   * Apt.installedBackport replaced with Apt.backportInstalled.  (API change)
-     The old property would install dependencies from backports even when
-     the versions in stable satisfy the requested backport's dependencies.
-     The new property installs only the listed packages from backports;
-     all other dependencies come from stable.
-     So in some cases, you may need to list additional backports to install,
-     that would not have needed to be listed before. Due to this behavior
-     change the property has been renamed so uses of it will be checked.
-   * Restic.installed: stop trying to install a backport on jessie, because no
-     such backport exists."""]]
\ No newline at end of file
diff --git a/doc/news/version_5.7.0.mdwn b/doc/news/version_5.7.0.mdwn
new file mode 100644
index 00000000..194a2a6f
--- /dev/null
+++ b/doc/news/version_5.7.0.mdwn
@@ -0,0 +1,20 @@
+propellor 5.7.0 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Sbuild.built no longer includes Apt.stdSourcesList by default,
+     in order to support non-Debian OS's. (API change)
+     To upgrade: Simply add Sbuild.osDebianStandard to all Sbuild.built
+     calls which have osDebian.
+     Thanks, Sean Whitton
+   * Propellor.Property.PropellorRepo renamed to Propellor.Property.Localdir
+     to widen its scope. (API change)
+   * Added Localdir.removed property.
+     Thanks, Sean Whitton
+   * Sbuild.built uses Localdir.removed to clean up the propellor localdir
+     after it's done running in a schroot.
+     Thanks, Sean Whitton
+   * Cron.runPropellor made revertable. (minor API change)
+     Thanks, Sean Whitton
+   * Added Cron.jobDropped.
+     Thanks, Sean Whitton
+   * Added Utility.FileMode to the modules exported by Propellor.Utilities
+     to propellor library users."""]]
\ No newline at end of file

Added a comment: Patch series submitted
diff --git a/doc/todo/unpropelling_a_host/comment_2_fb572083e8f8bccef037d43a4f7487c2._comment b/doc/todo/unpropelling_a_host/comment_2_fb572083e8f8bccef037d43a4f7487c2._comment
new file mode 100644
index 00000000..728e3fae
--- /dev/null
+++ b/doc/todo/unpropelling_a_host/comment_2_fb572083e8f8bccef037d43a4f7487c2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="Patch series submitted"
+ date="2019-04-01T17:21:40Z"
+ content="""
+I've just mailed patches addressing this to Joey.
+"""]]

comment
diff --git a/doc/forum/need_help_to_write_a_property_of_a_generic_kind/comment_1_9de1b00ba845174d2e8df191578cde3c._comment b/doc/forum/need_help_to_write_a_property_of_a_generic_kind/comment_1_9de1b00ba845174d2e8df191578cde3c._comment
new file mode 100644
index 00000000..283d6864
--- /dev/null
+++ b/doc/forum/need_help_to_write_a_property_of_a_generic_kind/comment_1_9de1b00ba845174d2e8df191578cde3c._comment
@@ -0,0 +1,67 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-04-01T15:54:33Z"
+ content="""
+Building that, the first error message is this:
+
+      Expected type: RevertableProperty (HasInfo + DebianLike) UnixLike
+        Actual type: RevertableProperty
+                       (CombinedType
+                          (Property
+                             (Propellor.Types.MetaTypes.MetaTypes
+                                '['Propellor.Types.MetaTypes.WithInfo,
+                                  'Propellor.Types.MetaTypes.Targeting 'OSDebian,
+                                  'Propellor.Types.MetaTypes.Targeting 'OSBuntish,
+                                  'Propellor.Types.MetaTypes.Targeting 'OSArchLinux,
+                                  'Propellor.Types.MetaTypes.Targeting 'OSFreeBSD]))
+                          (Property UnixLike))
+                       UnixLike
+
+It's really complaining
+that it expected HasInfo + DebianLike and got HasInfo + UnixLike; ie your
+property seems to also support ArchLinux and FreeBSD. (Whether it really
+does, I don't know.)
+
+There seem to be several similar errors in the supported OS's, which don't
+help with focusing on the other errors..
+
+I have not found a solution to all of those, but part of the problem
+is that, inside a where clause a type annotation with a type variable
+such as `i` is not understood to refer to the same variable in the
+outer type annotation. There's some ghc extension that enables that,
+but I can never remember its name.
+
+After removing those inner type annotations, the remaining type error
+was with userGrantedProp.. So I removed its type annotation as well
+and let ghc infer its type. (Had to enable LANGUAGE TypeFamilies for it
+to be able to.) Here's what ghc thinks it is:
+
+    Top-level binding with no type signature:
+      userGrantedProp :: (Propellor.Types.Singletons.SingI outer,
+                          Propellor.Types.MetaTypes.NotSuperset
+                            '['Propellor.Types.MetaTypes.Targeting 'OSDebian,
+                              'Propellor.Types.MetaTypes.Targeting 'OSBuntish,
+                              'Propellor.Types.MetaTypes.Targeting 'OSArchLinux,
+                              'Propellor.Types.MetaTypes.Targeting 'OSFreeBSD]
+                            (Propellor.Types.MetaTypes.Targets outer)
+                          ~ 'Propellor.Types.MetaTypes.CanCombine) =>
+                         User
+                         -> [Privilege]
+                         -> ((((String -> Propellor Result) -> Propellor Result)
+                              -> Property (Propellor.Types.MetaTypes.MetaTypes outer))
+                             -> Property setupmetatypes)
+                         -> Desc
+                         -> ([Char] -> String -> [Char] -> [Char])
+                         -> ([Char] -> String -> [Char] -> String)
+                         -> RevertableProperty setupmetatypes UnixLike
+
+That's not very human friendly a way to write its type, but it gives some
+good direction. Note in particular that the type of withPassword seems to
+involve two different types of Property, not the single `Property i` that
+your original type uses in both places.
+
+I have a feeling though that there may be a bug in the code around withPassword
+that is leading to this type and that the type error is not really the root
+problem.
+"""]]

Added Utility.FileMode to the modules exported by Propellor.Utilities
Since File.mode uses FileMode, it seems it ought to be exported by
propellor somewhere. I don't want to make propellor Property modules
themselves export core data types though, so this is a compromise of
dubious utility.
diff --git a/debian/changelog b/debian/changelog
index 73540dfe..87e924e3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,6 +5,8 @@ propellor (5.7.0) UNRELEASED; urgency=medium
     To upgrade: Simply add Sbuild.osDebianStandard to all Sbuild.built
     calls which have osDebian.
     Thanks, Sean Whitton
+  * Added Utility.FileMode to the modules exported by Propellor.Utilities
+    to propellor library users.
 
  -- Joey Hess <id@joeyh.name>  Mon, 01 Apr 2019 11:35:15 -0400
 
diff --git a/doc/forum/How_can_File.mode_be_used_in_config.hs___63__/comment_1_c176c1507c6f08917b4e5d2a70b19ee4._comment b/doc/forum/How_can_File.mode_be_used_in_config.hs___63__/comment_1_c176c1507c6f08917b4e5d2a70b19ee4._comment
new file mode 100644
index 00000000..da031715
--- /dev/null
+++ b/doc/forum/How_can_File.mode_be_used_in_config.hs___63__/comment_1_c176c1507c6f08917b4e5d2a70b19ee4._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-04-01T15:49:26Z"
+ content="""
+Yes, you'll need to add a dependency on `unix` to get access to that.
+
+This does seem like an oversight, so I made Propellor.Utilities re-export
+it. But, I think I'd personally choose the dependency on `unix` instead
+of relying on that module, which does not guarantee any API stability.
+"""]]
diff --git a/src/Propellor/Git/VerifiedBranch.hs b/src/Propellor/Git/VerifiedBranch.hs
index 61f5baa0..408e0200 100644
--- a/src/Propellor/Git/VerifiedBranch.hs
+++ b/src/Propellor/Git/VerifiedBranch.hs
@@ -3,7 +3,6 @@ module Propellor.Git.VerifiedBranch where
 import Propellor.Base
 import Propellor.Git
 import Propellor.PrivData.Paths
-import Utility.FileMode
 
 {- To verify origin branch commit's signature, have to convince gpg
  - to use our keyring while running git verify-tag.
diff --git a/src/Propellor/Property/Bootstrap.hs b/src/Propellor/Property/Bootstrap.hs
index 25a6af33..6bbb4512 100644
--- a/src/Propellor/Property/Bootstrap.hs
+++ b/src/Propellor/Property/Bootstrap.hs
@@ -15,7 +15,6 @@ import Propellor.Bootstrap
 import Propellor.Types.Info
 import Propellor.Property.Chroot
 import Propellor.PrivData.Paths
-import Utility.FileMode
 
 import Data.List
 import qualified Data.ByteString as B
diff --git a/src/Propellor/Property/Ccache.hs b/src/Propellor/Property/Ccache.hs
index ea729b7c..fad3a28f 100644
--- a/src/Propellor/Property/Ccache.hs
+++ b/src/Propellor/Property/Ccache.hs
@@ -11,7 +11,6 @@ import Propellor.Base
 import qualified Propellor.Property.File as File
 import qualified Propellor.Property.Apt as Apt
 
-import Utility.FileMode
 import Utility.DataUnits
 import System.Posix.Files
 import qualified Data.Semigroup as Sem
diff --git a/src/Propellor/Property/Cron.hs b/src/Propellor/Property/Cron.hs
index b9fb10e0..0271b0b3 100644
--- a/src/Propellor/Property/Cron.hs
+++ b/src/Propellor/Property/Cron.hs
@@ -4,7 +4,6 @@ import Propellor.Base
 import qualified Propellor.Property.File as File
 import qualified Propellor.Property.Apt as Apt
 import Propellor.Bootstrap
-import Utility.FileMode
 
 import Data.Char
 
diff --git a/src/Propellor/Property/Debootstrap.hs b/src/Propellor/Property/Debootstrap.hs
index 923229be..6336e775 100644
--- a/src/Propellor/Property/Debootstrap.hs
+++ b/src/Propellor/Property/Debootstrap.hs
@@ -15,7 +15,6 @@ import qualified Propellor.Property.Apt as Apt
 import Propellor.Property.Chroot.Util
 import Propellor.Property.Qemu
 import Utility.Path
-import Utility.FileMode
 
 import Data.List
 import Data.Char
diff --git a/src/Propellor/Property/DiskImage.hs b/src/Propellor/Property/DiskImage.hs
index 29bc2d1c..b7651b98 100644
--- a/src/Propellor/Property/DiskImage.hs
+++ b/src/Propellor/Property/DiskImage.hs
@@ -42,7 +42,6 @@ import Propellor.Types.Info
 import Propellor.Types.Bootloader
 import Propellor.Container
 import Utility.Path
-import Utility.FileMode
 import Utility.DataUnits
 
 import Data.List (isPrefixOf, isInfixOf, sortBy, unzip4)
diff --git a/src/Propellor/Property/File.hs b/src/Propellor/Property/File.hs
index 3188879e..e6d657f9 100644
--- a/src/Propellor/Property/File.hs
+++ b/src/Propellor/Property/File.hs
@@ -3,7 +3,6 @@
 module Propellor.Property.File where
 
 import Propellor.Base
-import Utility.FileMode
 
 import qualified Data.ByteString.Lazy as L
 import Data.List (isInfixOf, isPrefixOf)
diff --git a/src/Propellor/Property/HostingProvider/Linode.hs b/src/Propellor/Property/HostingProvider/Linode.hs
index ebe8d261..fc5d1a0c 100644
--- a/src/Propellor/Property/HostingProvider/Linode.hs
+++ b/src/Propellor/Property/HostingProvider/Linode.hs
@@ -3,7 +3,6 @@ module Propellor.Property.HostingProvider.Linode where
 import Propellor.Base
 import qualified Propellor.Property.Grub as Grub
 import qualified Propellor.Property.File as File
-import Utility.FileMode
 
 -- | Configures grub to use the serial console as set up by Linode.
 -- Useful when running a distribution supplied kernel.
diff --git a/src/Propellor/Property/Openssl.hs b/src/Propellor/Property/Openssl.hs
index a91b8195..0cb7c9c2 100644
--- a/src/Propellor/Property/Openssl.hs
+++ b/src/Propellor/Property/Openssl.hs
@@ -5,10 +5,8 @@ module Propellor.Property.Openssl where
 import Propellor.Base
 import qualified Propellor.Property.Apt as Apt
 import qualified Propellor.Property.File as File
-import Utility.FileMode
 import Utility.SafeCommand
 
-
 installed :: Property DebianLike
 installed = Apt.installed ["openssl"]
 
diff --git a/src/Propellor/Property/Sbuild.hs b/src/Propellor/Property/Sbuild.hs
index fbd3da7a..b54f8170 100644
--- a/src/Propellor/Property/Sbuild.hs
+++ b/src/Propellor/Property/Sbuild.hs
@@ -89,7 +89,6 @@ import qualified Propellor.Property.File as File
 import qualified Propellor.Property.Schroot as Schroot
 import qualified Propellor.Property.Reboot as Reboot
 import qualified Propellor.Property.User as User
-import Utility.FileMode
 
 import Data.List
 
diff --git a/src/Propellor/Property/Schroot.hs b/src/Propellor/Property/Schroot.hs
index 2f399b7c..82afdc79 100644
--- a/src/Propellor/Property/Schroot.hs
+++ b/src/Propellor/Property/Schroot.hs
@@ -9,8 +9,6 @@ import Propellor.Types.Info
 import qualified Propellor.Property.File as File
 import qualified Propellor.Property.Apt as Apt
 
-import Utility.FileMode
-
 data UseOverlays = UseOverlays deriving (Eq, Show, Typeable)
 
 -- | Indicate that a schroots on a host should use @union-type=overlay@
diff --git a/src/Propellor/Property/Service.hs b/src/Propellor/Property/Service.hs
index 1c230ce0..396fbaf1 100644
--- a/src/Propellor/Property/Service.hs
+++ b/src/Propellor/Property/Service.hs
@@ -5,7 +5,6 @@ module Propellor.Property.Service where
 import Propellor.Base
 import Propellor.Types.Info
 import qualified Propellor.Property.File as File
-import Utility.FileMode
 
 type ServiceName = String
 
diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs
index e3dbbabd..c5cfbc71 100644
--- a/src/Propellor/Property/SiteSpecific/JoeySites.hs
+++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs
@@ -25,7 +25,6 @@ import qualified Propellor.Property.Network as Network
 import qualified Propellor.Property.Fail2Ban as Fail2Ban
 import qualified Propellor.Property.LetsEncrypt as LetsEncrypt
 import qualified Propellor.Property.Mount as Mount
-import Utility.FileMode
 import Utility.Split
 
 import Data.List
diff --git a/src/Propellor/Property/Ssh.hs b/src/Propellor/Property/Ssh.hs
index c23a121b..59698ec0 100644
--- a/src/Propellor/Property/Ssh.hs
+++ b/src/Propellor/Property/Ssh.hs
@@ -40,7 +40,6 @@ import qualified Propellor.Property.Service as Service
 import qualified Propellor.Property.Apt as Apt
 import Propellor.Property.User
 import Propellor.Types.Info
-import Utility.FileMode
 

(Diff truncated)
Sbuild.built no longer includes Apt.stdSourcesList by default, in order to support non-Debian OS's. (API change) To upgrade: Simply add Sbuild.osDebianStandard to all Sbuild.built calls which have osDebian. Thanks, Sean Whitton
diff --git a/debian/changelog b/debian/changelog
index 27496138..73540dfe 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+propellor (5.7.0) UNRELEASED; urgency=medium
+
+  * Sbuild.built no longer includes Apt.stdSourcesList by default,
+    in order to support non-Debian OS's. (API change)
+    To upgrade: Simply add Sbuild.osDebianStandard to all Sbuild.built
+    calls which have osDebian.
+    Thanks, Sean Whitton
+
+ -- Joey Hess <id@joeyh.name>  Mon, 01 Apr 2019 11:35:15 -0400
+
 propellor (5.6.1) unstable; urgency=medium
 
   * fix Libvirt.hs haddock build
diff --git a/doc/todo/Sbuild_support_for_Buntish.mdwn b/doc/todo/Sbuild_support_for_Buntish.mdwn
index 03a4835e..43a5d2d1 100644
--- a/doc/todo/Sbuild_support_for_Buntish.mdwn
+++ b/doc/todo/Sbuild_support_for_Buntish.mdwn
@@ -1,2 +1,4 @@
 Property.Sbuild claims to support Buntish Oses, but for me it fails in Apt.stdSourcesList, because that function currently (5.6.1) only supports
 Debian.  I suppose the right solution is to extend Apt.stdSourcesList, but maybe Property.Sbuild should do it's own thing?
+
+> Patch applied (and it is an API change) [[done]] --[[Joey]]

How can File.mode be used in config.hs?
diff --git a/doc/forum/How_can_File.mode_be_used_in_config.hs___63__.mdwn b/doc/forum/How_can_File.mode_be_used_in_config.hs___63__.mdwn
new file mode 100644
index 00000000..b2e1837c
--- /dev/null
+++ b/doc/forum/How_can_File.mode_be_used_in_config.hs___63__.mdwn
@@ -0,0 +1,7 @@
+Hello,
+
+if I try to use `File.mode` in my `config.hs`, I do not have access to modes
+defined in `Utility.FileMode` and `System.Posix.Files`. Is that intended? Is
+there a way to do it appart from changing `propellor.cabal`?
+
+Thanks!

Added a comment: patch submitted
diff --git a/doc/todo/Sbuild_support_for_Buntish/comment_6_8727a5eba0ae8daddba8a023dc845837._comment b/doc/todo/Sbuild_support_for_Buntish/comment_6_8727a5eba0ae8daddba8a023dc845837._comment
new file mode 100644
index 00000000..0c3449c7
--- /dev/null
+++ b/doc/todo/Sbuild_support_for_Buntish/comment_6_8727a5eba0ae8daddba8a023dc845837._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="patch submitted"
+ date="2019-03-29T23:29:22Z"
+ content="""
+I've e-mailed a tested patch to Joey, CCing David.
+"""]]

report bug
diff --git a/doc/todo/Debootstrap.built_should_install_the_relevant_archive_keyring_package.mdwn b/doc/todo/Debootstrap.built_should_install_the_relevant_archive_keyring_package.mdwn
new file mode 100644
index 00000000..23fa65ef
--- /dev/null
+++ b/doc/todo/Debootstrap.built_should_install_the_relevant_archive_keyring_package.mdwn
@@ -0,0 +1,5 @@
+Attempting to build a Buntish chroot using Debootstrap.built on a Debian host fails until the user installs the ubuntu-archive-keyring package.
+
+Debootstrap.built should ensure that the relevant *-archive-keyring package is installed before invoking debootstrap(1).
+
+--spwhitton

fix .dir-locals.el to avoid apparent memory leak bug with Emacs 26
diff --git a/doc/coding_style.mdwn b/doc/coding_style.mdwn
index bf127fe0..8c464b9d 100644
--- a/doc/coding_style.mdwn
+++ b/doc/coding_style.mdwn
@@ -120,6 +120,6 @@ Note for emacs users: You can put the following snippet into a file called
 	         (tab-width . 8)
 	         (fill-column . 80)))
 	 ;; Warn about spaces used for indentation:
-	 (haskell-mode . ((eval . (highlight-regexp "^ *")))))
+	 (haskell-mode . ((eval . (highlight-regexp "^ +")))))
 
 Also consider [haskell-tab-indent-mode](https://spwhitton.name/tech/code/haskell-tab-indent/).  The standard indentation modes that come with haskell-mode do not work well with tabs for indentation.  This mode works well for hacking on Propellor.

Need help to write a property of a generic kind
diff --git a/doc/forum/need_help_to_write_a_property_of_a_generic_kind.mdwn b/doc/forum/need_help_to_write_a_property_of_a_generic_kind.mdwn
new file mode 100644
index 00000000..bdbee67e
--- /dev/null
+++ b/doc/forum/need_help_to_write_a_property_of_a_generic_kind.mdwn
@@ -0,0 +1,69 @@
+Hello,
+
+I have written a property to create a Mysql user which take the password from
+privdata. Now, I need to generate many passwords for several PHP sites, so I
+wrote a function to generate password using a hash of a secret salt and
+information from the context (site name).  This password will be written in a
+.php file to configure the application.
+
+I added a function `Mysql.userGrantedOnDatabaseWithPassword`, so that I can give
+it the computed password and use a common function to return the property.
+The problem is that when using privdata, the common function should return a:
+
+    ReversibleProperty (HasInfo + DebianLike) UnixLike
+
+And when not using privdata, it should return a:
+
+    ReversibleProperty DebianLike UnixLike
+
+The function takes a parameter to handle the password retrieval (`i` is `(HasInfo
++ DebianLike)` or `DebianLike`):
+
+    ((((String -> Propellor Result) -> Propellor Result) -> Property i) -> Property i)
+
+This is a type similar to `withPrivData`, but adapted to give just the
+password:
+
+	-- | Common code to get password from private data.
+	withPasswordFromPrivData
+		:: IsContext c
+		=> User
+		-> c
+		-> ((((String -> Propellor Result) -> Propellor Result)
+			-> Property (HasInfo + UnixLike))
+				-> Property (HasInfo + UnixLike))
+	withPasswordFromPrivData (User username) context = \mkprop ->
+		withPrivData (Password username) context
+			$ \getdata -> mkprop
+				$ \a -> getdata $ \priv -> a $ privDataVal priv
+
+	-- | Common code to pass password from parameter.
+	withPasswordFromParameter
+		:: String
+		-> ((((String -> Propellor Result) -> Propellor Result)
+			-> Property UnixLike) -> Property UnixLike)
+	withPasswordFromParameter password = \mkprop ->
+		mkprop $ \a -> a password
+
+I do not find a way to write the type of my function with the common code, the
+current best is:
+
+	userGrantedProp
+		:: Combines (Property i) (Property UnixLike)
+		=> User
+		-> [Privilege]
+		-> ((((String -> Propellor Result) -> Propellor Result)
+			-> Property i) -> Property i)
+		-> String
+		-> (String -> String -> String -> String)
+		-> (String -> String -> String -> String)
+		-> RevertableProperty (CombinedType (Property i) (Property UnixLike)) UnixLike
+	userGrantedProp (User username) privs withPassword setupDesc setupSql userGrants =
+
+But it still does not compile.
+
+The full code is available on my `mysql-wip` branch on
+`http://git.ni.fr.eu.org/nicolas/propellor.git`, I would be glad if you can have
+a look, pure haskell fun guaranteed :-).
+
+Thanks.

Added a comment
diff --git a/doc/forum/Adding_support_for_a_SQL_server/comment_9_a952549ea4d54c8becc8e9c1b058eec6._comment b/doc/forum/Adding_support_for_a_SQL_server/comment_9_a952549ea4d54c8becc8e9c1b058eec6._comment
new file mode 100644
index 00000000..f8ecaa9d
--- /dev/null
+++ b/doc/forum/Adding_support_for_a_SQL_server/comment_9_a952549ea4d54c8becc8e9c1b058eec6._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="comment 9"
+ date="2019-03-26T17:26:03Z"
+ content="""
+Hello,
+
+I have added a function to restore a database from a backup. It works like the Borg.restored property, it will restore only if the database is empty.
+
+Also included is a fix to wait that the server is available. This is needed when a container is just started for example.
+"""]]

Added a comment
diff --git a/doc/todo/Sbuild_support_for_Buntish/comment_5_e976f396ed6e0aa596fed5c7777e08a0._comment b/doc/todo/Sbuild_support_for_Buntish/comment_5_e976f396ed6e0aa596fed5c7777e08a0._comment
new file mode 100644
index 00000000..876ef434
--- /dev/null
+++ b/doc/todo/Sbuild_support_for_Buntish/comment_5_e976f396ed6e0aa596fed5c7777e08a0._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 5"
+ date="2019-03-18T01:35:38Z"
+ content="""
+`Sbuild.builtFor` assumes that ccache and eatmydata are installed, so I think that those need to be moved out of `Sbuild.standard` and back where they were.
+
+David, have you tested that Debian schroots still work with Joey's patch?
+"""]]

idea
diff --git a/doc/todo/serialize_actions_via_free_applicative.mdwn b/doc/todo/serialize_actions_via_free_applicative.mdwn
new file mode 100644
index 00000000..8659e76e
--- /dev/null
+++ b/doc/todo/serialize_actions_via_free_applicative.mdwn
@@ -0,0 +1,34 @@
+A persistent problem with propellor is that Propellor actions cannot be
+compared for equality or serialized.
+
+This prevents eg, propellor outside a chroot from passing a Property to run
+to the propellor running inside the chroot. (Because Property contains 
+a Propellor action.) A workaround is used, that gives the 
+Property a name at compile time.
+
+Another problem is that Propellor actions currently run whatever IO they
+perform, and can't be examined in a no-op mode.
+
+If Propellor actions were somehow represented as an AST, all these problems
+would be eliminated; they could be serialized, compared, examined, and run
+in modes that don't really run them.
+
+(This might also allow the local propellor to ship the AST off to the
+remote propellor to run, without the remote propellor needing to be
+rebuilt, if they share the same version of the AST.)
+
+Unfortunately, a free Monad can't be serialized, it's an AST but an AST
+embedding haskell functions. However, a free Applicative can apparently be
+serialized. 
+
+See <https://www.cs.ox.ac.uk/jeremy.gibbons/publications/delivery.pdf>
+and <https://www.reddit.com/r/haskell/comments/7rlgu2/serialize_a_program_written_in_a_free_monad/>
+
+Question is, would an Applicative building an AST be sufficient for
+everything that a Propellor action needs to do?
+
+This needs some investigation of the kind of IO that Propellor actions do.
+Much of it, I suspect is not very monadic, in that it mostly does some IO
+and returns a Result, rather than building up complex IO sequences based on
+previous inputs. --[[Joey]]
+

comment
diff --git a/doc/forum/Support_writing_as_owner__63__/comment_1_794b11f84e0dcb29eba36bdfe1220191._comment b/doc/forum/Support_writing_as_owner__63__/comment_1_794b11f84e0dcb29eba36bdfe1220191._comment
new file mode 100644
index 00000000..8edcefaa
--- /dev/null
+++ b/doc/forum/Support_writing_as_owner__63__/comment_1_794b11f84e0dcb29eba36bdfe1220191._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-03-17T15:13:20Z"
+ content="""
+If propellor could fork and then setuid, that would allow this. But..
+
+* forking is problimatic in haskell since the RTS state gets shared
+  and bad things happen
+* the result of the setuid action would need to be communicated back to the
+  main process somehow
+
+The other way would be to re-exec propellor as the user 
+with a parameter that somehow tells it what action to run. But I don't know
+a general way to do that, without some way to name the property.
+(A problem which has also complicated some other parts of propellor eg
+running inside chroots.)
+"""]]

Added a comment: Works on my machine ;)
diff --git a/doc/todo/Sbuild_support_for_Buntish/comment_4_c9f3103d192017a3291b82969dfd34f6._comment b/doc/todo/Sbuild_support_for_Buntish/comment_4_c9f3103d192017a3291b82969dfd34f6._comment
new file mode 100644
index 00000000..10d12d46
--- /dev/null
+++ b/doc/todo/Sbuild_support_for_Buntish/comment_4_c9f3103d192017a3291b82969dfd34f6._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="Works on my machine ;)"
+ date="2019-03-16T00:19:05Z"
+ content="""
+I had to hand apply most of Joey's patch for reasons that escape me, but it seems to work OK. I just built an ubuntu chroot and used sbuild to build a package in it. I did have to copy part of the definition of standard into my own setup code (the installation of \"eatmydata\" and \"ccache\"). So maybe there is something that could be made smoother there.
+
+"""]]

patch
diff --git a/doc/todo/Sbuild_support_for_Buntish/comment_3_81d771c54f1baac80a2ac93e4534d7a9._comment b/doc/todo/Sbuild_support_for_Buntish/comment_3_81d771c54f1baac80a2ac93e4534d7a9._comment
new file mode 100644
index 00000000..435af1a2
--- /dev/null
+++ b/doc/todo/Sbuild_support_for_Buntish/comment_3_81d771c54f1baac80a2ac93e4534d7a9._comment
@@ -0,0 +1,64 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2019-03-06T22:11:45Z"
+ content="""
+Something like this (only tested it compiles):
+
+	diff --git a/src/Propellor/Property/Sbuild.hs b/src/Propellor/Property/Sbuild.hs
+	index 8cc2e3bec..25d5f6236 100644
+	--- a/src/Propellor/Property/Sbuild.hs
+	+++ b/src/Propellor/Property/Sbuild.hs
+	@@ -29,6 +29,7 @@ Suggested usage in @config.hs@:
+	 >    where
+	 >  	sidSchrootBuilt = Sbuild.built Sbuild.UseCcache $ props
+	 >  		& osDebian Unstable X86_32
+	+>		& Sbuild.standard
+	 >  		& Sbuild.update `period` Weekly (Just 1)
+	 >  		& Sbuild.useHostProxy mybox
+	 
+	@@ -64,6 +65,7 @@ module Propellor.Property.Sbuild (
+	 	built,
+	 	-- * Properties for use inside sbuild schroots
+ 		update,
+	+	standard,
+ 		useHostProxy,
+ 		-- * Global sbuild configuration
+	 	-- blockNetwork,
+	@@ -126,7 +128,7 @@ built'
+	 	-> String
+	 	-> String
+	 	-> RevertableProperty (HasInfo + DebianLike) Linux
+	-built' cc (Props ps) suite arch = provisioned <!> deleted
+	+built' cc ps suite arch = provisioned <!> deleted
+	   where
+	 	provisioned :: Property (HasInfo + DebianLike)
+	 	provisioned = combineProperties desc $ props
+	@@ -220,10 +222,7 @@ built' cc (Props ps) suite arch = provisioned <!> deleted
+	 
+	 	-- the schroot itself
+	 	schroot = Chroot.debootstrapped Debootstrap.BuilddD
+	-			schrootRoot (Props schrootProps)
+	-	schrootProps =
+	-		ps ++ [toChildProperty Apt.stdSourcesList
+	-		, toChildProperty $ Apt.installed ["eatmydata", "ccache"]]
+	+			schrootRoot ps
+	 
+	 	-- static values
+	 	suiteArch = suite ++ "-" ++ arch
+	@@ -251,6 +250,14 @@ built' cc (Props ps) suite arch = provisioned <!> deleted
+	 	  where
+	 		base = ["eatmydata"]
+	 
+	+-- | Some properties that will be wanted in most any Debian schroot.
+	+--
+	+-- Compiler caching, eatmydata, and standard apt sources.
+	+standard :: Property Debian
+	+standard = propertyList "standard sbuild properties" $ props
+	+	& Apt.stdSourcesList
+	+	& Apt.installed ["eatmydata", "ccache"]
+	+
+	 -- | Ensure that an sbuild schroot's packages and apt indexes are updated
+	 --
+	 -- This replaces use of sbuild-update(1).
+"""]]

Added a comment
diff --git a/doc/todo/Sbuild_support_for_Buntish/comment_2_9bd0cc2462c12d1746b7dbf2496ebfee._comment b/doc/todo/Sbuild_support_for_Buntish/comment_2_9bd0cc2462c12d1746b7dbf2496ebfee._comment
new file mode 100644
index 00000000..809daba1
--- /dev/null
+++ b/doc/todo/Sbuild_support_for_Buntish/comment_2_9bd0cc2462c12d1746b7dbf2496ebfee._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 2"
+ date="2019-03-06T21:39:13Z"
+ content="""
+When implementing the Sbuild module we discussed the use of toChildProps and concluded that it was inevitable.
+
+However, if requiring the user to pass things around a bit more is the price for making the Sbuild module work for other OSs, we had better do it.
+"""]]

comment
diff --git a/doc/todo/Sbuild_support_for_Buntish/comment_1_1b75bf6efd01918f0a4db958ba8afe2b._comment b/doc/todo/Sbuild_support_for_Buntish/comment_1_1b75bf6efd01918f0a4db958ba8afe2b._comment
new file mode 100644
index 00000000..241e62e4
--- /dev/null
+++ b/doc/todo/Sbuild_support_for_Buntish/comment_1_1b75bf6efd01918f0a4db958ba8afe2b._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-03-06T19:35:16Z"
+ content="""
+In a way the problem is that schrootProps uses toChildProperty,
+which bypasses Propellor's type-level OS system.
+
+I think it may be possible to move the use of Apt.stdSourcesList
+out of Sbuild.built', and have the user pass those properties into it,
+along with the OS property and their other desired properties, 
+and let propellor type check that the properties passed to it all work
+together.
+"""]]

comment
diff --git a/doc/forum/noisy_imageBuilt/comment_1_a6384f47cc8abffa9cf26bf4bf7215a7._comment b/doc/forum/noisy_imageBuilt/comment_1_a6384f47cc8abffa9cf26bf4bf7215a7._comment
new file mode 100644
index 00000000..5dc1f762
--- /dev/null
+++ b/doc/forum/noisy_imageBuilt/comment_1_a6384f47cc8abffa9cf26bf4bf7215a7._comment
@@ -0,0 +1,24 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-03-06T19:01:17Z"
+ content="""
+This output comes from Propellor.Property.Rsync.rsync because it runs 
+`rsync --info=progress2`.
+
+I suppose it could check if stdout is going to a tty and only enable
+it then.
+
+However, I do have some code I wrote once that uses propellor to build a live
+disk image that runs propellor to partition and then used the rsync property to
+copy the live image to disk (followed by applying more properties to it to
+configure the system it installed). And that code caught the rsync progress
+output and used it to display some kind of graphical progress bar.
+That kind of thing would be broken by such a change.
+(That's in my secret-project repository.)
+
+I don't know of anyone using such a thing in production, so I think it would be
+ok to just have a `PROPELLOR_VERBOSEPROGRESS=1` that such code could use to
+enable verbose progress from rsync etc, and otherwise disable it when stdout is
+not a tty.
+"""]]

diff --git a/doc/forum/Support_writing_as_owner__63__.mdwn b/doc/forum/Support_writing_as_owner__63__.mdwn
new file mode 100644
index 00000000..289536ce
--- /dev/null
+++ b/doc/forum/Support_writing_as_owner__63__.mdwn
@@ -0,0 +1 @@
+I have one propellor managed system where the home directory is NFS mounted, with `root_squash` enabled. This  means that Ssh.authorizedKey fails with permission problems. On the other hand, root can su to the user in question.  It seems like it might be possible for propellor (maybe even desirable?) to write files as the owner, rather than using chown.

diff --git a/doc/todo/Sbuild_support_for_Buntish.mdwn b/doc/todo/Sbuild_support_for_Buntish.mdwn
new file mode 100644
index 00000000..03a4835e
--- /dev/null
+++ b/doc/todo/Sbuild_support_for_Buntish.mdwn
@@ -0,0 +1,2 @@
+Property.Sbuild claims to support Buntish Oses, but for me it fails in Apt.stdSourcesList, because that function currently (5.6.1) only supports
+Debian.  I suppose the right solution is to extend Apt.stdSourcesList, but maybe Property.Sbuild should do it's own thing?

diff --git a/doc/forum/noisy_imageBuilt.mdwn b/doc/forum/noisy_imageBuilt.mdwn
new file mode 100644
index 00000000..99a275b7
--- /dev/null
+++ b/doc/forum/noisy_imageBuilt.mdwn
@@ -0,0 +1,7 @@
+There is a bunch of output at the last stage of imageBuilt, which ends with
+
+>      5,548,912   0%   22.61MB/s    0:00:00 (xfr#3, to-chk=0/24715)   
+>      loop deleted : /dev/loop0
+
+This is fine interactively, but when a propellor job fails and I get email, it includes roughly 2500 similar lines, which is not so great.
+It would be nice if it could detect being interactive, or maybe just be quiet all the time.

thoughts
diff --git a/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_3_e83459b7775832e3885999eb28dca045._comment b/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_3_e83459b7775832e3885999eb28dca045._comment
new file mode 100644
index 00000000..3a6837aa
--- /dev/null
+++ b/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_3_e83459b7775832e3885999eb28dca045._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2019-02-17T18:07:39Z"
+ content="""
+Thinking more about a hypothetical property like
+`userGroupFunction (\User u -> Group (u ++ "-group"))`
+the idea seems problimatic because all the properties that install a
+package with a dedicated user and group would seem to need to be changed
+to support putting the user in the group configured by the property.
+
+I suppose it could be documented to be limited to non-system users and
+groups, so only User.accountFor would need to support when making users and
+groups, and Ssh.userKeyAt etc would use it to tell what group to use for a
+non-system user. 
+
+Although, is Ssh.userKeyAt etc really limited to being
+used with non-system users? Perhaps User should have an additional
+SystemUser constructor to encode the distinction. Or perhaps this idea of
+mine is going in the wrong direction.
+"""]]

comment
diff --git a/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_2_c4453a2fe31d52ce0c5e6e615f1b18b2._comment b/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_2_c4453a2fe31d52ce0c5e6e615f1b18b2._comment
new file mode 100644
index 00000000..1442b72a
--- /dev/null
+++ b/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_2_c4453a2fe31d52ce0c5e6e615f1b18b2._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2019-02-13T21:48:30Z"
+ content="""
+Make that into a git patch and I will merge it.
+
+However.. If you `git grep userGroup` you will find all the other places
+that propellor assumes a user-group system. Seems it would be worth fixing
+those too, especially the other ones in Ssh.
+
+Seems like another approach to it could be to make
+`userGroup`'s behavior configurable based on another Property
+of the Host that sets Info containing say, a function from `User -> Group`.
+Looks to me that would be doable, if a little bit annoying since userGroup
+would need to change from a pure function to a Propellor action in order to
+use `askInfo`.
+"""]]

Added a comment
diff --git a/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_1_609a113d809294c792d406ba72b0a1f2._comment b/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_1_609a113d809294c792d406ba72b0a1f2._comment
new file mode 100644
index 00000000..2014af74
--- /dev/null
+++ b/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__/comment_1_609a113d809294c792d406ba72b0a1f2._comment
@@ -0,0 +1,36 @@
+[[!comment format=mdwn
+ username="picca"
+ avatar="http://cdn.libravatar.org/avatar/7e61c80d28018b10d31f6db7dddb864c"
+ subject="comment 1"
+ date="2019-02-13T11:33:20Z"
+ content="""
+something like this
+
+    -- | Ensures that a user's authorized_keys contains a line.
+    -- Any other lines in the file are preserved as-is.
+    authorizedKey' :: User -> Group -> String -> RevertableProperty UnixLike UnixLike
+    authorizedKey' user@(User u) grp l = add <!> remove
+      where
+    	add = property' (u ++ \" has authorized_keys\") $ \w -> do
+    		f <- liftIO $ dotFile \"authorized_keys\" user
+    		ensureProperty w $ modAuthorizedKey' f user grp $
+    			f `File.containsLine` l
+    				`requires` File.dirExists (takeDirectory f)
+    	remove = property' (u ++ \" lacks authorized_keys\") $ \w -> do
+    		f <- liftIO $ dotFile \"authorized_keys\" user
+    		ifM (liftIO $ doesFileExist f)
+    			( ensureProperty w $ modAuthorizedKey' f user grp $
+    				f `File.lacksLine` l
+    			, return NoChange
+    			)
+    
+    modAuthorizedKey' :: FilePath -> User -> Group -> Property UnixLike -> Property UnixLike
+    modAuthorizedKey' f user grp p = p
+    	`before` File.mode f (combineModes [ownerWriteMode, ownerReadMode])
+    	`before` File.ownerGroup f user grp
+    	`before` File.ownerGroup (takeDirectory f) user grp
+
+then it is trivial to rewrite the previous properties :)
+
+but I do no know if this is the right path to follow.
+"""]]

diff --git a/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__.mdwn b/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__.mdwn
new file mode 100644
index 00000000..9b684ca3
--- /dev/null
+++ b/doc/forum/chown:_invalid_group:___8216__com-sixs:com-sixs__8217__.mdwn
@@ -0,0 +1,23 @@
+Hello Joey
+
+I try to use
+
+    Ssh.authorizedKey (User "com-sixs") sshKeyPubComSixs
+
+on a system where the account are available in a ldap.
+On this system the group is different from the user name
+name -> grp-name
+
+So I end up with this error message
+
+    chown: invalid group: ‘com-sixs:com-sixs’
+    sixs3.exp.synchrotron-soleil.fr com-sixs has authorized_keys ... failed
+
+so my questions are.
+
+- Is it mandatory to have a user and the identical group on a unix system ?
+- Can we add a Group parameter to the authorizedKey property ?
+
+thanks for your help
+
+Fred 

add news item for propellor 5.6.1
diff --git a/doc/news/version_5.3.6.mdwn b/doc/news/version_5.3.6.mdwn
deleted file mode 100644
index 7a7a417e..00000000
--- a/doc/news/version_5.3.6.mdwn
+++ /dev/null
@@ -1,13 +0,0 @@
-propellor 5.3.6 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Fix build with ghc 8.4, which broke due to the Semigroup Monoid change.
-   * Dropped support for building propellor with ghc 7 (as in debian
-     oldstable), to avoid needing to depend on the semigroups transitional
-     package, but also because it's just too old to be worth supporting.
-   * stack.yaml: Updated to lts-9.21.
-   * Make Schroot.overlaysInTmpfs revertable
-     Thanks, Sean Whitton
-   * Update shim each time propellor is run in a container, to deal with
-     library version changes.
-   * Unbound: Added support for various DNS record types.
-     Thanks, Félix Sipma."""]]
\ No newline at end of file
diff --git a/doc/news/version_5.6.1.mdwn b/doc/news/version_5.6.1.mdwn
new file mode 100644
index 00000000..739d49f7
--- /dev/null
+++ b/doc/news/version_5.6.1.mdwn
@@ -0,0 +1,4 @@
+propellor 5.6.1 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * fix Libvirt.hs haddock build
+     Thanks, Sean Whitton"""]]
\ No newline at end of file

add news item for propellor 5.6.0
diff --git a/doc/news/version_5.3.5.mdwn b/doc/news/version_5.3.5.mdwn
deleted file mode 100644
index a7da0f0c..00000000
--- a/doc/news/version_5.3.5.mdwn
+++ /dev/null
@@ -1,7 +0,0 @@
-propellor 5.3.5 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Apt.stdSourcesList now adds stable-updates suite
-     Thanks, Sean Whitton
-   * Significantly increased propellor build speed when your config.hs
-     is in a fork of the propellor repository, by avoiding redundant builds
-     of propellor library."""]]
\ No newline at end of file
diff --git a/doc/news/version_5.6.0.mdwn b/doc/news/version_5.6.0.mdwn
new file mode 100644
index 00000000..e3ecf2a4
--- /dev/null
+++ b/doc/news/version_5.6.0.mdwn
@@ -0,0 +1,22 @@
+propellor 5.6.0 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * withOS had a type level bug that allowed ensureProperty to be used inside
+     it with a Property that does not match the type of the withOS itself.
+     (API change)
+     The fix may cause some of your valid uses of withOS to no longer type
+     check; the best way to work around that is to use pickOS to pick between
+     several properties that are further specialized using withOS.
+     For an example of how to do that, see the source code to
+     Propellor.Property.Borg.installed
+   * Propellor.Property.Cron.runPropellor is a Property DebianLike; it was
+     incorrectly a Property UnixLike before and that wrong type was hidden by
+     the withOS bug.
+   * Some openbsd portability fixes. Thanks, rsiddharth.
+   * Added Libvirt module. Thanks, Sean Whitton.
+   * When bootstrapping on Debian, libghc-stm-dev may not be available,
+     as it's become part of ghc, so check before trying to install it.
+   * Fix build with ghc 8.6.3.
+   * Avoid exposing the constructor of OuterMetaTypesWitness, to avoid
+     the kind of mistake that led to the withOS bug.
+   * Merged Utility changes from git-annex.
+   * Fix --spin crash when ~/.ssh/ directory did not already exist."""]]
\ No newline at end of file

Fix --spin crash when ~/.ssh/ directory did not already exist.
diff --git a/debian/changelog b/debian/changelog
index 8bff519b..44187394 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -19,6 +19,7 @@ propellor (5.6.0) UNRELEASED; urgency=medium
   * Avoid exposing the constructor of OuterMetaTypesWitness, to avoid
     the kind of mistake that led to the withOS bug.
   * Merged Utility changes from git-annex.
+  * Fix --spin crash when ~/.ssh/ directory did not already exist.
 
  -- Joey Hess <id@joeyh.name>  Tue, 23 Oct 2018 11:37:16 -0400
 
diff --git a/doc/forum/__126____47__.ssh__47__propellor:_createDirectory:_does_not_exist___40__No_such_file_or_directory__41__/comment_1_b3a31b1fb2fbe7ada648d758398686ca._comment b/doc/forum/__126____47__.ssh__47__propellor:_createDirectory:_does_not_exist___40__No_such_file_or_directory__41__/comment_1_b3a31b1fb2fbe7ada648d758398686ca._comment
new file mode 100644
index 00000000..c961763d
--- /dev/null
+++ b/doc/forum/__126____47__.ssh__47__propellor:_createDirectory:_does_not_exist___40__No_such_file_or_directory__41__/comment_1_b3a31b1fb2fbe7ada648d758398686ca._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-01-18T16:11:19Z"
+ content="""
+Think I've fixed this now.
+"""]]
diff --git a/src/Propellor/Ssh.hs b/src/Propellor/Ssh.hs
index a8f50ed0..9ba15d86 100644
--- a/src/Propellor/Ssh.hs
+++ b/src/Propellor/Ssh.hs
@@ -19,7 +19,7 @@ sshCachingParams :: HostName -> IO [CommandParam]
 sshCachingParams hn = do
 	home <- myHomeDir
 	let socketfile = socketFile home hn
-	createDirectoryIfMissing False (takeDirectory socketfile)
+	createDirectoryIfMissing True (takeDirectory socketfile)
 	let ps =
 		[ Param "-o"
 		, Param ("ControlPath=" ++ socketfile)

update comment
diff --git a/doc/forum/Supported_OS/comment_1_f324bed708305e2667bd00f80544dd90._comment b/doc/forum/Supported_OS/comment_1_f324bed708305e2667bd00f80544dd90._comment
index 4869922e..84aad7f3 100644
--- a/doc/forum/Supported_OS/comment_1_f324bed708305e2667bd00f80544dd90._comment
+++ b/doc/forum/Supported_OS/comment_1_f324bed708305e2667bd00f80544dd90._comment
@@ -22,8 +22,8 @@ on multiple OS's:
 	upgraded :: Property (DebianLike + FreeBSD)
 	upgraded = Apt.upgraded `pickOS` Pkg.upgraded
 
-The `withOS` function lets a single property do different things for
-different OS versions as well as different OS's.
+The `pickOS` function lets a single property do different things for
+different OS's.
 
 The ArchLinux and FreeBSD ports were done by propellor users,
 and both are good examples of the scope of the changes involved in making

diff --git a/doc/forum/__126____47__.ssh__47__propellor:_createDirectory:_does_not_exist___40__No_such_file_or_directory__41__.mdwn b/doc/forum/__126____47__.ssh__47__propellor:_createDirectory:_does_not_exist___40__No_such_file_or_directory__41__.mdwn
new file mode 100644
index 00000000..c35d5ba3
--- /dev/null
+++ b/doc/forum/__126____47__.ssh__47__propellor:_createDirectory:_does_not_exist___40__No_such_file_or_directory__41__.mdwn
@@ -0,0 +1,21 @@
+Hello,
+
+while  running propellor on a brand new  installed machine.
+I got this error message
+
+
+    [master 4c06fcd] propellor spin
+     1 file changed, 2 insertions(+), 2 deletions(-)
+    Git commit ... done
+    Password for 'https://picca@salsa.debian.org': 
+    To https://salsa.debian.org/picca/propellor.git
+       d8cfab0..4c06fcd  master -> master
+    Push to central git repository ... done
+    propellor: /home/picca/.ssh/propellor: createDirectory: does not exist (No such file or directory)
+
+
+so it seems that propellor does not create the .ssh directory if it does not exists.
+
+cheers
+
+Frederic

Added a comment
diff --git a/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_3_431073c65fc258d3dcce8d9968c96daf._comment b/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_3_431073c65fc258d3dcce8d9968c96daf._comment
new file mode 100644
index 00000000..451bb21f
--- /dev/null
+++ b/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_3_431073c65fc258d3dcce8d9968c96daf._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="thom@386bbca5d0520f44e47909c31e6b0138a4c493b8"
+ nickname="thom"
+ avatar="http://cdn.libravatar.org/avatar/326b70d806eee1cec938adf3efa8809b"
+ subject="comment 3"
+ date="2018-12-31T13:00:53Z"
+ content="""
+Thanks Joey!
+"""]]

followup
diff --git a/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_2_c96da2520b700b2c39769d53febc3ae8._comment b/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_2_c96da2520b700b2c39769d53febc3ae8._comment
new file mode 100644
index 00000000..f02ef69b
--- /dev/null
+++ b/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_2_c96da2520b700b2c39769d53febc3ae8._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2018-12-30T18:38:51Z"
+ content="""
+I've made the necessary changes to support ghc 8.6.3.
+"""]]

stack install pkg is broken
diff --git a/doc/README.mdwn b/doc/README.mdwn
index 88726a6d..76d05255 100644
--- a/doc/README.mdwn
+++ b/doc/README.mdwn
@@ -37,11 +37,11 @@ see [configuration for the Haskell newbie](https://propellor.branchable.com/hask
 ## quick start
 
 1. Get propellor installed on your development machine (ie, laptop).
-     `cabal install propellor`
+     `apt-get install propellor`
           or
-     `stack install propellor`
+     `cabal install propellor`
           or
-     `apt-get install propellor`
+     `cabal unpack propellor; cd propellor-version; stack install`
 2. Run `propellor --init` ; this will set up a `~/.propellor/` git
    repository for you.
 3. Edit `~/.propellor/config.hs`, and add a host you want to manage.
diff --git a/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_1_58051e973d4b4c269b1fa90517a3adc6._comment b/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_1_58051e973d4b4c269b1fa90517a3adc6._comment
new file mode 100644
index 00000000..5227cf3d
--- /dev/null
+++ b/doc/forum/compiling_5.5.0_fails_with_lts_13.0/comment_1_58051e973d4b4c269b1fa90517a3adc6._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-12-30T17:10:47Z"
+ content="""
+Unfortunately `stack install propellor` ignores the working stack.yaml
+shipped with propellor, and tries to use the default resolver and package
+set.
+
+I've adjusted the README to not suggest using that broken command.
+"""]]

can't build propellor with lts 13.0
diff --git a/doc/forum/compiling_5.5.0_fails_with_lts_13.0.mdwn b/doc/forum/compiling_5.5.0_fails_with_lts_13.0.mdwn
new file mode 100644
index 00000000..7b543f7f
--- /dev/null
+++ b/doc/forum/compiling_5.5.0_fails_with_lts_13.0.mdwn
@@ -0,0 +1,74 @@
+Running `stack install propellor` today fails in two ways:
+
+First up:
+
+    In the dependencies for propellor-5.5.0:
+    IfElse needed, but the stack configuration has no specified version  (latest
+           matching version is 0.85) needed since propellor is a build target.
+
+    Some different approaches to resolving this:
+
+    * Consider trying 'stack solver', which uses the cabal-install solver to
+    attempt to find some working build configuration. This can be convenient
+    when dealing with many complicated constraint errors, but results may be
+    unpredictable.
+
+    * Recommended action: try adding the following to your extra-deps
+    in /Users/thom/.stack/global-project/stack.yaml:
+
+    IfElse-0.85@sha256:6939b94acc6a55f545f63a168a349dd2fbe4b9a7cca73bf60282db5cc6aa47d2
+
+
+Once that's added, propellor fails to compile with:
+
+
+    [ 39 of 174] Compiling Propellor.Types  ( src/Propellor/Types.hs, .stack-work/dist/x86_64-osx/Cabal-2.4.0.1/build/Propellor/Types.o )
+
+    /private/var/folders/0v/w1nt655j39q9954g7y_2_jlh0000gn/T/stack8634/propellor-5.5.0/src/Propellor/Types.hs:187:10: error:
+        • Illegal nested constraint ‘SingI (Combine x y)’
+          (Use UndecidableInstances to permit this)
+        • In the instance declaration for
+            ‘Combines (Property (MetaTypes x)) (Property (MetaTypes y))’
+        |
+    187 | instance (CheckCombinable x y ~ 'CanCombine, SingI (Combine x y)) => Combines (Property (MetaTypes x)) (Property (MetaTypes y)) where
+        |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+    /private/var/folders/0v/w1nt655j39q9954g7y_2_jlh0000gn/T/stack8634/propellor-5.5.0/src/Propellor/Types.hs:190:10: error:
+        • Illegal nested constraint ‘SingI (Combine x y)’
+          (Use UndecidableInstances to permit this)
+        • In the instance declaration for
+            ‘Combines (RevertableProperty (MetaTypes x) (MetaTypes x')) (RevertableProperty (MetaTypes y) (MetaTypes y'))’
+        |
+    190 | instance (CheckCombinable x y ~ 'CanCombine, CheckCombinable x' y' ~ 'CanCombine, SingI (Combine x y), SingI (Combine x' y')) => Combines (RevertableProperty (MetaTypes x) (MetaTypes x')) (RevertableProperty (MetaTypes y) (MetaTypes y')) where
+        |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+    /private/var/folders/0v/w1nt655j39q9954g7y_2_jlh0000gn/T/stack8634/propellor-5.5.0/src/Propellor/Types.hs:190:10: error:
+        • Illegal nested constraint ‘SingI (Combine x' y')’
+          (Use UndecidableInstances to permit this)
+        • In the instance declaration for
+            ‘Combines (RevertableProperty (MetaTypes x) (MetaTypes x')) (RevertableProperty (MetaTypes y) (MetaTypes y'))’
+        |
+    190 | instance (CheckCombinable x y ~ 'CanCombine, CheckCombinable x' y' ~ 'CanCombine, SingI (Combine x y), SingI (Combine x' y')) => Combines (RevertableProperty (MetaTypes x) (MetaTypes x')) (RevertableProperty (MetaTypes y) (MetaTypes y')) where
+        |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+    /private/var/folders/0v/w1nt655j39q9954g7y_2_jlh0000gn/T/stack8634/propellor-5.5.0/src/Propellor/Types.hs:195:10: error:
+        • Illegal nested constraint ‘SingI (Combine x y)’
+          (Use UndecidableInstances to permit this)
+        • In the instance declaration for
+            ‘Combines (RevertableProperty (MetaTypes x) (MetaTypes x')) (Property (MetaTypes y))’
+        |
+    195 | instance (CheckCombinable x y ~ 'CanCombine, SingI (Combine x y)) => Combines (RevertableProperty (MetaTypes x) (MetaTypes x')) (Property (MetaTypes y)) where
+        |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+    /private/var/folders/0v/w1nt655j39q9954g7y_2_jlh0000gn/T/stack8634/propellor-5.5.0/src/Propellor/Types.hs:197:10: error:
+        • Illegal nested constraint ‘SingI (Combine x y)’
+          (Use UndecidableInstances to permit this)
+        • In the instance declaration for
+            ‘Combines (Property (MetaTypes x)) (RevertableProperty (MetaTypes y) (MetaTypes y'))’
+        |
+    197 | instance (CheckCombinable x y ~ 'CanCombine, SingI (Combine x y)) => Combines (Property (MetaTypes x)) (RevertableProperty (MetaTypes y) (MetaTypes y')) where
+        |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+
+I can reproduce this by bumping the lts version to 13.0 in master's stack.yaml and uttering `stack build`.

comment
diff --git a/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network/comment_1_9469ea9eaf70e57ba1b36891978725cf._comment b/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network/comment_1_9469ea9eaf70e57ba1b36891978725cf._comment
new file mode 100644
index 00000000..638a8d6b
--- /dev/null
+++ b/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network/comment_1_9469ea9eaf70e57ba1b36891978725cf._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-12-08T16:15:43Z"
+ content="""
+Perhaps runPropellor could be parameterized in some way, so
+you can provide whatever check you decide you want.
+
+This is where [[todo/integrate_shell-monad]] would come in handy, to
+build up and manipulate the shell script for the cron job.
+"""]]

typos
diff --git a/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network.mdwn b/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network.mdwn
index 8b2e4797..831dc1e0 100644
--- a/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network.mdwn
+++ b/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network.mdwn
@@ -1,4 +1,4 @@
-I don't have `Cron.runPropellor` on my laptop because it if often offline.  But I would like a cronjob that tries to spin the host if its online.  Mainly to keep sbuild chroots up-to-date.
+I don't have `Cron.runPropellor` on my laptop because it is often offline.  But I would like a cronjob that tries to spin the host if it's online.  Mainly to keep sbuild chroots up-to-date.
 
 I was wondering what the cleanest way to implement this would be.  `Cron.runPropellor` could be split into `Cron.runPropellor` and `Cron.runPropellorWhenOnline`, the latter of which does `wget http://google.com >/dev/null` and exits if that command fails.
 

post todo
diff --git a/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network.mdwn b/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network.mdwn
new file mode 100644
index 00000000..8b2e4797
--- /dev/null
+++ b/doc/todo/want_Cron.runPropellor_that_does_nothing_if_no_network.mdwn
@@ -0,0 +1,9 @@
+I don't have `Cron.runPropellor` on my laptop because it if often offline.  But I would like a cronjob that tries to spin the host if its online.  Mainly to keep sbuild chroots up-to-date.
+
+I was wondering what the cleanest way to implement this would be.  `Cron.runPropellor` could be split into `Cron.runPropellor` and `Cron.runPropellorWhenOnline`, the latter of which does `wget http://google.com >/dev/null` and exits if that command fails.
+
+Or there could be some kind of property which, when set on a host, causes all spins to abort if the host if offline.
+
+And is wgetting Google's homepage the right way to check that we have Internet access?
+
+--spwhitton

libghc-stm-dev package won't be in new versions of debian
In Bootstrap, still try to install the package to support bootstrapping
to old systems. If it's not available the bootstrapping will still
succeed. The added apt-cache check is only to avoid apt complaining when
asked to install a not available package.
In debian/control, depend on ghc that includes stm, although propellor
still supports being used with older versions of ghc
Of course this control file is not being used for the package in debian
any longer afaik, so something else will be done there.
diff --git a/debian/changelog b/debian/changelog
index 99236fff..776e57cb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,6 +2,8 @@ propellor (5.5.1) UNRELEASED; urgency=medium
 
   * Some openbsd portability fixes. Thanks, rsiddharth.
   * Added Libvirt module. Thanks, Sean Whitton.
+  * When bootstrapping on Debian, libghc-stm-dev may not be available,
+    as it's become part of ghc, so check before trying to install it.
 
  -- Joey Hess <id@joeyh.name>  Tue, 23 Oct 2018 11:37:16 -0400
 
diff --git a/debian/control b/debian/control
index 0a8701a0..5a46822f 100644
--- a/debian/control
+++ b/debian/control
@@ -4,7 +4,7 @@ Priority: optional
 Build-Depends: 
 	debhelper (>= 9),
 	git (>= 2.0),
-	ghc (>= 7.6),
+	ghc (>= 8.4.3),
 	cabal-install,
 	libghc-async-dev,
 	libghc-split-dev,
@@ -16,7 +16,6 @@ Build-Depends:
 	libghc-mtl-dev,
 	libghc-transformers-dev,
 	libghc-exceptions-dev (>= 0.6),
-	libghc-stm-dev,
 	libghc-text-dev,
 	libghc-hashable-dev,
 Maintainer: Joey Hess <id@joeyh.name>
@@ -28,7 +27,7 @@ Package: propellor
 Architecture: any
 Section: admin
 Depends: ${misc:Depends}, ${shlibs:Depends},
-	ghc (>= 7.4),
+	ghc (>= 8.4.3),
 	cabal-install,
 	libghc-async-dev,
 	libghc-split-dev,
@@ -40,7 +39,6 @@ Depends: ${misc:Depends}, ${shlibs:Depends},
 	libghc-mtl-dev,
 	libghc-transformers-dev,
 	libghc-exceptions-dev (>= 0.6),
-	libghc-stm-dev,
 	libghc-text-dev,
 	libghc-hashable-dev,
 	git (>= 2.0),
diff --git a/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn b/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn
index 3d85a02d..4305e396 100644
--- a/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn
+++ b/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn
@@ -3,3 +3,5 @@ haskell-stm is included with ghc and won't be shipped as an installable package
 Propellor needs to stop trying to install haskell-stm on Debian buster or newer (and it should also be dropped from debian/control of course, but that can happen on the Debian side).
 
 --spwhitton
+
+> [[done]] --[[Joey]]
diff --git a/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid/comment_1_dbb0a50414b1ac58cad8584a7c99078e._comment b/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid/comment_1_dbb0a50414b1ac58cad8584a7c99078e._comment
new file mode 100644
index 00000000..a53a144a
--- /dev/null
+++ b/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid/comment_1_dbb0a50414b1ac58cad8584a7c99078e._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-12-04T18:58:48Z"
+ content="""
+Bootstrap's package installation ignores errors, so if the package is not
+available, it will at worst display an error message and continue.
+
+However, I went ahead and made it check with apt-cache if the package is
+available, to avoid the user seeing an apt error here.
+
+I suppose users of Arch and FreeBSD may want to make similar changes, if
+their package managers also display errors; I don't know if they do or even
+if this change is going to affect those distributions.
+Probably better to let those users deal with it if similar changes are made
+to those distributions, so I'm going to close this.
+"""]]
diff --git a/src/Propellor/Bootstrap.hs b/src/Propellor/Bootstrap.hs
index 66e6e1ff..6ca133cb 100644
--- a/src/Propellor/Bootstrap.hs
+++ b/src/Propellor/Bootstrap.hs
@@ -95,6 +95,8 @@ checkDepsCommand bs sys = go (getBuilder bs)
 	go Cabal = "if ! cabal configure >/dev/null 2>&1; then " ++ depsCommand bs sys ++ "; fi"
 	go Stack = "if ! stack build --dry-run >/dev/null 2>&1; then " ++ depsCommand bs sys ++ "; fi"
 
+data Dep = Dep String | OldDep String
+
 -- Install build dependencies of propellor, using the specified
 -- Bootstrapper.
 --
@@ -128,32 +130,34 @@ depsCommand bs msys = "( " ++ intercalate " ; " (go bs) ++ ") || true"
 
 	useapt builder = "apt-get update" : map aptinstall (debdeps builder)
 
-	aptinstall p = "DEBIAN_FRONTEND=noninteractive apt-get -qq --no-upgrade --no-install-recommends -y install " ++ p
+	aptinstall (Dep p) = "DEBIAN_FRONTEND=noninteractive apt-get -qq --no-upgrade --no-install-recommends -y install " ++ p
+	aptinstall (OldDep p) = "if LANG=C apt-cache policy " ++ p ++ "| grep -q Candidate:; then " ++ aptinstall (Dep p) ++ "; fi"
 	pkginstall p = "ASSUME_ALWAYS_YES=yes pkg install " ++ p
 	pacmaninstall p = "pacman -S --noconfirm --needed " ++ p
 
 	debdeps Cabal =
-		[ "gnupg"
+		[ Dep "gnupg"
 		-- Below are the same deps listed in debian/control.
-		, "ghc"
-		, "cabal-install"
-		, "libghc-async-dev"
-		, "libghc-split-dev"
-		, "libghc-hslogger-dev"
-		, "libghc-unix-compat-dev"
-		, "libghc-ansi-terminal-dev"
-		, "libghc-ifelse-dev"
-		, "libghc-network-dev"
-		, "libghc-mtl-dev"
-		, "libghc-transformers-dev"
-		, "libghc-exceptions-dev"
-		, "libghc-stm-dev"
-		, "libghc-text-dev"
-		, "libghc-hashable-dev"
+		, Dep "ghc"
+		, Dep "cabal-install"
+		, Dep "libghc-async-dev"
+		, Dep "libghc-split-dev"
+		, Dep "libghc-hslogger-dev"
+		, Dep "libghc-unix-compat-dev"
+		, Dep "libghc-ansi-terminal-dev"
+		, Dep "libghc-ifelse-dev"
+		, Dep "libghc-network-dev"
+		, Dep "libghc-mtl-dev"
+		, Dep "libghc-transformers-dev"
+		, Dep "libghc-exceptions-dev"
+		, Dep "libghc-text-dev"
+		, Dep "libghc-hashable-dev"
+		-- Deps that are only needed on old systems.
+		, OldDep "libghc-stm-dev"
 		]
 	debdeps Stack =
-		[ "gnupg"
-		, "haskell-stack"
+		[ Dep "gnupg"
+		, Dep "haskell-stack"
 		]
 
 	fbsddeps Cabal =

don't imply that stm is out of buster altogether!
diff --git a/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn b/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn
index 5aadd48c..3d85a02d 100644
--- a/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn
+++ b/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn
@@ -1,4 +1,4 @@
-haskell-stm is included with ghc and won't be shipped with Debian buster.
+haskell-stm is included with ghc and won't be shipped as an installable package in Debian buster.
 
 Propellor needs to stop trying to install haskell-stm on Debian buster or newer (and it should also be dropped from debian/control of course, but that can happen on the Debian side).
 

post bug
diff --git a/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn b/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn
new file mode 100644
index 00000000..5aadd48c
--- /dev/null
+++ b/doc/todo/haskell-stm_now_bundled_with_ghc_in_Debian_sid.mdwn
@@ -0,0 +1,5 @@
+haskell-stm is included with ghc and won't be shipped with Debian buster.
+
+Propellor needs to stop trying to install haskell-stm on Debian buster or newer (and it should also be dropped from debian/control of course, but that can happen on the Debian side).
+
+--spwhitton

response
diff --git a/doc/forum/installing_apt_packages_without_running_new_services/comment_1_7c64eb0d72d9f84ecc62136b0367ef3d._comment b/doc/forum/installing_apt_packages_without_running_new_services/comment_1_7c64eb0d72d9f84ecc62136b0367ef3d._comment
new file mode 100644
index 00000000..41fa4078
--- /dev/null
+++ b/doc/forum/installing_apt_packages_without_running_new_services/comment_1_7c64eb0d72d9f84ecc62136b0367ef3d._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-12-01T21:39:14Z"
+ content="""
+One way is to enable Propellor.Property.Service.noServices
+during the install and revert it afterwards, but that does prevent any
+services being started while it's enabled.
+
+I don't know of a very good way to do this on a Debian system. If you can
+find one, I'm sure propellor can use it.
+
+It might be possible, when systemd is used, to first apply
+Propellor.Property.Systemd.disabled on the service that has not been
+installed yet. I have not checked if that works.
+"""]]

diff --git a/doc/forum/installing_apt_packages_without_running_new_services.mdwn b/doc/forum/installing_apt_packages_without_running_new_services.mdwn
new file mode 100644
index 00000000..d044ef05
--- /dev/null
+++ b/doc/forum/installing_apt_packages_without_running_new_services.mdwn
@@ -0,0 +1,3 @@
+How would one create a Property that installs a package without starting the corresponding service?
+
+I'm asking because sometimes the default config is broken, so you need to fix it before starting the service.

merged libvirt
diff --git a/debian/changelog b/debian/changelog
index e9c8bb00..99236fff 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,7 @@
 propellor (5.5.1) UNRELEASED; urgency=medium
 
   * Some openbsd portability fixes. Thanks, rsiddharth.
+  * Added Libvirt module. Thanks, Sean Whitton.
 
  -- Joey Hess <id@joeyh.name>  Tue, 23 Oct 2018 11:37:16 -0400
 
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_13_066d41df795b69e096487ae7334824d0._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_13_066d41df795b69e096487ae7334824d0._comment
new file mode 100644
index 00000000..07b32566
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_13_066d41df795b69e096487ae7334824d0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 13"""
+ date="2018-11-11T20:58:35Z"
+ content="""
+I've merged the branch, unsure if this should remain open for anything
+discussed above, so leaving it for now.
+"""]]

Added a comment
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_12_2a42bef328b8dc17754050e3cdb7e7d2._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_12_2a42bef328b8dc17754050e3cdb7e7d2._comment
new file mode 100644
index 00000000..84fa1ada
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_12_2a42bef328b8dc17754050e3cdb7e7d2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 12"
+ date="2018-11-10T23:29:35Z"
+ content="""
+(Hmm, here on Debian stretch, passing `--autostart` does not actually cause the VM to be marked for autostarting.  This is a bug in virt-install, though, as we're using the command line interface as documented --  I confirmed this using `PROPELLOR_DEBUG=1`.)
+"""]]

Added a comment
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_11_feec29fe99528e66b0cbc0388793e10e._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_11_feec29fe99528e66b0cbc0388793e10e._comment
new file mode 100644
index 00000000..97467c3b
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_11_feec29fe99528e66b0cbc0388793e10e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 11"
+ date="2018-11-10T23:17:52Z"
+ content="""
+All done, I think.  Thank you for a useful review.  Commit messages and comments should explain my changes.
+"""]]

code review
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_10_b48444a7ec6a69019a2fda927925cac1._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_10_b48444a7ec6a69019a2fda927925cac1._comment
new file mode 100644
index 00000000..9b142dcd
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_10_b48444a7ec6a69019a2fda927925cac1._comment
@@ -0,0 +1,40 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""code review"""
+ date="2018-11-06T14:59:06Z"
+ content="""
+Let's comment out the QCow2 constructor until that case is handled.
+
+With NumVCPUs and MiBMemory both Int, and used in the same property, they
+could get mixed up. Recommend newtypes.
+
+Would it make sense for defaultNetworkAutostarted
+to itself run the virsh net-start? It would simplify the example.
+
+It's named kvmDefined; is it actually guaranteed to use kvm and not some other VM?
+
+What happens when osVariant is Nothing and no --os-variant is passed?
+When osType is Nothing? Is it still likely to work?
+
+Please make osType not have a default case and define it for all the
+current constructors. That way, the next person to
+add an Linux distro to propellor won't forget to update it.
+
+The chroot nuking code depends on some implementation details in DiskImage,
+so I'd be inclined to move it to that module. (Which probably has similar
+code that can be factored out.)
+
+The "defined" scriptProperty uses a lot of values that are unlikely to
+contain spaces or other script unsafe stuff, but it would still be good to
+shellEscape them. (Or it could be rewritten to run virt-install w/o a
+shell, read its output, and write the file.)
+
+The "started" scriptProperty also needs some escaping. (Although I'd be
+inclined to parse virsh list in haskell, but up to you.)
+
+Minor: The `& Libvirt.defaultNetworkAutostarted` example line is currently
+indented by spaces while the other lines use tabs.
+
+Minor: I'd use `$` in some of the places where you have a parenthesized
+do block or other multiline block of code.
+"""]]

Added a comment
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_9_4ba83dedf873a1a70fc050f22fca343e._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_9_4ba83dedf873a1a70fc050f22fca343e._comment
new file mode 100644
index 00000000..94f2ef9b
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_9_4ba83dedf873a1a70fc050f22fca343e._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 9"
+ date="2018-11-06T03:12:26Z"
+ content="""
+Thanks.  I've now implemented enough of this to support my usecase in the libvirt branch of <https://git.spwhitton.name/propellor>.
+
+There are TODOs, but now seems as good a time as any for someone to implement the qcow2 support . . .
+
+With regard to your idea, taking down the VM and running propellor on the qcow2 file seems like it will not be useful to very many people.  ISTM that treating the VM as a host and spinning it is right.
+"""]]

feedback
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_8_f7ceb2909d6884a9b13500b7c660469a._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_8_f7ceb2909d6884a9b13500b7c660469a._comment
new file mode 100644
index 00000000..0af0baaa
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_8_f7ceb2909d6884a9b13500b7c660469a._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 8"""
+ date="2018-11-05T16:40:57Z"
+ content="""
+Seems that kvmRunning would need a warning that changes to the propellor
+configuration of the VM's Host won't affect the VM. Because it's unusual for
+propellor to only be able to set something up and not change it afterwards.
+
+But kvmRunning is certianly a useful low level property, and combining with
+other properties like that is good.
+
+Hmm, it's actually possible to mount a qcow2 image using libguestfs-tools.
+<http://ask.xmodulo.com/mount-qcow2-disk-image-linux.html>
+So, propellor could temporarily take down the VM and run inside the qcow2
+to update it! Although doing that every time propellor is run seems
+suboptimal. It could keep the chroot around and only update the qcow2 image
+if the chroot needed to be updated. I am not sure how I feel about that
+idea.
+
+We could also make conducting easier to set up, perhaps not needing `main`
+to be modified to use it.
+"""]]

Added a comment: New design: requesting feedback
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_7_246609ff0b30329fe64fe1c100b62c45._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_7_246609ff0b30329fe64fe1c100b62c45._comment
new file mode 100644
index 00000000..1aa82a09
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_7_246609ff0b30329fe64fe1c100b62c45._comment
@@ -0,0 +1,49 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="New design: requesting feedback"
+ date="2018-11-04T17:39:51Z"
+ content="""
+Having slept on it, and also looked at some more of virt-install(1), I have a new design.  I'd be grateful for feedback on this, before implementation.
+
+We have two properties: `Libvirt.kvmRunning` and `Libvirt.kvmRunningConducted`, where
+
+    kvmRunningConnected host = conducts host `requires` kvmRunning host
+
+The basic reason for separating these two properties is that for the conducting to work, various network things have to be set up, and there isn't a configuration that it would be sensible to have as a default.  More generally, libvirt isn't at all suited to declarative configuration.  What propellor can do well is build an image and have libvirt generate a barebones XML configuration file to boot the image.  This is what `Libvirt.kvmRunning` will do.  After that, we're going to have to leave it up to the user.  I suspect that outside of the very simplest cases, they are going to have to make a series of virsh(1) calls, using `flagFile` to ensure that it only happens once.
+
+`Libvirt.kvmRunning` will work like this:
+
+1. ensure libvirt etc. are installed
+2. build the image if it doesn't exist
+3. nuke the chroot used to build the image
+3. if VM config does not exist,
+    1. `virt-install -n vm-hostname --description \"vm-hostname VM\" --os-type=Linux --os-variant=debian9 --ram=1024 --vcpus=2 --autostart --disk path=/var/lib/libvirt/images/vm-hostname.img,device=disk,bus=virtio --import --print-xml >/tmp/foo`
+    2. `virsh define /tmp/foo`
+        - `virt-install --print-xml` and then `virsh define` avoids the problem of virt-install not exiting until after the VM has been shutdown at least once/the virt-viewer instance launched by virt-install has been closed
+    3. `virsh start vm-hostname`
+
+Sample usage:
+
+    laptop :: Host
+    laptop = host \"iris.silentflame.com\" $ props
+    	& osDebian (Stable \"stretch\") X86_64
+    	& Libvirt.kvmRunning Raw 1GB 2 develacc -- specification of image type, RAM and vCPUs to assign
+    
+    develacc :: Host
+    develacc = host \"develacc.iris.silentflame.com\" $ props
+    	& osDebian Unstable X86_64
+    	& hasPartition
+    		( partition EXT4
+    			`mountedAt` \"/\"
+    			`addFreeSpace` MegaBytes 10240
+    		)
+    	& Apt.installed [\"linux-image-amd64\"]
+    	& Grub.installed PC
+    
+    	& ipv4 \"192.168.122.31\"
+    	& Network.static \"ens3\" (IPv4 \"192.168.122.31\")
+    		(Just (Network.Gateway (IPv4 \"192.168.122.1\")))
+    		`requires` Network.cleanInterfacesFile
+    	& Hostname.sane
+"""]]

Added a comment: creating the libvirt VM
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_6_9c2792cec842dba7a8fabb24c2c33da0._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_6_9c2792cec842dba7a8fabb24c2c33da0._comment
new file mode 100644
index 00000000..931b21fe
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_6_9c2792cec842dba7a8fabb24c2c33da0._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="creating the libvirt VM"
+ date="2018-11-04T01:03:06Z"
+ content="""
+I've now an adhoc, proof-of-concept libvirt VM provisioned by my config.hs, just using a raw disk image.  It turns out that propellor should not be writing the XML configuration file in /etc, but having libvirt generate it.  This is because the config is not meant to be directly edited.  So, propellor should call virt-install(1) to setup and boot the VM.
+
+My code uses virt-install's --import option, also passing it the location of the disk image generated by propellor.  The main problem is that the invocation of virt-install won't return until after the VM first shuts down; the idea is that you are running the OS installer and then you reboot.  Possibly using --boot instead of --import will help here; not sure.
+
+We will need the user to specify how much RAM and how many vCPUs to assign to the VM.  All the other parameters to virt-install can be determined by looking at the properties of the VM `Host`.
+
+Otherwise, the user will need to set an IP property on the VM so that it can be conducted.  I think we will need to leave the user to do this, as there are so many possible network configurations for libvirt VMs.  But we could probably provide helper properties.  In particular, the standard setup will be to use `Network.static`, though I'm not sure about how to do that with indeterministic interface names.
+"""]]

Added a comment
diff --git a/doc/forum/Make_clean_fails_in_openbsd/comment_2_be7daa63ed7b5689f3e626eedd2fb648._comment b/doc/forum/Make_clean_fails_in_openbsd/comment_2_be7daa63ed7b5689f3e626eedd2fb648._comment
new file mode 100644
index 00000000..ca5c4c81
--- /dev/null
+++ b/doc/forum/Make_clean_fails_in_openbsd/comment_2_be7daa63ed7b5689f3e626eedd2fb648._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="s@aa9ff9ce06b08acfd2a93ebd342ce6879430fbdd"
+ nickname="s"
+ avatar="http://cdn.libravatar.org/avatar/81bf27f8b35011d1846711fa37a5588f"
+ subject="comment 2"
+ date="2018-10-28T19:43:55Z"
+ content="""
+Apologies for the haste. I'll post patches under [[/todo]] in<br/>
+the future
+"""]]

Added a comment
diff --git a/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd/comment_2_b9f9c1903f1a54bad8d9021702056f41._comment b/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd/comment_2_b9f9c1903f1a54bad8d9021702056f41._comment
new file mode 100644
index 00000000..09a5b01e
--- /dev/null
+++ b/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd/comment_2_b9f9c1903f1a54bad8d9021702056f41._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="s@aa9ff9ce06b08acfd2a93ebd342ce6879430fbdd"
+ nickname="s"
+ avatar="http://cdn.libravatar.org/avatar/81bf27f8b35011d1846711fa37a5588f"
+ subject="comment 2"
+ date="2018-10-28T19:43:21Z"
+ content="""
+> ...I suspect it would be sufficient to use -p?
+
+I think you're right, `-pf` should be sufficient.
+
+> If you're going to be posting a bunch of openbsd porting patches, which I hope you are, please use [[/todo]] so they don't flood the forum and so it's obvious which have been applied and which not.
+
+Apologies for the haste. I'll post patches under [[/todo]] in<br/>
+the future and take a look at [[/contributing]]. Thanks for<br/>
+pointing out.
+"""]]

patch applied
diff --git a/debian/changelog b/debian/changelog
index b2051120..e9c8bb00 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+propellor (5.5.1) UNRELEASED; urgency=medium
+
+  * Some openbsd portability fixes. Thanks, rsiddharth.
+
+ -- Joey Hess <id@joeyh.name>  Tue, 23 Oct 2018 11:37:16 -0400
+
 propellor (5.5.0) unstable; urgency=medium
 
   * letsencrypt': Pass --expand to support expanding the list of domains
diff --git a/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd/comment_1_ccf181b032aad9134ff513878956d1b2._comment b/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd/comment_1_ccf181b032aad9134ff513878956d1b2._comment
new file mode 100644
index 00000000..f5ac7ae0
--- /dev/null
+++ b/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd/comment_1_ccf181b032aad9134ff513878956d1b2._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-10-23T15:34:56Z"
+ content="""
+Thanks for the patch. I've applied it. I suspect it would be sufficient to
+use -p?<Down>
+
+If you're going to be posting a bunch of openbsd porting patches,
+which I hope you are, please use [[todo]] so they don't flood the forum
+and so it's obvious which have been applied and which not.
+
+Also, see [[contributing]] for some other useful things to do.
+"""]]

patch applied
diff --git a/doc/forum/Make_clean_fails_in_openbsd/comment_1_27faa3850b462e8930752209f41e2c2f._comment b/doc/forum/Make_clean_fails_in_openbsd/comment_1_27faa3850b462e8930752209f41e2c2f._comment
new file mode 100644
index 00000000..c7939851
--- /dev/null
+++ b/doc/forum/Make_clean_fails_in_openbsd/comment_1_27faa3850b462e8930752209f41e2c2f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-10-23T15:31:13Z"
+ content="""
+Thanks for the patch. The only thing you could have done better is post
+this in [[todo]].
+"""]]

New forum post about an issue with `Make clean` in openbsd.
diff --git a/doc/forum/Make_clean_fails_in_openbsd.mdwn b/doc/forum/Make_clean_fails_in_openbsd.mdwn
new file mode 100644
index 00000000..0f73586a
--- /dev/null
+++ b/doc/forum/Make_clean_fails_in_openbsd.mdwn
@@ -0,0 +1,25 @@
+openbsd requires specifying the path for the [`find`][0] command. So this:
+
+    find -name \*.o
+    find: unknown option -- n
+    usage: find [-dHhLXx] [-f path] path ... [expression]
+
+
+fails.
+
+This works:
+
+
+    find . -name \*.o
+    ./dist/build/Utility/Applicative.o
+    ./dist/build/Utility/PosixFiles.o
+    ./dist/build/Utility/Split.o
+    ...
+
+
+as expected.
+
+Here's a patch for it: [0001-Makefile-Update-clean.patch][1].
+
+[0]: https://man.openbsd.org/find
+[1]: https://ricketyspace.net/patch/0001-Makefile-Update-clean.patch

New forum post about an issue with Propellor.Bootstrap.cabalBuild (patch available).
diff --git a/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd.mdwn b/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd.mdwn
new file mode 100644
index 00000000..c66bbc23
--- /dev/null
+++ b/doc/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd.mdwn
@@ -0,0 +1,6 @@
+The `-a` option is unfortunately [not available in openbsd's version][1] of the `cp` command.
+
+Here's a patch for it [0001-src-Update-Propellor.Bootstrap.cabalBuild.patch][2].
+
+[1]: https://man.openbsd.org/cp
+[2]: https://ricketyspace.net/patch/0001-src-Update-Propellor.Bootstrap.cabalBuild.patch

add news item for propellor 5.5.0
diff --git a/doc/news/version_5.3.4.mdwn b/doc/news/version_5.3.4.mdwn
deleted file mode 100644
index 09358138..00000000
--- a/doc/news/version_5.3.4.mdwn
+++ /dev/null
@@ -1,8 +0,0 @@
-propellor 5.3.4 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Apt.trustsKey: Use apt-key to add key rather than manually driving gpg,
-     which seems to not work anymore.
-     Thanks, Russell Sim.
-   * Firewall: Reorder iptables parameters that are order
-     dependant to make --to-dest and --to-source work.
-     Thanks, Russell Sim"""]]
\ No newline at end of file
diff --git a/doc/news/version_5.5.0.mdwn b/doc/news/version_5.5.0.mdwn
new file mode 100644
index 00000000..360a5314
--- /dev/null
+++ b/doc/news/version_5.5.0.mdwn
@@ -0,0 +1,20 @@
+propellor 5.5.0 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * letsencrypt': Pass --expand to support expanding the list of domains
+   * Split mailname property out of Hostname.sane, since bad mailname
+     guesses can lead to ugly surprises. (API change)
+   * Removed HostingProvider.CloudatCost module as it lacks a maintainer.
+     (If anyone would like to maintain it, send a patch adding it back.)
+     (API change)
+   * Added Systemd.escapePath helper function useful when creating mount
+     units.
+   * Added Sudo.sudoersDFile property.
+   * Sudo.enabledFor: Write to /etc/sudoers.d/000users rather than to
+     /etc/sudoers. (Any old lines it wrote to /etc/sudoers will be removed.)
+     This fixes a potential ordering problem; the property used to append
+     the line to /etc/sudoers, but that would override more specific lines
+     in the include directory.
+   * Borg: Added UsesEnvVar.
+   * Added DiskImage.noBootloader, useful for eg, direct booting with
+     qemu. Thanks, David Bremner.
+   * Added Apt.backportInstalledMin."""]]
\ No newline at end of file

Added a comment
diff --git a/doc/forum/Adding_support_for_a_SQL_server/comment_8_2c604eb5c627c36ec68a1a7198e00710._comment b/doc/forum/Adding_support_for_a_SQL_server/comment_8_2c604eb5c627c36ec68a1a7198e00710._comment
new file mode 100644
index 00000000..0724001b
--- /dev/null
+++ b/doc/forum/Adding_support_for_a_SQL_server/comment_8_2c604eb5c627c36ec68a1a7198e00710._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="Nicolas.Schodet"
+ avatar="http://cdn.libravatar.org/avatar/0d7ec808ec329d04ee9a93c0da3c0089"
+ subject="comment 8"
+ date="2018-10-19T20:34:10Z"
+ content="""
+Hello,
+
+I have made a second version.
+
+About reverting `installed`, I noticed that it only removes the meta package, which is quite useless. May be I should just drop revertability on this one.
+
+The problem of installing a software just to revert a property can also be seen in `Apache.modEnabled` for exemple.
+
+Any comments are welcome.
+
+Thanks.
+"""]]

Added a comment: maybe some equivalent of CryptPassword
diff --git a/doc/forum/dm-crypt__47__LUKS_encryption_and_key_management/comment_3_a749abb97ebafd26bb695663b68673c5._comment b/doc/forum/dm-crypt__47__LUKS_encryption_and_key_management/comment_3_a749abb97ebafd26bb695663b68673c5._comment
new file mode 100644
index 00000000..f4448ddf
--- /dev/null
+++ b/doc/forum/dm-crypt__47__LUKS_encryption_and_key_management/comment_3_a749abb97ebafd26bb695663b68673c5._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="maybe some equivalent of CryptPassword"
+ date="2018-10-16T11:51:23Z"
+ content="""
+Storing plaintext luks passwords on disk doesn't sound great for most applications, but I wonder if the encrypted form could be stored in privdata. Something using e.g. \"cryptsetup luksDump\" or \"cryptsetup luksHeaderBackup\". I have no idea how practical it is to generate such data without being logged into the machine in question.
+"""]]

Added a comment: needs update-initramfs
diff --git a/doc/forum/__34__predictable__34___network_interface_names/comment_2_25a2911fa57ea3da20f25b25d7c4406b._comment b/doc/forum/__34__predictable__34___network_interface_names/comment_2_25a2911fa57ea3da20f25b25d7c4406b._comment
new file mode 100644
index 00000000..e284c8f1
--- /dev/null
+++ b/doc/forum/__34__predictable__34___network_interface_names/comment_2_25a2911fa57ea3da20f25b25d7c4406b._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="needs update-initramfs"
+ date="2018-10-14T21:03:28Z"
+ content="""
+I guess that's a more productive line of thinking, I wouldn't expect these vm's to have more than one network interface. One gotcha that took a bit to figure out is that the masking needs update-initramfs to be seen at boot. The following seems to be working for me:
+
+[[!format haskell \"\"\"
+& File.hasContent \"/etc/systemd/network/99-default.link\" []
+        `onChange` ( Cmd.cmdProperty \"update-initramfs\" [\"-u\"] `changesFile` \"/initrd.img\" )
+\"\"\"]]
+"""]]

Added Apt.backportInstalledMin.
This commit was sponsored by Boyd Stephen Smith Jr. on Patreon.
diff --git a/debian/changelog b/debian/changelog
index b0f7121b..5b283861 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -17,6 +17,7 @@ propellor (5.5.0) UNRELEASED; urgency=medium
   * Borg: Added UsesEnvVar.
   * Added DiskImage.noBootloader, useful for eg, direct booting with
     qemu. Thanks, David Bremner.
+  * Added Apt.backportInstalledMin.
 
  -- Joey Hess <id@joeyh.name>  Thu, 09 Aug 2018 10:54:41 -0400
 
diff --git a/doc/forum/Apt.backportInstalledMin___63__/comment_1_4e5e6b479e478897eea3337b9468db15._comment b/doc/forum/Apt.backportInstalledMin___63__/comment_1_4e5e6b479e478897eea3337b9468db15._comment
new file mode 100644
index 00000000..83b976d2
--- /dev/null
+++ b/doc/forum/Apt.backportInstalledMin___63__/comment_1_4e5e6b479e478897eea3337b9468db15._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-10-14T16:28:46Z"
+ content="""
+Indeed, that's the kind of improvement I will gladly
+accept any time, and should be very easy to add. So don't hesitate to add
+properties like that and send patches.
+
+(In this case I had 5 minutes so I implemented it already.)
+"""]]
diff --git a/src/Propellor/Property/Apt.hs b/src/Propellor/Property/Apt.hs
index 064221f9..6d7fc4d6 100644
--- a/src/Propellor/Property/Apt.hs
+++ b/src/Propellor/Property/Apt.hs
@@ -241,6 +241,10 @@ type Package = String
 installed :: [Package] -> Property DebianLike
 installed = installed' ["-y"]
 
+-- | Minimal install of package, without recommends.
+installedMin :: [Package] -> Property DebianLike
+installedMin = installed' ["--no-install-recommends", "-y"]
+
 installed' :: [String] -> [Package] -> Property DebianLike
 installed' params ps = robustly $ check (not <$> isInstalled' ps) go
 	`describe` unwords ("apt installed":ps)
@@ -253,20 +257,23 @@ installed' params ps = robustly $ check (not <$> isInstalled' ps) go
 -- dependencies from stable-backports too, you will need to include those
 -- dependencies in the list of packages passed to this function.
 backportInstalled :: [Package] -> Property Debian
-backportInstalled ps = withOS desc $ \w o -> case o of
+backportInstalled = backportInstalled' ["-y"]
+
+-- | Minimal install from the stable-backports suite, without recommends.
+backportInstalledMin :: [Package] -> Property Debian
+backportInstalledMin = backportInstalled' ["--no-install-recommends", "-y"]
+
+backportInstalled' :: [String] -> [Package] -> Property Debian
+backportInstalled' params ps = withOS desc $ \w o -> case o of
 	(Just (System (Debian _ suite) _)) -> case backportSuite suite of
 		Nothing -> unsupportedOS'
 		Just bs -> ensureProperty w $
-			runApt (["install", "-y"] ++ ((++ '/':bs) <$> ps))
+			runApt (("install":params) ++ ((++ '/':bs) <$> ps))
 				`changesFile` dpkgStatus
 	_ -> unsupportedOS'
   where
 	desc = unwords ("apt installed backport":ps)
 
--- | Minimal install of package, without recommends.
-installedMin :: [Package] -> Property DebianLike
-installedMin = installed' ["--no-install-recommends", "-y"]
-
 removed :: [Package] -> Property DebianLike
 removed ps = check (any (== IsInstalled) <$> getInstallStatus ps)
 	(runApt (["-y", "remove"] ++ ps))

comment
diff --git a/doc/forum/__34__predictable__34___network_interface_names/comment_1_6bf05129a9aa5b427c0838753b5b0673._comment b/doc/forum/__34__predictable__34___network_interface_names/comment_1_6bf05129a9aa5b427c0838753b5b0673._comment
new file mode 100644
index 00000000..c3e4e663
--- /dev/null
+++ b/doc/forum/__34__predictable__34___network_interface_names/comment_1_6bf05129a9aa5b427c0838753b5b0673._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-10-14T16:18:37Z"
+ content="""
+I don't think this is specific to disk image creation, you just need a
+property that arranges whatever configuration will lead to the names you
+want.
+
+You may be looking for /lib/systemd/network/99-default.link which can be
+masked to get the kernel's traditional names.
+"""]]

diff --git a/doc/forum/Apt.backportInstalledMin___63__.mdwn b/doc/forum/Apt.backportInstalledMin___63__.mdwn
new file mode 100644
index 00000000..64d95c72
--- /dev/null
+++ b/doc/forum/Apt.backportInstalledMin___63__.mdwn
@@ -0,0 +1 @@
+I just installed git-annex using Apt.backportInstalled on a server and was kindof of horrified by the dependendencies dragged in. I suspect much of this is probably just youtube-dl, which should be fixed soon, but anyway, shouldn't there be a way to install from backports without recommends?

diff --git a/doc/forum/__34__predictable__34___network_interface_names.mdwn b/doc/forum/__34__predictable__34___network_interface_names.mdwn
new file mode 100644
index 00000000..88b4b414
--- /dev/null
+++ b/doc/forum/__34__predictable__34___network_interface_names.mdwn
@@ -0,0 +1,3 @@
+When using propellor to install/create VM images, one naturally wants to set some kind of sane network configuration. Unfortunately the name of the network interface in the guest (or newly installed system) varies according to the hardware setup. As a concrete example, in a newly created stretch amd64 image it is ens0, while in a stretch s390x image it is enc0.  I guess the Debian installer must have some way of figuring this out and creating a sane /etc/network/interfaces. Is this something that Property.DiskImage can help with, or do I need to carry per-VM configuration information? I don't mind so much the extra config info, but it's a bit annoying that I need to boot the vm to see what the network device is called.
+
+I guess the Luddite solution is to turn off interface renaming via boot options; I'm not sure that option will always be available to me, e.g. when deploying images on someone else's host.

Added a comment: insufficient magic
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_5_364df45dda89ed83cf8db6fa4cbdc186._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_5_364df45dda89ed83cf8db6fa4cbdc186._comment
new file mode 100644
index 00000000..5062ed5d
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_5_364df45dda89ed83cf8db6fa4cbdc186._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="insufficient magic"
+ date="2018-10-14T11:12:36Z"
+ content="""
+right, changing the backing image would probably break everything.
+"""]]

comment
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_4_dbd2c399c8ef8ac56ae06f1a701fdc45._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_4_dbd2c399c8ef8ac56ae06f1a701fdc45._comment
new file mode 100644
index 00000000..8ce06a1c
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_4_dbd2c399c8ef8ac56ae06f1a701fdc45._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2018-10-14T01:10:16Z"
+ content="""
+I do think that the conditional property would be a good way for this to
+work.
+
+I think there could also be VMs where you don't want the overhead of
+running propellor inside the VM (especially if the emulation is slow, or
+you don't want to allocate that much memory to the VM, or just have a lot
+of VMs), and the content is disposable. Then propellor could restart the VM
+when it changes the disk image.
+
+There's room for multiple ways to do it.. 
+
+The disk image building side of this looks easy to me, so if you do the libvirt
+stuff, Sean, I might contribute something. :)
+"""]]

name bikeshedding
diff --git a/debian/changelog b/debian/changelog
index cc0e0a15..b0f7121b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -15,6 +15,8 @@ propellor (5.5.0) UNRELEASED; urgency=medium
     the line to /etc/sudoers, but that would override more specific lines
     in the include directory.
   * Borg: Added UsesEnvVar.
+  * Added DiskImage.noBootloader, useful for eg, direct booting with
+    qemu. Thanks, David Bremner.
 
  -- Joey Hess <id@joeyh.name>  Thu, 09 Aug 2018 10:54:41 -0400
 
diff --git a/doc/forum/support_for_non-bootable_disk_images/comment_5_ee60d5bf1cdd1fd0e4319eed99f614c1._comment b/doc/forum/support_for_non-bootable_disk_images/comment_5_ee60d5bf1cdd1fd0e4319eed99f614c1._comment
new file mode 100644
index 00000000..9ebe3062
--- /dev/null
+++ b/doc/forum/support_for_non-bootable_disk_images/comment_5_ee60d5bf1cdd1fd0e4319eed99f614c1._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2018-10-14T00:39:51Z"
+ content="""
+Ah right, [[todo/support_for_libvirt_KVM_VMs]];
+your patch is kind of a prerequisite for that. Pulling the kernel and
+initrd out of the chroot is a good idea!
+
+"Host" is slightly ambiguous around disk image building because
+a disk image can be built for a Host by `imageBuiltFor`. I've gone ahead
+and merged it in with the NoBootloader name.
+"""]]
diff --git a/propellor.cabal b/propellor.cabal
index 518505a4..0454fc92 100644
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -74,7 +74,6 @@ Library
     Propellor.Property.Cron
     Propellor.Property.DebianMirror
     Propellor.Property.Debootstrap
-    Propellor.Property.DirectBoot
     Propellor.Property.DiskImage
     Propellor.Property.DiskImage.PartSpec
     Propellor.Property.Dns
diff --git a/src/Propellor/Property/DirectBoot.hs b/src/Propellor/Property/DirectBoot.hs
deleted file mode 100644
index 4807471e..00000000
--- a/src/Propellor/Property/DirectBoot.hs
+++ /dev/null
@@ -1,7 +0,0 @@
-module Propellor.Property.DirectBoot(installed) where
-
-import Propellor.Base
-import Propellor.Types.Bootloader
-
-installed :: Property (HasInfo + UnixLike)
-installed = pureInfoProperty "direct boot" [DirectBoot]
diff --git a/src/Propellor/Property/DiskImage.hs b/src/Propellor/Property/DiskImage.hs
index a41af18c..fa41808e 100644
--- a/src/Propellor/Property/DiskImage.hs
+++ b/src/Propellor/Property/DiskImage.hs
@@ -18,6 +18,7 @@ module Propellor.Property.DiskImage (
 	imageBuiltFrom,
 	imageExists,
 	GrubTarget(..),
+	noBootloader,
 ) where
 
 import Propellor.Base
@@ -228,7 +229,7 @@ imageBuilt' rebuild img mkchroot tabletype partspec =
 			ubootFlashKernelFinalized p
 		[FlashKernelInstalled, UbootInstalled p] -> 
 			ubootFlashKernelFinalized p
-                [DirectBoot] -> directBootFinalized
+		[NoBootloader] -> noBootloaderFinalized
 		_ -> unbootable "multiple bootloaders are installed; don't know which to use"
 
 -- | This property is automatically added to the chroot when building a
@@ -470,9 +471,6 @@ grubFinalized grubtarget _img mnt loopdevs =
 ubootFinalized :: (FilePath -> FilePath -> Property Linux) -> Finalization
 ubootFinalized p (RawDiskImage img) mnt _loopdevs = p img mnt
 
-directBootFinalized :: Finalization
-directBootFinalized _img _mnt _loopDevs = doNothing
-
 flashKernelFinalized :: Finalization
 flashKernelFinalized _img mnt _loopdevs = FlashKernel.flashKernelMounted mnt
 
@@ -481,6 +479,15 @@ ubootFlashKernelFinalized p img mnt loopdevs =
 	ubootFinalized p img mnt loopdevs
 		`before` flashKernelFinalized img mnt loopdevs
 
+-- | Normally a boot loader is installed on a disk image. However,
+-- when the disk image will be booted by eg qemu booting the kernel and
+-- initrd, no boot loader is needed, and this property can be used.
+noBootloader :: Property (HasInfo + UnixLike)
+noBootloader = pureInfoProperty "no bootloader" [NoBootloader]
+
+noBootloaderFinalized :: Finalization
+noBootloaderFinalized _img _mnt _loopDevs = doNothing
+
 isChild :: FilePath -> Maybe MountPoint -> Bool
 isChild mntpt (Just d)
 	| d `equalFilePath` mntpt = False
diff --git a/src/Propellor/Types/Bootloader.hs b/src/Propellor/Types/Bootloader.hs
index cdb37a31..52a6da02 100644
--- a/src/Propellor/Types/Bootloader.hs
+++ b/src/Propellor/Types/Bootloader.hs
@@ -10,7 +10,7 @@ data BootloaderInstalled
 	= GrubInstalled GrubTarget
 	| FlashKernelInstalled
 	| UbootInstalled (FilePath -> FilePath -> Property Linux)
-        | DirectBoot
+	| NoBootloader
 	deriving (Typeable)
 
 -- | Platforms that grub can boot.
@@ -20,7 +20,7 @@ instance Show BootloaderInstalled where
 	show (GrubInstalled _) = "GrubInstalled"
 	show FlashKernelInstalled = "FlashKernelInstalled"
 	show (UbootInstalled _) = "UbootInstalled"
-        show DirectBoot = "DirectBoot"
+	show NoBootloader = "NoBootloader"
 
 instance IsInfo [BootloaderInstalled] where
 	propagateInfo _ = PropagateInfo False

comment
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_2_54538a03d7085513538baa2970983ae0._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_2_54538a03d7085513538baa2970983ae0._comment
new file mode 100644
index 00000000..497e364a
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_2_54538a03d7085513538baa2970983ae0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2018-10-14T00:36:55Z"
+ content="""
+@david, but you'd not then want to change the backing raw image, I assume,
+or does qcow somehow deal with that?
+"""]]

Added a comment: qcow and raw imgs
diff --git a/doc/todo/support_for_libvirt_KVM_VMs/comment_2_9aa111329fc476a2b978aabe4cc4c0f0._comment b/doc/todo/support_for_libvirt_KVM_VMs/comment_2_9aa111329fc476a2b978aabe4cc4c0f0._comment
new file mode 100644
index 00000000..db451976
--- /dev/null
+++ b/doc/todo/support_for_libvirt_KVM_VMs/comment_2_9aa111329fc476a2b978aabe4cc4c0f0._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="qcow and raw imgs"
+ date="2018-10-13T23:48:46Z"
+ content="""
+Maybe this is obvious, but it's cheap to generate a qcow image \"backed\" by an existing raw image
+
+To quote from a script I have lying around to let a non-root user boot a root owned, read-only image
+[[!format txt \"\"\"
+qemu-img create -b /srv/vm/$vm.img -f qcow2 $img
+\"\"\"]]
+
+"""]]

Added a comment: Naming and other hard problems
diff --git a/doc/forum/support_for_non-bootable_disk_images/comment_4_33cf3405000896fb42b9165a206e2417._comment b/doc/forum/support_for_non-bootable_disk_images/comment_4_33cf3405000896fb42b9165a206e2417._comment
new file mode 100644
index 00000000..55e4e20b
--- /dev/null
+++ b/doc/forum/support_for_non-bootable_disk_images/comment_4_33cf3405000896fb42b9165a206e2417._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="Naming and other hard problems"
+ date="2018-10-13T23:16:07Z"
+ content="""
+I'm not too attached to the terminology, \"direct booting\" just what an unscientific survey of sysadmin types came up with. QemuBoot is more descriptive, although I do wonder if it's really specific to Qemu.  As far as I understand (which is just from reading the Xen wiki), Xen dom0 can also (and originally could only) boot this way.  In fact I think the last Xen VPS I had worked like this, which was a pain as a guest admin. Maybe the connecting thread is that the boot is controlled by the host rather than the guest VM.  HostBoot would be one option, although NoBootloader is also fine with me. I think things like QemuBootloader or whatever would likely be layered on top.
+
+I'm less sure about copying kernel and initrd than when I first wrote that. If it's reasonable to depend on the existence of the foo.img.chroot,  then it's quite convenient to boot from the already conveniently present kernel and initramfs.
+
+I'll have to see how hard it is to get basic networking with just qemu. It might make sense to use libvirt to run the VMs, especially since that's what the production deployment uses.  I saw [[spwhitton]] had some ideas about libvirt.
+
+
+
+"""]]

code review
diff --git a/doc/forum/support_for_non-bootable_disk_images/comment_3_8dd7f3dd8c80fda70233e395da2204b2._comment b/doc/forum/support_for_non-bootable_disk_images/comment_3_8dd7f3dd8c80fda70233e395da2204b2._comment
new file mode 100644
index 00000000..d1761e51
--- /dev/null
+++ b/doc/forum/support_for_non-bootable_disk_images/comment_3_8dd7f3dd8c80fda70233e395da2204b2._comment
@@ -0,0 +1,33 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2018-10-13T21:41:25Z"
+ content="""
+Code^Wwhitespace review:
+
+* I noticed some places were using spaces for indentation;
+  please use tabs in propellor.
+* In "module Propellor.Property.DirectBoot(installed)'
+  there should be a space after the name of the module.
+* Needs comments explaining what properties are for.
+
+Naming ideas: Basically this is using qemu as the bootloader, rather than
+going through an (emulated) BIOS to start a bootloader. So I'm thinking
+names like QemuBootloader or NoBootloader, or NoBIOS. Don't want to
+bikeshed this too hard, it would be ok to keep the DirectBoot name, but
+I think Propellor.Property.DirectBoot at least needs a comment explaining what it's
+for, it would be confusing for a propellor user to stumble across that
+module without context.
+
+Your idea to copy the kernel and initrd out of the image so qemu can use
+them seems to point toward having a Property that gets one of these images
+booted up using qemu. And then the QemuBootloader name would make a lot of
+sense, because it would allow for later expansion to other emulators. Not
+that you have to build such a thing, but it's worth considering that someone
+may later want to.
+
+(In fact I could use such a thing, but I don't know how I'd want it to
+work. Should propellor only use the chroot for initial image build, and
+then ssh into the booted VM and run propellor in there when there are
+config updates? Or restart the VM when the image is changed?)
+"""]]

comment
diff --git a/doc/forum/__35__propellor_on_irc.oftc.net/comment_1_6e9595651c19d98353254f0914b685e1._comment b/doc/forum/__35__propellor_on_irc.oftc.net/comment_1_6e9595651c19d98353254f0914b685e1._comment
new file mode 100644
index 00000000..187004c7
--- /dev/null
+++ b/doc/forum/__35__propellor_on_irc.oftc.net/comment_1_6e9595651c19d98353254f0914b685e1._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-10-13T21:36:16Z"
+ content="""
++1 user for initiative ;)
+
+Although I will not want to help with any big type errors on irc ;)
+"""]]

diff --git a/doc/forum/__35__propellor_on_irc.oftc.net.mdwn b/doc/forum/__35__propellor_on_irc.oftc.net.mdwn
new file mode 100644
index 00000000..9f644611
--- /dev/null
+++ b/doc/forum/__35__propellor_on_irc.oftc.net.mdwn
@@ -0,0 +1,2 @@
+This might be wildly optimistic, but I registered the IRC channel #propellor on irc.oftc.net. I have no strong opinions on irc networks, but #git-annex is already there. Please join so you can answer my questions ;).
+

Added a comment: As commits
diff --git a/doc/forum/support_for_non-bootable_disk_images/comment_2_cced7ce2491cf440ee1d576b75ab4539._comment b/doc/forum/support_for_non-bootable_disk_images/comment_2_cced7ce2491cf440ee1d576b75ab4539._comment
new file mode 100644
index 00000000..51cad6ff
--- /dev/null
+++ b/doc/forum/support_for_non-bootable_disk_images/comment_2_cced7ce2491cf440ee1d576b75ab4539._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="As commits"
+ date="2018-10-08T13:03:06Z"
+ content="""
+I pushed the changes to
+
+https://salsa.debian.org/bremner/propellor/commits/proposed/direct-boot
+"""]]

Added a comment: Initial attempt at a patch
diff --git a/doc/forum/support_for_non-bootable_disk_images/comment_1_94727e8ddf14f868225b99c83fbf406d._comment b/doc/forum/support_for_non-bootable_disk_images/comment_1_94727e8ddf14f868225b99c83fbf406d._comment
new file mode 100644
index 00000000..b4ade339
--- /dev/null
+++ b/doc/forum/support_for_non-bootable_disk_images/comment_1_94727e8ddf14f868225b99c83fbf406d._comment
@@ -0,0 +1,65 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="Initial attempt at a patch"
+ date="2018-10-08T12:48:38Z"
+ content="""
+Here is a simple approach, that at least allows the image building to complete. I also managed to boot one of the images on AMD64. Probably it needs more testing, and I'm sure there are style and naming issues.
+[[!format text \"\"\"
+diff --git a/src/Propellor/Property/DirectBoot.hs b/src/Propellor/Property/DirectBoot.hs
+new file mode 100644
+index 00000000..4807471e
+--- /dev/null
++++ b/src/Propellor/Property/DirectBoot.hs
+@@ -0,0 +1,7 @@
++module Propellor.Property.DirectBoot(installed) where
++
++import Propellor.Base
++import Propellor.Types.Bootloader
++
++installed :: Property (HasInfo + UnixLike)
++installed = pureInfoProperty \"direct boot\" [DirectBoot]
+diff --git a/src/Propellor/Property/DiskImage.hs b/src/Propellor/Property/DiskImage.hs
+index 289de151..a41af18c 100644
+--- a/src/Propellor/Property/DiskImage.hs
++++ b/src/Propellor/Property/DiskImage.hs
+@@ -228,6 +228,7 @@ imageBuilt' rebuild img mkchroot tabletype partspec =
+                        ubootFlashKernelFinalized p
+                [FlashKernelInstalled, UbootInstalled p] -> 
+                        ubootFlashKernelFinalized p
++                [DirectBoot] -> directBootFinalized
+                _ -> unbootable \"multiple bootloaders are installed; don't know which to use\"
+ 
+ -- | This property is automatically added to the chroot when building a
+@@ -469,6 +470,9 @@ grubFinalized grubtarget _img mnt loopdevs =
+ ubootFinalized :: (FilePath -> FilePath -> Property Linux) -> Finalization
+ ubootFinalized p (RawDiskImage img) mnt _loopdevs = p img mnt
+ 
++directBootFinalized :: Finalization
++directBootFinalized _img _mnt _loopDevs = doNothing
++
+ flashKernelFinalized :: Finalization
+ flashKernelFinalized _img mnt _loopdevs = FlashKernel.flashKernelMounted mnt
+ 
+diff --git a/src/Propellor/Types/Bootloader.hs b/src/Propellor/Types/Bootloader.hs
+index 65117bd2..cdb37a31 100644
+--- a/src/Propellor/Types/Bootloader.hs
++++ b/src/Propellor/Types/Bootloader.hs
+@@ -10,6 +10,7 @@ data BootloaderInstalled
+        = GrubInstalled GrubTarget
+        | FlashKernelInstalled
+        | UbootInstalled (FilePath -> FilePath -> Property Linux)
++        | DirectBoot
+        deriving (Typeable)
+ 
+ -- | Platforms that grub can boot.
+@@ -19,6 +20,7 @@ instance Show BootloaderInstalled where
+        show (GrubInstalled _) = \"GrubInstalled\"
+        show FlashKernelInstalled = \"FlashKernelInstalled\"
+        show (UbootInstalled _) = \"UbootInstalled\"
++        show DirectBoot = \"DirectBoot\"
+ 
+ instance IsInfo [BootloaderInstalled] where
+        propagateInfo _ = PropagateInfo False
+\"\"\"]]
+"""]]

removed
diff --git a/doc/forum/support_for_non-bootable_disk_images/comment_1_4c4a376db9071336011abbf2993022f2._comment b/doc/forum/support_for_non-bootable_disk_images/comment_1_4c4a376db9071336011abbf2993022f2._comment
deleted file mode 100644
index 60cbc9f0..00000000
--- a/doc/forum/support_for_non-bootable_disk_images/comment_1_4c4a376db9071336011abbf2993022f2._comment
+++ /dev/null
@@ -1,68 +0,0 @@
-[[!comment format=mdwn
- username="david"
- avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
- subject="Initial attempt"
- date="2018-10-08T12:43:42Z"
- content="""
-I tried to solve this in the stupidest possible way. I'll paste diff here, as it's small and I'm not really confident it's ready for merging.
-
-
-[[!format \"\"\"
-diff --git a/src/Propellor/Property/DirectBoot.hs b/src/Propellor/Property/DirectBoot.hs
-new file mode 100644
-index 00000000..4807471e
---- /dev/null
-+++ b/src/Propellor/Property/DirectBoot.hs
-@@ -0,0 +1,7 @@
-+module Propellor.Property.DirectBoot(installed) where
-+
-+import Propellor.Base
-+import Propellor.Types.Bootloader
-+
-+installed :: Property (HasInfo + UnixLike)
-+installed = pureInfoProperty \"direct boot\" [DirectBoot]
-diff --git a/src/Propellor/Property/DiskImage.hs b/src/Propellor/Property/DiskImage.hs
-index 289de151..a41af18c 100644
---- a/src/Propellor/Property/DiskImage.hs
-+++ b/src/Propellor/Property/DiskImage.hs
-@@ -228,6 +228,7 @@ imageBuilt' rebuild img mkchroot tabletype partspec =
-                        ubootFlashKernelFinalized p
-                [FlashKernelInstalled, UbootInstalled p] -> 
-                        ubootFlashKernelFinalized p
-+                [DirectBoot] -> directBootFinalized
-                _ -> unbootable \"multiple bootloaders are installed; don't know which to use\"
- 
- -- | This property is automatically added to the chroot when building a
-@@ -469,6 +470,9 @@ grubFinalized grubtarget _img mnt loopdevs =
- ubootFinalized :: (FilePath -> FilePath -> Property Linux) -> Finalization
- ubootFinalized p (RawDiskImage img) mnt _loopdevs = p img mnt
- 
-+directBootFinalized :: Finalization
-+directBootFinalized _img _mnt _loopDevs = doNothing
-+
- flashKernelFinalized :: Finalization
- flashKernelFinalized _img mnt _loopdevs = FlashKernel.flashKernelMounted mnt
- 
-diff --git a/src/Propellor/Types/Bootloader.hs b/src/Propellor/Types/Bootloader.hs
-index 65117bd2..cdb37a31 100644
---- a/src/Propellor/Types/Bootloader.hs
-+++ b/src/Propellor/Types/Bootloader.hs
-@@ -10,6 +10,7 @@ data BootloaderInstalled
-        = GrubInstalled GrubTarget
-        | FlashKernelInstalled
-        | UbootInstalled (FilePath -> FilePath -> Property Linux)
-+        | DirectBoot
-        deriving (Typeable)
- 
- -- | Platforms that grub can boot.
-@@ -19,6 +20,7 @@ instance Show BootloaderInstalled where
-        show (GrubInstalled _) = \"GrubInstalled\"
-        show FlashKernelInstalled = \"FlashKernelInstalled\"
-        show (UbootInstalled _) = \"UbootInstalled\"
-+        show DirectBoot = \"DirectBoot\"
- 
- instance IsInfo [BootloaderInstalled] where
-        propagateInfo _ = PropagateInfo False
-
-\"\"\"]]
-"""]]