Recent changes to this wiki:

diff --git a/doc/forum/CUPS_configuration.mdwn b/doc/forum/CUPS_configuration.mdwn
index 335caedc..48e2ff4f 100644
--- a/doc/forum/CUPS_configuration.mdwn
+++ b/doc/forum/CUPS_configuration.mdwn
@@ -1 +1,3 @@
 Any ideas for good ways to manage CUPS config?  /etc/cups/printers.conf starts with `# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING`. I can do the obvious stop / replace / restart, but am curious if anyone has any success stories or pitfalls to relate.
+
+A very quick search suggests using "lpadmin" is the approved way of updating CUPS config. So I guess I can run some Cmd.cmpProperty calls

diff --git a/doc/forum/CUPS_configuration.mdwn b/doc/forum/CUPS_configuration.mdwn
new file mode 100644
index 00000000..335caedc
--- /dev/null
+++ b/doc/forum/CUPS_configuration.mdwn
@@ -0,0 +1 @@
+Any ideas for good ways to manage CUPS config?  /etc/cups/printers.conf starts with `# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING`. I can do the obvious stop / replace / restart, but am curious if anyone has any success stories or pitfalls to relate.

Added a comment: first attempt
diff --git a/doc/todo/Support_for_mirroring_bare_git_repos/comment_1_f8d0ade5f31f85c1db50b3ec6a9a3818._comment b/doc/todo/Support_for_mirroring_bare_git_repos/comment_1_f8d0ade5f31f85c1db50b3ec6a9a3818._comment
new file mode 100644
index 00000000..fb6ff177
--- /dev/null
+++ b/doc/todo/Support_for_mirroring_bare_git_repos/comment_1_f8d0ade5f31f85c1db50b3ec6a9a3818._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="first attempt"
+ date="2020-05-16T23:44:41Z"
+ content="""
+This isn't very general, but it seems to work
+
+[[!format haskell \"\"\"
+bareMirror :: String -> String -> Property  DebianLike
+bareMirror dir url = propertyList (\"bare mirror of \" ++ url ++ \" in \" ++ dir ) $ props
+  & Git.installed
+  & Git.bareRepo dir (User \"root\") Git.SharedAll
+  & Git.repoConfigured dir (\"remote.origin.url\", url)
+  & Git.repoConfigured dir (\"remote.origin.mirror\", \"true\")
+  & Git.repoConfigured dir (\"remote.origin.fetch\", \"+refs/*:refs/*\")
+  & Cmd.cmdProperty \"git\" [\"-C\", dir, \"fetch\", \"origin\" ] `changesFileContent` (dir </> \"HEAD\")
+\"\"\"]]
+"""]]

diff --git a/doc/todo/Support_for_mirroring_bare_git_repos.mdwn b/doc/todo/Support_for_mirroring_bare_git_repos.mdwn
new file mode 100644
index 00000000..3c5da097
--- /dev/null
+++ b/doc/todo/Support_for_mirroring_bare_git_repos.mdwn
@@ -0,0 +1,2 @@
+Since "git pull" has the potential to fail because of merge problems (this is not theoretical, it happened to me today), I'd prefer to just fetch into a bare repo.
+I don't know the best way to go about this. Maybe a "Git.fetched" function that does not assume a non-bare repo (as Git.cloned currently does). 

