Recent changes to this wiki:

comment
diff --git a/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_2_bd74fdd792309a70d7de5f5198cf1092._comment b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_2_bd74fdd792309a70d7de5f5198cf1092._comment
new file mode 100644
index 00000000..93944ebf
--- /dev/null
+++ b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_2_bd74fdd792309a70d7de5f5198cf1092._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2019-07-19T14:09:01Z"
+ content="""
+Funny, I never considered that the Firewall properties don't do anything
+persistent.
+
+I don't think we want to get propellor involved in booting the system,
+either..
+
+Using iptables-save seems to have a problem: If there are other iptables
+rules that were not set by this run of propellor, it will save those
+as well. So it could save rules that were set up by something else that was
+intended to be temporary, or perhaps rules that were set by a earlier
+propellor config and that then got deleted out of the propellor config.
+
+Another way to do it could be to have Firewall.rule add its configuration
+to Info and then Firewall.save could see the collected Info from all
+the rules and use it to generate the boot script itself.
+"""]]

Added a comment: probably low level is needed
diff --git a/doc/forum/ipv6_support_for_P.Property.Firewall/comment_1_d301cfd7a7cb0987a73b8d32df4dac97._comment b/doc/forum/ipv6_support_for_P.Property.Firewall/comment_1_d301cfd7a7cb0987a73b8d32df4dac97._comment
new file mode 100644
index 00000000..3a35317d
--- /dev/null
+++ b/doc/forum/ipv6_support_for_P.Property.Firewall/comment_1_d301cfd7a7cb0987a73b8d32df4dac97._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="probably low level is needed"
+ date="2019-07-19T12:38:30Z"
+ content="""
+A tiny amount of investigation reveals that there are protocols that make sense only for one of ip{6,}tables, e.g. icmpv6. So probably ip6tables needs to be invoked separately.
+"""]]

diff --git a/doc/forum/ipv6_support_for_P.Property.Firewall.mdwn b/doc/forum/ipv6_support_for_P.Property.Firewall.mdwn
new file mode 100644
index 00000000..4648e3d4
--- /dev/null
+++ b/doc/forum/ipv6_support_for_P.Property.Firewall.mdwn
@@ -0,0 +1 @@
+would it make sense for Firewall.rule to call ip6tables as well as iptables? Or is a lower level interface with e.g. rule6 invoking ip6tables. To be honest I haven't tested ip6tables on machines without ipv6 support, so I don't know how gracefully it fails.

Added a comment: A first attempt
diff --git a/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_1_0656133cfbc13b7369a74f351a9388c4._comment b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_1_0656133cfbc13b7369a74f351a9388c4._comment
new file mode 100644
index 00000000..06939eec
--- /dev/null
+++ b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_1_0656133cfbc13b7369a74f351a9388c4._comment
@@ -0,0 +1,94 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="A  first attempt"
+ date="2019-07-18T23:30:44Z"
+ content="""
+Here's what I came up with. I don't know if I'm missing some more obvious way. Thanks to Stefan Gronke on github for answering \"what's a simple way to make an iptables systemd service\"
+
+[[!format haskell \"\"\"
+module Propellor.Property.SiteSpecific.Tethera.Firewall (
+    iptablesRules
+  , iptablesUnits
+  , saved
+  ) where
+
+import Propellor.Base
+import Propellor.Property.Firewall
+-- import qualified Propellor.Property.Cmd as Cmd
+import qualified Propellor.Property.File as File
+
+iptablesRules :: [Port] -> [Port] -> Property DebianLike
+iptablesRules tcpPorts udpPorts = propertyList \"IPTables based firewall\" $ props
+  & installed
+  & rule INPUT Filter DROP (Ctstate [INVALID])
+  & rule INPUT Filter ACCEPT (InIFace \"lo\")
+  & rule OUTPUT Filter ACCEPT (OutIFace \"lo\")
+  & rule INPUT Filter ACCEPT (Ctstate [ESTABLISHED, RELATED])
+  & rule INPUT Filter ACCEPT (Proto ICMP)
+  & openPorts TCP tcpPorts
+  & openPorts UDP udpPorts
+  & rule OUTPUT Filter ACCEPT Everything
+  & rule INPUT Filter DROP Everything
+  & rule FORWARD Filter DROP Everything
+  where
+    openPorts proto lst = combineProperties \"open TCP ports\" $
+                   toProps (map
+                             (\p -> (rule INPUT Filter ACCEPT 
+                                     ((Proto proto) :- (DPort p)) ))
+                             lst)
+
+saved :: Property UnixLike
+saved = combineProperties \"iptables rules saved\" $ props
+  & cmdProperty \"iptables-save\" [\"-f\", rulesFile ]
+        `changesFile` rulesFile
+    `requires` File.dirExists rulesDir
+  & cmdProperty \"ip6tables-save\" [\"-f\", rules6File ]
+        `changesFile` rules6File
+    `requires` File.dirExists rulesDir
+  where
+    rulesDir = \"/etc/iptables\"
+    rulesFile = rulesDir ++ \"/iptables.rules\"
+    rules6File = rulesDir ++ \"/ip6tables.rules\"
+
+iptablesUnits :: Property UnixLike  
+iptablesUnits = combineProperties \"systemd units for iptables\" $ props
+                & unitFile \"iptables\"
+                & unitFile \"ip6tables\"                
+  where
+    unitDir = \"/etc/systemd/system\"
+    unitFile baseName = combineProperties (\"systemd units for \" ++ baseName) $ props
+                & File.hasContent (unitDir ++ \"/\"++baseName++\".service\")
+                [
+                  \"[Unit]\"
+                , \"Description=Packet Filtering Framework\"
+                , \"DefaultDependencies=no\"
+                , \"After=systemd-sysctl.service\"
+                , \"Before=sysinit.target\"
+                , \"[Service]\"
+                , \"Type=oneshot\"
+                , \"ExecStart=/sbin/\"++baseName++\"-restore /etc/iptables/\"++baseName++\".rules\"
+                , \"ExecReload=/sbin/\"++baseName++\"-restore /etc/iptables/\"++baseName++\".rules\"
+                , \"ExecStop=/usr/local/bin/flush-\"++baseName++\".sh\"
+                , \"RemainAfterExit=yes\"
+                , \"[Install]\"
+                , \"WantedBy=multi-user.target\"
+                ]
+                & File.hasContent fipSh
+                [
+                  \"#!/bin/sh\"
+                , \"iptables -F\"
+                , \"iptables -X\"
+                , \"iptables -t nat -F\"
+                , \"iptables -t nat -X\"
+                , \"iptables -t mangle -F\"
+                , \"iptables -t mangle -X\"
+                , \"iptables -P INPUT ACCEPT\"
+                , \"iptables -P FORWARD ACCEPT\"
+                , \"iptables -P OUTPUT ACCEPT\"
+                ]
+                & File.mode fipSh 0755
+      where
+            fipSh = \"/usr/local/bin/flush-\"++baseName++\".sh\"
+\"\"\"]]
+"""]]

