diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,17 @@
+propellor (4.7.7) unstable; urgency=medium
+
+  * Locale: Display an error message when /etc/locale.gen does not contain
+    the requested locale.
+  * Attic module is deprecated and will warn when used.
+    Attic is no longer available in Debian and appears to have been
+    mostly supersceded by Borg.
+  * Obnam module is deprecated and will warn when used.
+    Obnam has been retired by its author.
+  * Add Typeable instance to Bootstrapper, fixing build with old versions
+    of ghc. (Previous attempt was incomplete.)
+
+ -- Joey Hess <id@joeyh.name>  Wed, 23 Aug 2017 12:15:31 -0400
+
 propellor (4.7.6) unstable; urgency=medium
 
   * Sbuild: Add Sbuild.userConfig property.
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+propellor (4.7.7) unstable; urgency=medium
+
+  * Locale: Display an error message when /etc/locale.gen does not contain
+    the requested locale.
+  * Attic module is deprecated and will warn when used.
+    Attic is no longer available in Debian and appears to have been
+    mostly supersceded by Borg.
+  * Obnam module is deprecated and will warn when used.
+    Obnam has been retired by its author.
+  * Add Typeable instance to Bootstrapper, fixing build with old versions
+    of ghc. (Previous attempt was incomplete.)
+
+ -- Joey Hess <id@joeyh.name>  Wed, 23 Aug 2017 12:15:31 -0400
+
 propellor (4.7.6) unstable; urgency=medium
 
   * Sbuild: Add Sbuild.userConfig property.
diff --git a/joeyconfig.hs b/joeyconfig.hs
--- a/joeyconfig.hs
+++ b/joeyconfig.hs
@@ -120,7 +120,7 @@
 clam = host "clam.kitenet.net" $ props
 	& standardSystem Unstable X86_64
 		["Unreliable server. Anything here may be lost at any time!" ]
-	& ipv4 "64.137.182.29"
+	& ipv4 "45.62.211.6"
 
 	& CloudAtCost.decruft
 	& Ssh.hostKeys hostContext
@@ -201,6 +201,10 @@
 	-- No hardware clock
 	& Apt.serviceInstalledRunning "ntp"
 