add news item for propellor 5.10.2
diff --git a/doc/news/version_5.10.2.mdwn b/doc/news/version_5.10.2.mdwn
new file mode 100644
index 00000000..264b7f60
--- /dev/null
+++ b/doc/news/version_5.10.2.mdwn
@@ -0,0 +1,10 @@
+propellor 5.10.2 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Fix build with ghc 8.6.3.
+     Thanks, Robin Munn
+   * Bootstrap: Fix typo in Arch Linux dependencies.
+     Thanks, Robin Munn
+   * Bootstrap: Add haskell-type-errors package on Arch Linux.
+     Thanks, Robin Munn
+   * Apt.buildDepIn: Run build-dep command in a temporary directory,
+     since it may sometimes not clean up all the files it creates."""]]
\ No newline at end of file
diff --git a/doc/news/version_5.7.0.mdwn b/doc/news/version_5.7.0.mdwn
deleted file mode 100644
index 194a2a6f..00000000
--- a/doc/news/version_5.7.0.mdwn
+++ /dev/null
@@ -1,20 +0,0 @@
-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

Fix typo in man page
diff --git a/doc/usage.mdwn b/doc/usage.mdwn
index fb19250e..569637ee 100644
--- a/doc/usage.mdwn
+++ b/doc/usage.mdwn
@@ -141,7 +141,7 @@ and configured in haskell.
 
   If propellor is run in a directory containing a config.hs, it
   assumes that the current directory is a propellor repository, and 
-  uses the configuration from the current directory, rather tnan
+  uses the configuration from the current directory, rather than
   ~/.propellor/ 
 
 # ENVIRONMENT

diff --git a/doc/forum/Branch_not_signed_with_trusted_gpg_key_warning.mdwn b/doc/forum/Branch_not_signed_with_trusted_gpg_key_warning.mdwn
new file mode 100644
index 00000000..48c84b3a
--- /dev/null
+++ b/doc/forum/Branch_not_signed_with_trusted_gpg_key_warning.mdwn
@@ -0,0 +1,79 @@
+When I `propellor --spin HOST`, I started to get this warning:
+
+```
+** warning: git branch origin/master is not signed with a trusted gpg key; refusing to deploy it! (Running with previous configuration instead.)
+```
+
+Here's the relevant output from propellor:
+
+```
+Preprocessing library for propellor-5.9.1..                                                                                                                               
+Building library for propellor-5.9.1..                                                                                                                                    
+Preprocessing executable 'propellor-config' for propellor-5.9.1..                                                                                                         
+Building executable 'propellor-config' for propellor-5.9.1..                                                                                                              
+Propellor build ... done                                                                                                                                                  
+[master ee86ede9] propellor spin                                                                                                                                          
+Git commit ... done                                                                                                                                                       
+Enumerating objects: 1, done.                                                                                                                                             
+Counting objects: 100% (1/1), done.                                                                                                                                       
+Writing objects: 100% (1/1), 869 bytes | 869.00 KiB/s, done.                                                                                                              
+Total 1 (delta 0), reused 0 (delta 0)                                                                                                                                    
+To [redacted].com:sr/propellor.git                                                                                                                      
+   ed5038fa..ee86ede9  master -> master                                                                                                                                  
+Push to central git repository ... done                                                                                                                                  
+gpg: encrypted with 4096-bit RSA key, ID 0x[redacted]0F5, created 2016-09-06                                                                                          
+      "Siddharth Ravikumar <[redacted]@[redacted].com>"                                                                                                                      
+From [redacted].com:sr/propellor                                                                                                                        
+   ed5038fa..ee86ede9  master     -> origin/master                                                                                                                       
+Pull from central git repository ... done                                                                                                                                
+gpg: Signature made Thu Apr  9 09:09:25 2020 EDT                                                                                                                         
+gpg:                using RSA key [redacted]                                                                                               
+gpg: /usr/local/propellor/privdata/trustdb.gpg: trustdb created                                                                                                          
+gpg: Good signature from "Siddharth Ravikumar <[redacted]@[redacted].com>" [expired]                                                                              
+gpg: Note: This key has expired!                                                                                                                                         
+Primary key fingerprint: [redacted]                                                                                              
+gpg: Signature expires Fri Apr  9 09:09:25 2021 EDT                                                                                                                      
+** warning: git branch origin/master is not signed with a trusted gpg key; refusing to deploy it! (Running with previous configuration instead.)                         
+Sending privdata (5352 bytes) to cygnus.[redacted].net ... done                                                                                                        
+From .                                                                                                                                                                   
+ * branch              HEAD       -> FETCH_HEAD                                                                                                                          
+Sending git update to cygnus.[redacted].net ... done                                                                                                                   
+Pull from central git repository ... done                                                                                                                                
+gpg: Signature made Thu Apr  9 09:09:25 2020 EDT                                                                                                                         
+gpg:                using RSA key [redacted]                                                                                               
+gpg: /usr/local/propellor/privdata/trustdb.gpg: trustdb created                                                                                                          
+gpg: Good signature from "Siddharth Ravikumar <[redacted]@[redacted].com>" [expired]                                                                              
+gpg: Note: This key has expired!
+Primary key fingerprint: [redacted]
+gpg: Signature expires Fri Apr  9 09:09:25 2021 EDT
+** warning: git branch origin/master is not signed with a trusted gpg key; refusing to deploy it! (Running with previous configuration instead.)
+Preprocessing library for propellor-5.9.1..
+Building library for propellor-5.9.1..
+Preprocessing executable 'propellor-config' for propellor-5.9.1..
+Building executable 'propellor-config' for propellor-5.9.1..
+Propellor build ... done
+cygnus.[redacted].net has Operating System (Debian Linux (Stable "buster")) X86_64 ... ok
+cygnus.[redacted].net standard sources.list ... ok
+
+```
+
+
+The gpg key in question is not expired and the secret key for it is available on the machine from where I'm doing `propellor --spin`:
+
+
+```
+ gpg --edit-key '[fpr redacted]'
+Secret key is available.
+
+sec  rsa4096/0x[redacted]
+     created: 2016-09-06  expires: 2020-09-02  usage: SC
+     trust: ultimate      validity: ultimate
+ssb  rsa4096/0x[redacted]
+     created: 2016-09-06  expires: 2020-09-02  usage: E
+[ultimate] (1). Siddharth Ravikumar <[redacted]@[redacted].com>
+[ultimate] (2)  Siddharth Ravikumar <[redacted]@[redacted].com>
+
+```
+
+Any idea why I'm getting the warning about the branch not signed with a trusted a gpg key. How should I resolve this issue?
+

diff --git a/doc/forum/DNS_for_LAN.mdwn b/doc/forum/DNS_for_LAN.mdwn
new file mode 100644
index 00000000..da899e9e
--- /dev/null
+++ b/doc/forum/DNS_for_LAN.mdwn
@@ -0,0 +1 @@
+I'd like to setup DNS for hosts on my LAN (mainly for running propellor). I already have dnsmasq installed to support libvirt. Should I just use dnsmasq, or is there some other thing nicely integrated with propellor?

comment
diff --git a/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_3_41d73c97ed105aad773027d64e66cc38._comment b/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_3_41d73c97ed105aad773027d64e66cc38._comment
new file mode 100644
index 00000000..f742280f
--- /dev/null
+++ b/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_3_41d73c97ed105aad773027d64e66cc38._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2020-02-25T21:22:22Z"
+ content="""
+Ghc 8.8 is fixed thanks to your patch.
+
+I was curious how cabal build failed w/o -dynamic, and found
+this <https://bugs.archlinux.org/task/54563#comment158808>
+which includes a simple change that the archlinux maintainers
+could make if they didh't want this to be a self-inflicted wound
+on their users.
+"""]]

comment
diff --git a/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_2_ee81823a34396b98cda15282019dcafc._comment b/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_2_ee81823a34396b98cda15282019dcafc._comment
new file mode 100644
index 00000000..c5b85e05
--- /dev/null
+++ b/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_2_ee81823a34396b98cda15282019dcafc._comment
@@ -0,0 +1,30 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2020-02-20T17:47:46Z"
+ content="""
+Seems odd that the way Arch has installed ghc would
+make `cabal install` fail without additional options being added very time.
+That does not strike me as a good decision if it's the case. I guess that
+the -dynamic should only be set on Arch, since only it has inflicted this
+problem on itself.
+
+Would appreciate a patch with the ghc 8.8 fixes.
+
+I would not be surprised if cabal new-build does not provide any good way
+to find out where the executable was put, because after all cabal build
+doesn't either (just it's easier to guess there). Cabal expects a workflow
+where that's followed by cabal install, or cabal run.
+
+This might be one way: `cabal new-install --symlink-bindir=.`  
+But with my older version of cabal, that seems to not actually work,
+indeed I can't get it to install the binaries anywhere. Maybe it does
+work with the newer cabal where new-install is the default.
+
+Needing to detect whether new-build was used or not is an added
+complication.
+
+Best way I've found:
+
+	find dist-newstyle/ -executable -type f |grep 'propellor$'
+"""]]

Added a comment: One more thing
diff --git a/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_1_80326b7fe6ea0f301872a02bb2462a5d._comment b/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_1_80326b7fe6ea0f301872a02bb2462a5d._comment
new file mode 100644
index 00000000..5d1fab2d
--- /dev/null
+++ b/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails/comment_1_80326b7fe6ea0f301872a02bb2462a5d._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="rmunn@24f62461074e9165181dd6ec6ac66473353a24e9"
+ nickname="rmunn"
+ avatar="http://cdn.libravatar.org/avatar/5fb7a86e278e5b3b427f3b9a3cda71e1"
+ subject="One more thing"
+ date="2020-02-18T04:50:58Z"
+ content="""
+I haven't yet prepared a patch for this, but in src/Propellor/Bootstrap.hs, the `archlinuxdeps Cabal` list of should have `\"haskell-type-errors\"` added to it. That's the name of the Archlinux package for [https://hackage.haskell.org/package/type-errors](https://hackage.haskell.org/package/type-errors). Without that package, Cabal has to download type-errors and its dependencies before building Propellor, but with that package added, Archlinux's package manager can manage that package (and keep it up-to-date) instead.
+
+With that one change, the `archlinuxdeps Cabal` list is complete (at least as of yesterday when I tested it).
+
+I'll prepare a patch for this and submit it to propellor@joeyh.name soon.
+"""]]

Describe three different Haskell issues with bootstrapping on Archlinux
diff --git a/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails.mdwn b/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails.mdwn
new file mode 100644
index 00000000..0ff23880
--- /dev/null
+++ b/doc/forum/Bootstrapping_with_Cabal_on_Archlinux_fails.mdwn
@@ -0,0 +1,46 @@
+Bootstrapping Propellor with Cabal is currently failing for me on Archlinux, for several reasons.
+
+## Dynamic linking
+
+The `ghc` package in Archlinux [uses dynamic linking](https://wiki.archlinux.org/index.php/Haskell#Problems_with_linking) for the GHC boot libraries. This means that the `cabal install` and `cabal build` steps in src/Propellor/Bootstrap.hs need the `--ghc-options=-dynamic` option added. I don't know if it's safe to do that for all OSes, or if this is something that Bootstrap.hs will need to do only on Arch.
+
+## GHC 8.8
+
+Archlinux, being a rolling-release distro, has version 8.8.1 of GHC available. This means that once I add the `--ghc-options=-dynamic` option to the `cabal install` and `cabal build` steps, Propellor now fails to build on my Archlinux system with the GHC compiler complaining about src/Propellor/Property/Installer/Target.hs. Specifically, the `UserInput i` line in the definition of `targetInstalled` produces an "Illegal polymorphic type" error:
+
+```
+src/Propellor/Property/Installer/Target.hs:137:12: error:
+    • Illegal polymorphic type:
+        forall metatypes.
+        (Combines
+           (RevertableProperty metatypes metatypes)
+           (RevertableProperty metatypes metatypes),
+         CombinedType
+           (RevertableProperty metatypes metatypes)
+           (RevertableProperty metatypes metatypes)
+         ~ RevertableProperty metatypes metatypes) =>
+        Propellor.Property.Versioned.VerSpec v metatypes
+        -> RevertableProperty metatypes metatypes
+      Perhaps you intended to use RankNTypes
+    • In the expansion of type synonym ‘Propellor.Property.Versioned.VersionedBy’
+      In the expansion of type synonym ‘Versioned’
+      In the type signature:
+        targetInstalled :: UserInput i =>
+                           Versioned v Host
+                           -> v
+                              -> i
+                                 -> TargetPartTable
+                                    -> RevertableProperty (HasInfo + DebianLike) (HasInfo
+                                                                                  + DebianLike)
+    |
+137 |         :: UserInput i 
+    |            ^^^^^^^^^^^^...
+```
+
+This appears to be  due to [stricter type synonym validity-checking in GHC 8.8](https://gitlab.haskell.org/ghc/ghc/wikis/migration/8.8#stricter-type-synonym-validity-checking). I had to add the `RankNTypes`, `TypeFamilies`, and `FlexibleContexts` extensions to Target.hs in order to make GHC 8.8 happy. (That's a minimal set: removing any one of those three produced one of three different compiler errors, which I won't reproduce here for brevity's safe). This appears to be safe on all OSes, since Propellor compiled happily on my laptop, which is running a Buntish variant called Linux Mint (where GHC 8.0.2 is what Apt gave me). (Though do note that I only tested that on Arch and Mint, and didn't do any testing on Debian to see whether GHC 7.x or earlier is still happy with those extensions being present in the source file).
+
+## New-style cabal
+
+Once I added the `--ghc-options=-dynamic` option to Cabal, and added those three extensions to the first line of Target.hs, I was then faced with another error: the `ln -sf` step failed because `dist/build/propellor-config/propellor-config` didn't exist. The version of Cabal that comes with Archlinux has apparently switched to [Nix-style local builds](https://cabal.readthedocs.io/en/latest/nix-local-build-overview.html) as the default action when you run `cabal build`, and the `propellor-config` binary ended up in `/usr/local/propellor/dist-newstyle/build/x86_64-linux/ghc-8.8.1/propellor-5.10.1/x/propellor-config/build/propellor-config/propellor-config`.
+
+This is the point where, not being a Haskell programmer myself, my ability to Google the problem was exhausted. I'm sure there's a way to get Cabal to tell you where it will put the files it's about to build (similar to `stack path --dist-dir`), but at this point, I needed to get back to working on other things. So I punted and just added `& bootstrapWith (Robustly Stack)` to the properties of my Archlinux host. :-) Bootstrapping with Stack was successful, BTW.

Added a comment
diff --git a/doc/forum/using_propellor_on_low_RAM_devices__63__/comment_2_b58e57d9edb7c574ff8a72dbcd24d1b7._comment b/doc/forum/using_propellor_on_low_RAM_devices__63__/comment_2_b58e57d9edb7c574ff8a72dbcd24d1b7._comment
new file mode 100644
index 00000000..9356298b
--- /dev/null
+++ b/doc/forum/using_propellor_on_low_RAM_devices__63__/comment_2_b58e57d9edb7c574ff8a72dbcd24d1b7._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://launchpad.net/~barthelemy"
+ nickname="barthelemy"
+ avatar="http://cdn.libravatar.org/avatar/e99cb15f6029de3225721b3ebdd0233905eb69698e9b229a8c4cc510a4135438"
+ subject="comment 2"
+ date="2020-01-07T00:38:09Z"
+ content="""
+Hi Joey,
+
+thank you for the feedback. I'm glad to know it is supposed to work in those cases.
+It seems freedombox uses btrfs and swapfiles do not work on btrfs partitions. I thus tried with zram (apt get install zram-tools, which set up a 256 MiB swap).
+
+I could then run propellor --spin to the server, it passed.
+Then I rm -rf /usr/local/propellor on server and ran propellor --spin again.
+The build passed again (it took ~75 minute and at some point ghc took 570MiB but it succeedded).
+
+I'm back on track, thank you again!
+"""]]

comment
diff --git a/doc/forum/using_propellor_on_low_RAM_devices__63__/comment_1_fc192587233c3cda7d0f78f67311de49._comment b/doc/forum/using_propellor_on_low_RAM_devices__63__/comment_1_fc192587233c3cda7d0f78f67311de49._comment
new file mode 100644
index 00000000..af019cf6
--- /dev/null
+++ b/doc/forum/using_propellor_on_low_RAM_devices__63__/comment_1_fc192587233c3cda7d0f78f67311de49._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2020-01-04T19:02:08Z"
+ content="""
+500 mb seems a bit higher than typical; my own config.hs (500 lines)
+needs 416 mb to build, and the example config.hs included in propellor
+needs 245 mb.
+
+I typically install swapspace on systems with 1 gb or less and it works
+fine. I think the smallest system I've used propellor with was 500 mb.
+"""]]

diff --git a/doc/forum/using_propellor_on_low_RAM_devices__63__.mdwn b/doc/forum/using_propellor_on_low_RAM_devices__63__.mdwn
new file mode 100644
index 00000000..7bcbd0cc
--- /dev/null
+++ b/doc/forum/using_propellor_on_low_RAM_devices__63__.mdwn
@@ -0,0 +1,18 @@
+I'm trying to use propellor (and to learn haskell!) to manage my laptop and a small server, both running debian stable. 
+
+The server is a lime2 soc [1], with only 1GiB of RAM, and no swap (I think this is the default setup from the freedombox image).
+
+propellor --spin failed when targeting the server: on the server, ghc got killed by the OOM killer.
+
+I then simplified my config.hs and successfully ran "cabal build -j1" from the server.
+At some point during the successful build, ghc was using 400MiB of memory.
+This is 40% of the whole memory, I fear the OOM killer will strike again if I don't change something.
+I'll probably try to enable swap.
+
+Propellor seems designed with embedded devices in mind (eg. with the image builder), I'm surprised it demands that much RAM.
+Am I missing something?
+Do people cross-compile propellor to avoid the issue?
+
+Cheers!
+
+[1] https://www.olimex.com/Products/OLinuXino/A20/A20-OLinuXino-LIME2

Added a comment
diff --git a/doc/todo/spin_without_remote_compilation/comment_8_6a7a6a3acce0b0865e2a389e60c46179._comment b/doc/todo/spin_without_remote_compilation/comment_8_6a7a6a3acce0b0865e2a389e60c46179._comment
new file mode 100644
index 00000000..1325399d
--- /dev/null
+++ b/doc/todo/spin_without_remote_compilation/comment_8_6a7a6a3acce0b0865e2a389e60c46179._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="balu"
+ avatar="http://cdn.libravatar.org/avatar/2ec9dd5a234ce82f117bd81d1e44f2cb"
+ subject="comment 8"
+ date="2019-11-27T16:28:41Z"
+ content="""
+I am very interested in having this feature in the debian package of propellor and would like to help. What is missing to accomplish that?
+"""]]

Added a comment
diff --git a/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_3_ab42e31ff116bf56dca6cdff9bba2d29._comment b/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_3_ab42e31ff116bf56dca6cdff9bba2d29._comment
new file mode 100644
index 00000000..eb8abfb3
--- /dev/null
+++ b/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_3_ab42e31ff116bf56dca6cdff9bba2d29._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="eugen"
+ avatar="http://cdn.libravatar.org/avatar/7e7e5700d7017735fd00c2dfcd3f91e4"
+ subject="comment 3"
+ date="2019-11-21T20:29:20Z"
+ content="""
+Indeed, I can see how etckeeper provides a very easy way to check exactly what has changed to /etc (also) after a propellor spin. When I'm manually editing an /etc file I know what the changes are, but not so when a tool does it for me. So, it's important to verify, for example, that propellor did indeed what I *thought* I told it to do (not sure if propellor has an option to report the /etc changes it did).
+
+By using both etckeeper and propellor, which one do you consider to have the authoritative status (power?) over /etc? Do you still manually edit /etc files?
+"""]]

comment
diff --git a/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_2_41084ce268e4aa667b1c59f8352aa774._comment b/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_2_41084ce268e4aa667b1c59f8352aa774._comment
new file mode 100644
index 00000000..84c22a04
--- /dev/null
+++ b/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_2_41084ce268e4aa667b1c59f8352aa774._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2019-11-21T15:16:36Z"
+ content="""
+Also, when the propellor configuration is changed, it's very useful to have
+a record of how that change affected the host. While etckeeper's record is
+limited to /etc, that does cover a large percentage of such changes.
+"""]]

comment
diff --git a/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_1_008690e4e3828123a2c47a4b1abc413e._comment b/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_1_008690e4e3828123a2c47a4b1abc413e._comment
new file mode 100644
index 00000000..752bbd01
--- /dev/null
+++ b/doc/forum/etckeeper_made_obsolete_by_propellor__63__/comment_1_008690e4e3828123a2c47a4b1abc413e._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-11-21T14:57:57Z"
+ content="""
+I use both. To be fully described by the propellor configuration, it would
+need to pin the system to a specific version of every package installed on
+it, and that's generally not practical because there are new security
+updates all the time. It's useful to have etckeeper keeping track of
+changes made to configuration during upgrades.
+
+I do find etckeeper generally less useful on those type of systems, but it
+still more than pays for itself.
+"""]]

diff --git a/doc/forum/etckeeper_made_obsolete_by_propellor__63__.mdwn b/doc/forum/etckeeper_made_obsolete_by_propellor__63__.mdwn
index b35d49c9..ea605ef4 100644
--- a/doc/forum/etckeeper_made_obsolete_by_propellor__63__.mdwn
+++ b/doc/forum/etckeeper_made_obsolete_by_propellor__63__.mdwn
@@ -1 +1,2 @@
 I'm still learning about these two programs.  I haven't use them yet, but I will (at least propellor). It seems to me there exists a bit of functionality overlapping between them: propellor's config file might be enough to describe all your changes you want to /etc for a host..? In this case, etckeeper would appear to be useful just as a "change log".. What's your thoughts on this? Do you use both propellor and etckeeper?
+-- eugen

diff --git a/doc/forum/etckeeper_made_obsolete_by_propellor__63__.mdwn b/doc/forum/etckeeper_made_obsolete_by_propellor__63__.mdwn
new file mode 100644
index 00000000..b35d49c9
--- /dev/null
+++ b/doc/forum/etckeeper_made_obsolete_by_propellor__63__.mdwn
@@ -0,0 +1 @@
+I'm still learning about these two programs.  I haven't use them yet, but I will (at least propellor). It seems to me there exists a bit of functionality overlapping between them: propellor's config file might be enough to describe all your changes you want to /etc for a host..? In this case, etckeeper would appear to be useful just as a "change log".. What's your thoughts on this? Do you use both propellor and etckeeper?

add news item for propellor 5.10.1
diff --git a/doc/news/version_5.10.1.mdwn b/doc/news/version_5.10.1.mdwn
new file mode 100644
index 00000000..797664be
--- /dev/null
+++ b/doc/news/version_5.10.1.mdwn
@@ -0,0 +1,15 @@
+propellor 5.10.1 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ Joey Hess ]
+   * Localdir.hasOriginUrl: Depend on Git.installed.
+   * Localdir.hasOriginUrl: Type changed from UnixLike to DebianLike
+     because Git.installed is not implemented for other unixes.
+     (API change)
+   * Changed the ChrootBootstrapper type class's buildchroot method
+     to take a Info parameter, instead of Maybe System.
+     (The System can be extracted from the Info.)
+     (API change)
+ * [ Sean Whitton ]
+   * Chroot.{de,}bootstrapped uses the chroot's configured apt proxy and
+     mirror, if these exist, when debootstrapping the chroot.
+   * Rename Sbuild.useHostProxy -&gt; Chroot.useHostProxy. (API change)"""]]
\ No newline at end of file
diff --git a/doc/news/version_5.6.1.mdwn b/doc/news/version_5.6.1.mdwn
deleted file mode 100644
index 739d49f7..00000000
--- a/doc/news/version_5.6.1.mdwn
+++ /dev/null
@@ -1,4 +0,0 @@
-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

