diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+propellor (4.3.1) unstable; urgency=medium
+
+  * Added Propellor.Property.FreeDesktop module.
+  * Added reservedSpacePercentage to the PartSpec EDSL.
+
+ -- Joey Hess <id@joeyh.name>  Thu, 06 Jul 2017 17:03:15 -0400
+
 propellor (4.3.0) unstable; urgency=medium
 
   * DiskImage: Removed grubBooted; properties that used to need it as a
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+propellor (4.3.1) unstable; urgency=medium
+
+  * Added Propellor.Property.FreeDesktop module.
+  * Added reservedSpacePercentage to the PartSpec EDSL.
+
+ -- Joey Hess <id@joeyh.name>  Thu, 06 Jul 2017 17:03:15 -0400
+
 propellor (4.3.0) unstable; urgency=medium
 
   * DiskImage: Removed grubBooted; properties that used to need it as a
diff --git a/joeyconfig.hs b/joeyconfig.hs
--- a/joeyconfig.hs
+++ b/joeyconfig.hs
@@ -21,14 +21,11 @@
 import qualified Propellor.Property.Postfix as Postfix
 import qualified Propellor.Property.Apache as Apache
 import qualified Propellor.Property.LetsEncrypt as LetsEncrypt
-import qualified Propellor.Property.LightDM as LightDM
-import qualified Propellor.Property.XFCE as XFCE
 import qualified Propellor.Property.Grub as Grub
 import qualified Propellor.Property.Obnam as Obnam
 import qualified Propellor.Property.Gpg as Gpg
 import qualified Propellor.Property.Systemd as Systemd
 import qualified Propellor.Property.Journald as Journald
-import qualified Propellor.Property.Chroot as Chroot
 import qualified Propellor.Property.Fail2Ban as Fail2Ban
 import qualified Propellor.Property.Aiccu as Aiccu
 import qualified Propellor.Property.OS as OS
@@ -39,8 +36,6 @@
 import qualified Propellor.Property.SiteSpecific.GitAnnexBuilder as GitAnnexBuilder
 import qualified Propellor.Property.SiteSpecific.Branchable as Branchable
 import qualified Propellor.Property.SiteSpecific.JoeySites as JoeySites
-import Propellor.Property.DiskImage
-import Propellor.Property.Bootstrap
 
 main :: IO ()           --     _         ______`|                       ,-.__
 main = defaultMain hosts --  /   \___-=O`/|O`/__|                      (____.'
@@ -49,7 +44,6 @@
 hosts :: [Host]          --   *             \ | |           '--------'
 hosts =                 --                  (o)  `
 	[ darkstar
-	, demo
 	, gnu
 	, dragon
 	, clam
@@ -96,37 +90,6 @@
 	& Ssh.userKeys (User "joey") hostContext
 		[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1YoyHxZwG5Eg0yiMTJLSWJ/+dMM6zZkZiR4JJ0iUfP+tT2bm/lxYompbSqBeiCq+PYcSC67mALxp1vfmdOV//LWlbXfotpxtyxbdTcQbHhdz4num9rJQz1tjsOsxTEheX5jKirFNC5OiKhqwIuNydKWDS9qHGqsKcZQ8p+n1g9Lr3nJVGY7eRRXzw/HopTpwmGmAmb9IXY6DC2k91KReRZAlOrk0287LaK3eCe1z0bu7LYzqqS+w99iXZ/Qs0m9OqAPnHZjWQQ0fN4xn5JQpZSJ7sqO38TBAimM+IHPmy2FTNVVn9zGM+vN1O2xr3l796QmaUG1+XLL0shfR/OZbb joey@darkstar")
 		]
-
-	& imageBuilt "/srv/propellor-disk.img"
-		(Chroot.hostChroot demo (Chroot.Debootstrapped mempty))
-		MSDOS
-		[ partition EXT2 `mountedAt` "/boot"
-			`setFlag` BootFlag
-		, partition EXT4 `mountedAt` "/"
-			`mountOpt` errorReadonly
-			`addFreeSpace` MegaBytes 256
-		, swapPartition (MegaBytes 256)
-		]
-		`before` File.ownerGroup "/srv/propellor-disk.img" (User "joey") (Group "joey")
-
-demo :: Host
-demo = host "demo" $ props
-	& osDebian Unstable X86_64
-	& Apt.installed ["linux-image-amd64"]
-	& Grub.installed PC
-	& bootstrappedFrom GitRepoOutsideChroot
-	& User.accountFor user
-	& User.hasDesktopGroups user
-	& root `User.hasInsecurePassword` "debian"
-	& user `User.hasInsecurePassword` "debian"
-	& XFCE.installedMin
-	& XFCE.networkManager
-	& XFCE.defaultPanelFor user File.OverwriteExisting
-	& LightDM.autoLogin user
-	& Apt.installed ["firefox"]
-  where
-	user = User "user"
-	root = User "root"
 
 gnu :: Host
 gnu = host "gnu.kitenet.net" $ props
diff --git a/propellor.cabal b/propellor.cabal
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -1,5 +1,5 @@
 Name: propellor
-Version: 4.3.0
+Version: 4.3.1
 Cabal-Version: >= 1.20
 License: BSD2
 Maintainer: Joey Hess <id@joeyh.name>
diff --git a/src/Propellor/Property/ConfFile.hs b/src/Propellor/Property/ConfFile.hs
--- a/src/Propellor/Property/ConfFile.hs
+++ b/src/Propellor/Property/ConfFile.hs
@@ -11,6 +11,7 @@
 	containsIniSetting,
 	hasIniSection,
 	lacksIniSection,
+	iniFileContains,
 ) where
 
 import Propellor.Base
@@ -114,3 +115,13 @@
 	(const []) -- remove all lines of section
 	id -- add no lines if section is missing
 	f
+
+-- | Specifies the whole content of a .ini file.
+--
+-- Revertijg this causes the file not to exist.
+iniFileContains :: FilePath -> [(IniSection, [(IniKey, String)])] -> RevertableProperty UnixLike UnixLike
+iniFileContains f l = f `hasContent` content <!> notPresent f
+  where
+	content = concatMap sectioncontent l
+	sectioncontent (section, keyvalues) = iniHeader section :
+		map (\(key, value) -> key ++ "=" ++ value) keyvalues
diff --git a/src/Propellor/Property/DiskImage/PartSpec.hs b/src/Propellor/Property/DiskImage/PartSpec.hs
--- a/src/Propellor/Property/DiskImage/PartSpec.hs
+++ b/src/Propellor/Property/DiskImage/PartSpec.hs
@@ -69,6 +69,14 @@
 setSize :: PartSpec -> PartSize -> PartSpec
 setSize (mp, o, p) sz = (mp, o, const (p sz))
 
+-- | Sets the percent of the filesystem blocks reserved for the super-user.
+--
+-- The default is 5% for ext2 and ext4. Some filesystems may not support
+-- this.
+reservedSpacePercentage :: PartSpec -> Int -> PartSpec
+reservedSpacePercentage s percent = adjustp s $ \p -> 
+	p { partMkFsOpts = ("-m"):show percent:partMkFsOpts p }
+
 -- | Sets a flag on the partition.
 setFlag :: PartSpec -> PartFlag -> PartSpec
 setFlag s f = adjustp s $ \p -> p { partFlags = (f, True):partFlags p }
