module Propellor.Property.Apache where

import Propellor.Base
import qualified Propellor.Property.File as File
import qualified Propellor.Property.Apt as Apt
import qualified Propellor.Property.Service as Service
import qualified Propellor.Property.LetsEncrypt as LetsEncrypt

installed :: Property DebianLike
installed :: Property DebianLike
installed = [Package] -> Property DebianLike
Apt.installed ["apache2"]

restarted :: Property DebianLike
restarted :: Property DebianLike
restarted = Package -> Property DebianLike
Service.restarted "apache2"

reloaded :: Property DebianLike
reloaded :: Property DebianLike
reloaded = Package -> Property DebianLike
Service.reloaded "apache2"

type ConfigLine = String

type ConfigFile = [ConfigLine]

siteEnabled :: Domain -> ConfigFile -> RevertableProperty DebianLike DebianLike
siteEnabled :: Package -> [Package] -> RevertableProperty DebianLike DebianLike
siteEnabled domain :: Package
domain cf :: [Package]
cf = Package -> [Package] -> Property DebianLike
siteEnabled' Package
domain [Package]
cf Property DebianLike
-> Property DebianLike -> RevertableProperty DebianLike DebianLike
forall setupmetatypes undometatypes.
Property setupmetatypes
-> Property undometatypes
-> RevertableProperty setupmetatypes undometatypes
<!> Package -> Property DebianLike
siteDisabled Package
domain

siteEnabled' :: Domain -> ConfigFile -> Property DebianLike
siteEnabled' :: Package -> [Package] -> Property DebianLike
siteEnabled' domain :: Package
domain cf :: [Package]
cf = Package -> Props DebianLike -> Property DebianLike
forall k (metatypes :: k).
SingI metatypes =>
Package
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties ("apache site enabled " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain) (Props DebianLike -> Property DebianLike)
-> Props DebianLike -> Property DebianLike
forall a b. (a -> b) -> a -> b
$ Props UnixLike
props
	Props UnixLike