close
diff --git a/doc/todo/Debootstrap_module_should_respect_a_configured_Apt.proxy.mdwn b/doc/todo/Debootstrap_module_should_respect_a_configured_Apt.proxy.mdwn
index 8887f438..fc817415 100644
--- a/doc/todo/Debootstrap_module_should_respect_a_configured_Apt.proxy.mdwn
+++ b/doc/todo/Debootstrap_module_should_respect_a_configured_Apt.proxy.mdwn
@@ -27,3 +27,5 @@ so tried on my own
 to my opinion the schroot config file generated by Sbuild property does something wrong.
 
 Cheers
+
+> [[done]]; I merged patches from spwhitton. --[[Joey]]

comment
diff --git a/doc/forum/Conceptual_:_HostName_vs._Domain/comment_1_6a80853161714e19cdae006ec19097fb._comment b/doc/forum/Conceptual_:_HostName_vs._Domain/comment_1_6a80853161714e19cdae006ec19097fb._comment
new file mode 100644
index 00000000..86c38d79
--- /dev/null
+++ b/doc/forum/Conceptual_:_HostName_vs._Domain/comment_1_6a80853161714e19cdae006ec19097fb._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-11-11T17:26:24Z"
+ content="""
+I think LetsEncrypt's use of Domain is intentional; a certificate is for a
+domain and you can't get one for eg a bare IP address or an unqualified
+hostname.
+
+AFAICS, Domain is a FQDN.
+
+(Propellor.Property.Hostname has to deal with details of /etc/hosts,
+but it does not actually use the Domain type anywhere.)
+
+More generally, it's common for a propellor module to have some
+`type Foo = String` that's only used to make parameters more self-documenting
+and doesn't have any particular meaning beyond whatever string a Property might
+use. One shouldn't worry if two modules have data types that seem to
+overlap in content when that's all they're used for. Of course it's nicer to
+have less stringy data types, via ADTs or smart constructors, when possible.
+"""]]