diff --git a/doc/forum/How_to_make_P.Property.Firewall.rule_persistent.mdwn b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent.mdwn
new file mode 100644
index 00000000..25360b26
--- /dev/null
+++ b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent.mdwn
@@ -0,0 +1,33 @@
+The following seems to more or less work (at least the output from
+"iptables -L -v" looks plausible. But it's not persistent.
+It doesn't seem sensible to wait for propellor to run again to set up a firewall after reboot. Any ideas for how to make this persistent?
+
+[[!format haskell """
+module Propellor.Property.SiteSpecific.Tethera.Firewall (
+  ipFirewall,
+  ) where
+
+import Propellor.Base
+import Propellor.Property.Firewall
+
+ipFirewall :: [Port] -> [Port] -> Property DebianLike
+ipFirewall tcpPorts udpPorts = propertyList "IPTables based firewall" $ props
+  & installed
+  & rule INPUT Filter DROP (Ctstate [INVALID])
+  & rule INPUT Filter ACCEPT (InIFace "lo")
+  & rule OUTPUT Filter ACCEPT (OutIFace "lo")
+  & rule INPUT Filter ACCEPT (Ctstate [ESTABLISHED, RELATED])
+  & rule INPUT Filter ACCEPT (Proto ICMP)
+  & openPorts TCP tcpPorts
+  & openPorts UDP udpPorts
+  & rule OUTPUT Filter ACCEPT Everything
+  & rule INPUT Filter DROP Everything
+  & rule FORWARD Filter DROP Everything
+  where
+    openPorts proto lst = combineProperties "open TCP ports" $
+                   toProps (map
+                             (\p -> (rule INPUT Filter ACCEPT 
+                                     ((Proto proto) :- (DPort p)) ))
+                             lst)
+      
+"""]]

add news item for propellor 5.9.1
diff --git a/doc/news/version_5.6.0.mdwn b/doc/news/version_5.6.0.mdwn
deleted file mode 100644
index e3ecf2a4..00000000
--- a/doc/news/version_5.6.0.mdwn
+++ /dev/null
@@ -1,22 +0,0 @@
-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
diff --git a/doc/news/version_5.9.1.mdwn b/doc/news/version_5.9.1.mdwn
new file mode 100644
index 00000000..dd7bcd5e
--- /dev/null
+++ b/doc/news/version_5.9.1.mdwn
@@ -0,0 +1,11 @@
+propellor 5.9.1 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Apt: Debian has changed the name of the suite for testing security updates
+     from testing to testing-security.
+   * Apt: Also the suite for stable releases from bullseye on will be
+     suffixed with "-security".
+   * Apt.update: Pass --allow-releaseinfo-change when updating Unstable
+     or Testing, so that code name changes that happen in those suites
+     during a stable release don't prevent updating the rolling suites.
+   * Systemd.machined: Fix a bug that caused the systemd-container package
+     to not be installed when used with Debian buster."""]]
\ No newline at end of file

Added a comment
diff --git a/doc/forum/apt_releaseinfo/comment_3_14f13cddb537766dc2b8234c731e0834._comment b/doc/forum/apt_releaseinfo/comment_3_14f13cddb537766dc2b8234c731e0834._comment
new file mode 100644
index 00000000..495651f3
--- /dev/null
+++ b/doc/forum/apt_releaseinfo/comment_3_14f13cddb537766dc2b8234c731e0834._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 3"
+ date="2019-07-17T15:47:26Z"
+ content="""
+I think so, but presumably they are being often misused.
+"""]]

Apt.update: Pass --allow-releaseinfo-change when updating Unstable or Testing
So that code name changes that happen in those suites during a stable
release don't prevent updating the rolling suites.
diff --git a/debian/changelog b/debian/changelog
index 0f51140a..2de322ee 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -4,6 +4,9 @@ propellor (5.9.1) UNRELEASED; urgency=medium
     from testing to testing-security.
   * Apt: Also the suite for stable releases from bullseye on will be
     suffixed with "-security".
+  * Apt.update: Pass --allow-releaseinfo-change when updating Unstable
+    or Testing, so that code name changes that happen in those suites
+    during a stable release don't prevent updating the rolling suites.
 
  -- Joey Hess <id@joeyh.name>  Wed, 10 Jul 2019 22:02:35 -0400
 
diff --git a/doc/forum/apt_releaseinfo/comment_2_d8381b5e727b6e54f8e4a5cd9792e09c._comment b/doc/forum/apt_releaseinfo/comment_2_d8381b5e727b6e54f8e4a5cd9792e09c._comment
new file mode 100644
index 00000000..401271d9
--- /dev/null
+++ b/doc/forum/apt_releaseinfo/comment_2_d8381b5e727b6e54f8e4a5cd9792e09c._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2019-07-16T15:09:57Z"
+ content="""
+That matches my intuition of it. And propellor's Unstable and Testing
+are indeed intended to explicitly request a rolling release.
+(I thought that "unstable" and "testing" were also intended to explicitly
+request that?)
+
+Anyway, I've made Apt.update add the new argument for Unstable and Testing.
+"""]]
diff --git a/src/Propellor/Property/Apt.hs b/src/Propellor/Property/Apt.hs
index bc190e59..4faf0984 100644
--- a/src/Propellor/Property/Apt.hs
+++ b/src/Propellor/Property/Apt.hs
@@ -214,10 +214,21 @@ noninteractiveEnv =
 
 -- | Have apt update its lists of packages, but without upgrading anything.
 update :: Property DebianLike
-update = combineProperties ("apt update") $ props
+update = combineProperties desc $ props
 	& pendingConfigured
-	& runApt ["update"]
-		`assume` MadeChange
+	& aptupdate
+  where
+	desc = "apt update"
+	aptupdate :: Property DebianLike
+	aptupdate = withOS desc $ \w o -> case o of
+		(Just (System (Debian _ suite) _))
+			| not (isStable suite) -> ensureProperty w $
+				-- rolling suites' release info can change
+				runApt ["update", "--allow-releaseinfo-change"]
+					`assume` MadeChange
+		_ -> ensureProperty w $ 
+			runApt ["update"]
+				`assume` MadeChange
 
 -- | Have apt upgrade packages, adding new packages and removing old as
 -- necessary. Often used in combination with the `update` property.

Added a comment
diff --git a/doc/forum/apt_releaseinfo/comment_1_a6897e3cb6089c4f3db3d37e71ff9659._comment b/doc/forum/apt_releaseinfo/comment_1_a6897e3cb6089c4f3db3d37e71ff9659._comment
new file mode 100644
index 00000000..b354208d
--- /dev/null
+++ b/doc/forum/apt_releaseinfo/comment_1_a6897e3cb6089c4f3db3d37e71ff9659._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 1"
+ date="2019-07-12T06:39:18Z"
+ content="""
+I think that the point of this was to prevent people with 'stable' in their sources.list from accidentally upgrading to a new stable release.  Similarly, to prevent users with 'testing' in their sources.list from upgrading to the new testing, when what they wanted to do was track stable+1.
+
+I think that when a user uses propellor's `Testing` and `Unstable` types they are explicitly requesting a rolling release, so it seems find to pass it for those suites.
+
+This is not based on reading any discussions about the new feature.  Just my own inference as to its purpose.
+"""]]

diff --git a/doc/forum/Contribution_and_community.mdwn b/doc/forum/Contribution_and_community.mdwn
new file mode 100644
index 00000000..87c57afd
--- /dev/null
+++ b/doc/forum/Contribution_and_community.mdwn
@@ -0,0 +1,10 @@
+Propellor seems inaccessible to me.
+
+The contribution workflow is based on emails or unstructured todo wiki subpages. It is unclear where to get help.
+
+I suggest you switch to using https://gitlab.haskell.org for example
+
+Getting contributions in open source is about how accessible your project is. That includes not only codebase, but especially workflow.
+I also barely see anyone respond to propellor topics on #haskell freenode.
+
+We use propellor at work and I'm already wondering if ansible would have been a better choice.

seeking advice from DDs
diff --git a/doc/forum/apt_releaseinfo.mdwn b/doc/forum/apt_releaseinfo.mdwn
new file mode 100644
index 00000000..f817da69
--- /dev/null
+++ b/doc/forum/apt_releaseinfo.mdwn
@@ -0,0 +1,17 @@
+Since apt-get has changed behavior and refuses to update if the code name
+in a Release file has changed from the one it saw before, propellor systems
+that are tracking Unstable or Testing need a manual intervention after each
+major stable release (`apt-get update --allow-releaseinfo-change`).
+
+(It seems that when unattended-updates is available, it does automatically
+accept the change.)
+
+I am seeking advice about what propellor should do about this. Should 
+Apt.update include --allow-releaseinfo-change when the host is following a
+rolling suite? 
+
+Or does doing so defeat whatever presumably good rationalle there is for
+making this a manual action? Or perhaps there is no really good reason apt
+does this when following a folling suite?
+
+--[[Joey]]

add news item for propellor 5.9.0
diff --git a/doc/news/version_5.5.0.mdwn b/doc/news/version_5.5.0.mdwn
deleted file mode 100644
index 360a5314..00000000
--- a/doc/news/version_5.5.0.mdwn
+++ /dev/null
@@ -1,20 +0,0 @@
-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
diff --git a/doc/news/version_5.9.0.mdwn b/doc/news/version_5.9.0.mdwn
new file mode 100644
index 00000000..160b1187
--- /dev/null
+++ b/doc/news/version_5.9.0.mdwn
@@ -0,0 +1,26 @@
+propellor 5.9.0 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Added custom type error messages when Properties don't combine due to
+     conflicting MetaTypes.
+   * Added custom type error messages for ensureProperty and tightenTargets.
+   * Note that those changes made ghc 8.0.1 in a few cases unable to infer
+     types when ensureProperty or tightenTargets is used, while later ghc
+     versions had no difficulty. If this affects building your properties,
+     adding a type annotation to the code will work around the problem.
+   * Added custom type error messages displayed when type inference
+     fails when using ensureProperty and tightenTargets, that suggest
+     adding a type annotation.
+   * Use the type-errors library to detect when the type checker gets stuck
+     unable to reduce type-level operations on MetaTypes, and avoid
+     displaying massive error messages.
+   * But, since type-errors is a new library not available in eg Debian
+     yet, added a WithTypeErrors build flag. When the library is not
+     available, cabal will automatically disable that build flag,
+     and it will build without the type-errors library.
+   * EnsurePropertyAllowed, TightenTargetsAllowed, and CheckCombinable
+     types have changed to Constraint.
+     (API change)
+   * Try harder to avoid displaying an excessive amount of type error
+     messages when many properties have been combined in a props list.
+   * Libvirt.installed: install libvirt-daemon-system
+     Thanks, David Bremner"""]]
\ No newline at end of file

