diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,14 @@
+propellor (4.4.0) unstable; urgency=medium
+
+  * Propellor.Property.Timezone: New module, contributed by Sean Whitton.
+  * Propellor.Property.Sudo.enabledFor: Made revertable.
+    (minor API change)
+  * Propellor.Property.LightDM.autoLogin: Made revertable.
+    (minor API change)
+  * Propellor.Property.Conffile: Added lacksIniSetting.
+
+ -- Joey Hess <id@joeyh.name>  Mon, 17 Jul 2017 12:55:02 -0400
+
 propellor (4.3.4) unstable; urgency=medium
 
   * Propellor.Property.Versioned: New module which allows different
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,14 @@
+propellor (4.4.0) unstable; urgency=medium
+
+  * Propellor.Property.Timezone: New module, contributed by Sean Whitton.
+  * Propellor.Property.Sudo.enabledFor: Made revertable.
+    (minor API change)
+  * Propellor.Property.LightDM.autoLogin: Made revertable.
+    (minor API change)
+  * Propellor.Property.Conffile: Added lacksIniSetting.
+
+ -- Joey Hess <id@joeyh.name>  Mon, 17 Jul 2017 12:55:02 -0400
+
 propellor (4.3.4) unstable; urgency=medium
 
   * Propellor.Property.Versioned: New module which allows different
diff --git a/propellor.cabal b/propellor.cabal
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -1,5 +1,5 @@
 Name: propellor
-Version: 4.3.4
+Version: 4.4.0
 Cabal-Version: >= 1.20
 License: BSD2
 Maintainer: Joey Hess <id@joeyh.name>
@@ -150,6 +150,7 @@
     Propellor.Property.Sudo
     Propellor.Property.Systemd
     Propellor.Property.Systemd.Core
+    Propellor.Property.Timezone
     Propellor.Property.Tor
     Propellor.Property.Unbound
     Propellor.Property.User
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
@@ -9,6 +9,7 @@
 	IniSection,
 	IniKey,
 	containsIniSetting,
+	lacksIniSetting,
 	hasIniSection,
 	lacksIniSection,
 	iniFileContains,
@@ -92,6 +93,19 @@
 	go []      = [confline]
 	go (l:ls)  = if isKeyVal l then confline : ls else l : go ls
 	isKeyVal x = (filter (/= ' ') . takeWhile (/= '=')) x `elem` [key, '#':key]
+
+-- | Removes a key=value setting from a section of an .ini file.
+-- Note that the section heading is left in the file, so this is not a
+-- perfect reversion of containsIniSetting.
+lacksIniSetting :: FilePath -> (IniSection, IniKey, String) -> Property UnixLike
+lacksIniSetting f (header, key, value) = adjustIniSection
+	(f ++ " section [" ++ header ++ "] lacks " ++ key ++ "=" ++ value)
+	header
+	(filter (/= confline))
+	id
+	f
+  where
+	confline = key ++ "=" ++ value
 
 -- | Ensures that a .ini file exists and contains a section
 -- with a given key=value list of settings.
diff --git a/src/Propellor/Property/LightDM.hs b/src/Propellor/Property/LightDM.hs
--- a/src/Propellor/Property/LightDM.hs
+++ b/src/Propellor/Property/LightDM.hs
@@ -10,8 +10,12 @@
 installed = Apt.installed ["lightdm"]
 
 -- | Configures LightDM to skip the login screen and autologin as a user.
-autoLogin :: User -> Property DebianLike
-autoLogin (User u) = "/etc/lightdm/lightdm.conf" `ConfFile.containsIniSetting`
-	("Seat:*", "autologin-user", u)
-	`describe` "lightdm autologin"
-	`requires` installed
+autoLogin :: User -> RevertableProperty DebianLike DebianLike
+autoLogin (User u) = (setup <!> cleanup)
+	`describe` ("lightdm autologin for " ++ u)
+  where
+	cf = "/etc/lightdm/lightdm.conf"
+	setting = ("Seat:*", "autologin-user", u)
+	setup = cf `ConfFile.containsIniSetting` setting
+		`requires` installed
+	cleanup = tightenTargets $ cf `ConfFile.lacksIniSetting` setting
diff --git a/src/Propellor/Property/Sudo.hs b/src/Propellor/Property/Sudo.hs
--- a/src/Propellor/Property/Sudo.hs
+++ b/src/Propellor/Property/Sudo.hs
@@ -9,23 +9,33 @@
 
 -- | Allows a user to sudo. If the user has a password, sudo is configured
 -- to require it. If not, NOPASSWORD is enabled for the user.