+	& JoeySites.homePowerMonitor
+		(User "joey")
+		(Context "homepower.joeyh.name")
+		(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMAmVYddg/RgCbIj+cLcEiddeFXaYFnbEJ3uGj9G/EyV joey@honeybee")
 	& JoeySites.homeRouter
 	& Apt.installed ["mtr-tiny", "iftop", "screen"]
 	& Postfix.satellite
@@ -226,7 +230,7 @@
 kite = host "kite.kitenet.net" $ props
 	& standardSystemUnhardened Testing X86_64 [ "Welcome to kite!" ]
 	& ipv4 "66.228.36.95"
-	& ipv6 "2600:3c03::f03c:91ff:fe73:b0d2"
+	-- & ipv6 "2600:3c03::f03c:91ff:fe73:b0d2"
 	& alias "kitenet.net"
 	& alias "wren.kitenet.net" -- temporary
 	& Ssh.hostKeys (Context "kitenet.net")
diff --git a/propellor.cabal b/propellor.cabal
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -1,5 +1,5 @@
 Name: propellor
-Version: 4.7.6
+Version: 4.7.7
 Cabal-Version: >= 1.20
 License: BSD2
 Maintainer: Joey Hess <id@joeyh.name>
diff --git a/src/Propellor/Bootstrap.hs b/src/Propellor/Bootstrap.hs
--- a/src/Propellor/Bootstrap.hs
+++ b/src/Propellor/Bootstrap.hs
@@ -33,7 +33,7 @@
 -- `OSOnly` uses the OS's native packages of Cabal and all of propellor's
 -- build dependencies. It may not work on all systems.
 data Bootstrapper = Robustly Builder | OSOnly
-	deriving (Show)
+	deriving (Show, Typeable)
 
 data Builder = Cabal | Stack
 	deriving (Show, Typeable)
diff --git a/src/Propellor/Property/Attic.hs b/src/Propellor/Property/Attic.hs
--- a/src/Propellor/Property/Attic.hs
+++ b/src/Propellor/Property/Attic.hs
@@ -1,8 +1,12 @@
 -- | Maintainer: Félix Sipma <felix+propellor@gueux.org>
 --
 -- Support for the Attic backup tool <https://attic-backup.org/>
+--
+-- This module is deprecated because Attic is not available in debian
+-- stable any longer (so the installed property no longer works), and it
+-- appears to have been mostly supersceded by Borg.
 
-module Propellor.Property.Attic
+module Propellor.Property.Attic {-# DEPRECATED "Use Borg instead" #-}
 	( installed
 	, repoExists
 	, init
diff --git a/src/Propellor/Property/Locale.hs b/src/Propellor/Property/Locale.hs
--- a/src/Propellor/Property/Locale.hs
+++ b/src/Propellor/Property/Locale.hs
@@ -63,7 +63,7 @@
 			then ensureProperty w $
 				fileProperty desc (foldr uncomment []) f
 					`onChange` regenerate
-			else return FailedChange -- locale unavailable for generation
+			else error $ "locale " ++ locale ++ " is not present in /etc/locale.gen, even in commented out form; cannot generate"
 	ensureUnavailable :: Property DebianLike
 	ensureUnavailable = tightenTargets $ 
 		fileProperty (locale ++ " locale not generated") (foldr comment []) f
diff --git a/src/Propellor/Property/Obnam.hs b/src/Propellor/Property/Obnam.hs
--- a/src/Propellor/Property/Obnam.hs
+++ b/src/Propellor/Property/Obnam.hs
@@ -1,6 +1,9 @@
 -- | Support for the Obnam backup tool <http://obnam.org/>
+--
+-- This module is deprecated because Obnam has been retired by its
+-- author.
 
-module Propellor.Property.Obnam where
+module Propellor.Property.Obnam {-# DEPRECATED "Obnam has been retired; time to transition to something else" #-} where
 
 import Propellor.Base
 import qualified Propellor.Property.Apt as Apt
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
@@ -520,7 +520,6 @@
 
 	& "/etc/aliases" `File.hasPrivContentExposed` ctx
 		`onChange` Postfix.newaliases
-	& hasPostfixCert ctx
 
 	& "/etc/postfix/mydomain" `File.containsLines`
 		[ "/.*\\.kitenet\\.net/\tOK"
@@ -583,9 +582,9 @@
 		, "milter_default_action = accept"
 
 		, "# TLS setup -- server"
-		, "smtpd_tls_CAfile = /etc/ssl/certs/joeyca.pem"
-		, "smtpd_tls_cert_file = /etc/ssl/certs/postfix.pem"
-		, "smtpd_tls_key_file = /etc/ssl/private/postfix.pem"
+		, "smtpd_tls_CAfile = /etc/letsencrypt/live/kitenet.net/fullchain.pem"
+		, "smtpd_tls_cert_file = /etc/letsencrypt/live/kitenet.net/cert.pem"
+		, "smtpd_tls_key_file = /etc/letsencrypt/live/kitenet.net/privkey.pem"
 		, "smtpd_tls_loglevel = 1"
 		, "smtpd_tls_received_header = yes"
 		, "smtpd_use_tls = yes"
@@ -593,9 +592,9 @@
 		, "smtpd_tls_session_cache_database = sdbm:/etc/postfix/smtpd_scache"
 
 		, "# TLS setup -- client"
-		, "smtp_tls_CAfile = /etc/ssl/certs/joeyca.pem"
-		, "smtp_tls_cert_file = /etc/ssl/certs/postfix.pem"
-		, "smtp_tls_key_file = /etc/ssl/private/postfix.pem"
+		, "smtp_tls_CAfile = /etc/letsencrypt/live/kitenet.net/fullchain.pem"
+		, "smtp_tls_cert_file = /etc/letsencrypt/live/kitenet.net/cert.pem"
+		, "smtp_tls_key_file = /etc/letsencrypt/live/kitenet.net/privkey.pem"
 		, "smtp_tls_loglevel = 1"
 		, "smtp_use_tls = yes"
 		, "smtp_tls_session_cache_database = sdbm:/etc/postfix/smtp_scache"
@@ -614,6 +613,12 @@
 		"!include auth-passwdfile.conf.ext"
 		`onChange` Service.restarted "dovecot"
 		`describe` "dovecot auth.conf"
+	& "/etc/dovecot/conf.d/10-ssl.conf" `File.containsLines`
+		[ "ssl_cert = </etc/letsencrypt/live/kitenet.net/fullchain.pem"
+		, "ssl_key = </etc/letsencrypt/live/kitenet.net/privkey.pem"
+		]
+		`onChange` Service.restarted "dovecot"
+		`describe` "dovecot letsencrypt certs"
 	& File.hasPrivContent dovecotusers ctx
 		`onChange` (dovecotusers `File.mode`
 			combineModes [ownerReadMode, groupReadMode])
@@ -711,16 +716,9 @@
 		, "smtp_sasl_tls_security_options = noanonymous"
 		, "relayhost = [kitenet.net]"
 		, "smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd"
-		, "# kite's fingerprint"
-		, "smtp_tls_fingerprint_cert_match = 13:B0:0C:F3:11:83:A5:EB:A9:37:C6:C5:ED:16:60:86"
 		]
 		`onChange` Postfix.reloaded
 
-hasPostfixCert :: Context -> Property (HasInfo + UnixLike)
-hasPostfixCert ctx = combineProperties "postfix tls cert installed" $ props
-	& "/etc/ssl/certs/postfix.pem" `File.hasPrivContentExposed` ctx
-	& "/etc/ssl/private/postfix.pem" `File.hasPrivContent` ctx
-
 -- Legacy static web sites and redirections from kitenet.net to newer
 -- sites.
 legacyWebSites :: Property (HasInfo + DebianLike)
@@ -795,6 +793,15 @@
 		, "# Redirect all to joeyh.name."
 		, "rewriterule (.*) http://joeyh.name$1 [r]"
 		]
+	& alias "homepower.joeyh.name"
+	& apacheSite "homepower.joeyh.name"
+		[ "DocumentRoot /srv/web/homepower.joeyh.name"
+		, "<Directory /srv/web/homepower.joeyh.name>"
+		, "  Options Indexes ExecCGI"
+		, "  AllowOverride None"
+		, Apache.allowAll
+		, "</Directory>"
+		]
   where
 	kitenetcfg =
 		-- /var/www is empty
@@ -930,6 +937,49 @@
 	& Systemd.started "goodmorning.timer"
 	& "/etc/systemd/logind.conf" `ConfFile.containsIniSetting`
 		("Login", "LidSwitchIgnoreInhibited", "no")
+
+-- My home power monitor.
+homePowerMonitor :: IsContext c => User -> c -> (SshKeyType, Ssh.PubKeyText) -> Property (HasInfo + DebianLike)
+homePowerMonitor user ctx sshkey = propertyList "home power monitor" $ props
+	& Apache.installed
+	& Apt.installed ["python2", "python-pymodbus"]
+	& File.ownerGroup "/var/www/html" user (userGroup user)
+	& Git.cloned user "git://git.kitenet.net/joey/homepower" d Nothing
+		`onChange` buildpoller
+	& Systemd.enabled servicename
+		`requires` serviceinstalled
+		`onChange` Systemd.started servicename
+	& Cron.niceJob "homepower upload"
+		(Cron.Times "1 * * * *") user d rsynccommand
+		`requires` Ssh.userKeyAt (Just sshkeyfile) user ctx sshkey
+  where
+	d = "/var/www/html/homepower"
+	sshkeyfile = d </> ".ssh/key"
+	buildpoller = userScriptProperty (User "joey")
+		[ "cd " ++ d
+		, "make"
+		]
+		`assume` MadeChange
+		`requires` Apt.installed ["ghc", "make"]
+	servicename = "homepower"
+	servicefile = "/etc/systemd/system/" ++ servicename ++ ".service"
+	serviceinstalled = servicefile `File.hasContent`
+		[ "[Unit]"
+		, "Description=home power monitor"
+		, ""
+		, "[Service]"
+		, "ExecStart=" ++ d ++ "/poller"
+		, "WorkingDirectory=" ++ d
+		, "User=joey"
+		, "Group=joey"
+		, ""
+		, "[Install]"
+		, "WantedBy=multi-user.target"
+		]
+	-- Only upload when eth0 is up; eg the satellite internet is up.
+	-- Any changes to the rsync command will need my .authorized_keys
+	-- rsync server command to be updated too.
+	rsynccommand = "if ip route | grep '^default' | grep -q eth0; then rsync -e 'ssh -i" ++ sshkeyfile ++ "' -avz rrds/recent/ joey@kitenet.net:/srv/web/homepower.joeyh.name/rrds/recent/; fi"
 
 -- My home router, running hostapd and dnsmasq for wlan0,
 -- with eth0 connected to a satellite modem, and a fallback ppp connection.