comment
diff --git a/doc/forum/Setting_altenative___63__/comment_1_cc9f01e46e6cc2940382309cd17b3575._comment b/doc/forum/Setting_altenative___63__/comment_1_cc9f01e46e6cc2940382309cd17b3575._comment
new file mode 100644
index 00000000..741326f6
--- /dev/null
+++ b/doc/forum/Setting_altenative___63__/comment_1_cc9f01e46e6cc2940382309cd17b3575._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-11-11T17:23:24Z"
+ content="""
+There is not. I'd welcome a property submission.
+"""]]

diff --git a/doc/forum/Setting_altenative___63__.mdwn b/doc/forum/Setting_altenative___63__.mdwn
new file mode 100644
index 00000000..b40d1fe0
--- /dev/null
+++ b/doc/forum/Setting_altenative___63__.mdwn
@@ -0,0 +1,7 @@
+Everything is in the title : is there a property to ensure that the 'alternative' is set in a given way ?
+
+I guess the simplest otherwise would be to use a `Cmd` to do it (through usage of `update-alternative`), but I am wondering if there is already a property to do that…
+
+Thanks in advance,
+
+Serge

diff --git a/doc/forum/Conceptual_:_HostName_vs._Domain.mdwn b/doc/forum/Conceptual_:_HostName_vs._Domain.mdwn
new file mode 100644
index 00000000..334c9d82
--- /dev/null
+++ b/doc/forum/Conceptual_:_HostName_vs._Domain.mdwn
@@ -0,0 +1,22 @@
+Hello,
+
+Writing properties, I often hesitate between using types `HostName` or `Domain` for the FQDN of a machine.
+This is not 'very important' since both are "just" `String`, but the type carries semantics and I'd rather keep consistent (helps understanding the code better).
+
+Here are the docs :
+
+http://hackage.haskell.org/package/propellor-5.9.1/docs/Propellor-Types-OS.html#t:HostName
+http://hackage.haskell.org/package/propellor-5.9.1/docs/Propellor-Types-Dns.html#t:Domain
+
+So `HostName` documentation to me looks like really corresponding to a machine's FQDN, but may also be the IP of the machine.
+Conversely `Domain` is not documented (in its module) but it is used in the 'domain part of the FQDN' in some modules; eg. in Propellor/Property/Hostname.hs
+Even clearer is the `Propellor.Property.DNS` module in which I clearly understand the choice of `Domain` vs. `HostName`.
+
+Still it seems to me that sometimes one sees `Domain` where a `HostName` would be expected. One such example is in `LetsEncrypt`
+Maybe I am just to confused by a few places where `Domain` is used while I would (maybe wrongly) expect `HostName` ?
+
+What am I missing ?
+
+Cheers,
+
+Serge.

