summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoey Hess2016-02-07 22:36:24 -0400
committerJoey Hess2016-02-07 22:36:24 -0400
commitb0be26473ee303afa0ceab4076e024e79daecb98 (patch)
treeab186eb7ab72e365457c14241709d4acf78f78a5 /src
parenta568c7c0367b1ef6f01d0e8e638bb0f3fc7b2cb8 (diff)
parentb493414d30c7aef37af904e55316436554fe54b2 (diff)
Merge branch 'joeyconfig'
Diffstat (limited to 'src')
-rw-r--r--src/Propellor/Property/Apache.hs41
-rw-r--r--src/Propellor/Property/LetsEncrypt.hs55
-rw-r--r--src/Propellor/Property/Obnam.hs12
3 files changed, 52 insertions, 56 deletions
diff --git a/src/Propellor/Property/Apache.hs b/src/Propellor/Property/Apache.hs
index e841be9e..dee7a5fc 100644
--- a/src/Propellor/Property/Apache.hs
+++ b/src/Propellor/Property/Apache.hs
@@ -155,18 +155,23 @@ virtualHost' domain (Port p) docroot addedcfg = siteEnabled domain $
-- Example:
--
-- > httpsVirtualHost "example.com" "/var/www"
--- > (LetsEncrypt.AgreeTos (Just "me@my.domain"))
-httpsVirtualHost :: Domain -> WebRoot -> LetsEncrypt.AgreeTOS -> Property NoInfo
+-- > (LetsEncrypt.AgreeTOS (Just "me@my.domain"))
+--
+-- Note that reverting this property does not remove the certificate from
+-- letsencrypt's cert store.
+httpsVirtualHost :: Domain -> WebRoot -> LetsEncrypt.AgreeTOS -> RevertableProperty NoInfo
httpsVirtualHost domain docroot letos = httpsVirtualHost' domain docroot letos []
-- | Like `httpsVirtualHost` but with additional config lines added.
-httpsVirtualHost' :: Domain -> WebRoot -> LetsEncrypt.AgreeTOS -> [ConfigLine] -> Property NoInfo
-httpsVirtualHost' domain docroot letos addedcfg = setup
- `requires` modEnabled "rewrite"
- `requires` modEnabled "ssl"
- `before` LetsEncrypt.letsEncrypt letos domain docroot certinstaller
+httpsVirtualHost' :: Domain -> WebRoot -> LetsEncrypt.AgreeTOS -> [ConfigLine] -> RevertableProperty NoInfo
+httpsVirtualHost' domain docroot letos addedcfg = setup <!> teardown
where
- setup = siteEnabled' domain $
+ setup = setuphttp
+ `requires` modEnabled "rewrite"
+ `requires` modEnabled "ssl"
+ `before` setuphttps
+ teardown = siteDisabled domain
+ setuphttp = siteEnabled' domain $
-- The sslconffile is only created after letsencrypt gets
-- the cert. The "*" is needed to make apache not error
-- when the file doesn't exist.
@@ -179,20 +184,22 @@ httpsVirtualHost' domain docroot letos addedcfg = setup
-- Everything else redirects to https
, "RewriteRule ^/(.*) https://" ++ domain ++ "/$1 [L,R,NE]"
]
- certinstaller _domain certfile privkeyfile chainfile _fullchainfile =
- combineProperties (domain ++ " ssl cert installed")
+ setuphttps = LetsEncrypt.letsEncrypt letos domain docroot
+ `onChange` combineProperties (domain ++ " ssl cert installed")
[ File.dirExists (takeDirectory cf)
- , File.hasContent cf $ vhost (Port 443)
- [ "SSLEngine on"
- , "SSLCertificateFile " ++ certfile
- , "SSLCertificateKeyFile" ++ privkeyfile
- , "SSLCertificateChainFile " ++ chainfile
- ]
- -- always reload; the cert has changed
+ , File.hasContent cf sslvhost
+ `onChange` reloaded
+ -- always reload since the cert has changed
, reloaded
]
where
cf = sslconffile "letsencrypt"
+ sslvhost = vhost (Port 443)
+ [ "SSLEngine on"
+ , "SSLCertificateFile " ++ LetsEncrypt.certFile domain
+ , "SSLCertificateKeyFile " ++ LetsEncrypt.privKeyFile domain
+ , "SSLCertificateChainFile " ++ LetsEncrypt.chainFile domain
+ ]
sslconffile s = "/etc/apache2/sites-available/ssl/" ++ domain ++ "/" ++ s ++ ".conf"
vhost (Port p) ls =
[ "<VirtualHost *:"++show p++">"
diff --git a/src/Propellor/Property/LetsEncrypt.hs b/src/Propellor/Property/LetsEncrypt.hs
index 651cffd9..d5528c64 100644
--- a/src/Propellor/Property/LetsEncrypt.hs
+++ b/src/Propellor/Property/LetsEncrypt.hs
@@ -23,22 +23,29 @@ type WebRoot = FilePath
--
-- This should work with any web server, as long as letsencrypt can
-- write its temp files to the web root. The letsencrypt client does
--- not modify the web server's configuration in any way; instead the
--- `CertInstaller` is used once the client has successfully obtained the
--- certificate.
---
--- This also handles renewing the certificate, and the `CertInstaller` is
--- also run after renewal. For renewel to work well, propellor needs to be
--- run periodically (at least a couple times per month).
+-- not modify the web server's configuration in any way; this only obtains
+-- the certificate it does not make the web server use it.
--
--- See `Propellor.Property.Apache.httpsVirtualHost` for a property built using this.
-letsEncrypt :: AgreeTOS -> Domain -> WebRoot -> CertInstaller -> Property NoInfo
+-- This also handles renewing the certificate.
+-- For renewel to work well, propellor needs to be
+-- run periodically (at least a couple times per month).
+--
+-- This property returns `MadeChange` when the certificate is initially
+-- obtained, and when it's renewed. So, it can be combined with a property
+-- to make the webserver (or other server) use the certificate:
+--
+-- > letsEncrypt (AgreeTOS (Just "me@example.com")) "example.com" "/var/www"
+-- > `onChange` Apache.reload
+--
+-- See `Propellor.Property.Apache.httpsVirtualHost` for a more complete
+-- integration of apache with letsencrypt, that's built on top of this.
+letsEncrypt :: AgreeTOS -> Domain -> WebRoot -> Property NoInfo
letsEncrypt tos domain = letsEncrypt' tos domain []
-- | Like `letsEncrypt`, but the certificate can be obtained for multiple
-- domains.
-letsEncrypt' :: AgreeTOS -> Domain -> [Domain] -> WebRoot -> CertInstaller -> Property NoInfo
-letsEncrypt' (AgreeTOS memail) domain domains webroot certinstaller =
+letsEncrypt' :: AgreeTOS -> Domain -> [Domain] -> WebRoot -> Property NoInfo
+letsEncrypt' (AgreeTOS memail) domain domains webroot =
prop `requires` installed
where
prop = property desc $ do
@@ -48,9 +55,9 @@ letsEncrypt' (AgreeTOS memail) domain domains webroot certinstaller =
if ok
then do
endstats <- liftIO getstats
- if startstats == endstats
- then return NoChange
- else ensureProperty certsinstalled
+ if startstats /= endstats
+ then return MadeChange
+ else return NoChange
else do
liftIO $ hPutStr stderr transcript
return FailedChange
@@ -79,26 +86,8 @@ letsEncrypt' (AgreeTOS memail) domain domains webroot certinstaller =
statfile f = catchMaybeIO $ do
s <- getFileStatus f
return (fileID s, deviceID s, fileMode s, fileSize s, modificationTime s)
-
- certsinstalled = propertyList ("certs installed") $
- flip map alldomains $ \d -> certinstaller d
- (certFile d)
- (privKeyFile d)
- (chainFile d)
- (fullChainFile d)
-
--- | A property that installs a certificate, once letsencrypt obtains it.
---
--- For example, it could configure the web server to use the certificate
--- files, and restart the web server.
-type CertInstaller = Domain -> CertFile -> PrivKeyFile -> ChainFile -> FullChainFile -> Property NoInfo
-
--- | Locations of certificate files generated by lets encrypt.
-type CertFile = FilePath
-type PrivKeyFile = FilePath
-type ChainFile = FilePath
-type FullChainFile = FilePath
+-- | The cerificate files that letsencrypt will make available for a domain.
liveCertDir :: Domain -> FilePath
liveCertDir d = "/etc/letsencrypt/live" </> d
diff --git a/src/Propellor/Property/Obnam.hs b/src/Propellor/Property/Obnam.hs
index 9a391967..92c97f18 100644
--- a/src/Propellor/Property/Obnam.hs
+++ b/src/Propellor/Property/Obnam.hs
@@ -62,23 +62,23 @@ backup' dir crontimes params numclients = cronjob `describe` desc
unwords $ catMaybes
[ if numclients == OnlyClient
-- forcelock fails if repo does not exist yet
- then Just $ forcelock ++ " 2>/dev/null ;"
+ then Just $ forcelockcmd ++ " 2>/dev/null ;"
else Nothing
- , Just backup
+ , Just backupcmd
, if any isKeepParam params
- then Just $ "&& " ++ forget
+ then Just $ "&& " ++ forgetcmd
else Nothing
]
- forcelock = unwords $
+ forcelockcmd = unwords $
[ "obnam"
, "force-lock"
] ++ map shellEscape params
- backup = unwords $
+ backupcmd = unwords $
[ "obnam"
, "backup"
, shellEscape dir
] ++ map shellEscape params
- forget = unwords $
+ forgetcmd = unwords $
[ "obnam"
, "forget"
] ++ map shellEscape params