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 [Package
"apache2"]
restarted :: Property DebianLike
restarted :: Property DebianLike
restarted = Package -> Property DebianLike
Service.restarted Package
"apache2"
reloaded :: Property DebianLike
reloaded :: Property DebianLike
reloaded = Package -> Property DebianLike
Service.reloaded Package
"apache2"
type ConfigLine = String
type ConfigFile = [ConfigLine]
siteEnabled :: Domain -> ConfigFile -> RevertableProperty DebianLike DebianLike
siteEnabled :: Package -> [Package] -> RevertableProperty DebianLike DebianLike
siteEnabled Package
domain [Package]
cf = Package -> [Package] -> Property DebianLike
siteEnabled' Package
domain [Package]
cf 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' Package
domain [Package]
cf = forall {k} (metatypes :: k).
SingI metatypes =>
Package
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties (Package
"apache site enabled " forall a. [a] -> [a] -> [a]
++ Package
domain) forall a b. (a -> b) -> a -> b
$ Props UnixLike
props
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
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
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))
& forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Bool -> Bool
not forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Bool
isenabled)
(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty Package
"a2ensite" [Package
"--quiet", Package
domain])
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
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 Package
"a2query" [Package -> CommandParam
Param Package
"-q", Package -> CommandParam
Param Package
"-s", Package -> CommandParam
Param Package
domain]
siteDisabled :: Domain -> Property DebianLike
siteDisabled :: Package -> Property DebianLike
siteDisabled Package
domain = forall {k} (metatypes :: k).
SingI metatypes =>
Package
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties
(Package
"apache site disabled " forall a. [a] -> [a] -> [a]
++ Package
domain)
(forall {k} (metatypes :: k).
[Property (MetaTypes metatypes)] -> Props (MetaTypes metatypes)
toProps forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Package -> Property UnixLike
File.notPresent (Package -> [Package]
siteCfg Package
domain))
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` (Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty Package
"a2dissite" [Package
"--quiet", Package
domain] forall (p :: * -> *) i.
Checkable p i =>
p i -> Result -> Property i
`assume` Result
MadeChange)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
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 Package
domain [Package]
cf = forall {k} (metatypes :: k).
SingI metatypes =>
Package
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties (Package
"apache site available " forall a. [a] -> [a] -> [a]
++ Package
domain) forall a b. (a -> b) -> a -> b
$
forall {k} (metatypes :: k).
[Property (MetaTypes metatypes)] -> Props (MetaTypes metatypes)
toProps forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall (p :: * -> *) (untightened :: [MetaType])
(tightened :: [MetaType]).
(TightenTargets p, TightenTargetsAllowed untightened tightened,
SingI tightened) =>
p (MetaTypes untightened) -> p (MetaTypes tightened)
tightenTargets forall a b. (a -> b) -> a -> b
$
forall a b. (a -> b) -> [a] -> [b]
map (Package -> [Package] -> Property UnixLike
`File.hasContent` (Package
commentforall a. a -> [a] -> [a]
:[Package]
cf)) (Package -> [Package]
siteCfg Package
domain)
where
comment :: Package
comment = Package
"# deployed with propellor, do not modify"
modEnabled :: String -> RevertableProperty DebianLike DebianLike
modEnabled :: Package -> RevertableProperty DebianLike DebianLike
modEnabled Package
modname = Property DebianLike
enable forall setupmetatypes undometatypes.
Property setupmetatypes
-> Property undometatypes
-> RevertableProperty setupmetatypes undometatypes
<!> Property DebianLike
disable
where
enable :: CombinedType (Property DebianLike) (Property DebianLike)
enable = forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Bool -> Bool
not forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Bool
isenabled)
(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty Package
"a2enmod" [Package
"--quiet", Package
modname])
forall p. IsProp p => p -> Package -> p
`describe` (Package
"apache module enabled " forall a. [a] -> [a] -> [a]
++ Package
modname)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
disable :: CombinedType (Property DebianLike) (Property DebianLike)
disable = forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check IO Bool
isenabled
(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty Package
"a2dismod" [Package
"--quiet", Package
modname])
forall p. IsProp p => p -> Package -> p
`describe` (Package
"apache module disabled " forall a. [a] -> [a] -> [a]
++ Package
modname)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
isenabled :: IO Bool
isenabled = Package -> [CommandParam] -> IO Bool
boolSystem Package
"a2query" [Package -> CommandParam
Param Package
"-q", Package -> CommandParam
Param Package
"-m", Package -> CommandParam
Param Package
modname]
confEnabled :: String -> RevertableProperty DebianLike DebianLike
confEnabled :: Package -> RevertableProperty DebianLike DebianLike
confEnabled Package
confname = Property DebianLike
enable forall setupmetatypes undometatypes.
Property setupmetatypes
-> Property undometatypes
-> RevertableProperty setupmetatypes undometatypes
<!> Property DebianLike
disable
where
enable :: CombinedType (Property DebianLike) (Property DebianLike)
enable = forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Bool -> Bool
not forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Bool
isenabled)
(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty Package
"a2enconf" [Package
"--quiet", Package
confname])
forall p. IsProp p => p -> Package -> p
`describe` (Package
"apache configuration enabled " forall a. [a] -> [a] -> [a]
++ Package
confname)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
disable :: CombinedType (Property DebianLike) (Property DebianLike)
disable = forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check IO Bool
isenabled
(Package -> [Package] -> UncheckedProperty UnixLike
cmdProperty Package
"a2disconf" [Package
"--quiet", Package
confname])
forall p. IsProp p => p -> Package -> p
`describe` (Package
"apache configuration disabled " forall a. [a] -> [a] -> [a]
++ Package
confname)
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
isenabled :: IO Bool
isenabled = Package -> [CommandParam] -> IO Bool
boolSystem Package
"a2query" [Package -> CommandParam
Param Package
"-q", Package -> CommandParam
Param Package
"-c", Package -> CommandParam
Param Package
confname]
listenPorts :: [Port] -> Property DebianLike
listenPorts :: [Port] -> Property DebianLike
listenPorts [Port]
ps = Package
"/etc/apache2/ports.conf" Package -> [Package] -> Property UnixLike
`File.hasContent` forall a b. (a -> b) -> [a] -> [b]
map forall {t}. ConfigurableValue t => t -> Package
portline [Port]
ps
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
restarted
where
portline :: t -> Package
portline t
port = Package
"Listen " forall a. [a] -> [a] -> [a]
++ forall {t}. ConfigurableValue t => t -> Package
val t
port
siteCfg :: Domain -> [FilePath]
siteCfg :: Package -> [Package]
siteCfg Package
domain =
[ Package
"/etc/apache2/sites-available/" forall a. [a] -> [a] -> [a]
++ Package
domain
, Package
"/etc/apache2/sites-available/" forall a. [a] -> [a] -> [a]
++ Package
domain forall a. [a] -> [a] -> [a]
++ Package
".conf"
]
multiSSL :: Property DebianLike
multiSSL :: Property DebianLike
multiSSL = forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Package -> IO Bool
doesDirectoryExist Package
"/etc/apache2/conf.d") forall a b. (a -> b) -> a -> b
$
Package
"/etc/apache2/conf.d/ssl" Package -> [Package] -> Property UnixLike
`File.hasContent`
[ Package
"NameVirtualHost *:443"
, Package
"SSLStrictSNIVHostCheck off"
]
forall p. IsProp p => p -> Package -> p
`describe` Package
"apache SNI enabled"
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
allowAll :: ConfigLine
allowAll :: Package
allowAll = [Package] -> Package
unlines
[ Package
"<IfVersion < 2.4>"
, Package
"Order allow,deny"
, Package
"allow from all"
, Package
"</IfVersion>"
, Package
"<IfVersion >= 2.4>"
, Package
"Require all granted"
, Package
"</IfVersion>"
]
iconDir :: ConfigLine
iconDir :: Package
iconDir = [Package] -> Package
unlines
[ Package
"<Directory \"/usr/share/apache2/icons\">"
, Package
"Options Indexes MultiViews"
, Package
"AllowOverride None"
, Package
allowAll
, Package
" </Directory>"
]
type WebRoot = FilePath
virtualHost :: Domain -> Port -> WebRoot -> RevertableProperty DebianLike DebianLike
virtualHost :: Package
-> Port -> Package -> RevertableProperty DebianLike DebianLike
virtualHost Package
domain Port
port Package
docroot = Package
-> Port
-> Package
-> [Package]
-> RevertableProperty DebianLike DebianLike
virtualHost' Package
domain Port
port Package
docroot []
virtualHost' :: Domain -> Port -> WebRoot -> [ConfigLine] -> RevertableProperty DebianLike DebianLike
virtualHost' :: Package
-> Port
-> Package
-> [Package]
-> RevertableProperty DebianLike DebianLike
virtualHost' Package
domain Port
port Package
docroot [Package]
addedcfg = Package -> [Package] -> RevertableProperty DebianLike DebianLike
siteEnabled Package
domain forall a b. (a -> b) -> a -> b
$
[ Package
"<VirtualHost *:" forall a. [a] -> [a] -> [a]
++ forall {t}. ConfigurableValue t => t -> Package
val Port
port forall a. [a] -> [a] -> [a]
++ Package
">"
, Package
"ServerName " forall a. [a] -> [a] -> [a]
++ Package
domain forall a. [a] -> [a] -> [a]
++ Package
":" forall a. [a] -> [a] -> [a]
++ forall {t}. ConfigurableValue t => t -> Package
val Port
port
, Package
"DocumentRoot " forall a. [a] -> [a] -> [a]
++ Package
docroot
, Package
"ErrorLog /var/log/apache2/error.log"
, Package
"LogLevel warn"
, Package
"CustomLog /var/log/apache2/access.log combined"
, Package
"ServerSignature On"
]
forall a. [a] -> [a] -> [a]
++ [Package]
addedcfg forall a. [a] -> [a] -> [a]
++
[ Package
"</VirtualHost>"
]
httpsVirtualHost :: Domain -> WebRoot -> LetsEncrypt.AgreeTOS -> RevertableProperty DebianLike DebianLike
httpsVirtualHost :: Package
-> Package -> AgreeTOS -> RevertableProperty DebianLike DebianLike
httpsVirtualHost Package
domain Package
docroot AgreeTOS
letos = Package
-> Package
-> AgreeTOS
-> [Package]
-> RevertableProperty DebianLike DebianLike
httpsVirtualHost' Package
domain Package
docroot AgreeTOS
letos []
httpsVirtualHost' :: Domain -> WebRoot -> LetsEncrypt.AgreeTOS -> [ConfigLine] -> RevertableProperty DebianLike DebianLike
httpsVirtualHost' :: Package
-> Package
-> AgreeTOS
-> [Package]
-> RevertableProperty DebianLike DebianLike
httpsVirtualHost' Package
domain Package
docroot AgreeTOS
letos [Package]
addedcfg = Property DebianLike
setup forall setupmetatypes undometatypes.
Property setupmetatypes
-> Property undometatypes
-> RevertableProperty setupmetatypes undometatypes
<!> Property DebianLike
teardown
where
setup :: CombinedType
(CombinedType
(Property DebianLike) (RevertableProperty DebianLike DebianLike))
(Property DebianLike)
setup = Property DebianLike
setuphttp
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Package -> RevertableProperty DebianLike DebianLike
modEnabled Package
"rewrite"
forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Package -> RevertableProperty DebianLike DebianLike
modEnabled Package
"ssl"
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 forall a b. (a -> b) -> a -> b
$
(Package
"IncludeOptional " forall a. [a] -> [a] -> [a]
++ Package -> Package
sslconffile Package
"*")
forall a. a -> [a] -> [a]
: forall {t}. ConfigurableValue t => t -> [Package] -> [Package]
vhost (Int -> Port
Port Int
80)
[ Package
"RewriteEngine On"
, Package
"RewriteRule ^/.well-known/(.*) - [L]"
, Package
"RewriteRule ^/(.*) https://" forall a. [a] -> [a] -> [a]
++ Package
domain forall a. [a] -> [a] -> [a]
++ Package
"/$1 [L,R,NE]"
])
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
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
postsetuphttps
postsetuphttps :: Property
(MetaTypes
(Combine
(Combine
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish])
'[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]))
postsetuphttps = forall {k} (metatypes :: k).
SingI metatypes =>
Package
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties (Package
domain forall a. [a] -> [a] -> [a]
++ Package
" ssl cert installed") forall a b. (a -> b) -> a -> b
$ Props UnixLike
props
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
forall x y. Combines x y => x -> y -> CombinedType x y
`onChange` Property DebianLike
reloaded
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 = forall {t}. ConfigurableValue t => t -> [Package] -> [Package]
vhost (Int -> Port
Port Int
443)
[ Package
"SSLEngine on"
, Package
"SSLCertificateFile " forall a. [a] -> [a] -> [a]
++ Package -> Package
LetsEncrypt.certFile Package
domain
, Package
"SSLCertificateKeyFile " forall a. [a] -> [a] -> [a]
++ Package -> Package
LetsEncrypt.privKeyFile Package
domain
, Package
"SSLCertificateChainFile " forall a. [a] -> [a] -> [a]
++ Package -> Package
LetsEncrypt.chainFile Package
domain
]
cf :: Package
cf = Package -> Package
sslconffile Package
"letsencrypt"
sslconffile :: Package -> Package
sslconffile Package
s = Package
"/etc/apache2/sites-available/ssl/" forall a. [a] -> [a] -> [a]
++ Package
domain forall a. [a] -> [a] -> [a]
++ Package
"/" forall a. [a] -> [a] -> [a]
++ Package
s forall a. [a] -> [a] -> [a]
++ Package
".conf"
vhost :: t -> [Package] -> [Package]
vhost t
p [Package]
ls =
[ Package
"<VirtualHost *:" forall a. [a] -> [a] -> [a]
++ forall {t}. ConfigurableValue t => t -> Package
val t
p forall a. [a] -> [a] -> [a]
++Package
">"
, Package
"ServerName " forall a. [a] -> [a] -> [a]
++ Package
domain forall a. [a] -> [a] -> [a]
++ Package
":" forall a. [a] -> [a] -> [a]
++ forall {t}. ConfigurableValue t => t -> Package
val t
p
, Package
"DocumentRoot " forall a. [a] -> [a] -> [a]
++ Package
docroot
, Package
"ErrorLog /var/log/apache2/error.log"
, Package
"LogLevel warn"
, Package
"CustomLog /var/log/apache2/access.log combined"
, Package
"ServerSignature On"
] forall a. [a] -> [a] -> [a]
++ [Package]
ls forall a. [a] -> [a] -> [a]
++ [Package]
addedcfg forall a. [a] -> [a] -> [a]
++
[ Package
"</VirtualHost>"
]