Added a comment: Using noServices to configure apache before running it...
diff --git a/doc/forum/installing_apt_packages_without_running_new_services/comment_2_b819efe3a4f00f1b9993d5a31e65f2e9._comment b/doc/forum/installing_apt_packages_without_running_new_services/comment_2_b819efe3a4f00f1b9993d5a31e65f2e9._comment
new file mode 100644
index 00000000..467e55cf
--- /dev/null
+++ b/doc/forum/installing_apt_packages_without_running_new_services/comment_2_b819efe3a4f00f1b9993d5a31e65f2e9._comment
@@ -0,0 +1,99 @@
+[[!comment format=mdwn
+ username="serge1cohen"
+ avatar="http://cdn.libravatar.org/avatar/df873622c2eeb5b34222b7af0d47abd0"
+ subject="Using noServices to configure apache before running it..."
+ date="2019-10-31T22:56:56Z"
+ content="""
+Hello there,
+
+I was typically in this situation : starting an apache server on a specific IP (the other IPs of the machine -on port 80- are used by other server processes), in particular to be able to get a certificate from let's encrypt.
+
+When using :
+
+    micro_apache :: Domain -> String -> FilePath -> Property DebianLike
+    micro_apache fqdn ip dr = combineProperties \"Setting a micro apache server running only for interface\" $ props
+    	& Apache.installed
+    	& File.hasContent \"/etc/apache2/ports.conf\" [(\"Listen \" ++ ip ++ \":80\")]
+    	& Apache.siteDisabled \"000-default\"
+    	& Apache.siteEnabled fqdn
+    		[ \"<VirtualHost \" ++ ip ++ \":80>\"
+    		, \"ServerName \" ++ fqdn ++ \":80\"
+    		, \"DocumentRoot \" ++ dr
+    		, \"ErrorLog /var/log/apache2/\" ++ fqdn ++ \"_error.log\"
+    		, \"LogLevel warn\"
+    		, \"CustomLog /var/log/apache2/\" ++ fqdn ++ \"_access.log combined\"
+    		, \"ServerSignature On\"
+    		, \"</VirtualHost>\"
+    		]
+    	& Apache.restarted
+    	& Apache.reloaded
+
+The property is problematic (the initial 'Apache.installed' starts the apache server listening to ALL IPs). 
+But at least at the end it seems that I get a 'running' service :
+
+    root@d4:~# systemctl status apache2.service 
+    ● apache2.service - The Apache HTTP Server
+       Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
+       Active: active (running) since Thu 2019-10-31 16:59:41 CET; 17min ago
+
+
+
+To avoid the transient service wrongly configured (it also messes up with the server serving port 80 on another IP) case I tried :
+
+    micro_apache :: Domain -> String -> FilePath -> Property (HasInfo + DebianLike)
+    micro_apache fqdn ip dr = combineProperties \"Setting a micro apache server running only for interface\" $ props
+      	& ( Apache.installed `requires` Service.noServices ) -- => Needs to change type to Property (HasInfo + DebianLike)
+    	& File.hasContent \"/etc/apache2/ports.conf\" [(\"Listen \" ++ ip ++ \":80\")]
+    	& Apache.siteDisabled \"000-default\"
+    	& Apache.siteEnabled fqdn
+    		[ \"<VirtualHost \" ++ ip ++ \":80>\"
+    		, \"ServerName \" ++ fqdn ++ \":80\"
+    		, \"DocumentRoot \" ++ dr
+    		, \"ErrorLog /var/log/apache2/\" ++ fqdn ++ \"_error.log\"
+    		, \"LogLevel warn\"
+    		, \"CustomLog /var/log/apache2/\" ++ fqdn ++ \"_access.log combined\"
+    		, \"ServerSignature On\"
+    		, \"</VirtualHost>\"
+    		]
+      	& ( revert Service.noServices `before` Apache.restarted ) -- => Needs to change type to Property (HasInfo + DebianLike)
+
+But then the configuration leads to having apache in an \"ghost state\", neither started nor stopped :
+
+    root@d4:~# systemctl status apache2
+    ● apache2.service - The Apache HTTP Server
+       Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
+       Active: inactive (dead)
+         Docs: https://httpd.apache.org/docs/2.4/
+
+Which leads to an unavailable http service, and as a consequence to a failure in ACME / let's encrypt.
+Indeed it seems that the service is started using the 'old' Service system. The nice thing is that this makes it possible to use the 'noServices' property. The problem is that the systemd module is in a state not working anymore with 'Service'.
+
+Finally I had to mix the 'noServices' property with a couple of 'Systemd' properties so that the server is properly restarted once the configuration is correct. This leads to a bit longer property but at least it works :
+
+    micro_apache :: Domain -> String -> FilePath -> Property (HasInfo + DebianLike)
+    micro_apache fqdn ip dr = combineProperties \"Setting a micro apache server running only for interface\" $ props
+      	& ( Apache.installed `requires` Service.noServices ) -- => Needs to change type to Property (HasInfo + DebianLike)
+    	& Systemd.stopped \"apache2\"  -- 'clean' of the systemd module 
+    	& File.hasContent \"/etc/apache2/ports.conf\" [(\"Listen \" ++ ip ++ \":80\")]
+    	& Apache.siteDisabled \"000-default\"
+    	& Apache.siteEnabled fqdn
+    		[ \"<VirtualHost \" ++ ip ++ \":80>\"
+    		, \"ServerName \" ++ fqdn ++ \":80\"
+    		, \"DocumentRoot \" ++ dr
+    		, \"ErrorLog /var/log/apache2/\" ++ fqdn ++ \"_error.log\"
+    		, \"LogLevel warn\"
+    		, \"CustomLog /var/log/apache2/\" ++ fqdn ++ \"_access.log combined\"
+    		, \"ServerSignature On\"
+    		, \"</VirtualHost>\"
+    		]
+      	& ( revert Service.noServices  -- => Needs to change type to Property (HasInfo + DebianLike)
+    		`before` Systemd.running \"apache2\" ) -- restarting through systemd
+
+With this done, it seems to work.
+
+Notice, however, that if apache was completely avoiding the 'old service' system, then we could not even benefit from the 'noService' in the first place. Would there be another solution to reach the same result ?
+
+Hope this might help
+
+Serge.
+"""]]

comment
diff --git a/doc/forum/isCopyOf_does_not_work_on_nfs_filesystem/comment_1_b1ffea063d9928889df17d9a8f3e8a5d._comment b/doc/forum/isCopyOf_does_not_work_on_nfs_filesystem/comment_1_b1ffea063d9928889df17d9a8f3e8a5d._comment
new file mode 100644
index 00000000..935b23b9
--- /dev/null
+++ b/doc/forum/isCopyOf_does_not_work_on_nfs_filesystem/comment_1_b1ffea063d9928889df17d9a8f3e8a5d._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-10-01T14:06:35Z"
+ content="""
+Your NFS server must have root squash enabled then. So any propellor
+properties that try to set the owner will fail (File.ownerGroup).
+
+It's entirely reasonable for properties to need to set the owner of a file.
+Many properties make files owned by a specific user and having them
+squashed to "nobody" would break their purpose.
+
+There's only one property in propellor that currently uses File.isCopyOf,
+and that property is in fact installing a user's configuration file, which
+needs to be owned by that user. So changing that property's behavior is
+out.
+
+So your options are, disable the NFS root squash, or avoid using propellor
+properties that set file ownership. If you wanted to make a variant of
+isCopyOf that didn't preserve permissions, we could perhaps look at adding
+that to propellor.
+"""]]

diff --git a/doc/forum/isCopyOf_does_not_work_on_nfs_filesystem.mdwn b/doc/forum/isCopyOf_does_not_work_on_nfs_filesystem.mdwn
new file mode 100644
index 00000000..dff1fdc4
--- /dev/null
+++ b/doc/forum/isCopyOf_does_not_work_on_nfs_filesystem.mdwn
@@ -0,0 +1,25 @@
+Hello, I try to copy a vm image to a directory like this
+
+    & "/nfs/share-temp/panbox-rel.img" `File.isCopyOf` panboxName
+
+
+but when I run this, I get this error message
+
+    sixs3.exp.synchrotron-soleil.fr /root/vm/panbox-rel.img owner picca:grp-instrumentation ... done
+    cp: failed to preserve ownership for '/nfs/share-temp/panbox-rel.img.propellor-new~': Operation not permitted
+    ** error: cp failed
+    ** warning: Cannot continue!
+    CallStack (from HasCallStack):
+      error, called at src/Propellor/Message.hs:143:9 in propellor-5.6.0-GGUJL7KihFnDmzjFSP3dov:Propellor.Message
+    sixs3.exp.synchrotron-soleil.fr /nfs/share-temp/panbox-rel.img is copy of /root/vm/panbox-rel.img ... failed
+
+I understand thaht it is not possible to use cp --preserve... on the nfs system.
+
+So is seems that Propellor miss a copyFile whcih is usable also on nfs system :).
+what is the best way to solve this problem.
+
+I can copy the file without the preserve flag.
+
+Cheers
+
+Fred

Problem report regarding unprivileged systemd-nspawn containers
diff --git a/doc/forum/Unprivileged_containers_break_propellor.mdwn b/doc/forum/Unprivileged_containers_break_propellor.mdwn
new file mode 100644
index 00000000..0cb02c9b
--- /dev/null
+++ b/doc/forum/Unprivileged_containers_break_propellor.mdwn
@@ -0,0 +1,53 @@
+When trying to set up an unprivileged nspawn container, e.g., like shown below, propellor breaks, as it bind-mounts the `/usr/local/propellor` directory from the host, which leads to broken UIDs when seen from inside the container. I'm assuming `propellChroot` in `src/Propellor/Property/Chroot.hs` is the code that's responsible. Unfortunately, I'm not very firm in Haskell, so I'm not sure I can solve this in reasonable time, but I'll give it a shot.
+
+
+Example config:
+
+```
+rec0 :: Systemd.Container
+rec0 =  Systemd.debContainer "rec0" $ props
+        & Systemd.containerCfg "--network-veth"
+        & Systemd.containerCfg "-U"
+        & osDebian (Stable "buster") X86_64
+        & Apt.stdSourcesList
+        & Apt.installed ["pdns-recursor"] `requires` Systemd.running Systemd.networkd
+```
+
+This is the relevant output from a spin that includes the above container definition:
+
+```
+rec0 has container configuration --network-veth ... ok
+rec0 has container configuration -U ... ok
+rec0 has Operating System (Debian Linux (Stable "buster")) X86_64 ... ok
+rec0 standard sources.list ... ok
+Failed to connect to bus: Operation not permitted
+rec0 apt removed cron ifupdown rsyslog iptables isc-dhcp-client ... ok
+rec0 apt installed pdns-recursor ... failed
+propy nspawned rec0 ... failed
+propy overall ... failed
+```
+
+I figured out the (likely) cause like this:
+
+```
+$ findmnt /var/lib/container/rec0/usr/local/propellor
+TARGET                                      SOURCE                                     FSTYPE OPTIONS
+/var/lib/container/rec0/usr/local/propellor /dev/mapper/sys-root[/usr/local/propellor] ext4   rw,relatime,errors=remount-ro
+$ ls -l /var/lib/container/rec0/usr/local/propellor/dist/build/propellor-config/
+total 12272
+drwxr-xr-x 2 vu-rec0-0 vg-rec0-0    4096 Sep 24 01:19 autogen
+-rwxr-xr-x 1 root      root      6279024 Sep 24 03:16 propellor-config
+-rwxr-xr-x 1 root      root      6279024 Sep 24 03:16 propellor-config.built
+drwxr-xr-x 2 vu-rec0-0 vg-rec0-0    4096 Sep 24 03:16 propellor-config-tmp
+```
+
+I have `libnss-mymachines` setup, so the high UID/GID allocated by systemd show up with symbolic names. From inside the container, the root-owned files will show up as `nobody`:
+
+```
+# ls -l /usr/local/propellor/dist/build/propellor-config/
+total 12272
+drwxr-xr-x 2 root   root       4096 Sep 24 01:19 autogen
+-rwxr-xr-x 1 nobody nogroup 6279024 Sep 24 03:16 propellor-config
+drwxr-xr-x 2 root   root       4096 Sep 24 03:16 propellor-config-tmp
+-rwxr-xr-x 1 nobody nogroup 6279024 Sep 24 03:16 propellor-config.built
+```