close
diff --git a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
index 8c2ed77a..7d87b48e 100644
--- a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
+++ b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
@@ -27,4 +27,6 @@ whittle them down to a more useful error. --[[Joey]]
 > > a simpler error would be a big improvement. Such large error messages
 > > can make ghc use an excessive amount of memory. --[[Joey]]
 
+now [[done]]! --[[Joey]]
+
 [[!tag user/joey]]

Revert "Revert "custom type error messages""
This reverts commit 665ea0d3d9e1b0e90278fd659dee0ef8642030da.
diff --git a/debian/changelog b/debian/changelog
index c263fc96..c74cd929 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,26 @@
-propellor (5.8.1) UNRELEASED; urgency=medium
-
+propellor (5.9.0) UNRELEASED; urgency=medium
+
+  * Avoid displaying an excessive amount of type error messages when many
+    properties have been combined in a props list.
+  * Added custom type error messages when Properties don't combine due to
+    conflicting MetaTypes.
+  * Added custom type error messages for ensureProperty and tightenTargets.
+  * Note that those changes made ghc 8.0.1 in a few cases unable to infer
+    types when ensureProperty or tightenTargets is used. Adding a type
+    annotation will work around this problem, if you cannot upgrade
+    to a newer ghc that handles them better.
+  * Use the type-errors library to detect when the type checker gets stuck
+    unable to reduce type-level operations on MetaTypes, and avoid 
+    displaying massive error messages in such a case.
+  * But, since type-errors is a new library not available in eg Debian
+    yet, added a WithTypeErrors build flag. When the library is not
+    available, cabal will automatically disable that build flag,
+    and it will build without the type-errors library.
+  * ensureProperty: The constraints have been simplified
+    to EnsurePropertyAllowed. (API change)
+  * ensureProperty: The contraints have been simplified
+    to TightenTargetsAllowed. (API change)
+  * CheckCombinable generates a Bool. (API change)
   * Libvirt.installed: install libvirt-daemon-system
     Thanks, David Bremner
 
diff --git a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
index d21c92fe..8c2ed77a 100644
--- a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
+++ b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
@@ -6,7 +6,25 @@ For example, a RevertableProperty is sometimes used where only a regular
 Property is accepted. In this case, the error could suggest that the user
 apply `setupRevertableProperty` to extract the setup side of the RevertableProperty.
 
-> The `custom-error-types` branch has this implemented quite nicely.
-> Unfortunately, it ran into a ghc bug <https://gitlab.haskell.org/ghc/ghc/issues/16894>
+> I tried this, it didn't seem worth the complication however. --[[Joey]]
+
+And, when a Property HasInfo is provided to ensureProperty, propellor could
+explain, in the compile error, why it can't let the user do that.
+
+> Done this and also used custom errors when properties' types don't let
+> them be combined. --[[Joey]]
+
+The new type-errors library builds a lot of stuff on top of this.
+Its ability to detect "stuckness" seems like it may be able to catch
+the very long type errors that we sometimes see when using propellor, and
+whittle them down to a more useful error. --[[Joey]]
+
+> > Actually I think the stuckness would not help with that, though it
+> > could help with other mistakes. In particular, forgetting to provide
+> > a parameter to a property constructor can lead to a massive
+> > error message that leaks type family stuff from MetaTypes, due to
+> > the type checker getting stuck. Detecting that and replacing it with
+> > a simpler error would be a big improvement. Such large error messages
+> > can make ghc use an excessive amount of memory. --[[Joey]]
 
 [[!tag user/joey]]
diff --git a/propellor.cabal b/propellor.cabal
index 300313c0..71d3c578 100644
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -35,6 +35,9 @@ Description:
  .
  It is configured using haskell.
 
+Flag WithTypeErrors
+  Description: Build with type-errors library for better error messages
+
 Library
   Default-Language: Haskell98
   GHC-Options: -Wall -fno-warn-tabs -O0
@@ -47,6 +50,9 @@ Library
     directory, filepath, IfElse, process, bytestring, hslogger, split,
     unix, unix-compat, ansi-terminal, containers (>= 0.5), network, async,
     time, mtl, transformers, exceptions (>= 0.6), stm, text, hashable
+  if flag(WithTypeErrors)
+    Build-Depends: type-errors
+    CPP-Options: -DWITH_TYPE_ERRORS
 
   Exposed-Modules:
     Propellor
diff --git a/src/Propellor/EnsureProperty.hs b/src/Propellor/EnsureProperty.hs
index ab624706..5ed0325f 100644
--- a/src/Propellor/EnsureProperty.hs
+++ b/src/Propellor/EnsureProperty.hs
@@ -8,7 +8,7 @@ module Propellor.EnsureProperty
 	( ensureProperty
 	, property'
 	, OuterMetaTypesWitness
-	, Cannot_ensureProperty_WithInfo
+	, EnsurePropertyAllowed
 	) where
 
 import Propellor.Types
@@ -16,6 +16,8 @@ import Propellor.Types.Core
 import Propellor.Types.MetaTypes
 import Propellor.Exception
 
+import GHC.TypeLits
+import Data.Type.Bool
 import Data.Monoid
 import Prelude
 
@@ -41,19 +43,40 @@ ensureProperty
 		-- -Wredundant-constraints is turned off because
 		-- this constraint appears redundant, but is actually
 		-- crucial.