-enabledFor :: User -> Property DebianLike
-enabledFor user@(User u) = go `requires` Apt.installed ["sudo"]
+enabledFor :: User -> RevertableProperty DebianLike DebianLike
+enabledFor user@(User u) = setup `requires` Apt.installed ["sudo"] <!> cleanup
   where
-	go :: Property UnixLike
-	go = property' desc $ \w -> do
+	setup :: Property UnixLike
+	setup = property' desc $ \w -> do
 		locked <- liftIO $ isLockedPassword user
 		ensureProperty w $
 			fileProperty desc
 				(modify locked . filter (wanted locked))
-				"/etc/sudoers"
-	desc = u ++ " is sudoer"
+				sudoers
+	  where
+		desc = u ++ " is sudoer"
+	
+	cleanup :: Property DebianLike
+	cleanup = tightenTargets $ 
+		fileProperty desc (filter notuserline) sudoers
+	  where
+		desc = u ++ " is not sudoer"
+	
+	sudoers = "/etc/sudoers"
 	sudobaseline = u ++ " ALL=(ALL:ALL)"
+	notuserline l = not (sudobaseline `isPrefixOf` l)
 	sudoline True = sudobaseline ++ " NOPASSWD:ALL"
 	sudoline False = sudobaseline ++ " ALL"
 	wanted locked l
 		-- TOOD: Full sudoers file format parse.. 
-		| not (sudobaseline `isPrefixOf` l) = True
+		| notuserline l = True
 		| "NOPASSWD" `isInfixOf` l = locked
 		| otherwise = True
 	modify locked ls
diff --git a/src/Propellor/Property/Timezone.hs b/src/Propellor/Property/Timezone.hs
new file mode 100644
--- /dev/null
+++ b/src/Propellor/Property/Timezone.hs
@@ -0,0 +1,21 @@
+-- | Maintainer: Sean Whitton <spwhitton@spwhitton.name>
+
+module Propellor.Property.Timezone where
+
+import Propellor.Base
+import qualified Propellor.Property.Apt as Apt
+import qualified Propellor.Property.File as File
+
+-- | A timezone from /usr/share/zoneinfo
+type Timezone = String
+
+-- | Sets the system's timezone
+configured :: Timezone -> Property DebianLike
+configured zone = File.hasContent "/etc/timezone" [zone]
+	`onChange` update
+	`describe` (zone ++ " timezone configured")
+  where
+	update = Apt.reConfigure "tzdata" mempty
+		-- work around a bug in recent tzdata.  See
+		-- https://bugs.launchpad.net/ubuntu/+source/tzdata/+bug/1554806/
+		`requires` File.notPresent "/etc/localtime"
diff --git a/src/Propellor/Property/Versioned.hs b/src/Propellor/Property/Versioned.hs
--- a/src/Propellor/Property/Versioned.hs
+++ b/src/Propellor/Property/Versioned.hs
@@ -18,11 +18,11 @@
 -- 
 -- > demo :: Versioned Int (RevertableProperty DebianLike DebianLike)
 -- > demo ver =
--- >    ver (   (== 1) --> Apache.modEnabled "foo"
+-- > 	ver (   (== 1) --> Apache.modEnabled "foo"
 -- >		`requires` Apache.modEnabled "foosupport"
 -- >	    <|> (== 2) --> Apache.modEnabled "bar"
 -- > 	    <|> (> 2)  --> Apache.modEnabled "baz"
--- >        )
+-- > 	    )
 -- >
 -- > foo :: Host
 -- > foo = host "foo.example.com" $ props
diff --git a/src/Propellor/Types.hs b/src/Propellor/Types.hs
--- a/src/Propellor/Types.hs
+++ b/src/Propellor/Types.hs
@@ -107,6 +107,10 @@
 
 -- | A property that can be reverted. The first Property is run
 -- normally and the second is run when it's reverted.
+--
+-- See `Propellor.Property.Versioned.Versioned` 
+-- for a way to use RevertableProperty to define different
+-- versions of a host.
 data RevertableProperty setupmetatypes undometatypes = RevertableProperty
 	{ setupRevertableProperty :: Property setupmetatypes
 	, undoRevertableProperty :: Property undometatypes