chef needs to go away, my little bit to help
diff --git a/doc/README.mdwn b/doc/README.mdwn
index 76d05255..e2d51e68 100644
--- a/doc/README.mdwn
+++ b/doc/README.mdwn
@@ -26,7 +26,7 @@ and
 and
 [Docker](http://hackage.haskell.org/package/propellor/docs/Propellor-Property-Docker.html), etc.
 
-There is no special language as used in puppet, chef, ansible, etc.. just
+There is no special language as used in puppet, ansible, etc.. just
 the full power of Haskell. Hopefully that power can be put to good use in
 making declarative properties that are powerful, nicely idempotent, and
 easy to adapt to a system's special needs!

Added a comment: Works !
diff --git a/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo/comment_2_152c6b9d0ac402c374d9cfaf9ef14904._comment b/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo/comment_2_152c6b9d0ac402c374d9cfaf9ef14904._comment
new file mode 100644
index 00000000..ef6658a2
--- /dev/null
+++ b/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo/comment_2_152c6b9d0ac402c374d9cfaf9ef14904._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="serge1cohen"
+ avatar="http://cdn.libravatar.org/avatar/df873622c2eeb5b34222b7af0d47abd0"
+ subject="Works !"
+ date="2019-09-16T16:50:42Z"
+ content="""
+Hi again,
+
+I have just commuted all HasInfo and Debian (to have HasInfo first) and all works !
+Cool, thanks !
+
+Serge.
+"""]]

response
diff --git a/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo/comment_1_6e0f5ebebe81a632dccafb97cfe49e70._comment b/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo/comment_1_6e0f5ebebe81a632dccafb97cfe49e70._comment
new file mode 100644
index 00000000..04eb0f2b
--- /dev/null
+++ b/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo/comment_1_6e0f5ebebe81a632dccafb97cfe49e70._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-09-16T15:07:56Z"
+ content="""
+The problem is that you have "Debian + HasInfo" and the compiler expects
+"HasInfo + Debian". If you swap the order it will compile.
+
+Internally these types are represented as type-level lists, eg
+`[Debian, HasInfo]`. Unfortunately list items are ordered.
+What's needed is a type-level set. Using
+<http://hackage.haskell.org/package/type-level-sets>
+or something like it would avoid the problem, and is planned eventually.
+(But not yet, it [affects compile performance](https://github.com/dorchard/type-level-sets/issues/17)
+and [actually still depends on list ordering](https://github.com/dorchard/type-level-sets/issues/5).)
+
+In the meantime, there's a de-facto standard ordering of the items in a
+Property's metatypes list, and using some other ordering will result
+in this problem. If you let ghc infer the type of a property, the result
+will always use the standard ordering.
+"""]]

diff --git a/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo.mdwn b/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo.mdwn
new file mode 100644
index 00000000..5f90612a
--- /dev/null
+++ b/doc/forum/Combining_properties_with_HasInfo_and_another_without_HasInfo.mdwn
@@ -0,0 +1,101 @@
+Hello,
+
+I am working on making a property to setup a CMS, involving configuration with passwrod...
+
+I have a first property installing the required packages with signature :
+
+    wp_pkgs :: Property Debian
+
+I have made a second property to store the password/priv data to the 'proper file' which has signature (the data is stored in the privData with context the hostname and field the 'DbId')
+
+    type DbId = String
+    wp_dbconf ::  HostName -> DbId -> Property (Debian + HasInfo)
+
+
+I now want to combine those properties to make a single entry point using the following code :
+
+
+    wordpressSite :: HostName -> DbId -> Property (Debian + HasInfo)
+    wordpressSite hn id = desc ==> wp_conf hn id
+      where
+        desc :: String
+        desc = ("Installing and configuring WordPress to answer at name " ++ hn)
+ 
+        wp_conf :: HostName -> DbId -> Property (Debian + HasInfo)
+        wp_conf hn id =
+          wp_pkgs
+         `before` wp_dbconf hn id
+
+which gives me this error :
+
+    /src/Propellor/Property/SiteSpecific/IPANEMA.hs:221:7: error:
+        • Couldn't match type ‘'Propellor.Types.MetaTypes.Targeting
+                                 'OSDebian’
+                         with ‘'Propellor.Types.MetaTypes.WithInfo’
+          Expected type: Property (Debian + HasInfo)
+            Actual type: CombinedType
+                           (Property Debian)
+                           (Property
+                              (Propellor.Types.MetaTypes.MetaTypes
+                                 '['Propellor.Types.MetaTypes.Targeting 'OSDebian,
+                                   'Propellor.Types.MetaTypes.WithInfo]))
+        • In the expression: wp_pkgs `before` wp_dbconf hn id
+          In an equation for ‘wp_conf’:
+              wp_conf hn id = wp_pkgs `before` wp_dbconf hn id
+          In an equation for ‘wordpressSite’:
+              wordpressSite hn id
+                = desc ==> wp_conf hn id
+                where
+                    desc :: String
+                    desc
+                      = ("Installing and configuring WordPress to answer at name " ++ hn)
+                    wp_conf :: HostName -> DbId -> Property (Debian + HasInfo)
+                    wp_conf hn id = wp_pkgs `before` wp_dbconf hn id
+        |
+    221 |       wp_pkgs
+        |       ^^^^^^^...
+
+I understand that `before` is not happy having different types of Property on both sides.
+
+I then tried also using *props* (with or without embedding it within a *propertyList*). Here is the version with *propertyList*
+
+      wp_conf hn id =
+      propertyList "Setting up a wordpress site" $ props
+         & wp_pkgs
+         & wp_dbconf hn id
+
+Which also complains that I am trying to combine Debian with (Debian + HasInfo) (or at least that is how I understand the error message) :
+
+    src/Propellor/Property/SiteSpecific/IPANEMA.hs:221:52: error:
+        • Couldn't match type ‘'Propellor.Types.MetaTypes.Targeting
+                                 'OSDebian’
+                         with ‘'Propellor.Types.MetaTypes.WithInfo’
+          Expected type: Props
+                           (Propellor.Types.MetaTypes.MetaTypes
+                              '['Propellor.Types.MetaTypes.Targeting 'OSDebian,
+                                'Propellor.Types.MetaTypes.WithInfo])
+            Actual type: Props
+                           (Propellor.Types.MetaTypes.MetaTypes
+                              (Propellor.Types.MetaTypes.Combine
+                                 '['Propellor.Types.MetaTypes.Targeting 'OSDebian]
+                                 '['Propellor.Types.MetaTypes.Targeting 'OSDebian,
+                                   'Propellor.Types.MetaTypes.WithInfo]))
+        • In the second argument of ‘($)’, namely
+            ‘props & wp_pkgs & wp_dbconf hn id’
+          In the expression:
+            propertyList "Setting up a wordpress site"
+              $ props & wp_pkgs & wp_dbconf hn id
+          In an equation for ‘wp_conf’:
+              wp_conf hn id
+                = propertyList "Setting up a wordpress site"
+                    $ props & wp_pkgs & wp_dbconf hn id
+        |
+    221 |       propertyList "Setting up a wordpress site" $ props
+        |                                                    ^^^^^...
+
+
+I guess that is a regular pattern (mixing few properties with *HasInfo* with other that do not *HasInfo*) but all the code that I am looking at seems to work with *props* or some *before* or *require* combination.
+
+I don't understand what I am doing *wrong* here.
+
+

Added a comment
diff --git a/doc/forum/running_commands_in_Libvirt_guests/comment_5_669f05bac2b09ddbf735f9afdaed4400._comment b/doc/forum/running_commands_in_Libvirt_guests/comment_5_669f05bac2b09ddbf735f9afdaed4400._comment
new file mode 100644
index 00000000..fe6e7f15
--- /dev/null
+++ b/doc/forum/running_commands_in_Libvirt_guests/comment_5_669f05bac2b09ddbf735f9afdaed4400._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 5"
+ date="2019-08-20T13:37:47Z"
+ content="""
+Perhaps inChroot should just be moved into mkConfig.
+"""]]

Added a comment: grub failure
diff --git a/doc/forum/running_commands_in_Libvirt_guests/comment_4_5a2b2748c7e9eadc3c85ad6037ebc39a._comment b/doc/forum/running_commands_in_Libvirt_guests/comment_4_5a2b2748c7e9eadc3c85ad6037ebc39a._comment
new file mode 100644
index 00000000..67c11f0a
--- /dev/null
+++ b/doc/forum/running_commands_in_Libvirt_guests/comment_4_5a2b2748c7e9eadc3c85ad6037ebc39a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="grub failure"
+ date="2019-08-19T02:16:24Z"
+ content="""
+I narrowed it down to the call to Grub.mkConfig, which basically calls \"update-grub\". If I just copy the ConfFile.containsShellSetting from Grub.configured, then things work fine, presumably because of some later call to update-grub (when the image is finalized?).  I'm just guessing, but maybe something later sets up /boot so that update-grub can succeed. I noticed the the call to mkConfig in Grub.installed is guarded against being in a contained, so maybe Grub.configured needs something similar.
+"""]]

Added a comment
diff --git a/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_4_279d93da4d178cadec5b30b0f48c7196._comment b/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_4_279d93da4d178cadec5b30b0f48c7196._comment
new file mode 100644
index 00000000..2ce5be48
--- /dev/null
+++ b/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_4_279d93da4d178cadec5b30b0f48c7196._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 4"
+ date="2019-08-18T16:13:30Z"
+ content="""
+Okay.  Your approach in the code you posted seems good on a quick look over.
+"""]]