-> Property DebianLike
-> Props
     (MetaTypes
        (Combine
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
              'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]))
forall a p (y :: [a]) (x :: [a]).
(IsProp p, MetaTypes y ~ GetMetaTypes p,
 CheckCombinableNote x y (NoteFor ('Text "&"))) =>
Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
& Package -> [Package] -> Property DebianLike
siteAvailable Package
domain [Package]
cf
		Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
		Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
	Props DebianLike
-> Property DebianLike
-> Props
     (MetaTypes
        (Combine
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]))
forall a p (y :: [a]) (x :: [a]).
(IsProp p, MetaTypes y ~ GetMetaTypes p,
 CheckCombinableNote x y (NoteFor ('Text "&"))) =>
Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
& IO Bool -> UncheckedProperty UnixLike -> Property UnixLike
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Bool -> Bool
not (Bool -> Bool) -> IO Bool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Bool
isenabled)
		(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty "a2ensite" ["--quiet", Package
domain])
			Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
			Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
  where
	isenabled :: IO Bool
isenabled = Package -> [CommandParam] -> IO Bool
boolSystem "a2query" [Package -> CommandParam
Param "-q", Package -> CommandParam
Param "-s", Package -> CommandParam
Param Package
domain]

siteDisabled :: Domain -> Property DebianLike
siteDisabled :: Package -> Property DebianLike
siteDisabled domain :: Package
domain = Package -> Props UnixLike -> Property UnixLike
forall k (metatypes :: k).
SingI metatypes =>
Package
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties
	("apache site disabled " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain)
	([Property UnixLike] -> Props UnixLike
forall k (metatypes :: k).
[Property (MetaTypes metatypes)] -> Props (MetaTypes metatypes)
toProps ([Property UnixLike] -> Props UnixLike)
-> [Property UnixLike] -> Props UnixLike
forall a b. (a -> b) -> a -> b
$ (Package -> Property UnixLike) -> [Package] -> [Property UnixLike]
forall a b. (a -> b) -> [a] -> [b]
map Package -> Property UnixLike
File.notPresent (Package -> [Package]
siteCfg Package
domain))
		Property UnixLike
-> Property UnixLike
-> CombinedType (Property UnixLike) (Property UnixLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` (Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty "a2dissite" ["--quiet", Package
domain] UncheckedProperty UnixLike -> Result -> Property UnixLike
forall (p :: * -> *) i.
Checkable p i =>
p i -> Result -> Property i
`assume` Result
MadeChange)
		Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
		Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded

siteAvailable :: Domain -> ConfigFile -> Property DebianLike
siteAvailable :: Package -> [Package] -> Property DebianLike
siteAvailable domain :: Package
domain cf :: [Package]
cf = Package -> Props DebianLike -> Property DebianLike
forall k (metatypes :: k).
SingI metatypes =>
Package
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties ("apache site available " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain) (Props DebianLike -> Property DebianLike)
-> Props DebianLike -> Property DebianLike
forall a b. (a -> b) -> a -> b
$
	[Property DebianLike] -> Props DebianLike
forall k (metatypes :: k).
[Property (MetaTypes metatypes)] -> Props (MetaTypes metatypes)
toProps ([Property DebianLike] -> Props DebianLike)
-> [Property DebianLike] -> Props DebianLike
forall a b. (a -> b) -> a -> b
$ (Property UnixLike -> Property DebianLike)
-> [Property UnixLike] -> [Property DebianLike]
forall a b. (a -> b) -> [a] -> [b]
map Property UnixLike -> Property DebianLike
forall (p :: * -> *) (untightened :: [MetaType])
       (tightened :: [MetaType]).
(TightenTargets p, TightenTargetsAllowed untightened tightened,
 SingI tightened) =>
p (MetaTypes untightened) -> p (MetaTypes tightened)
tightenTargets ([Property UnixLike] -> [Property DebianLike])
-> [Property UnixLike] -> [Property DebianLike]
forall a b. (a -> b) -> a -> b
$
		(Package -> Property UnixLike) -> [Package] -> [Property UnixLike]
forall a b. (a -> b) -> [a] -> [b]
map (Package -> [Package] -> Property UnixLike
`File.hasContent` (Package
commentPackage -> [Package] -> [Package]
forall a. a -> [a] -> [a]
:[Package]
cf)) (Package -> [Package]
siteCfg Package
domain)
  where
	comment :: Package
comment = "# deployed with propellor, do not modify"

modEnabled :: String -> RevertableProperty DebianLike DebianLike
modEnabled :: Package -> RevertableProperty DebianLike DebianLike
modEnabled modname :: Package
modname = Property DebianLike
enable Property DebianLike
-> Property DebianLike -> RevertableProperty DebianLike DebianLike
forall setupmetatypes undometatypes.
Property setupmetatypes
-> Property undometatypes
-> RevertableProperty setupmetatypes undometatypes
<!> Property DebianLike
disable
  where
	enable :: CombinedType (Property DebianLike) (Property DebianLike)
enable = IO Bool -> UncheckedProperty UnixLike -> Property UnixLike
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Bool -> Bool
not (Bool -> Bool) -> IO Bool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Bool
isenabled)
		(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty "a2enmod" ["--quiet", Package
modname])
			Property UnixLike -> Package -> Property UnixLike
forall p. IsProp p => p -> Package -> p
`describe` ("apache module enabled " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
modname)
			Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
			Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
	disable :: CombinedType (Property DebianLike) (Property DebianLike)
disable = IO Bool -> UncheckedProperty UnixLike -> Property UnixLike
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check IO Bool
isenabled
		(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty "a2dismod" ["--quiet", Package
modname])
			Property UnixLike -> Package -> Property UnixLike
forall p. IsProp p => p -> Package -> p
`describe` ("apache module disabled " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
modname)
			Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
			Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
	isenabled :: IO Bool
isenabled = Package -> [CommandParam] -> IO Bool
boolSystem "a2query" [Package -> CommandParam
Param "-q", Package -> CommandParam
Param "-m", Package -> CommandParam
Param Package
modname]

-- | Control whether an apache configuration file is enabled. 
--
-- The String is the base name of the configuration, eg "charset" or "gitweb".
confEnabled :: String -> RevertableProperty DebianLike DebianLike
confEnabled :: Package -> RevertableProperty DebianLike DebianLike
confEnabled confname :: Package
confname = Property DebianLike
enable Property DebianLike
-> Property DebianLike -> RevertableProperty DebianLike DebianLike
forall setupmetatypes undometatypes.
Property setupmetatypes
-> Property undometatypes
-> RevertableProperty setupmetatypes undometatypes
<!> Property DebianLike
disable
  where
	enable :: CombinedType (Property DebianLike) (Property DebianLike)
enable = IO Bool -> UncheckedProperty UnixLike -> Property UnixLike
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Bool -> Bool
not (Bool -> Bool) -> IO Bool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Bool
isenabled)
		(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty "a2enconf" ["--quiet", Package
confname])
			Property UnixLike -> Package -> Property UnixLike
forall p. IsProp p => p -> Package -> p
`describe` ("apache configuration enabled " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
confname)
			Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
			Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
	disable :: CombinedType (Property DebianLike) (Property DebianLike)
disable = IO Bool -> UncheckedProperty UnixLike -> Property UnixLike
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check IO Bool
isenabled
		(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty "a2disconf" ["--quiet", Package
confname])
			Property UnixLike -> Package -> Property UnixLike
forall p. IsProp p => p -> Package -> p
`describe` ("apache configuration disabled " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
confname)
			Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
			Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
	isenabled :: IO Bool
isenabled = Package -> [CommandParam] -> IO Bool
boolSystem "a2query" [Package -> CommandParam
Param "-q", Package -> CommandParam
Param "-c", Package -> CommandParam
Param Package
confname]

-- | Make apache listen on the specified ports.
--
-- Note that ports are also specified inside a site's config file,
-- so that also needs to be changed.
listenPorts :: [Port] -> Property DebianLike
listenPorts :: [Port] -> Property DebianLike
listenPorts ps :: [Port]
ps = "/etc/apache2/ports.conf" Package -> [Package] -> Property UnixLike
`File.hasContent` (Port -> Package) -> [Port] -> [Package]
forall a b. (a -> b) -> [a] -> [b]
map Port -> Package
forall t. ConfigurableValue t => t -> Package
portline [Port]
ps
	Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
restarted
  where
	portline :: t -> Package
portline port :: t
port = "Listen " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ t -> Package
forall t. ConfigurableValue t => t -> Package
val t
port

-- This is a list of config files because different versions of apache
-- use different filenames. Propellor simply writes them all.
siteCfg :: Domain -> [FilePath]
siteCfg :: Package -> [Package]
siteCfg domain :: Package
domain =
	-- Debian pre-2.4
	[ "/etc/apache2/sites-available/" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain
	-- Debian 2.4+
	, "/etc/apache2/sites-available/" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ ".conf"
	]

-- | Configure apache to use SNI to differentiate between
-- https hosts.
--
-- This was off by default in apache 2.2.22. Newver versions enable
-- it by default. This property uses the filename used by the old version.
multiSSL :: Property DebianLike
multiSSL :: Property DebianLike
multiSSL = IO Bool -> Property DebianLike -> Property DebianLike
forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Package -> IO Bool
doesDirectoryExist "/etc/apache2/conf.d") (Property DebianLike -> Property DebianLike)
-> Property DebianLike -> Property DebianLike
forall a b. (a -> b) -> a -> b
$
	"/etc/apache2/conf.d/ssl" Package -> [Package] -> Property UnixLike
`File.hasContent`
		[ "NameVirtualHost *:443"
		, "SSLStrictSNIVHostCheck off"
		]
		Property UnixLike -> Package -> Property UnixLike
forall p. IsProp p => p -> Package -> p
`describe` "apache SNI enabled"
		Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded

-- | Config file fragment that can be inserted into a <Directory>
-- stanza to allow global read access to the directory.
--
-- Works with multiple versions of apache that have different ways to do
-- it.
allowAll :: ConfigLine
allowAll :: Package
allowAll = [Package] -> Package
unlines
	[ "<IfVersion < 2.4>"
	, "Order allow,deny"
	, "allow from all"
	, "</IfVersion>"
	, "<IfVersion >= 2.4>"
	, "Require all granted"
	, "</IfVersion>"
	]

-- | Config file fragment that can be inserted into a <VirtualHost>
-- stanza to allow apache to display directory index icons.
iconDir :: ConfigLine
iconDir :: Package
iconDir = [Package] -> Package
unlines
	[ "<Directory \"/usr/share/apache2/icons\">"
	, "Options Indexes MultiViews"
	, "AllowOverride None"
	, Package
allowAll
	, "  </Directory>"
	]

type WebRoot = FilePath

-- | A basic virtual host, publishing a directory, and logging to
-- the combined apache log file. Not https capable.
virtualHost :: Domain -> Port -> WebRoot -> RevertableProperty DebianLike DebianLike
virtualHost :: Package
-> Port -> Package -> RevertableProperty DebianLike DebianLike
virtualHost domain :: Package
domain port :: Port
port docroot :: Package
docroot = Package
-> Port
-> Package
-> [Package]
-> RevertableProperty DebianLike DebianLike
virtualHost' Package
domain Port
port Package
docroot []

-- | Like `virtualHost` but with additional config lines added.
virtualHost' :: Domain -> Port -> WebRoot -> [ConfigLine] -> RevertableProperty DebianLike DebianLike
virtualHost' :: Package
-> Port
-> Package
-> [Package]
-> RevertableProperty DebianLike DebianLike
virtualHost' domain :: Package
domain port :: Port
port docroot :: Package
docroot addedcfg :: [Package]
addedcfg = Package -> [Package] -> RevertableProperty DebianLike DebianLike
siteEnabled Package
domain ([Package] -> RevertableProperty DebianLike DebianLike)
-> [Package] -> RevertableProperty DebianLike DebianLike
forall a b. (a -> b) -> a -> b
$
	[ "<VirtualHost *:" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Port -> Package
forall t. ConfigurableValue t => t -> Package
val Port
port Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ ">"
	, "ServerName " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ ":" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Port -> Package
forall t. ConfigurableValue t => t -> Package
val Port
port
	, "DocumentRoot " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
docroot
	, "ErrorLog /var/log/apache2/error.log"
	, "LogLevel warn"
	, "CustomLog /var/log/apache2/access.log combined"
	, "ServerSignature On"
	]
	[Package] -> [Package] -> [Package]
forall a. [a] -> [a] -> [a]
++ [Package]
addedcfg [Package] -> [Package] -> [Package]
forall a. [a] -> [a] -> [a]
++
	[ "</VirtualHost>"
	]

-- | A virtual host using https, with the certificate obtained
-- using `Propellor.Property.LetsEncrypt.letsEncrypt`.
--
-- http connections are redirected to https.
--
-- Example:
--
-- > httpsVirtualHost "example.com" "/var/www"
-- > 	(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 DebianLike DebianLike
httpsVirtualHost :: Package
-> Package -> AgreeTOS -> RevertableProperty DebianLike DebianLike
httpsVirtualHost domain :: Package
domain docroot :: Package
docroot letos :: AgreeTOS
letos = Package
-> Package
-> AgreeTOS
-> [Package]
-> RevertableProperty DebianLike DebianLike
httpsVirtualHost' Package
domain Package
docroot AgreeTOS
letos []

-- | Like `httpsVirtualHost` but with additional config lines added.
httpsVirtualHost' :: Domain -> WebRoot -> LetsEncrypt.AgreeTOS -> [ConfigLine] -> RevertableProperty DebianLike DebianLike
httpsVirtualHost' :: Package
-> Package
-> AgreeTOS
-> [Package]
-> RevertableProperty DebianLike DebianLike
httpsVirtualHost' domain :: Package
domain docroot :: Package
docroot letos :: AgreeTOS
letos addedcfg :: [Package]
addedcfg = Property DebianLike
setup Property DebianLike
-> Property DebianLike -> RevertableProperty DebianLike DebianLike
forall setupmetatypes undometatypes.
Property setupmetatypes
-> Property undometatypes
-> RevertableProperty setupmetatypes undometatypes
<!> Property DebianLike
teardown
  where
	setup :: CombinedType (Property DebianLike) (Property DebianLike)
setup = Property DebianLike
setuphttp
		Property DebianLike
-> RevertableProperty DebianLike DebianLike
-> CombinedType
     (Property DebianLike) (RevertableProperty DebianLike DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Package -> RevertableProperty DebianLike DebianLike
modEnabled "rewrite"
		Property DebianLike
-> RevertableProperty DebianLike DebianLike
-> CombinedType
     (Property DebianLike) (RevertableProperty DebianLike DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Package -> RevertableProperty DebianLike DebianLike
modEnabled "ssl"
		Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`before` Property DebianLike
setuphttps
	teardown :: Property DebianLike
teardown = Package -> Property DebianLike
siteDisabled Package
domain
	setuphttp :: CombinedType (Property DebianLike) (Property UnixLike)
setuphttp = (Package -> [Package] -> Property DebianLike
siteEnabled' Package
domain ([Package] -> Property DebianLike)
-> [Package] -> Property DebianLike
forall a b. (a -> b) -> a -> b
$
		-- The sslconffile is only created after letsencrypt gets
		-- the cert. The "*" is needed to make apache not error
		-- when the file doesn't exist.
		("IncludeOptional " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package -> Package
sslconffile "*")
		Package -> [Package] -> [Package]
forall a. a -> [a] -> [a]
: Port -> [Package] -> [Package]
forall t. ConfigurableValue t => t -> [Package] -> [Package]
vhost (Int -> Port
Port 80)
			[ "RewriteEngine On"
			-- Pass through .well-known directory on http for the
			-- letsencrypt acme challenge.
			, "RewriteRule ^/.well-known/(.*) - [L]"
			-- Everything else redirects to https
			, "RewriteRule ^/(.*) https://" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ "/$1 [L,R,NE]"
			])
		Property DebianLike
-> Property UnixLike
-> CombinedType (Property DebianLike) (Property UnixLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Package -> Property UnixLike
File.dirExists (Package -> Package
takeDirectory Package
cf)
	setuphttps :: CombinedType (Property DebianLike) (Property DebianLike)
setuphttps = AgreeTOS -> Package -> Package -> Property DebianLike
LetsEncrypt.letsEncrypt AgreeTOS
letos Package
domain Package
docroot
		Property DebianLike
-> Property DebianLike
-> CombinedType (Property DebianLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
postsetuphttps
	postsetuphttps :: Property DebianLike
postsetuphttps = Package -> Props DebianLike -> Property DebianLike
forall k (metatypes :: k).
SingI metatypes =>
Package
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties (Package
domain Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ " ssl cert installed") (Props DebianLike -> Property DebianLike)
-> Props DebianLike -> Property DebianLike
forall a b. (a -> b) -> a -> b
$ Props UnixLike
props
		Props UnixLike
-> Property DebianLike
-> Props
     (MetaTypes
        (Combine
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
              'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]))
forall a p (y :: [a]) (x :: [a]).
(IsProp p, MetaTypes y ~ GetMetaTypes p,
 CheckCombinableNote x y (NoteFor ('Text "&"))) =>
Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
& Package -> [Package] -> Property UnixLike
File.hasContent Package
cf [Package]
sslvhost
			Property UnixLike
-> Property DebianLike
-> CombinedType (Property UnixLike) (Property DebianLike)
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
		-- always reload since the cert has changed
		Props DebianLike
-> Property DebianLike
-> Props
     (MetaTypes
        (Combine
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]))
forall a p (y :: [a]) (x :: [a]).
(IsProp p, MetaTypes y ~ GetMetaTypes p,
 CheckCombinableNote x y (NoteFor ('Text "&"))) =>
Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
& Property DebianLike
reloaded
	  where
		sslvhost :: [Package]
sslvhost = Port -> [Package] -> [Package]
forall t. ConfigurableValue t => t -> [Package] -> [Package]
vhost (Int -> Port
Port 443)
			[ "SSLEngine on"
			, "SSLCertificateFile " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package -> Package
LetsEncrypt.certFile Package
domain
			, "SSLCertificateKeyFile " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package -> Package
LetsEncrypt.privKeyFile Package
domain
			, "SSLCertificateChainFile " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package -> Package
LetsEncrypt.chainFile Package
domain
			]
	cf :: Package
cf = Package -> Package
sslconffile "letsencrypt"
	sslconffile :: Package -> Package
sslconffile s :: Package
s = "/etc/apache2/sites-available/ssl/" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ "/" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
s Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ ".conf"
	vhost :: t -> [Package] -> [Package]
vhost p :: t
p ls :: [Package]
ls =
		[ "<VirtualHost *:" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ t -> Package
forall t. ConfigurableValue t => t -> Package
val t
p Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++">"
		, "ServerName " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
domain Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ ":" Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ t -> Package
forall t. ConfigurableValue t => t -> Package
val t
p
		, "DocumentRoot " Package -> Package -> Package
forall a. [a] -> [a] -> [a]
++ Package
docroot
		, "ErrorLog /var/log/apache2/error.log"
		, "LogLevel warn"
		, "CustomLog /var/log/apache2/access.log combined"
		, "ServerSignature On"
		] [Package] -> [Package] -> [Package]
forall a. [a] -> [a] -> [a]
++ [Package]
ls [Package] -> [Package] -> [Package]
forall a. [a] -> [a] -> [a]
++ [Package]
addedcfg [Package] -> [Package] -> [Package]
forall a. [a] -> [a] -> [a]
++
		[ "</VirtualHost>"
		]