-		( Cannot_ensureProperty_WithInfo inner ~ 'True
-		, (Targets inner `NotSuperset` Targets outer) ~ 'CanCombine
-		)
+		( EnsurePropertyAllowed inner outer ~ 'True)
 	=> OuterMetaTypesWitness outer
 	-> Property (MetaTypes inner)
 	-> Propellor Result
 ensureProperty _ = maybe (return NoChange) catchPropellor . getSatisfy
 
--- The name of this was chosen to make type errors a bit more understandable.
-type family Cannot_ensureProperty_WithInfo (l :: [a]) :: Bool where
-	Cannot_ensureProperty_WithInfo '[] = 'True
-	Cannot_ensureProperty_WithInfo (t ': ts) =
-		Not (t `EqT` 'WithInfo) && Cannot_ensureProperty_WithInfo ts
+type family EnsurePropertyAllowed inner outer where
+	EnsurePropertyAllowed inner outer = 
+		(EnsurePropertyNoInfo inner)
+			&&
+		(EnsurePropertyTargetOSMatches inner outer)
+
+type family EnsurePropertyNoInfo (l :: [a]) :: Bool where
+	EnsurePropertyNoInfo '[] = 'True
+	EnsurePropertyNoInfo (t ': ts) = If (Not (t `EqT` 'WithInfo))
+		(EnsurePropertyNoInfo ts)
+		(TypeError ('Text "Cannot use ensureProperty with a Property that HasInfo."))
+
+type family EnsurePropertyTargetOSMatches inner outer where
+	EnsurePropertyTargetOSMatches inner outer = 
+		If (Targets outer `IsSubset` Targets inner)
+			'True
+			(IfStuck (Targets outer)
+				(TypeError
+					('Text "ensureProperty outer Property type is not able to be inferred here."
+					 ':$$: 'Text "Consider adding a type annotation."
+					)
+				)
+				(TypeError
+					('Text "ensureProperty inner Property is missing support for: "
+					 ':$$: PrettyPrintMetaTypes (Difference (Targets outer) (Targets inner))
+					)
+				)
+			)
 
 -- | Constructs a property, like `property`, but provides its
 -- `OuterMetaTypesWitness`.
diff --git a/src/Propellor/PropAccum.hs b/src/Propellor/PropAccum.hs
index c60ced73..3fc83202 100644
--- a/src/Propellor/PropAccum.hs
+++ b/src/Propellor/PropAccum.hs
@@ -19,6 +19,7 @@ import Propellor.Types.MetaTypes
 import Propellor.Types.Core
 import Propellor.Property
 
+import GHC.TypeLits
 import Data.Monoid
 import Prelude
 
@@ -45,6 +46,16 @@ type family GetMetaTypes x where
 	GetMetaTypes (Property (MetaTypes t)) = MetaTypes t
 	GetMetaTypes (RevertableProperty (MetaTypes t) undo) = MetaTypes t
 
+-- When many properties are combined, ghc error message
+-- can include quite a lot of code, typically starting with
+-- `props  and including all the properties up to and including the
+-- one that fails to combine. Point the user in the right direction.
+type family NoteFor symbol :: ErrorMessage where
+	NoteFor symbol =
+		'Text "Probably the problem is with the last property added with "
+			':<>: symbol
+			':<>: 'Text " in the code excerpt below."
+
 -- | Adds a property to a Props.
 --
 -- Can add Properties and RevertableProperties
@@ -55,7 +66,7 @@ type family GetMetaTypes x where
 		-- this constraint appears redundant, but is actually
 		-- crucial.
 		, MetaTypes y ~ GetMetaTypes p
-		, CheckCombinable x y ~ 'CanCombine
+		, CheckCombinableNote x y (NoteFor ('Text "&")) ~ 'True
 		)
 	=> Props (MetaTypes x)
 	-> p
@@ -70,7 +81,7 @@ Props c & p = Props (c ++ [toChildProperty p])
 		-- this constraint appears redundant, but is actually

(Diff truncated)
point to branch
diff --git a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
index 95f86143..d21c92fe 100644
--- a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
+++ b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
@@ -6,27 +6,7 @@ For example, a RevertableProperty is sometimes used where only a regular
 Property is accepted. In this case, the error could suggest that the user
 apply `setupRevertableProperty` to extract the setup side of the RevertableProperty.
 
-And, when a Property HasInfo is provided to ensureProperty, propellor could
-explain, in the compile error, why it can't let the user do that.
-
-Custom errors need a type class to be used. So, could do something like this:
-
-	class NeedsProperty a where
-		withProperty :: (Property metatype -> b) -> b
-
-	instance NeedsProperty (Property metatype) where withProperty = id
-
-	instance TypeError (Text "Use setupRevertableProperty ...")
-        	 => NeedsProperty RevertableProperty where
-			withProperty = error "unreachable"
-
-(While propellor needs to be buildable with older versions of ghc,
-the `instance TypeError` can just be wrapped in an ifdef to make it only be
-used by the new ghc.)
-
-> The new type-errors library builds a lot of stuff on top of this.
-> Its ability to detect "stuckness" seems like it may be able to catch
-> the very long type errors that we sometimes see when using propellor, and
-> whittle them down to a more useful error. --[[Joey]]
+> The `custom-error-types` branch has this implemented quite nicely.
+> Unfortunately, it ran into a ghc bug <https://gitlab.haskell.org/ghc/ghc/issues/16894>
 
 [[!tag user/joey]]

Revert "custom type error messages"
This reverts commits 14f6ae30809d8bbdb10b91cc59757e865a365df8
de21ef26861db458b0dfb0212cf501f9f8ed459b e20662e6a8881db55394a6366be17ca4e509bc2a
Until this bug is resolved, these custom error types hide more basic
errors. https://gitlab.haskell.org/ghc/ghc/issues/16894
diff --git a/debian/changelog b/debian/changelog
index c74cd929..c263fc96 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,26 +1,5 @@
-propellor (5.9.0) UNRELEASED; urgency=medium
-
-  * Avoid displaying an excessive amount of type error messages when many
-    properties have been combined in a props list.
-  * Added custom type error messages when Properties don't combine due to
-    conflicting MetaTypes.
-  * Added custom type error messages for ensureProperty and tightenTargets.
-  * Note that those changes made ghc 8.0.1 in a few cases unable to infer
-    types when ensureProperty or tightenTargets is used. Adding a type
-    annotation will work around this problem, if you cannot upgrade
-    to a newer ghc that handles them better.
-  * Use the type-errors library to detect when the type checker gets stuck
-    unable to reduce type-level operations on MetaTypes, and avoid 
-    displaying massive error messages in such a case.
-  * But, since type-errors is a new library not available in eg Debian
-    yet, added a WithTypeErrors build flag. When the library is not
-    available, cabal will automatically disable that build flag,
-    and it will build without the type-errors library.
-  * ensureProperty: The constraints have been simplified
-    to EnsurePropertyAllowed. (API change)
-  * ensureProperty: The contraints have been simplified
-    to TightenTargetsAllowed. (API change)
-  * CheckCombinable generates a Bool. (API change)
+propellor (5.8.1) UNRELEASED; urgency=medium
+
   * Libvirt.installed: install libvirt-daemon-system
     Thanks, David Bremner
 
diff --git a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
index 8c2ed77a..95f86143 100644
--- a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
+++ b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
@@ -6,25 +6,27 @@ For example, a RevertableProperty is sometimes used where only a regular
 Property is accepted. In this case, the error could suggest that the user
 apply `setupRevertableProperty` to extract the setup side of the RevertableProperty.
 
-> I tried this, it didn't seem worth the complication however. --[[Joey]]
-
 And, when a Property HasInfo is provided to ensureProperty, propellor could
 explain, in the compile error, why it can't let the user do that.
 
-> Done this and also used custom errors when properties' types don't let
-> them be combined. --[[Joey]]
-
-The new type-errors library builds a lot of stuff on top of this.
-Its ability to detect "stuckness" seems like it may be able to catch
-the very long type errors that we sometimes see when using propellor, and
-whittle them down to a more useful error. --[[Joey]]
-
-> > Actually I think the stuckness would not help with that, though it
-> > could help with other mistakes. In particular, forgetting to provide
-> > a parameter to a property constructor can lead to a massive
-> > error message that leaks type family stuff from MetaTypes, due to
-> > the type checker getting stuck. Detecting that and replacing it with
-> > a simpler error would be a big improvement. Such large error messages
-> > can make ghc use an excessive amount of memory. --[[Joey]]
+Custom errors need a type class to be used. So, could do something like this:
+
+	class NeedsProperty a where
+		withProperty :: (Property metatype -> b) -> b
+
+	instance NeedsProperty (Property metatype) where withProperty = id
+
+	instance TypeError (Text "Use setupRevertableProperty ...")
+        	 => NeedsProperty RevertableProperty where
+			withProperty = error "unreachable"
+
+(While propellor needs to be buildable with older versions of ghc,
+the `instance TypeError` can just be wrapped in an ifdef to make it only be
+used by the new ghc.)
+
+> The new type-errors library builds a lot of stuff on top of this.
+> Its ability to detect "stuckness" seems like it may be able to catch
+> the very long type errors that we sometimes see when using propellor, and
+> whittle them down to a more useful error. --[[Joey]]
 
 [[!tag user/joey]]
diff --git a/propellor.cabal b/propellor.cabal
index 71d3c578..300313c0 100644
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -35,9 +35,6 @@ Description:
  .
  It is configured using haskell.
 
-Flag WithTypeErrors
-  Description: Build with type-errors library for better error messages
-
 Library
   Default-Language: Haskell98
   GHC-Options: -Wall -fno-warn-tabs -O0
@@ -50,9 +47,6 @@ Library
     directory, filepath, IfElse, process, bytestring, hslogger, split,
     unix, unix-compat, ansi-terminal, containers (>= 0.5), network, async,
     time, mtl, transformers, exceptions (>= 0.6), stm, text, hashable
-  if flag(WithTypeErrors)
-    Build-Depends: type-errors
-    CPP-Options: -DWITH_TYPE_ERRORS
 
   Exposed-Modules:
     Propellor
diff --git a/src/Propellor/EnsureProperty.hs b/src/Propellor/EnsureProperty.hs
index 5ed0325f..ab624706 100644
--- a/src/Propellor/EnsureProperty.hs
+++ b/src/Propellor/EnsureProperty.hs
@@ -8,7 +8,7 @@ module Propellor.EnsureProperty
 	( ensureProperty
 	, property'
 	, OuterMetaTypesWitness
-	, EnsurePropertyAllowed
+	, Cannot_ensureProperty_WithInfo
 	) where
 
 import Propellor.Types
@@ -16,8 +16,6 @@ import Propellor.Types.Core
 import Propellor.Types.MetaTypes
 import Propellor.Exception
 
-import GHC.TypeLits
-import Data.Type.Bool
 import Data.Monoid
 import Prelude
 
@@ -43,40 +41,19 @@ ensureProperty
 		-- -Wredundant-constraints is turned off because
 		-- this constraint appears redundant, but is actually
 		-- crucial.
-		( EnsurePropertyAllowed inner outer ~ 'True)
+		( Cannot_ensureProperty_WithInfo inner ~ 'True
+		, (Targets inner `NotSuperset` Targets outer) ~ 'CanCombine
+		)
 	=> OuterMetaTypesWitness outer
 	-> Property (MetaTypes inner)
 	-> Propellor Result
 ensureProperty _ = maybe (return NoChange) catchPropellor . getSatisfy
 
-type family EnsurePropertyAllowed inner outer where
-	EnsurePropertyAllowed inner outer = 
-		(EnsurePropertyNoInfo inner)
-			&&
-		(EnsurePropertyTargetOSMatches inner outer)
-
-type family EnsurePropertyNoInfo (l :: [a]) :: Bool where
-	EnsurePropertyNoInfo '[] = 'True
-	EnsurePropertyNoInfo (t ': ts) = If (Not (t `EqT` 'WithInfo))
-		(EnsurePropertyNoInfo ts)
-		(TypeError ('Text "Cannot use ensureProperty with a Property that HasInfo."))
-
-type family EnsurePropertyTargetOSMatches inner outer where
-	EnsurePropertyTargetOSMatches inner outer = 
-		If (Targets outer `IsSubset` Targets inner)
-			'True
-			(IfStuck (Targets outer)
-				(TypeError
-					('Text "ensureProperty outer Property type is not able to be inferred here."
-					 ':$$: 'Text "Consider adding a type annotation."
-					)
-				)
-				(TypeError
-					('Text "ensureProperty inner Property is missing support for: "
-					 ':$$: PrettyPrintMetaTypes (Difference (Targets outer) (Targets inner))
-					)
-				)
-			)
+-- The name of this was chosen to make type errors a bit more understandable.
+type family Cannot_ensureProperty_WithInfo (l :: [a]) :: Bool where
+	Cannot_ensureProperty_WithInfo '[] = 'True
+	Cannot_ensureProperty_WithInfo (t ': ts) =
+		Not (t `EqT` 'WithInfo) && Cannot_ensureProperty_WithInfo ts
 
 -- | Constructs a property, like `property`, but provides its
 -- `OuterMetaTypesWitness`.
diff --git a/src/Propellor/PropAccum.hs b/src/Propellor/PropAccum.hs
index 3fc83202..c60ced73 100644
--- a/src/Propellor/PropAccum.hs
+++ b/src/Propellor/PropAccum.hs
@@ -19,7 +19,6 @@ import Propellor.Types.MetaTypes
 import Propellor.Types.Core
 import Propellor.Property
 
-import GHC.TypeLits
 import Data.Monoid
 import Prelude
 
@@ -46,16 +45,6 @@ type family GetMetaTypes x where
 	GetMetaTypes (Property (MetaTypes t)) = MetaTypes t
 	GetMetaTypes (RevertableProperty (MetaTypes t) undo) = MetaTypes t
 
--- When many properties are combined, ghc error message
--- can include quite a lot of code, typically starting with
--- `props  and including all the properties up to and including the
--- one that fails to combine. Point the user in the right direction.
-type family NoteFor symbol :: ErrorMessage where
-	NoteFor symbol =
-		'Text "Probably the problem is with the last property added with "

(Diff truncated)
custom type error messages
* Avoid displaying an excessive amount of type error messages when many
properties have been combined in a props list.
* Added custom type error messages when Properties don't combine due to
conflicting metatypes.
* Added custom type error messages for ensureProperty and tightenTargets.
* ensureProperty: The constraints have been simplified
to EnsurePropertyAllowed. (API change)
* ensureProperty: The contraints have been simplified
to TightenTargetsAllowed. (API change)
* CheckCombinable generates a Bool. (API change)
This commit was sponsored by Jake Vosloo on Patreon.
diff --git a/debian/changelog b/debian/changelog
index c263fc96..8944ff8f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,15 @@
-propellor (5.8.1) UNRELEASED; urgency=medium
-
+propellor (5.9.0) UNRELEASED; urgency=medium
+
+  * Avoid displaying an excessive amount of type error messages when many
+    properties have been combined in a props list.
+  * Added custom type error messages when Properties don't combine due to
+    conflicting metatypes.
+  * Added custom type error messages for ensureProperty and tightenTargets.
+  * ensureProperty: The constraints have been simplified
+    to EnsurePropertyAllowed. (API change)
+  * ensureProperty: The contraints have been simplified
+    to TightenTargetsAllowed. (API change)
+  * CheckCombinable generates a Bool. (API change)
   * Libvirt.installed: install libvirt-daemon-system
     Thanks, David Bremner
 
diff --git a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
index 95f86143..8c2ed77a 100644
--- a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
+++ b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
@@ -6,27 +6,25 @@ For example, a RevertableProperty is sometimes used where only a regular
 Property is accepted. In this case, the error could suggest that the user
 apply `setupRevertableProperty` to extract the setup side of the RevertableProperty.
 
+> I tried this, it didn't seem worth the complication however. --[[Joey]]
+
 And, when a Property HasInfo is provided to ensureProperty, propellor could
 explain, in the compile error, why it can't let the user do that.
 
-Custom errors need a type class to be used. So, could do something like this:
-
-	class NeedsProperty a where
-		withProperty :: (Property metatype -> b) -> b
-
-	instance NeedsProperty (Property metatype) where withProperty = id
-
-	instance TypeError (Text "Use setupRevertableProperty ...")
-        	 => NeedsProperty RevertableProperty where
-			withProperty = error "unreachable"
-
-(While propellor needs to be buildable with older versions of ghc,
-the `instance TypeError` can just be wrapped in an ifdef to make it only be
-used by the new ghc.)
-
-> The new type-errors library builds a lot of stuff on top of this.
-> Its ability to detect "stuckness" seems like it may be able to catch
-> the very long type errors that we sometimes see when using propellor, and
-> whittle them down to a more useful error. --[[Joey]]
+> Done this and also used custom errors when properties' types don't let
+> them be combined. --[[Joey]]
+
+The new type-errors library builds a lot of stuff on top of this.
+Its ability to detect "stuckness" seems like it may be able to catch
+the very long type errors that we sometimes see when using propellor, and
+whittle them down to a more useful error. --[[Joey]]
+
+> > Actually I think the stuckness would not help with that, though it
+> > could help with other mistakes. In particular, forgetting to provide
+> > a parameter to a property constructor can lead to a massive
+> > error message that leaks type family stuff from MetaTypes, due to
+> > the type checker getting stuck. Detecting that and replacing it with
+> > a simpler error would be a big improvement. Such large error messages
+> > can make ghc use an excessive amount of memory. --[[Joey]]
 
 [[!tag user/joey]]
diff --git a/src/Propellor/EnsureProperty.hs b/src/Propellor/EnsureProperty.hs
index ab624706..01203d04 100644
--- a/src/Propellor/EnsureProperty.hs
+++ b/src/Propellor/EnsureProperty.hs
@@ -8,7 +8,7 @@ module Propellor.EnsureProperty
 	( ensureProperty
 	, property'
 	, OuterMetaTypesWitness
-	, Cannot_ensureProperty_WithInfo
+	, EnsurePropertyAllowed
 	) where
 
 import Propellor.Types
@@ -16,6 +16,8 @@ import Propellor.Types.Core
 import Propellor.Types.MetaTypes
 import Propellor.Exception
 
+import GHC.TypeLits
+import Data.Type.Bool
 import Data.Monoid
 import Prelude
 
@@ -41,19 +43,33 @@ ensureProperty
 		-- -Wredundant-constraints is turned off because
 		-- this constraint appears redundant, but is actually
 		-- crucial.
-		( Cannot_ensureProperty_WithInfo inner ~ 'True
-		, (Targets inner `NotSuperset` Targets outer) ~ 'CanCombine
-		)
+		( EnsurePropertyAllowed inner outer ~ 'True)
 	=> OuterMetaTypesWitness outer
 	-> Property (MetaTypes inner)
 	-> Propellor Result
 ensureProperty _ = maybe (return NoChange) catchPropellor . getSatisfy
 
--- The name of this was chosen to make type errors a bit more understandable.
-type family Cannot_ensureProperty_WithInfo (l :: [a]) :: Bool where
-	Cannot_ensureProperty_WithInfo '[] = 'True
-	Cannot_ensureProperty_WithInfo (t ': ts) =
-		Not (t `EqT` 'WithInfo) && Cannot_ensureProperty_WithInfo ts
+type family EnsurePropertyAllowed inner outer where
+	EnsurePropertyAllowed inner outer = 
+		(EnsurePropertyNoInfo inner)
+			&&
+		(EnsurePropertyTargetOSMatches inner outer)
+
+type family EnsurePropertyNoInfo (l :: [a]) :: Bool where
+	EnsurePropertyNoInfo '[] = 'True
+	EnsurePropertyNoInfo (t ': ts) = If (Not (t `EqT` 'WithInfo))
+		(EnsurePropertyNoInfo ts)
+		(TypeError ('Text "Cannot use ensureProperty with a Property that HasInfo."))
+
+type family EnsurePropertyTargetOSMatches inner outer where
+	EnsurePropertyTargetOSMatches inner outer = 
+		If (Targets outer `IsSubset` Targets inner)
+			'True
+			( TypeError
+				( 'Text "ensureProperty inner Property is missing support for: "
+				  ':$$: PrettyPrintMetaTypes (Difference (Targets outer) (Targets inner))
+				)
+			)
 
 -- | Constructs a property, like `property`, but provides its
 -- `OuterMetaTypesWitness`.
diff --git a/src/Propellor/PropAccum.hs b/src/Propellor/PropAccum.hs
index c60ced73..3fc83202 100644
--- a/src/Propellor/PropAccum.hs
+++ b/src/Propellor/PropAccum.hs
@@ -19,6 +19,7 @@ import Propellor.Types.MetaTypes
 import Propellor.Types.Core
 import Propellor.Property
 
+import GHC.TypeLits
 import Data.Monoid
 import Prelude
 
@@ -45,6 +46,16 @@ type family GetMetaTypes x where
 	GetMetaTypes (Property (MetaTypes t)) = MetaTypes t
 	GetMetaTypes (RevertableProperty (MetaTypes t) undo) = MetaTypes t
 
+-- When many properties are combined, ghc error message
+-- can include quite a lot of code, typically starting with
+-- `props  and including all the properties up to and including the
+-- one that fails to combine. Point the user in the right direction.
+type family NoteFor symbol :: ErrorMessage where
+	NoteFor symbol =
+		'Text "Probably the problem is with the last property added with "
+			':<>: symbol
+			':<>: 'Text " in the code excerpt below."
+
 -- | Adds a property to a Props.
 --
 -- Can add Properties and RevertableProperties
@@ -55,7 +66,7 @@ type family GetMetaTypes x where
 		-- this constraint appears redundant, but is actually
 		-- crucial.
 		, MetaTypes y ~ GetMetaTypes p
-		, CheckCombinable x y ~ 'CanCombine
+		, CheckCombinableNote x y (NoteFor ('Text "&")) ~ 'True
 		)
 	=> Props (MetaTypes x)
 	-> p
@@ -70,7 +81,7 @@ Props c & p = Props (c ++ [toChildProperty p])
 		-- this constraint appears redundant, but is actually
 		-- crucial.
 		, MetaTypes y ~ GetMetaTypes p
-		, CheckCombinable x y ~ 'CanCombine
+		, CheckCombinableNote x y (NoteFor ('Text "&^")) ~ 'True
 		)
 	=> Props (MetaTypes x)
 	-> p
@@ -82,7 +93,7 @@ Props c &^ p = Props (toChildProperty p : c)
 	-- -Wredundant-constraints is turned off because
 	-- this constraint appears redundant, but is actually
 	-- crucial.
-	:: (CheckCombinable x z ~ 'CanCombine)
+	:: (CheckCombinableNote x z (NoteFor ('Text "!")) ~ 'True)
 	=> Props (MetaTypes x)
 	-> RevertableProperty (MetaTypes y) (MetaTypes z)
 	-> Props (MetaTypes (Combine x z))
diff --git a/src/Propellor/Property/Atomic.hs b/src/Propellor/Property/Atomic.hs
index 8519048b..2c7433f6 100644
--- a/src/Propellor/Property/Atomic.hs
+++ b/src/Propellor/Property/Atomic.hs
@@ -46,10 +46,8 @@ type CheckAtomicResourcePair a = AtomicResourcePair a -> Propellor (AtomicResour
 -- inactiveAtomicResource, and if it was successful,
 -- atomically activating that resource.
 atomicUpdate
-	-- Constriaints inherited from ensureProperty.

(Diff truncated)
type-errors library
diff --git a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
index 7eed443a..95f86143 100644
--- a/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
+++ b/doc/todo/use_ghc_8.0_custom_compile_errors.mdwn
@@ -24,4 +24,9 @@ Custom errors need a type class to be used. So, could do something like this:
 the `instance TypeError` can just be wrapped in an ifdef to make it only be
 used by the new ghc.)
 
+> The new type-errors library builds a lot of stuff on top of this.
+> Its ability to detect "stuckness" seems like it may be able to catch
+> the very long type errors that we sometimes see when using propellor, and
+> whittle them down to a more useful error. --[[Joey]]
+
 [[!tag user/joey]]

response
diff --git a/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_1_9feaf88f735f6571835502cc9e15524b._comment b/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_1_9feaf88f735f6571835502cc9e15524b._comment
new file mode 100644
index 00000000..a7173577
--- /dev/null
+++ b/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_1_9feaf88f735f6571835502cc9e15524b._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-06-15T16:35:46Z"
+ content="""
+The former seems easier than parsing the XML.
+
+I mean, aeson is quite good and easy to parse XML with,
+but I prefer to keep propellor's haskell dependencies minimal
+and so if you used aeson there would be a big question about merging the
+result into propellor core.
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_9_49c03760f833632a50b88be792395a5f._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_9_49c03760f833632a50b88be792395a5f._comment
new file mode 100644
index 00000000..94d697fd
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_9_49c03760f833632a50b88be792395a5f._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="s@aa9ff9ce06b08acfd2a93ebd342ce6879430fbdd"
+ nickname="s"
+ avatar="http://cdn.libravatar.org/avatar/81bf27f8b35011d1846711fa37a5588f"
+ subject="comment 9"
+ date="2019-06-15T16:04:22Z"
+ content="""
+Thanks again [@spwhitton](https://propellor.branchable.com/user/spwhitton/). I've verified the tag with Joey's GPG keys.
+
+Documenting here:
+
+Get Joey's [GPG keys](https://joeyh.name/contact/)
+
+```
+gpg2 --recv-keys  'E85A 5F63 B31D 24C1 EBF0 D81C C910 D922 2512 E3C7'
+```
+
+Verify the release tag before merging it into your local repo:
+
+```
+cd ~/.propellor
+git verify-tag X.Y.Z
+```
+
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_8_ba9fabe0096cd8808c4a50ea3ebe543c._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_8_ba9fabe0096cd8808c4a50ea3ebe543c._comment
new file mode 100644
index 00000000..b1344a10
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_8_ba9fabe0096cd8808c4a50ea3ebe543c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 8"
+ date="2019-06-08T20:21:57Z"
+ content="""
+The `git://` protocol is unencrypted and unauthenticated and you're not verifying Joey's PGP signature on the tag that you merge, so this approach is dangerous.
+
+I would insert a `git verify-tag` step in there.  You'd want to make a record of (and perhaps locally sign) Joey's PGP key.
+"""]]

diff --git a/doc/forum/WIP_adding_dhcp_records_to_libvirt.mdwn b/doc/forum/WIP_adding_dhcp_records_to_libvirt.mdwn
new file mode 100644
index 00000000..118f01ab
--- /dev/null
+++ b/doc/forum/WIP_adding_dhcp_records_to_libvirt.mdwn
@@ -0,0 +1,31 @@
+I'm working on adding static (predictable) dhcp records to libvirt guests (code at the end). It seems like I might need to either do the equivalent of
+[[!format bash """
+virsh net-update default delete ip-dhcp-host "<host mac='52:54:00:f0:62:01'/>"  --config --live || /bin/true
+virsh net-update default add ip-dhcp-host "<host mac='52:54:00:f0:62:01' ip='192.168.122.32'/>" --config --live
+"""]]
+or parse the xml output of "virsh net-dumpxml". Is there some simple lightweight xml parsing option? Last time I tried something like this was a decade ago using HXT.Arrow, which didn't really end well.
+
+[[!format haskell """
+staticDHCP :: Host -> IPAddr -> Maybe Network.Gateway -> Property UnixLike
+staticDHCP h ip gw = property "assign ip to host via dhcp" $ do
+                mac <- liftIO $ macAddress
+                case mac of
+                  Nothing -> errorMessage "no interface"
+                  Just addr -> makeChange $ unlessM (updateIt addr) $
+                                errorMessage "failed to update network"
+  where
+    updateIt mac = boolSystem "virsh" [ Param "net-update"
+                                  , Param "default"
+                                  , Param "add-last"
+                                  , Param "ip-dhcp-host"
+                                  , Param $ "<host mac=\""++mac++"\" ip=\""++(ifaceToString ip)++"\"/>"
+                                  , Param "--config"
+                                  , Param "--live"]
+    ifaceToString (IPv6 ipstr) = ipstr
+    ifaceToString (IPv4 ipstr) = ipstr
+    macAddress = do
+      ifaces <- virshGetColumns ["domiflist", hostName h]
+      case ifaces of
+        [] -> return Nothing
+        (i:_) -> return $ Just $ Propellor.Base.last i
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_7_de411d55ffbd72c5a4182168dead6b29._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_7_de411d55ffbd72c5a4182168dead6b29._comment
new file mode 100644
index 00000000..9f6afc6b
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_7_de411d55ffbd72c5a4182168dead6b29._comment
@@ -0,0 +1,46 @@
+[[!comment format=mdwn
+ username="s@aa9ff9ce06b08acfd2a93ebd342ce6879430fbdd"
+ nickname="s"
+ avatar="http://cdn.libravatar.org/avatar/81bf27f8b35011d1846711fa37a5588f"
+ subject="comment 7"
+ date="2019-06-06T03:13:02Z"
+ content="""
+Documenting it (in case there is another user who wishes to do the same):
+
+Add upstream repo and fetch tags:
+
+```
+$ cd ~/.propellor
+
+$ git remote add u git://propellor.branchable.com/propellor
+$ git fetch u --tags
+```
+
+Look for the list releases:
+
+```
+$ git tag -l
+0.1
+0.1.1
+0.1.2
+0.2.0
+0.2.1
+...
+...
+...
+X.Y.Z
+```
+
+To merge release `X.Y.Z` into your master branch, do:
+
+```
+$ git merge -X theirs --allow-unrelated-histories X.Y.Z
+```
+
+Fix any conflicts and:
+
+```
+$ git commit
+```
+
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_6_c7f1e82b71c3317a25230e076eb0a330._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_6_c7f1e82b71c3317a25230e076eb0a330._comment
new file mode 100644
index 00000000..eadab877
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_6_c7f1e82b71c3317a25230e076eb0a330._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="s@aa9ff9ce06b08acfd2a93ebd342ce6879430fbdd"
+ nickname="s"
+ avatar="http://cdn.libravatar.org/avatar/81bf27f8b35011d1846711fa37a5588f"
+ subject="comment 6"
+ date="2019-06-06T03:00:43Z"
+ content="""
+[@spwhitton](https://propellor.branchable.com/user/spwhitton/), Thank you very much. That worked!
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_5_05439bebb8c0dee0850fb2ffe3e117c3._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_5_05439bebb8c0dee0850fb2ffe3e117c3._comment
new file mode 100644
index 00000000..2b169a57
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_5_05439bebb8c0dee0850fb2ffe3e117c3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 5"
+ date="2019-06-05T15:08:02Z"
+ content="""
+You can pass `-X theirs --allow-unrelated-histories` or similar.
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_4_26738f91fe511b49552a68e70f201059._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_4_26738f91fe511b49552a68e70f201059._comment
new file mode 100644
index 00000000..ca112817
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_4_26738f91fe511b49552a68e70f201059._comment
@@ -0,0 +1,49 @@
+[[!comment format=mdwn
+ username="s@aa9ff9ce06b08acfd2a93ebd342ce6879430fbdd"
+ nickname="s"
+ avatar="http://cdn.libravatar.org/avatar/81bf27f8b35011d1846711fa37a5588f"
+ subject="comment 4"
+ date="2019-06-04T00:38:58Z"
+ content="""
+[@spwhitton](spwhittonhttps://propellor.branchable.com/user/spwhitton/), Sorry I should've mentioned it before. I've already tried merging upstream changes using `git merge`, I'm unable to merge it due to different commit histories:
+
+```
+cygnus$ git remote -v           
+s       g@git.rs:~/c/propellor.git (fetch)
+s       g@git.rs:~/c/propellor.git (push)
+u       git://propellor.branchable.com/propellor (fetch)
+u       git://propellor.branchable.com/propellor (push)
+
+
+cygnus$ git tag -l | grep 5.8.0
+5.8.0
+
+cygnus$ git merge 5.8.0
+fatal: refusing to merge unrelated histories
+cygnus$ git merge u/master
+fatal: refusing to merge unrelated histories
+```
+
+First commit in upstream repo:
+
+```
+cygnus$ git log --reverse u/master | head -n 5
+commit d9af8bac5eb7836a3c90e37e870fd73d30b841fd
+Author: Joey Hess <joey@kitenet.net>
+Date:   Sat Mar 29 23:10:52 2014 -0400
+
+    initial check-in
+```
+
+First commit in my repo:
+
+```
+cygnus$ git log --reverse s/master | head -n 5 
+commit ff6173d6cd45e383da0f315bc80b52d486306cbc
+Author: build <build@buildhost>
+Date:   Tue Nov 22 14:16:29 2016 -0700
+
+    distributed version of propellor
+
+```
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_3_a273b2f5a904e7b16576a750538296dc._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_3_a273b2f5a904e7b16576a750538296dc._comment
new file mode 100644
index 00000000..b2043e80
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_3_a273b2f5a904e7b16576a750538296dc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 3"
+ date="2019-06-03T03:43:33Z"
+ content="""
+You can always just fetch and merge upstream's release tags.
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_2_3dcd6f95340abed0accfecda716fd1f6._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_2_3dcd6f95340abed0accfecda716fd1f6._comment
new file mode 100644
index 00000000..d59d2ca9
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_2_3dcd6f95340abed0accfecda716fd1f6._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="s@aa9ff9ce06b08acfd2a93ebd342ce6879430fbdd"
+ nickname="s"
+ avatar="http://cdn.libravatar.org/avatar/81bf27f8b35011d1846711fa37a5588f"
+ subject="comment 2"
+ date="2019-06-02T01:10:43Z"
+ content="""
+[@spwhitton](https://propellor.branchable.com/user/spwhitton/), My current host machine is OpenBSD. So, I get propellor from `cabal`.
+
+Currently I've propellor 5.8.0 installed from cabal.
+
+My local propellor repo is itself is stuck at 5.3.5 (<https://git.ricketyspace.net/propellor/files.html>).
+
+I wanted to know if there was a way to manually merge upstream changes into my local propellor repo?
+
+"""]]

Added a comment
diff --git a/doc/forum/commands_that_need_files/comment_1_4ffacadef38a131fa7e22204f9c4f882._comment b/doc/forum/commands_that_need_files/comment_1_4ffacadef38a131fa7e22204f9c4f882._comment
new file mode 100644
index 00000000..c16fc161
--- /dev/null
+++ b/doc/forum/commands_that_need_files/comment_1_4ffacadef38a131fa7e22204f9c4f882._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 1"
+ date="2019-06-02T00:35:19Z"
+ content="""
+I would use (2).  Look for the string `withTmpFile` in Libvirt.hs to see how it's done.
+"""]]

Added a comment
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_1_e522e00ee4d4b072d80faef748450a52._comment b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_1_e522e00ee4d4b072d80faef748450a52._comment
new file mode 100644
index 00000000..3c3623de
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo/comment_1_e522e00ee4d4b072d80faef748450a52._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 1"
+ date="2019-06-02T00:34:48Z"
+ content="""
+The `upstream/master` thing is probably propellor's code looking in `/usr/src/propellor` for a new upstream version.
+
+Do you perhaps no longer have the Debian package of propellor installed?
+"""]]

diff --git a/doc/forum/commands_that_need_files.mdwn b/doc/forum/commands_that_need_files.mdwn
new file mode 100644
index 00000000..e4adf063
--- /dev/null
+++ b/doc/forum/commands_that_need_files.mdwn
@@ -0,0 +1,9 @@
+I want to run "virsh update-device guest-name snippet.xml", for the moment from Cmd.cmdProperty. snippet.xml should contain the actual configuration information.  I'm wondering what the best approach is.
+
+1. create a persistent copy of this file using File.hasContent or similar
+2. generate a temporary file when running the property.
+3. Use a file from the propellor repo
+
+(1) is slightly gross because the persistent copy is used only when running propellor.
+(2) I don't really know how to do in propellor; I guess it has to do with monads.
+(3) I don't know if this will work or is frowned upon for some reason.

diff --git a/doc/todo/dhcp_support_for_Propellor.Property.Libvirt.mdwn b/doc/todo/dhcp_support_for_Propellor.Property.Libvirt.mdwn
new file mode 100644
index 00000000..dd1a80d9
--- /dev/null
+++ b/doc/todo/dhcp_support_for_Propellor.Property.Libvirt.mdwn
@@ -0,0 +1,14 @@
+I'd like a convenient way to add dhcp info for libvirt guests (to libvirt's internal dhcp server).
+
+I'm thinking something along the lines of
+
+          Libvirt.dhcp  "default" (MAC "52:54:00:00:00:01") (IPv4 "192.168.122.31")
+
+where I guess the MAC (or a better name?) has to be defined. "default" is the libvirt network name.
+That property (and the undo) would translate into some call to "virsh net-update".
+
+This presumably needs a way to assign a matching MAC to the guest. We could maybe provide a convenience API that did both to avoid mismatches.
+
+I don't so far see a nice way to update the mac address on the guest. There is a --network mac=  for virt-install, so maybe an optional parameter for defined? I guess it needs to be different function, called by defined to avoid breaking API?
+
+

New post about merging upstream changes.
diff --git a/doc/forum/merging_upstream_changes_into_my_local_propellor_repo.mdwn b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo.mdwn
new file mode 100644
index 00000000..50578473
--- /dev/null
+++ b/doc/forum/merging_upstream_changes_into_my_local_propellor_repo.mdwn
@@ -0,0 +1,21 @@
+When there were upstream changes available, propellor used to prompt me to
+merge upstream changes into my local propellor repo with:
+
+    git merge upstream/master
+
+Of late, propellor has not been prompting me to merge upstream changes and
+my local propellor repo is stuck at ~version 5.3.5
+
+Is there is (another manual) way to merge upstream changes into my local propellor
+repo?
+
+My propellor repo is at
+
+    git clone git://git.ricketyspace.net/propellor.git
+
+Note that I've have some minor updates under the `src/` directory. [Some][0] [of][1] [them][2] were
+merged into upstream.
+
+[0]: https://propellor.branchable.com/forum/DNS_-_Support_for_Multiline_TXT_records/
+[1]: https://propellor.branchable.com/forum/Make_clean_fails_in_openbsd/
+[2]: https://propellor.branchable.com/forum/__96__Propellor.Bootstrap.cabalBuild__96___fails_in_openbsd/

post TODO
diff --git a/doc/todo/virtio-fs_image_type_for_Propellor.Property.Libvirt.mdwn b/doc/todo/virtio-fs_image_type_for_Propellor.Property.Libvirt.mdwn
new file mode 100644
index 00000000..841a2c9f
--- /dev/null
+++ b/doc/todo/virtio-fs_image_type_for_Propellor.Property.Libvirt.mdwn
@@ -0,0 +1,3 @@
+Seems that [the new virtio-fs](https://lwn.net/Articles/788333/) can be used for [the root filesystem of a libvirt VM](https://virtio-fs.gitlab.io/howto-boot.html).  That would allow propellor to keep updating the filesystem as it would just be a chroot on the KVM host, rather than an opaque image file.
+
+--spwhitton

add news item for propellor 5.8.0
diff --git a/doc/news/version_5.4.1.mdwn b/doc/news/version_5.4.1.mdwn
deleted file mode 100644
index ebb0e261..00000000
--- a/doc/news/version_5.4.1.mdwn
+++ /dev/null
@@ -1,14 +0,0 @@
-propellor 5.4.1 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Modernized and simplified the MetaTypes implementation now that
-     compatability with ghc 7 is no longer needed.
-   * Use git verify-commit to verify gpg signatures, rather than the old
-     method of parsing git log output. Needs git 2.0.
-   * Added ConfFile.containsShellSetting, ConfFile.lacksShellSetting,
-     and EtcDefault.set properties. Thanks, Sean Whitton
-   * Dns: Support TXT values longer than bind's maximum string length
-     of 255 bytes. Thanks, rsiddharth.
-   * Docker and HostingProvider.CloudAtCost modules are not being
-     maintained, so marked them as such.
-     Seeking a maintainer for the Docker module; I anticipate
-     removing the CloudAtCost module in the next API bump."""]]
\ No newline at end of file
diff --git a/doc/news/version_5.8.0.mdwn b/doc/news/version_5.8.0.mdwn
new file mode 100644
index 00000000..a00c611a
--- /dev/null
+++ b/doc/news/version_5.8.0.mdwn
@@ -0,0 +1,18 @@
+propellor 5.8.0 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * 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.
+   * 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.
+   * Fix Git.pulled always reporting a change.
+     Thanks, Sean Whitton"""]]
\ No newline at end of file

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.
+"""]]