diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,13 @@
+propellor (5.3.5) unstable; urgency=medium
+
+  * Apt.stdSourcesList now adds stable-updates suite
+    Thanks, Sean Whitton
+  * Significantly increased propellor build speed when your config.hs
+    is in a fork of the propellor repository, by avoiding redundant builds
+    of propellor library.
+
+ -- Joey Hess <id@joeyh.name>  Sun, 22 Apr 2018 12:27:45 -0400
+
 propellor (5.3.4) unstable; urgency=medium
 
   * Apt.trustsKey: Use apt-key to add key rather than manually driving gpg,
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+propellor (5.3.5) unstable; urgency=medium
+
+  * Apt.stdSourcesList now adds stable-updates suite
+    Thanks, Sean Whitton
+  * Significantly increased propellor build speed when your config.hs
+    is in a fork of the propellor repository, by avoiding redundant builds
+    of propellor library.
+
+ -- Joey Hess <id@joeyh.name>  Sun, 22 Apr 2018 12:27:45 -0400
+
 propellor (5.3.4) unstable; urgency=medium
 
   * Apt.trustsKey: Use apt-key to add key rather than manually driving gpg,
diff --git a/executables/propellor-config.hs b/executables/propellor-config.hs
new file mode 100644
--- /dev/null
+++ b/executables/propellor-config.hs
@@ -0,0 +1,29 @@
+-- This is the main configuration file for Propellor, and is used to build
+-- the propellor program.
+
+import Propellor
+import qualified Propellor.Property.File as File
+import qualified Propellor.Property.Apt as Apt
+import qualified Propellor.Property.Cron as Cron
+import qualified Propellor.Property.User as User
+
+main :: IO ()
+main = defaultMain hosts
+
+-- The hosts propellor knows about.
+hosts :: [Host]
+hosts =
+	[ mybox
+	]
+
+-- An example host.
+mybox :: Host
+mybox = host "mybox.example.com" $ props
+	& osDebian Unstable X86_64
+	& Apt.stdSourcesList
+	& Apt.unattendedUpgrades
+	& Apt.installed ["etckeeper"]
+	& Apt.installed ["ssh"]
+	& User.hasSomePassword (User "root")
+	& File.dirExists "/var/www"
+	& Cron.runPropellor (Cron.Times "30 * * * *")
diff --git a/executables/wrapper.hs b/executables/wrapper.hs
new file mode 100644
--- /dev/null
+++ b/executables/wrapper.hs
@@ -0,0 +1,6 @@
+module Main where
+
+import Propellor.Wrapper
+
+main :: IO ()
+main = runWrapper
diff --git a/joeyconfig.hs b/joeyconfig.hs
--- a/joeyconfig.hs
+++ b/joeyconfig.hs
@@ -33,7 +33,6 @@
 import qualified Propellor.Property.Journald as Journald
 import qualified Propellor.Property.Fail2Ban as Fail2Ban
 import qualified Propellor.Property.Laptop as Laptop
-import qualified Propellor.Property.OS as OS
 import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost
 import qualified Propellor.Property.HostingProvider.Linode as Linode
 import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean
@@ -49,7 +48,6 @@
 hosts :: [Host]          --   *             \ | |           '--------'
 hosts =                 --                  (o)  `
 	[ darkstar
-	, gnu
 	, dragon
 	, clam
 	, orca
@@ -64,25 +62,6 @@
 	, keysafe
 	] ++ monsters
 
-testvm :: Host
-testvm = host "testvm.kitenet.net" $ props
-	& osDebian Unstable X86_64
-	& OS.cleanInstallOnce (OS.Confirmed "testvm.kitenet.net")
-	 	`onChange` postinstall
-	& Hostname.sane
-	& Hostname.searchDomain
-	& Apt.installed ["linux-image-amd64"]
-	& Apt.installed ["ssh"]
-	& User.hasPassword (User "root")
-  where
-	postinstall :: Property (HasInfo + DebianLike)
-	postinstall = propertyList "fixing up after clean install" $ props
-		& OS.preserveRootSshAuthorized
-		& OS.preserveResolvConf
-		& Apt.update
-		& Grub.boots "/dev/sda"
-			`requires` Grub.installed Grub.PC
-
 darkstar :: Host
 darkstar = host "darkstar.kitenet.net" $ props
 	& osDebian Unstable X86_64
@@ -106,10 +85,9 @@
 	-- & imageBuiltFor honeybee
 	--	(RawDiskImage "/srv/honeybee.img")
 	--	(Debootstrapped mempty)
-
-gnu :: Host
-gnu = host "gnu.kitenet.net" $ props
-	& Postfix.satellite
+	& imageBuiltFor banana
+		(RawDiskImage "/srv/banana.img")
+		(Debootstrapped mempty)
 
 dragon :: Host
 dragon = host "dragon.kitenet.net" $ props
@@ -182,6 +160,17 @@
 	& Systemd.nspawned (GitAnnexBuilder.androidAutoBuilderContainer
 		(Cron.Times "1 1 * * *") "3h")
 
+banana :: Host
+banana = host "banana.kitenet.net" $ props
+	& lemaker_Banana_Pi
+	& hasPartition
+		( partition EXT4
+			`mountedAt` "/"
+			`setSize` MegaBytes 950
+		)
+	& osDebian Testing ARMHF
+	& User.hasInsecurePassword (User "root") "root"
+
 honeybee :: Host
 honeybee = host "honeybee.kitenet.net" $ props
 	& standardSystem Testing ARMHF
@@ -232,7 +221,6 @@
 	& ipv4 "66.228.36.95"
 	& ipv6 "2600:3c03::f03c:91ff:fe73:b0d2"
 	& alias "kitenet.net"
-	& alias "wren.kitenet.net" -- temporary
 	& Ssh.hostKeys (Context "kitenet.net")
 		[ (SshDsa, "ssh-dss AAAAB3NzaC1kc3MAAACBAO9tnPUT4p+9z7K6/OYuiBNHaij4Nzv5YVBih1vMl+ALz0gYAj8RWJzXmqp5buFAyfgOoLw+H9s1bBS01Sy3i07Dm6cx1fWG4RXL/E/3w1tavX99GD2bBxDBu890ebA5Tp+eFRJkS9+JwSvFiF6CP7NbVjifCagoUO56Ig048RwDAAAAFQDPY2xM3q6KwsVQliel23nrd0rV2QAAAIEAga3hj1hL00rYPNnAUzT8GAaSP62S4W68lusErH+KPbsMwFBFY/Ib1FVf8k6Zn6dZLh/HH/RtJi0JwdzPI1IFW+lwVbKfwBvhQ1lw9cH2rs1UIVgi7Wxdgfy8gEWxf+QIqn62wG+Ulf/HkWGvTrRpoJqlYRNS/gnOWj9Z/4s99koAAACBAM/uJIo2I0nK15wXiTYs/NYUZA7wcErugFn70TRbSgduIFH6U/CQa3rgHJw9DCPCQJLq7pwCnFH7too/qaK+czDk04PsgqV0+Jc7957gU5miPg50d60eJMctHV4eQ1FpwmGGfXxRBR9k2ZvikWYatYir3L6/x1ir7M0bA9IzNU45")
 		, (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA2QAJEuvbTmaN9ex9i9bjPhMGj+PHUYq2keIiaIImJ+8mo+yKSaGUxebG4tpuDPx6KZjdycyJt74IXfn1voGUrfzwaEY9NkqOP3v6OWTC3QeUGqDCeJ2ipslbEd9Ep9XBp+/ldDQm60D0XsIZdmDeN6MrHSbKF4fXv1bqpUoUILk=")
@@ -242,6 +230,7 @@
 
 	& Network.preserveStatic "eth0" `requires` Network.cleanInterfacesFile
 	& Apt.installed ["linux-image-amd64"]
+	& Apt.serviceInstalledRunning "swapspace"
 	& Linode.serialGrub
 	& Linode.mlocateEnabled
 	& Apt.unattendedUpgrades
@@ -341,7 +330,7 @@
 		, "search kitenet.net"
 		]
 	& alias "debug-me.joeyh.name"
-	-- debug-me installed manually until package is available
+	& Apt.installed ["debug-me"]
 	& Systemd.enabled "debug-me"
 
 	-- testing
@@ -637,8 +626,7 @@
 	, host "ns6.gandi.net" $ props
 		& ipv4 "217.70.177.40"
 	, host "animx" $ props
-		& ipv4 "76.7.162.186"
-		& ipv4 "76.7.162.187"
+		& ipv4 "76.7.174.49"
 	]
 
 
diff --git a/propellor.cabal b/propellor.cabal
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -1,5 +1,5 @@
 Name: propellor
-Version: 5.3.4
+Version: 5.3.5
 Cabal-Version: >= 1.20
 License: BSD2
 Maintainer: Joey Hess <id@joeyh.name>
@@ -35,38 +35,6 @@
  .
  It is configured using haskell.
 
-Executable propellor
-  Default-Language: Haskell98
-  Main-Is: wrapper.hs
-  GHC-Options: -threaded -Wall -fno-warn-tabs -O0
-  if impl(ghc >= 8.0)
-    GHC-Options: -fno-warn-redundant-constraints
-  Default-Extensions: TypeOperators
-  Hs-Source-Dirs: src
-  Build-Depends:
-    -- propellor needs to support the ghc shipped in Debian stable,
-    -- and also only depends on packages in Debian stable.
-    base >= 4.5, base < 5,
-    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
-  Other-Modules:
-    Propellor.DotDir
-
-Executable propellor-config
-  Default-Language: Haskell98
-  Main-Is: propellor-config.hs
-  GHC-Options: -threaded -Wall -fno-warn-tabs -O0
-  if impl(ghc >= 8.0)
-    GHC-Options: -fno-warn-redundant-constraints
-  Default-Extensions: TypeOperators
-  Hs-Source-Dirs: src
-  Build-Depends:
-    base >= 4.5, base < 5,
-    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
-
 Library
   Default-Language: Haskell98
   GHC-Options: -Wall -fno-warn-tabs -O0
@@ -75,6 +43,8 @@
   Default-Extensions: TypeOperators
   Hs-Source-Dirs: src
   Build-Depends:
+    -- propellor needs to support the ghc shipped in Debian stable,
+    -- and also only depends on packages in Debian stable.
     base >= 4.5, base < 5,
     directory, filepath, IfElse, process, bytestring, hslogger, split,
     unix, unix-compat, ansi-terminal, containers (>= 0.5), network, async,
@@ -83,6 +53,7 @@
   Exposed-Modules:
     Propellor
     Propellor.Base
+    Propellor.DotDir
     Propellor.Location
     Propellor.Property
     Propellor.Property.Aiccu
@@ -211,6 +182,7 @@
     Propellor.Types.ResultCheck
     Propellor.Types.Singletons
     Propellor.Types.ZFS
+    Propellor.Wrapper
   Other-Modules:
     Propellor.Bootstrap
     Propellor.Git
@@ -254,6 +226,23 @@
     System.Console.Concurrent
     System.Console.Concurrent.Internal
     System.Process.Concurrent
+    Paths_propellor
+
+Executable propellor-config
+  Default-Language: Haskell98
+  Hs-Source-Dirs: executables
+  Main-Is: propellor-config.hs
+  GHC-Options: -threaded -Wall -fno-warn-tabs -O0
+  if impl(ghc >= 8.0)
+    GHC-Options: -fno-warn-redundant-constraints
+  Default-Extensions: TypeOperators
+  Build-Depends: propellor, base
+
+Executable propellor
+  Default-Language: Haskell98
+  Hs-Source-Dirs: executables
+  Main-Is: wrapper.hs
+  Build-Depends: propellor, base
 
 source-repository head
   type: git
diff --git a/src/Propellor/Property/Apt.hs b/src/Propellor/Property/Apt.hs
--- a/src/Propellor/Property/Apt.hs
+++ b/src/Propellor/Property/Apt.hs
@@ -88,6 +88,8 @@
 binandsrc url suite = catMaybes
 	[ Just l
 	, Just $ srcLine l
+	, sul
+	, srcLine <$> sul
 	, bl
 	, srcLine <$> bl
 	]
@@ -96,6 +98,10 @@
 	bl = do
 		bs <- backportSuite suite
 		return $ debLine bs url stdSections
+	-- formerly known as 'volatile'
+	sul = do
+		sus <- stableUpdatesSuite suite
+		return $ debLine sus url stdSections
 
 stdArchiveLines :: Propellor SourcesGenerator
 stdArchiveLines = return . binandsrc =<< getMirror
diff --git a/src/Propellor/Property/Machine.hs b/src/Propellor/Property/Machine.hs
--- a/src/Propellor/Property/Machine.hs
+++ b/src/Propellor/Property/Machine.hs
@@ -48,10 +48,10 @@
 	marvell_SheevaPlug,
 	cubietech_Cubietruck,
 	olimex_A10_OLinuXino_LIME,
+	lemaker_Banana_Pi,
 	-- * ARM boards (untested)
 	cubietech_Cubieboard,
 	cubietech_Cubieboard2,
-	lemaker_Banana_Pi,
 	lemaker_Banana_Pro,
 	olimex_A10s_OLinuXino_Micro,
 	olimex_A20_OLinuXino_LIME,
diff --git a/src/Propellor/Property/Scheduled.hs b/src/Propellor/Property/Scheduled.hs
--- a/src/Propellor/Property/Scheduled.hs
+++ b/src/Propellor/Property/Scheduled.hs
@@ -21,7 +21,7 @@
 --
 -- This uses the description of the Property to keep track of when it was
 -- last run.
-period :: (IsProp (Property i)) => Property i -> Recurrance -> Property i
+period :: Property i -> Recurrance -> Property i
 period prop recurrance = flip describe desc $ adjustPropertySatisfy prop $ \satisfy -> do
 	lasttime <- liftIO $ getLastChecked (getDesc prop)
 	nexttime <- liftIO $ fmap startTime <$> nextTime schedule lasttime
@@ -37,7 +37,7 @@
 	desc = getDesc prop ++ " (period " ++ fromRecurrance recurrance ++ ")"
 
 -- | Like period, but parse a human-friendly string.
-periodParse :: (IsProp (Property i)) => Property i -> String -> Property i
+periodParse :: Property i -> String -> Property i
 periodParse prop s = case toRecurrance s of
 	Just recurrance -> period prop recurrance
 	Nothing -> adjustPropertySatisfy prop $ \_ -> do
diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs
--- a/src/Propellor/Property/SiteSpecific/JoeySites.hs
+++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs
@@ -15,6 +15,7 @@
 import qualified Propellor.Property.Cron as Cron
 import qualified Propellor.Property.Service as Service
 import qualified Propellor.Property.User as User
+import qualified Propellor.Property.Group as Group
 import qualified Propellor.Property.Borg as Borg
 import qualified Propellor.Property.Apache as Apache
 import qualified Propellor.Property.Postfix as Postfix
@@ -916,10 +917,15 @@
 	& File.ownerGroup "/var/www/html" user (userGroup user)
 	& Git.cloned user "git://git.kitenet.net/joey/homepower" d Nothing
 	& buildpoller
+	& Systemd.enabled setupservicename
+		`requires` setupserviceinstalled
+		`onChange` Systemd.started setupservicename
 	& Systemd.enabled servicename
 		`requires` serviceinstalled
 		`onChange` Systemd.started servicename
 	& User.hasGroup user (Group "dialout")
+	& Group.exists (Group "gpio") Nothing
+	& User.hasGroup user (Group "gpio")
 	& Cron.niceJob "homepower upload"
 		(Cron.Times "1 * * * *") user d rsynccommand
 		`requires` Ssh.userKeyAt (Just sshkeyfile) user ctx sshkey
@@ -951,6 +957,23 @@
 		, "[Install]"
 		, "WantedBy=multi-user.target"
 		]
+	setupservicename = "homepower-setup"
+	setupservicefile = "/etc/systemd/system/" ++ setupservicename ++ ".service"
+	setupserviceinstalled = setupservicefile `File.hasContent`
+		[ "[Unit]"
+		, "Description=home power monitor setup"
+		, ""
+		, "[Service]"
+		, "ExecStart=" ++ d ++ "/setup"
+		, "WorkingDirectory=" ++ d
+		, "User=root"
+		, "Group=root"
+		, "Type=oneshot"
+		, ""
+		, "[Install]"
+		, "WantedBy=multi-user.target"
+		, "WantedBy=homepower.target"
+		]
 	-- Any changes to the rsync command will need my .authorized_keys
 	-- rsync server command to be updated too.
 	rsynccommand = "rsync -e 'ssh -i" ++ sshkeyfile ++ "' -avz rrds/recent/ joey@kitenet.net:/srv/web/homepower.joeyh.name/rrds/recent/"
@@ -987,6 +1010,7 @@
 		, "dhcp-range=10.1.1.100,10.1.1.150,24h"
 		, "no-hosts"
 		, "address=/honeybee.kitenet.net/10.1.1.1"
+		, "address=/house.kitenet.net/10.1.1.1"
 		]
 		`onChange` Service.restarted "dnsmasq"
 	& ipmasq "wlan0"
@@ -1040,7 +1064,7 @@
 
 laptopSoftware :: Property DebianLike
 laptopSoftware = Apt.installed
-	[ "intel-microcode"
+	[ "intel-microcode", "acpi"
 	, "procmeter3", "xfce4", "procmeter3", "unclutter"
 	, "mplayer", "fbreader", "firefox", "chromium"
 	, "libdatetime-event-sunrise-perl", "libtime-duration-perl"
@@ -1055,6 +1079,7 @@
 	, "pmount", "tree", "pv"
 	, "arbtt", "hledger", "bc"
 	, "apache2", "ikiwiki", "libhighlight-perl"
+	, "avahi-daemon", "avahi-discover"
 	, "pal"
 	, "yeahconsole", "xkbset", "xinput"
 	, "assword", "pumpa"
@@ -1096,13 +1121,13 @@
 		["--debian", "sun7i-a20-cubietruck"]
 		`assume` MadeChange
 	mydts =
-		[ "/* Device tree addition enabling onewire sensors on CubieTruck GPIO pin PG8 */"
+		[ "/* Device tree addition enabling onewire sensors on CubieTruck GPIO pin PC21 */"
 		, "#include <dt-bindings/gpio/gpio.h>"
 		, ""
 		, "/ {"
 		, "\tonewire_device {"
 		, "\t\tcompatible = \"w1-gpio\";"
-		, "\t\tgpios = <&pio 6 8 GPIO_ACTIVE_HIGH>; /* PG8 */"
+		, "\t\tgpios = <&pio 2 21 GPIO_ACTIVE_HIGH>; /* PC21 */"
 		, "\t\tpinctrl-names = \"default\";"
 		, "\t\tpinctrl-0 = <&my_w1_pin>;"
 		, "\t};"
@@ -1110,7 +1135,7 @@
 		, ""
 		, "&pio {"
 		, "\tmy_w1_pin: my_w1_pin@0 {"
-		, "\t\tallwinner,pins = \"PG8\";"
+		, "\t\tallwinner,pins = \"PC21\";"
 		, "\t\tallwinner,function = \"gpio_in\";"
 		, "\t};"
 		, "};"
diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs
--- a/src/Propellor/Property/Systemd.hs
+++ b/src/Propellor/Property/Systemd.hs
@@ -217,7 +217,7 @@
 -- to bootstrap.
 --
 -- > container "webserver" $ \d -> Chroot.debootstrapped mempty d $ props
--- >	& osDebian Unstable X86_64
+-- >    & osDebian Unstable X86_64
 -- >    & Apt.installedRunning "apache2"
 -- >    & ...
 container :: MachineName -> (FilePath -> Chroot.Chroot) -> Container
@@ -238,7 +238,7 @@
 -- to bootstrap.
 --
 -- > debContainer "webserver" $ props
--- >	& osDebian Unstable X86_64
+-- >    & osDebian Unstable X86_64
 -- >    & Apt.installedRunning "apache2"
 -- >    & ...
 debContainer :: MachineName -> Props metatypes -> Container
diff --git a/src/Propellor/Wrapper.hs b/src/Propellor/Wrapper.hs
new file mode 100644
--- /dev/null
+++ b/src/Propellor/Wrapper.hs
@@ -0,0 +1,85 @@
+-- | This module is used to implement a wrapper program for propellor
+-- distribution.
+--
+-- Distributions should install this program into PATH.
+-- (Cabal builds it as dist/build/propellor/propellor).
+--
+-- This is not the propellor main program (that's config.hs).
+-- This bootstraps ~/.propellor/config.hs, builds it if
+-- it's not already built, and runs it.
+--
+-- If ./config.hs exists and looks like a propellor config file, 
+-- it instead builds and runs in the current working directory.
+
+module Propellor.Wrapper (runWrapper) where
+
+import Propellor.DotDir
+import Propellor.Message
+import Propellor.Bootstrap
+import Utility.Monad
+import Utility.Directory
+import Utility.FileMode
+import Utility.Process
+import Utility.Process.NonConcurrent
+import Utility.FileSystemEncoding
+
+import System.Environment (getArgs)
+import System.Exit
+import System.Posix
+import Data.List
+import Control.Monad.IfElse
+import Control.Applicative
+import Prelude
+
+runWrapper :: IO ()
+runWrapper = withConcurrentOutput $ do
+	useFileSystemEncoding
+	go =<< getArgs
+  where
+	go ["--init"] = interactiveInit
+	go args = ifM configInCurrentWorkingDirectory
+		( buildRunConfig args
+		, ifM (doesDirectoryExist =<< dotPropellor)
+			( do
+				checkRepoUpToDate
+				changeWorkingDirectory =<< dotPropellor
+				buildRunConfig args
+			, error "Seems that ~/.propellor/ does not exist. To set it up, run: propellor --init"
+			)
+		)
+
+buildRunConfig :: [String] -> IO ()
+buildRunConfig args = do
+	unlessM (doesFileExist "propellor") $ do
+		buildPropellor Nothing
+		putStrLn ""
+		putStrLn ""
+	(_, _, _, pid) <- createProcessNonConcurrent (proc "./propellor" args) 
+	exitWith =<< waitForProcessNonConcurrent pid
+
+configInCurrentWorkingDirectory :: IO Bool
+configInCurrentWorkingDirectory = ifM (doesFileExist "config.hs")
+	( do
+		-- This is a security check to avoid using the current
+		-- working directory as the propellor configuration
+		-- if it's not owned by the user, or is world-writable,
+		-- or group writable. (Some umasks may make directories
+		-- group writable, but typical ones do not.)
+		s <- getFileStatus "."
+		uid <- getRealUserID
+		if fileOwner s /= uid
+			then unsafe "you don't own the current directory"
+			else if checkMode groupWriteMode (fileMode s)
+				then unsafe "the current directory is group writable"
+				else if checkMode otherWriteMode (fileMode s)
+					then unsafe "the current directory is world-writable"
+					else ifM mentionspropellor
+						( return True
+						, notusing "it does not seem to be a propellor config file"
+						)
+	, return False
+	)
+  where
+	unsafe s = notusing (s ++ ". This seems unsafe.")
+	notusing s = error $ "Not using ./config.hs because " ++ s
+	mentionspropellor = ("Propellor" `isInfixOf`) <$> readFile "config.hs"
diff --git a/src/propellor-config.hs b/src/propellor-config.hs
deleted file mode 100644
--- a/src/propellor-config.hs
+++ /dev/null
@@ -1,29 +0,0 @@
--- This is the main configuration file for Propellor, and is used to build
--- the propellor program.
-
-import Propellor
-import qualified Propellor.Property.File as File
-import qualified Propellor.Property.Apt as Apt
-import qualified Propellor.Property.Cron as Cron
-import qualified Propellor.Property.User as User
-
-main :: IO ()
-main = defaultMain hosts
-
--- The hosts propellor knows about.
-hosts :: [Host]
-hosts =
-	[ mybox
-	]
-
--- An example host.
-mybox :: Host
-mybox = host "mybox.example.com" $ props
-	& osDebian Unstable X86_64
-	& Apt.stdSourcesList
-	& Apt.unattendedUpgrades
-	& Apt.installed ["etckeeper"]
-	& Apt.installed ["ssh"]
-	& User.hasSomePassword (User "root")
-	& File.dirExists "/var/www"
-	& Cron.runPropellor (Cron.Times "30 * * * *")
diff --git a/src/wrapper.hs b/src/wrapper.hs
deleted file mode 100644
--- a/src/wrapper.hs
+++ /dev/null
@@ -1,84 +0,0 @@
--- | Wrapper program for propellor distribution.
---
--- Distributions should install this program into PATH.
--- (Cabal builds it as dist/build/propellor/propellor).
---
--- This is not the propellor main program (that's config.hs).
--- This bootstraps ~/.propellor/config.hs, builds it if
--- it's not already built, and runs it.
---
--- If ./config.hs exists and looks like a propellor config file, 
--- it instead builds and runs in the current working directory.
-
-module Main where
-
-import Propellor.DotDir
-import Propellor.Message
-import Propellor.Bootstrap
-import Utility.Monad
-import Utility.Directory
-import Utility.FileMode
-import Utility.Process
-import Utility.Process.NonConcurrent
-import Utility.FileSystemEncoding
-
-import System.Environment (getArgs)
-import System.Exit
-import System.Posix
-import Data.List
-import Control.Monad.IfElse
-import Control.Applicative
-import Prelude
-
-main :: IO ()
-main = withConcurrentOutput $ do
-	useFileSystemEncoding
-	go =<< getArgs
-  where
-	go ["--init"] = interactiveInit
-	go args = ifM configInCurrentWorkingDirectory
-		( buildRunConfig args
-		, ifM (doesDirectoryExist =<< dotPropellor)
-			( do
-				checkRepoUpToDate
-				changeWorkingDirectory =<< dotPropellor
-				buildRunConfig args
-			, error "Seems that ~/.propellor/ does not exist. To set it up, run: propellor --init"
-			)
-		)
-
-buildRunConfig :: [String] -> IO ()
-buildRunConfig args = do
-	unlessM (doesFileExist "propellor") $ do
-		buildPropellor Nothing
-		putStrLn ""
-		putStrLn ""
-	(_, _, _, pid) <- createProcessNonConcurrent (proc "./propellor" args) 
-	exitWith =<< waitForProcessNonConcurrent pid
-
-configInCurrentWorkingDirectory :: IO Bool
-configInCurrentWorkingDirectory = ifM (doesFileExist "config.hs")
-	( do
-		-- This is a security check to avoid using the current
-		-- working directory as the propellor configuration
-		-- if it's not owned by the user, or is world-writable,
-		-- or group writable. (Some umasks may make directories
-		-- group writable, but typical ones do not.)
-		s <- getFileStatus "."
-		uid <- getRealUserID
-		if fileOwner s /= uid
-			then unsafe "you don't own the current directory"
-			else if checkMode groupWriteMode (fileMode s)
-				then unsafe "the current directory is group writable"
-				else if checkMode otherWriteMode (fileMode s)
-					then unsafe "the current directory is world-writable"
-					else ifM mentionspropellor
-						( return True
-						, notusing "it does not seem to be a propellor config file"
-						)
-	, return False
-	)
-  where
-	unsafe s = notusing (s ++ ". This seems unsafe.")
-	notusing s = error $ "Not using ./config.hs because " ++ s
-	mentionspropellor = ("Propellor" `isInfixOf`) <$> readFile "config.hs"