Added a comment
diff --git a/doc/forum/running_commands_in_Libvirt_guests/comment_3_c0b2c7b72d4fe63cc2eb0ddcf5745fc9._comment b/doc/forum/running_commands_in_Libvirt_guests/comment_3_c0b2c7b72d4fe63cc2eb0ddcf5745fc9._comment
new file mode 100644
index 00000000..89679fdd
--- /dev/null
+++ b/doc/forum/running_commands_in_Libvirt_guests/comment_3_c0b2c7b72d4fe63cc2eb0ddcf5745fc9._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 3"
+ date="2019-08-18T15:25:10Z"
+ content="""
+Unfortunately, there isn't enough information in your report for me to be able to think about what's going on.
+
+Perhaps you could look inside Libvirt.hs and try to determine why it is failing the first time but then succeeding.
+"""]]

Added a comment: "works" might be overstating it for Grub.configured
diff --git a/doc/forum/running_commands_in_Libvirt_guests/comment_2_b57bb2a74ce9028f08b3c9ce26a4864b._comment b/doc/forum/running_commands_in_Libvirt_guests/comment_2_b57bb2a74ce9028f08b3c9ce26a4864b._comment
new file mode 100644
index 00000000..e0cda846
--- /dev/null
+++ b/doc/forum/running_commands_in_Libvirt_guests/comment_2_b57bb2a74ce9028f08b3c9ce26a4864b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="&quot;works&quot; might be overstating it for Grub.configured"
+ date="2019-08-18T14:32:13Z"
+ content="""
+What actually happens is the first run it fails, and leaves the chroot lying around. The second run it succeeds, but this seems pretty fragile? Also it ends up allocating too much free space in the disk image, but that's not the end of the world.
+"""]]

Added a comment: Not a problem after all?
diff --git a/doc/forum/running_commands_in_Libvirt_guests/comment_1_3ca5dcbf17213af7c30c59a4148c6375._comment b/doc/forum/running_commands_in_Libvirt_guests/comment_1_3ca5dcbf17213af7c30c59a4148c6375._comment
new file mode 100644
index 00000000..8d6780be
--- /dev/null
+++ b/doc/forum/running_commands_in_Libvirt_guests/comment_1_3ca5dcbf17213af7c30c59a4148c6375._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="Not a problem after all?"
+ date="2019-08-18T14:04:06Z"
+ content="""
+It seems like the two things I was worried about are working fine, namely
+
+- running dconf update
+- running Grub.configured. I thought the latter was a problem but I just needed to make sure it came after Grub.installed.
+"""]]

removed
diff --git a/doc/forum/running_commands_in_Libvirt_guests/comment_1_3fb90d084e6e8ea08487e5970101b31b._comment b/doc/forum/running_commands_in_Libvirt_guests/comment_1_3fb90d084e6e8ea08487e5970101b31b._comment
deleted file mode 100644
index 97e3e205..00000000
--- a/doc/forum/running_commands_in_Libvirt_guests/comment_1_3fb90d084e6e8ea08487e5970101b31b._comment
+++ /dev/null
@@ -1,10 +0,0 @@
-[[!comment format=mdwn
- username="david"
- avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
- subject="how to configure grub?"
- date="2019-08-18T12:56:50Z"
- content="""
-One concrete example of something that fails in the initial image creation is Grub.configured
-
-Weirdly running \"dconf update\" seems to work, so maybe things are running inside a chroot?
-"""]]

Added a comment: how to configure grub?
diff --git a/doc/forum/running_commands_in_Libvirt_guests/comment_1_3fb90d084e6e8ea08487e5970101b31b._comment b/doc/forum/running_commands_in_Libvirt_guests/comment_1_3fb90d084e6e8ea08487e5970101b31b._comment
new file mode 100644
index 00000000..97e3e205
--- /dev/null
+++ b/doc/forum/running_commands_in_Libvirt_guests/comment_1_3fb90d084e6e8ea08487e5970101b31b._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="how to configure grub?"
+ date="2019-08-18T12:56:50Z"
+ content="""
+One concrete example of something that fails in the initial image creation is Grub.configured
+
+Weirdly running \"dconf update\" seems to work, so maybe things are running inside a chroot?
+"""]]

diff --git a/doc/forum/running_commands_in_Libvirt_guests.mdwn b/doc/forum/running_commands_in_Libvirt_guests.mdwn
new file mode 100644
index 00000000..b952ac0c
--- /dev/null
+++ b/doc/forum/running_commands_in_Libvirt_guests.mdwn
@@ -0,0 +1,5 @@
+I need to run some random binaries in the guest I created with Libvirt.defined as part of the configuration.
+
+I can define Cmd.property in the host definition, but what happens for the initial image creation? 
+
+Is there some idiom for this I am missing?

Added a comment: giving up on Firewall persistence
diff --git a/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_4_b3880a95912d446befd537a74989cba4._comment b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_4_b3880a95912d446befd537a74989cba4._comment
new file mode 100644
index 00000000..511deffa
--- /dev/null
+++ b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_4_b3880a95912d446befd537a74989cba4._comment
@@ -0,0 +1,87 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="giving up on Firewall persistence"
+ date="2019-08-11T11:29:07Z"
+ content="""
+I ran out of time/motivation to do this \"right\", so I just hardcoded all the things, and made a new module called IPTables
+
+[[!format haskell \"\"\"
+module Propellor.Property.SiteSpecific.Tethera.IPTables (
+  systemdUnits
+  , rules
+  ) where
+
+import Propellor.Base
+import qualified Propellor.Property.File as File
+
+
+systemdUnits :: Property UnixLike  
+systemdUnits = 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 -n /etc/iptables/\"++baseName++\".rules\"
+                , \"ExecReload=/sbin/\"++baseName++\"-restore -n /etc/iptables/\"++baseName++\".rules\"
+                , \"ExecStop=/usr/local/bin/flush-\"++baseName++\".sh\"
+                , \"RemainAfterExit=yes\"
+                , \"[Install]\"
+                , \"WantedBy=multi-user.target\"
+                ]
+                & File.hasContent fipSh
+                [
+                  \"#!/bin/sh\"
+                , baseName ++ \" -F INPUT\"
+                , baseName ++ \" -F FORWARD\"
+                , baseName ++ \" -F OUTPUT\"
+                , baseName ++ \" -P INPUT ACCEPT\"
+                , baseName ++ \" -P FORWARD ACCEPT\"
+                , baseName ++ \" -P OUTPUT ACCEPT\"
+                ]
+                & File.mode fipSh 0o0755
+      where
+            fipSh = \"/usr/local/bin/flush-\"++baseName++\".sh\"
+
+
+-- this currently makes the possibly bad assumption that the same rule
+-- file will work for both v4 and v6
+rules :: Property UnixLike
+rules  = combineProperties \"systemd units for iptables\" $ props
+         & ruleFile \"iptables\"
+         & ruleFile \"ip6tables\"                
+  where
+    ruleDir = \"/etc/iptables\"
+    ruleFile baseName = combineProperties (baseName ++ \" rules\") $ props
+                        & File.hasContent (ruleDir ++ \"/\"++baseName++\".rules\")
+
+                        [ \"*filter\"
+                        , \":INPUT ACCEPT [0:0]\"
+                        , \":FORWARD ACCEPT [0:0]\"
+                        , \":OUTPUT ACCEPT [0:0]\"
+                        , \"-A INPUT -m conntrack --ctstate INVALID -j DROP\"
+                        , \"-A INPUT -i lo -j ACCEPT\"
+                        , \"-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT\"
+                        , \"-A INPUT -p icmp -j ACCEPT\"
+                        , \"-6 -A INPUT -p ipv6-icmp -j ACCEPT\"
+                        , \"-6 -A INPUT -m state --state NEW -m udp -p udp -s fe80::/10 --dport 546 -j ACCEPT\"
+                        , \"-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT\"
+                        , \"-A INPUT -j DROP\"
+                        , \"-A FORWARD -j DROP\"
+                        , \"-A OUTPUT -o lo -j ACCEPT\"
+                        , \"-A OUTPUT -j ACCEPT\"
+                        , \"COMMIT\"
+                        ]
+                        `requires` File.dirExists ruleDir
+\"\"\"]]
+"""]]

Localdir.hasOriginUrl: Depend on Git.installed.
* Localdir.hasOriginUrl: Depend on Git.installed.
* Localdir.hasOriginUrl: Type changed from UnixLike to DebianLike
because Git.installed is not implemented for other unixes.
(API change)
This commit was sponsored by Denis Dzyubenko on Patreon.
diff --git a/debian/changelog b/debian/changelog
index 547cfb3a..3031d05a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+propellor (5.10.1) UNRELEASED; urgency=medium
+
+  * Localdir.hasOriginUrl: Depend on Git.installed.
+  * Localdir.hasOriginUrl: Type changed from UnixLike to DebianLike
+    because Git.installed is not implemented for other unixes.
+    (API change)
+
+ -- Joey Hess <id@joeyh.name>  Thu, 08 Aug 2019 11:33:37 -0400
+
 propellor (5.9.1) unstable; urgency=medium
 
   * Apt: Debian has changed the name of the suite for testing security updates
diff --git a/doc/forum/hasOriginUrl_does_not_work_if_git_was_not_installed/comment_1_2ef9109c5cd7e8ca89f309c48320ac20._comment b/doc/forum/hasOriginUrl_does_not_work_if_git_was_not_installed/comment_1_2ef9109c5cd7e8ca89f309c48320ac20._comment
new file mode 100644
index 00000000..b11da49f
--- /dev/null
+++ b/doc/forum/hasOriginUrl_does_not_work_if_git_was_not_installed/comment_1_2ef9109c5cd7e8ca89f309c48320ac20._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-08-08T15:28:13Z"
+ content="""
+I've made the property require Git.installed. 
+
+I guess this was not noticed because either I was using some other property
+that also installed git, or I only tried it outside a virtual machine, and
+so propellor had installed git as part of its process of bootstrapping a
+host.
+"""]]
diff --git a/src/Propellor/Property/Localdir.hs b/src/Propellor/Property/Localdir.hs
index 2323f569..69d9af74 100644
--- a/src/Propellor/Property/Localdir.hs
+++ b/src/Propellor/Property/Localdir.hs
@@ -9,6 +9,7 @@ import Propellor.Git.Config
 import Propellor.Types.Info
 import Propellor.Types.Container
 import Propellor.Property.Mount (partialBindMountsOf, umountLazy)
+import qualified Propellor.Property.Git as Git
 
 -- | Sets the url to use as the origin of propellor's git repository.
 --
@@ -19,8 +20,10 @@ import Propellor.Property.Mount (partialBindMountsOf, umountLazy)
 -- When hosts are being updated without using -- --spin, eg when using
 -- the `Propellor.Property.Cron.runPropellor` cron job, this property can
 -- be set to redirect them to a new git repository url.
-hasOriginUrl :: String -> Property (HasInfo + UnixLike)
-hasOriginUrl u = setInfoProperty p (toInfo (InfoVal (OriginUrl u)))
+hasOriginUrl :: String -> Property (HasInfo + DebianLike)
+hasOriginUrl u =
+	setInfoProperty p (toInfo (InfoVal (OriginUrl u)))
+		`requires` Git.installed
   where
 	p :: Property UnixLike
 	p = property ("propellor repo url " ++ u) $ do

diff --git a/doc/forum/hasOriginUrl_does_not_work_if_git_was_not_installed.mdwn b/doc/forum/hasOriginUrl_does_not_work_if_git_was_not_installed.mdwn
new file mode 100644
index 00000000..2422d17b
--- /dev/null
+++ b/doc/forum/hasOriginUrl_does_not_work_if_git_was_not_installed.mdwn
@@ -0,0 +1,14 @@
+Hello,
+
+I am creating virtual machines and set the url of propellor with 
+
+    & PropellorRepo.hasOriginUrl "https://salsa.debian.org/picca/propellor.git"
+
+I give the old name since I use the 5.6.0 version available in Debian stable.
+
+It systematically fail each time I provision the machine.
+I discovered that it failed due to a missing git.
+
+so it seems to me that this property should install git  before running :)
+
+cheers

Added a comment: unused parameter gw
diff --git a/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_3_00af4904cec24089b87c626769330bec._comment b/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_3_00af4904cec24089b87c626769330bec._comment
new file mode 100644
index 00000000..8e2e7025
--- /dev/null
+++ b/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_3_00af4904cec24089b87c626769330bec._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="unused parameter gw"
+ date="2019-08-03T15:48:10Z"
+ content="""
+For specifying an optional gateway. I never got that far in implimenting it.
+"""]]

Added a comment: Firewall.flush needed?
diff --git a/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_3_f9fb0a214ee8bc4fac11c3c16747cbe2._comment b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_3_f9fb0a214ee8bc4fac11c3c16747cbe2._comment
new file mode 100644
index 00000000..ad4bad4a
--- /dev/null
+++ b/doc/forum/How_to_make_P.Property.Firewall.rule_persistent/comment_3_f9fb0a214ee8bc4fac11c3c16747cbe2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="david"
+ avatar="http://cdn.libravatar.org/avatar/22c2d800db6a7699139df604a67cb221"
+ subject="Firewall.flush needed?"
+ date="2019-08-03T15:38:21Z"
+ content="""
+A simple(-minded) solution to the problem with ip-tables-save is to provide a way to invoke \"iptables -F\". It seems like this is needed in general, just to have a known starting point. At least most examples of setting up a firewall with iptables start by flushing the existing rules.
+"""]]

Added a comment
diff --git a/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_2_b83a1faeddc677a94add278dfc834d21._comment b/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_2_b83a1faeddc677a94add278dfc834d21._comment
new file mode 100644
index 00000000..8a636e35
--- /dev/null
+++ b/doc/forum/WIP_adding_dhcp_records_to_libvirt/comment_2_b83a1faeddc677a94add278dfc834d21._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 2"
+ date="2019-07-23T10:22:19Z"
+ content="""
+Seems the `gw` parameter is unused?  What was that for?
+"""]]

comment
diff --git a/doc/forum/Getting_Info_from_containers/comment_5_45f48be3688d2879098cc72be334cb8d._comment b/doc/forum/Getting_Info_from_containers/comment_5_45f48be3688d2879098cc72be334cb8d._comment
new file mode 100644
index 00000000..f94daf58
--- /dev/null
+++ b/doc/forum/Getting_Info_from_containers/comment_5_45f48be3688d2879098cc72be334cb8d._comment
@@ -0,0 +1,26 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2019-07-21T15:18:51Z"
+ content="""
+This seems like a reasonable change to make, although I am not sure I
+understand how you'd practially use it.
+
+But as far as how to implement it, you merely need to make an IsInfo
+instance for Host (or for [Host]) and then each of the container properties
+can add the Host of their container to the Info.
+
+Hmm, actually, this info is already provided in another way.
+In Propellor.Types.Chroot there is a ChrootInfo that builds up a map from
+chroot location to Host, and that gets added to the Info of the host where the
+chroot is used.
+
+As well as being used for regular chroots, the systemd containers are based
+on a chroot and so also use and provide it. Docker does not currently use
+it though. It has a separate DockerInfo that also happens to include the
+Host corresponding to the docker container.
+
+Anyway, I guess I'm a little bit unclear on what your original problem was,
+it might help if you could restate it in more detail to see if this would
+really help with it.
+"""]]

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