summaryrefslogtreecommitdiff
path: root/src/Propellor/Property/SiteSpecific
diff options
context:
space:
mode:
Diffstat (limited to 'src/Propellor/Property/SiteSpecific')
-rw-r--r--src/Propellor/Property/SiteSpecific/Branchable.hs2
-rw-r--r--src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs103
-rw-r--r--src/Propellor/Property/SiteSpecific/GitHome.hs11
-rw-r--r--src/Propellor/Property/SiteSpecific/IABak.hs13
-rw-r--r--src/Propellor/Property/SiteSpecific/JoeySites.hs233
5 files changed, 170 insertions, 192 deletions
diff --git a/src/Propellor/Property/SiteSpecific/Branchable.hs b/src/Propellor/Property/SiteSpecific/Branchable.hs
index 5c85610b..239bcbeb 100644
--- a/src/Propellor/Property/SiteSpecific/Branchable.hs
+++ b/src/Propellor/Property/SiteSpecific/Branchable.hs
@@ -9,7 +9,7 @@ import qualified Propellor.Property.Postfix as Postfix
import qualified Propellor.Property.Gpg as Gpg
import qualified Propellor.Property.Sudo as Sudo
-server :: [Host] -> Property HasInfo
+server :: [Host] -> Property (HasInfo + DebianLike)
server hosts = propertyList "branchable server" $ props
& "/etc/timezone" `File.hasContent` ["Etc/UTC"]
& "/etc/locale.gen" `File.containsLines`
diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs
index 2932baf7..ce89b94a 100644
--- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs
+++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs
@@ -25,7 +25,7 @@ builddir = gitbuilderdir </> "build"
type TimeOut = String -- eg, 5h
-autobuilder :: Architecture -> Times -> TimeOut -> Property HasInfo
+autobuilder :: Architecture -> Times -> TimeOut -> Property (HasInfo + DebianLike)
autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props
& Apt.serviceInstalledRunning "cron"
& Cron.niceJob "gitannexbuilder" crontimes (User builduser) gitbuilderdir
@@ -37,6 +37,7 @@ autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props
-- The builduser account does not have a password set,
-- instead use the password privdata to hold the rsync server
-- password used to upload the built image.
+ rsyncpassword :: Property (HasInfo + DebianLike)
rsyncpassword = withPrivData (Password builduser) context $ \getpw ->
property "rsync password" $ getpw $ \pw -> do
have <- liftIO $ catchDefaultIO "" $
@@ -46,7 +47,7 @@ autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props
then makeChange $ writeFile pwfile want
else noChange
-tree :: Architecture -> Flavor -> Property HasInfo
+tree :: Architecture -> Flavor -> Property DebianLike
tree buildarch flavor = combineProperties "gitannexbuilder tree" $ props
& Apt.installed ["git"]
& File.dirExists gitbuilderdir
@@ -66,14 +67,14 @@ tree buildarch flavor = combineProperties "gitannexbuilder tree" $ props
[ "git clone git://git-annex.branchable.com/ " ++ builddir
]
-buildDepsApt :: Property HasInfo
+buildDepsApt :: Property DebianLike
buildDepsApt = combineProperties "gitannexbuilder build deps" $ props
& Apt.buildDep ["git-annex"]
& buildDepsNoHaskellLibs
& Apt.buildDepIn builddir
`describe` "git-annex source build deps installed"
-buildDepsNoHaskellLibs :: Property NoInfo
+buildDepsNoHaskellLibs :: Property DebianLike
buildDepsNoHaskellLibs = Apt.installed
["git", "rsync", "moreutils", "ca-certificates",
"debhelper", "ghc", "curl", "openssh-client", "git-remote-gcrypt",
@@ -83,8 +84,9 @@ buildDepsNoHaskellLibs = Apt.installed
"libmagic-dev", "alex", "happy", "c2hs"
]
-haskellPkgsInstalled :: String -> Property NoInfo
-haskellPkgsInstalled dir = flagFile go ("/haskellpkgsinstalled")
+haskellPkgsInstalled :: String -> Property DebianLike
+haskellPkgsInstalled dir = tightenTargets $
+ flagFile go ("/haskellpkgsinstalled")
where
go = userScriptProperty (User builduser)
[ "cd " ++ builddir ++ " && ./standalone/" ++ dir ++ "/install-haskell-packages"
@@ -93,7 +95,7 @@ haskellPkgsInstalled dir = flagFile go ("/haskellpkgsinstalled")
-- Installs current versions of git-annex's deps from cabal, but only
-- does so once.
-cabalDeps :: Property NoInfo
+cabalDeps :: Property UnixLike
cabalDeps = flagFile go cabalupdated
where
go = userScriptProperty (User builduser)
@@ -101,20 +103,20 @@ cabalDeps = flagFile go cabalupdated
`assume` MadeChange
cabalupdated = homedir </> ".cabal" </> "packages" </> "hackage.haskell.org" </> "00-index.cache"
-autoBuilderContainer :: (System -> Flavor -> Property HasInfo) -> System -> Flavor -> Times -> TimeOut -> Systemd.Container
-autoBuilderContainer mkprop osver@(System _ arch) flavor crontime timeout =
- Systemd.container name osver (Chroot.debootstrapped mempty)
- & mkprop osver flavor
+autoBuilderContainer :: (DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)) -> DebianSuite -> Architecture -> Flavor -> Times -> TimeOut -> Systemd.Container
+autoBuilderContainer mkprop suite arch flavor crontime timeout =
+ Systemd.container name $ \d -> Chroot.debootstrapped mempty d $ props
+ & mkprop suite arch flavor
& autobuilder arch crontime timeout
where
name = arch ++ fromMaybe "" flavor ++ "-git-annex-builder"
type Flavor = Maybe String
-standardAutoBuilder :: System -> Flavor -> Property HasInfo
-standardAutoBuilder osver@(System _ arch) flavor =
+standardAutoBuilder :: DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)
+standardAutoBuilder suite arch flavor =
propertyList "standard git-annex autobuilder" $ props
- & os osver
+ & osDebian suite arch
& buildDepsApt
& Apt.stdSourcesList
& Apt.unattendedUpgrades
@@ -122,10 +124,10 @@ standardAutoBuilder osver@(System _ arch) flavor =
& User.accountFor (User builduser)
& tree arch flavor
-stackAutoBuilder :: System -> Flavor -> Property HasInfo
-stackAutoBuilder osver@(System _ arch) flavor =
+stackAutoBuilder :: DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)
+stackAutoBuilder suite arch flavor =
propertyList "git-annex autobuilder using stack" $ props
- & os osver
+ & osDebian suite arch
& buildDepsNoHaskellLibs
& Apt.stdSourcesList
& Apt.unattendedUpgrades
@@ -134,34 +136,34 @@ stackAutoBuilder osver@(System _ arch) flavor =
& tree arch flavor
& stackInstalled
-stackInstalled :: Property NoInfo
-stackInstalled = withOS "stack installed" $ \o ->
+stackInstalled :: Property Linux
+stackInstalled = withOS "stack installed" $ \w o ->
case o of
(Just (System (Debian (Stable "jessie")) "i386")) ->
- ensureProperty $ manualinstall "i386"
- _ -> ensureProperty $ Apt.installed ["haskell-stack"]
+ ensureProperty w $ manualinstall "i386"
+ _ -> ensureProperty w $ Apt.installed ["haskell-stack"]
where
-- Warning: Using a binary downloaded w/o validation.
- manualinstall arch = check (not <$> doesFileExist binstack) $
- propertyList "stack installed from upstream tarball"
- [ cmdProperty "wget" ["https://www.stackage.org/stack/linux-" ++ arch, "-O", tmptar]
+ manualinstall :: Architecture -> Property Linux
+ manualinstall arch = tightenTargets $ check (not <$> doesFileExist binstack) $
+ propertyList "stack installed from upstream tarball" $ props
+ & cmdProperty "wget" ["https://www.stackage.org/stack/linux-" ++ arch, "-O", tmptar]
`assume` MadeChange
- , File.dirExists tmpdir
- , cmdProperty "tar" ["xf", tmptar, "-C", tmpdir, "--strip-components=1"]
+ & File.dirExists tmpdir
+ & cmdProperty "tar" ["xf", tmptar, "-C", tmpdir, "--strip-components=1"]
`assume` MadeChange
- , cmdProperty "mv" [tmpdir </> "stack", binstack]
+ & cmdProperty "mv" [tmpdir </> "stack", binstack]
`assume` MadeChange
- , cmdProperty "rm" ["-rf", tmpdir, tmptar]
+ & cmdProperty "rm" ["-rf", tmpdir, tmptar]
`assume` MadeChange
- ]
binstack = "/usr/bin/stack"
tmptar = "/root/stack.tar.gz"
tmpdir = "/root/stack"
-armAutoBuilder :: System -> Flavor -> Property HasInfo
-armAutoBuilder osver flavor =
+armAutoBuilder :: DebianSuite -> Architecture -> Flavor -> Property (HasInfo + Debian)
+armAutoBuilder suite arch flavor =
propertyList "arm git-annex autobuilder" $ props
- & standardAutoBuilder osver flavor
+ & standardAutoBuilder suite arch flavor
& buildDepsNoHaskellLibs
-- Works around ghc crash with parallel builds on arm.
& (homedir </> ".cabal" </> "config")
@@ -172,26 +174,30 @@ armAutoBuilder osver flavor =
androidAutoBuilderContainer :: Times -> TimeOut -> Systemd.Container
androidAutoBuilderContainer crontimes timeout =
- androidContainer "android-git-annex-builder" (tree "android" Nothing) builddir
- & Apt.unattendedUpgrades
- & buildDepsNoHaskellLibs
- & autobuilder "android" crontimes timeout
+ androidAutoBuilderContainer' "android-git-annex-builder"
+ (tree "android" Nothing) builddir crontimes timeout
-- Android is cross-built in a Debian i386 container, using the Android NDK.
-androidContainer
- :: (IsProp (Property (CInfo NoInfo i)), (Combines (Property NoInfo) (Property i)))
- => Systemd.MachineName
- -> Property i
+androidAutoBuilderContainer'
+ :: Systemd.MachineName
+ -> Property DebianLike
-> FilePath
+ -> Times
+ -> TimeOut
-> Systemd.Container
-androidContainer name setupgitannexdir gitannexdir = Systemd.container name osver bootstrap
- & Apt.stdSourcesList
- & User.accountFor (User builduser)
- & File.dirExists gitbuilderdir
- & File.ownerGroup homedir (User builduser) (Group builduser)
- & flagFile chrootsetup ("/chrootsetup")
- `requires` setupgitannexdir
- & haskellPkgsInstalled "android"
+androidAutoBuilderContainer' name setupgitannexdir gitannexdir crontimes timeout =
+ Systemd.container name $ \d -> bootstrap d $ props
+ & osDebian (Stable "jessie") "i386"
+ & Apt.stdSourcesList
+ & User.accountFor (User builduser)
+ & File.dirExists gitbuilderdir
+ & File.ownerGroup homedir (User builduser) (Group builduser)
+ & flagFile chrootsetup ("/chrootsetup")
+ `requires` setupgitannexdir
+ & haskellPkgsInstalled "android"
+ & Apt.unattendedUpgrades
+ & buildDepsNoHaskellLibs
+ & autobuilder "android" crontimes timeout
where
-- Use git-annex's android chroot setup script, which will install
-- ghc-android and the NDK, all build deps, etc, in the home
@@ -200,5 +206,4 @@ androidContainer name setupgitannexdir gitannexdir = Systemd.container name osve
[ "cd " ++ gitannexdir ++ " && ./standalone/android/buildchroot-inchroot"
]
`assume` MadeChange
- osver = System (Debian (Stable "jessie")) "i386"
bootstrap = Chroot.debootstrapped mempty
diff --git a/src/Propellor/Property/SiteSpecific/GitHome.hs b/src/Propellor/Property/SiteSpecific/GitHome.hs
index 83a1a16a..f14b5f12 100644
--- a/src/Propellor/Property/SiteSpecific/GitHome.hs
+++ b/src/Propellor/Property/SiteSpecific/GitHome.hs
@@ -5,14 +5,15 @@ import qualified Propellor.Property.Apt as Apt
import Propellor.Property.User
-- | Clones Joey Hess's git home directory, and runs its fixups script.
-installedFor :: User -> Property NoInfo
+installedFor :: User -> Property DebianLike
installedFor user@(User u) = check (not <$> hasGitDir user) $
- property ("githome " ++ u) (go =<< liftIO (homedir user))
- `requires` Apt.installed ["git"]
+ go `requires` Apt.installed ["git"]
where
- go home = do
+ go :: Property DebianLike
+ go = property' ("githome " ++ u) $ \w -> do
+ home <- liftIO (homedir user)
let tmpdir = home </> "githome"
- ensureProperty $ combineProperties "githome setup"
+ ensureProperty w $ combineProperties "githome setup" $ toProps
[ userScriptProperty user ["git clone " ++ url ++ " " ++ tmpdir]
`assume` MadeChange
, property "moveout" $ makeChange $ void $
diff --git a/src/Propellor/Property/SiteSpecific/IABak.hs b/src/Propellor/Property/SiteSpecific/IABak.hs
index bb62fba7..b245e444 100644
--- a/src/Propellor/Property/SiteSpecific/IABak.hs
+++ b/src/Propellor/Property/SiteSpecific/IABak.hs
@@ -15,14 +15,14 @@ repo = "https://github.com/ArchiveTeam/IA.BAK/"
userrepo :: String
userrepo = "git@gitlab.com:archiveteam/IA.bak.users.git"
-publicFace :: Property HasInfo
+publicFace :: Property DebianLike
publicFace = propertyList "iabak public face" $ props
& Git.cloned (User "root") repo "/usr/local/IA.BAK" (Just "server")
& Apt.serviceInstalledRunning "apache2"
& Cron.niceJob "graph-gen" (Cron.Times "*/10 * * * *") (User "root") "/"
"/usr/local/IA.BAK/web/graph-gen.sh"
-gitServer :: [Host] -> Property HasInfo
+gitServer :: [Host] -> Property (HasInfo + DebianLike)
gitServer knownhosts = propertyList "iabak git server" $ props
& Git.cloned (User "root") repo "/usr/local/IA.BAK" (Just "server")
& Git.cloned (User "root") repo "/usr/local/IA.BAK/client" (Just "master")
@@ -42,7 +42,7 @@ gitServer knownhosts = propertyList "iabak git server" $ props
"/usr/local/IA.BAK"
"./expireemailer"
-registrationServer :: [Host] -> Property HasInfo
+registrationServer :: [Host] -> Property (HasInfo + DebianLike)
registrationServer knownhosts = propertyList "iabak registration server" $ props
& User.accountFor (User "registrar")
& Ssh.userKeys (User "registrar") (Context "IA.bak.users.git") sshKeys
@@ -66,7 +66,7 @@ sshKeys =
[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCoiE+CPiIQyfWnl/E9iKG3eo4QzlH30vi7xAgKolGaTu6qKy4XPtl+8MNm2Dqn9QEYRVyyOT/XH0yP5dRc6uyReT8dBy03MmLkVbj8Q+nKCz5YOMTxrY3sX6RRXU1zVGjeVd0DtC+rKRT7reoCxef42LAJTm8nCyZu/enAuso5qHqBbqulFz2YXEKfU1SEEXLawtvgGck1KmCyg+pqazeI1eHWXrojQf5isTBKfPQLWVppBkWAf5cA4wP5U1vN9dVirIdw66ds1M8vnGlkTBjxP/HLGBWGYhZHE7QXjXRsk2RIXlHN9q6GdNu8+F3HXS22mst47E4UAeRoiXSMMtF5")
]
-graphiteServer :: Property HasInfo
+graphiteServer :: Property (HasInfo + DebianLike)
graphiteServer = propertyList "iabak graphite server" $ props
& Apt.serviceInstalledRunning "apache2"
& Apt.installed ["libapache2-mod-wsgi", "graphite-carbon", "graphite-web"]
@@ -114,7 +114,8 @@ graphiteServer = propertyList "iabak graphite server" $ props
, "</VirtualHost>"
]
where
+ graphiteCSRF :: Property (HasInfo + DebianLike)
graphiteCSRF = withPrivData (Password "csrf-token") (Context "iabak.archiveteam.org") $
- \gettoken -> property "graphite-web CSRF token" $
- gettoken $ \token -> ensureProperty $ File.containsLine
+ \gettoken -> property' "graphite-web CSRF token" $ \w ->
+ gettoken $ \token -> ensureProperty w $ File.containsLine
"/etc/graphite/local_settings.py" ("SECRET_KEY = '"++ privDataVal token ++"'")
diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs
index 03f2efcb..a6cb3794 100644
--- a/src/Propellor/Property/SiteSpecific/JoeySites.hs
+++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs
@@ -1,6 +1,8 @@
-- | Specific configuration for Joey Hess's sites. Probably not useful to
-- others except as an example.
+{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
+
module Propellor.Property.SiteSpecific.JoeySites where
import Propellor.Base
@@ -18,13 +20,14 @@ import qualified Propellor.Property.Apache as Apache
import qualified Propellor.Property.Postfix as Postfix
import qualified Propellor.Property.Systemd as Systemd
import qualified Propellor.Property.Fail2Ban as Fail2Ban
+import qualified Propellor.Property.LetsEncrypt as LetsEncrypt
import Utility.FileMode
import Data.List
import System.Posix.Files
import Data.String.Utils
-scrollBox :: Property HasInfo
+scrollBox :: Property (HasInfo + DebianLike)
scrollBox = propertyList "scroll server" $ props
& User.accountFor (User "scroll")
& Git.cloned (User "scroll") "git://git.kitenet.net/scroll" (d </> "scroll") Nothing
@@ -94,16 +97,12 @@ scrollBox = propertyList "scroll server" $ props
s = d </> "login.sh"
g = d </> "game.sh"
-oldUseNetServer :: [Host] -> Property HasInfo
+oldUseNetServer :: [Host] -> Property (HasInfo + DebianLike)
oldUseNetServer hosts = propertyList "olduse.net server" $ props
& Apt.installed ["leafnode"]
& oldUseNetInstalled "oldusenet-server"
& oldUseNetBackup
- & check (not . isSymbolicLink <$> getSymbolicLinkStatus newsspool)
- (property "olduse.net spool in place" $ makeChange $ do
- removeDirectoryRecursive newsspool
- createSymbolicLink (datadir </> "news") newsspool
- )
+ & spoolsymlink
& "/etc/news/leafnode/config" `File.hasContent`
[ "# olduse.net configuration (deployed by propellor)"
, "expire = 1000000" -- no expiry via texpire
@@ -127,7 +126,7 @@ oldUseNetServer hosts = propertyList "olduse.net server" $ props
, "find -type d -empty | xargs --no-run-if-empty rmdir"
]
uucpcommand = "/usr/bin/uucp " ++ datadir
- nntpcfg = apachecfg "nntp.olduse.net" False
+ nntpcfg = apachecfg "nntp.olduse.net"
[ " DocumentRoot " ++ datadir ++ "/"
, " <Directory " ++ datadir ++ "/>"
, " Options Indexes FollowSymlinks"
@@ -135,7 +134,15 @@ oldUseNetServer hosts = propertyList "olduse.net server" $ props
, Apache.allowAll
, " </Directory>"
]
+
+ spoolsymlink :: Property UnixLike
+ spoolsymlink = check (not . isSymbolicLink <$> getSymbolicLinkStatus newsspool)
+ (property "olduse.net spool in place" $ makeChange $ do
+ removeDirectoryRecursive newsspool
+ createSymbolicLink (datadir </> "news") newsspool
+ )
+ oldUseNetBackup :: Property (HasInfo + DebianLike)
oldUseNetBackup = Obnam.backup datadir (Cron.Times "33 4 * * *")
[ "--repository=sftp://2318@usw-s002.rsync.net/~/olduse.net"
, "--client-name=spool"
@@ -149,12 +156,12 @@ oldUseNetServer hosts = propertyList "olduse.net server" $ props
`requires` Ssh.knownHost hosts "usw-s002.rsync.net" (User "root")
keyfile = "/root/.ssh/olduse.net.key"
-oldUseNetShellBox :: Property HasInfo
+oldUseNetShellBox :: Property DebianLike
oldUseNetShellBox = propertyList "olduse.net shellbox" $ props
& oldUseNetInstalled "oldusenet"
& Service.running "shellinabox"
-oldUseNetInstalled :: Apt.Package -> Property HasInfo
+oldUseNetInstalled :: Apt.Package -> Property DebianLike
oldUseNetInstalled pkg = check (not <$> Apt.isInstalled pkg) $
propertyList ("olduse.net " ++ pkg) $ props
& Apt.installed (words "build-essential devscripts debhelper git libncursesw5-dev libpcre3-dev pkg-config bison libicu-dev libidn11-dev libcanlock2-dev libuu-dev ghc libghc-strptime-dev libghc-hamlet-dev libghc-ifelse-dev libghc-hxt-dev libghc-utf8-string-dev libghc-missingh-dev libghc-sha-dev")
@@ -170,25 +177,25 @@ oldUseNetInstalled pkg = check (not <$> Apt.isInstalled pkg) $
]
`assume` MadeChange
`describe` "olduse.net built"
-
-kgbServer :: Property HasInfo
+
+kgbServer :: Property (HasInfo + Debian)
kgbServer = propertyList desc $ props
& installed
& File.hasPrivContent "/etc/kgb-bot/kgb.conf" anyContext
`onChange` Service.restarted "kgb-bot"
where
desc = "kgb.kitenet.net setup"
- installed = withOS desc $ \o -> case o of
+ installed :: Property Debian
+ installed = withOS desc $ \w o -> case o of
(Just (System (Debian Unstable) _)) ->
- ensureProperty $ propertyList desc
- [ Apt.serviceInstalledRunning "kgb-bot"
- , "/etc/default/kgb-bot" `File.containsLine` "BOT_ENABLED=1"
+ ensureProperty w $ propertyList desc $ props
+ & Apt.serviceInstalledRunning "kgb-bot"
+ & "/etc/default/kgb-bot" `File.containsLine` "BOT_ENABLED=1"
`describe` "kgb bot enabled"
`onChange` Service.running "kgb-bot"
- ]
_ -> error "kgb server needs Debian unstable (for kgb-bot 1.31+)"
-mumbleServer :: [Host] -> Property HasInfo
+mumbleServer :: [Host] -> Property (HasInfo + DebianLike)
mumbleServer hosts = combineProperties hn $ props
& Apt.serviceInstalledRunning "mumble-server"
& Obnam.backup "/var/lib/mumble-server" (Cron.Times "55 5 * * *")
@@ -209,7 +216,7 @@ mumbleServer hosts = combineProperties hn $ props
sshkey = "/root/.ssh/mumble.debian.net.key"
-- git.kitenet.net and git.joeyh.name
-gitServer :: [Host] -> Property HasInfo
+gitServer :: [Host] -> Property (HasInfo + DebianLike)
gitServer hosts = propertyList "git.kitenet.net setup" $ props
& Obnam.backupEncrypted "/srv/git" (Cron.Times "33 3 * * *")
[ "--repository=sftp://2318@usw-s002.rsync.net/~/git.kitenet.net"
@@ -246,14 +253,14 @@ gitServer hosts = propertyList "git.kitenet.net setup" $ props
& Apache.modEnabled "cgi"
where
sshkey = "/root/.ssh/git.kitenet.net.key"
- website hn = apacheSite hn True
- [ " DocumentRoot /srv/web/git.kitenet.net/"
+ website hn = Apache.httpsVirtualHost' hn "/srv/web/git.kitenet.net/" letos
+ [ Apache.iconDir
, " <Directory /srv/web/git.kitenet.net/>"
, " Options Indexes ExecCGI FollowSymlinks"
, " AllowOverride None"
, " AddHandler cgi-script .cgi"
, " DirectoryIndex index.cgi"
- , Apache.allowAll
+ , Apache.allowAll
, " </Directory>"
, ""
, " ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/"
@@ -266,7 +273,7 @@ gitServer hosts = propertyList "git.kitenet.net setup" $ props
type AnnexUUID = String
-- | A website, with files coming from a git-annex repository.
-annexWebSite :: Git.RepoUrl -> HostName -> AnnexUUID -> [(String, Git.RepoUrl)] -> Property HasInfo
+annexWebSite :: Git.RepoUrl -> HostName -> AnnexUUID -> [(String, Git.RepoUrl)] -> Property (HasInfo + DebianLike)
annexWebSite origin hn uuid remotes = propertyList (hn ++" website using git-annex") $ props
& Git.cloned (User "joey") origin dir Nothing
`onChange` setup
@@ -290,65 +297,44 @@ annexWebSite origin hn uuid remotes = propertyList (hn ++" website using git-ann
, "git update-server-info"
]
addremote (name, url) = "git remote add " ++ shellEscape name ++ " " ++ shellEscape url
- setupapache = apacheSite hn True
+ setupapache = Apache.httpsVirtualHost' hn dir letos
[ " ServerAlias www."++hn
- , ""
- , " DocumentRoot /srv/web/"++hn
- , " <Directory /srv/web/"++hn++">"
- , " Options FollowSymLinks"
- , " AllowOverride None"
- , Apache.allowAll
- , " </Directory>"
- , " <Directory /srv/web/"++hn++">"
+ , Apache.iconDir
+ , " <Directory "++dir++">"
, " Options Indexes FollowSymLinks ExecCGI"
, " AllowOverride None"
, " AddHandler cgi-script .cgi"
, " DirectoryIndex index.html index.cgi"
- , Apache.allowAll
+ , Apache.allowAll
, " </Directory>"
]
-apacheSite :: HostName -> Bool -> Apache.ConfigFile -> RevertableProperty NoInfo
-apacheSite hn withssl middle = Apache.siteEnabled hn $ apachecfg hn withssl middle
+letos :: LetsEncrypt.AgreeTOS
+letos = LetsEncrypt.AgreeTOS (Just "id@joeyh.name")
-apachecfg :: HostName -> Bool -> Apache.ConfigFile -> Apache.ConfigFile
-apachecfg hn withssl middle
- | withssl = vhost False ++ vhost True
- | otherwise = vhost False
- where
- vhost ssl =
- [ "<VirtualHost *:"++show port++">"
- , " ServerAdmin grue@joeyh.name"
- , " ServerName "++hn++":"++show port
- ]
- ++ mainhttpscert ssl
- ++ middle ++
- [ ""
- , " ErrorLog /var/log/apache2/error.log"
- , " LogLevel warn"
- , " CustomLog /var/log/apache2/access.log combined"
- , " ServerSignature On"
- , " "
- , " <Directory \"/usr/share/apache2/icons\">"
- , " Options Indexes MultiViews"
- , " AllowOverride None"
- , Apache.allowAll
- , " </Directory>"
- , "</VirtualHost>"
- ]
- where
- port = if ssl then 443 else 80 :: Int
-
-mainhttpscert :: Bool -> Apache.ConfigFile
-mainhttpscert False = []
-mainhttpscert True =
- [ " SSLEngine on"
- , " SSLCertificateFile /etc/ssl/certs/web.pem"
- , " SSLCertificateKeyFile /etc/ssl/private/web.pem"
- , " SSLCertificateChainFile /etc/ssl/certs/startssl.pem"
+apacheSite :: HostName -> Apache.ConfigFile -> RevertableProperty DebianLike DebianLike
+apacheSite hn middle = Apache.siteEnabled hn $ apachecfg hn middle
+
+apachecfg :: HostName -> Apache.ConfigFile -> Apache.ConfigFile
+apachecfg hn middle =
+ [ "<VirtualHost *:"++show port++">"
+ , " ServerAdmin grue@joeyh.name"
+ , " ServerName "++hn++":"++show port
+ ]
+ ++ middle ++
+ [ ""
+ , " ErrorLog /var/log/apache2/error.log"
+ , " LogLevel warn"
+ , " CustomLog /var/log/apache2/access.log combined"
+ , " ServerSignature On"
+ , " "
+ , Apache.iconDir
+ , "</VirtualHost>"
]
+ where
+ port = 80 :: Int
-gitAnnexDistributor :: Property HasInfo
+gitAnnexDistributor :: Property (HasInfo + DebianLike)
gitAnnexDistributor = combineProperties "git-annex distributor, including rsync server and signer" $ props
& Apt.installed ["rsync"]
& File.hasPrivContent "/etc/rsyncd.conf" (Context "git-annex distributor")
@@ -364,19 +350,18 @@ gitAnnexDistributor = combineProperties "git-annex distributor, including rsync
-- git-annex distribution signing key
& Gpg.keyImported (Gpg.GpgKeyId "89C809CB") (User "joey")
where
- endpoint d = combineProperties ("endpoint " ++ d)
- [ File.dirExists d
- , File.ownerGroup d (User "joey") (Group "joey")
- ]
+ endpoint d = combineProperties ("endpoint " ++ d) $ props
+ & File.dirExists d
+ & File.ownerGroup d (User "joey") (Group "joey")
-downloads :: [Host] -> Property HasInfo
+downloads :: [Host] -> Property (HasInfo + DebianLike)
downloads hosts = annexWebSite "/srv/git/downloads.git"
"downloads.kitenet.net"
"840760dc-08f0-11e2-8c61-576b7e66acfd"
[("eubackup", "ssh://eubackup.kitenet.net/~/lib/downloads/")]
`requires` Ssh.knownHost hosts "eubackup.kitenet.net" (User "joey")
-tmp :: Property HasInfo
+tmp :: Property (HasInfo + DebianLike)
tmp = propertyList "tmp.kitenet.net" $ props
& annexWebSite "/srv/git/joey/tmp.git"
"tmp.kitenet.net"
@@ -386,7 +371,7 @@ tmp = propertyList "tmp.kitenet.net" $ props
& pumpRss
-- Twitter, you kill us.
-twitRss :: Property HasInfo
+twitRss :: Property DebianLike
twitRss = combineProperties "twitter rss" $ props
& Git.cloned (User "joey") "git://git.kitenet.net/twitrss.git" dir Nothing
& check (not <$> doesFileExist (dir </> "twitRss")) compiled
@@ -409,11 +394,11 @@ twitRss = combineProperties "twitter rss" $ props
]
-- Work around for expired ssl cert.
-pumpRss :: Property NoInfo
+pumpRss :: Property DebianLike
pumpRss = Cron.job "pump rss" (Cron.Times "15 * * * *") (User "joey") "/srv/web/tmp.kitenet.net/"
"wget https://rss.io.jpope.org/feed/joeyh@identi.ca.atom -O pump.atom.new --no-check-certificate 2>/dev/null; sed 's/ & / /g' pump.atom.new > pump.atom"
-ircBouncer :: Property HasInfo
+ircBouncer :: Property (HasInfo + DebianLike)
ircBouncer = propertyList "IRC bouncer" $ props
& Apt.installed ["znc"]
& User.accountFor (User "znc")
@@ -428,20 +413,19 @@ ircBouncer = propertyList "IRC bouncer" $ props
where
conf = "/home/znc/.znc/configs/znc.conf"
-kiteShellBox :: Property NoInfo
-kiteShellBox = propertyList "kitenet.net shellinabox"
- [ Apt.installed ["openssl", "shellinabox", "openssh-client"]
- , File.hasContent "/etc/default/shellinabox"
+kiteShellBox :: Property DebianLike
+kiteShellBox = propertyList "kitenet.net shellinabox" $ props
+ & Apt.installed ["openssl", "shellinabox", "openssh-client"]
+ & File.hasContent "/etc/default/shellinabox"
[ "# Deployed by propellor"
, "SHELLINABOX_DAEMON_START=1"
, "SHELLINABOX_PORT=443"
, "SHELLINABOX_ARGS=\"--no-beep --service=/:SSH:kitenet.net\""
]
`onChange` Service.restarted "shellinabox"
- , Service.running "shellinabox"
- ]
+ & Service.running "shellinabox"
-githubBackup :: Property HasInfo
+githubBackup :: Property (HasInfo + DebianLike)
githubBackup = propertyList "github-backup box" $ props
& Apt.installed ["github-backup", "moreutils"]
& githubKeys
@@ -462,7 +446,7 @@ githubBackup = propertyList "github-backup box" $ props
] ++ map gitriddance githubMirrors
gitriddance (r, msg) = "(cd " ++ r ++ " && gitriddance " ++ shellEscape msg ++ ")"
-githubKeys :: Property HasInfo
+githubKeys :: Property (HasInfo + UnixLike)
githubKeys =
let f = "/home/joey/.github-keys"
in File.hasPrivContent f anyContext
@@ -482,12 +466,12 @@ githubMirrors =
where
plzuseurl u = "Please submit changes to " ++ u ++ " instead of using github pull requests, which are not part of my workflow. Just open a todo item there and link to a git repository containing your changes. Did you know, git is a distributed system? The git repository doesn't even need to be on github! Please send any complaints to Github; they don't allow turning off pull requests or redirecting them elsewhere. -- A robot acting on behalf of Joey Hess"
-rsyncNetBackup :: [Host] -> Property NoInfo
+rsyncNetBackup :: [Host] -> Property DebianLike
rsyncNetBackup hosts = Cron.niceJob "rsync.net copied in daily" (Cron.Times "30 5 * * *")
(User "joey") "/home/joey/lib/backup" "mkdir -p rsync.net && rsync --delete -az 2318@usw-s002.rsync.net: rsync.net"
`requires` Ssh.knownHost hosts "usw-s002.rsync.net" (User "joey")
-backupsBackedupFrom :: [Host] -> HostName -> FilePath -> Property NoInfo
+backupsBackedupFrom :: [Host] -> HostName -> FilePath -> Property DebianLike
backupsBackedupFrom hosts srchost destdir = Cron.niceJob desc
(Cron.Times "@reboot") (User "joey") "/" cmd
`requires` Ssh.knownHost hosts srchost (User "joey")
@@ -495,9 +479,9 @@ backupsBackedupFrom hosts srchost destdir = Cron.niceJob desc
desc = "backups copied from " ++ srchost ++ " on boot"
cmd = "sleep 30m && rsync -az --bwlimit=300K --partial --delete " ++ srchost ++ ":lib/backup/ " ++ destdir </> srchost
-obnamRepos :: [String] -> Property NoInfo
-obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs)
- (mkbase : map mkrepo rs)
+obnamRepos :: [String] -> Property UnixLike
+obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs) $
+ toProps (mkbase : map mkrepo rs)
where
mkbase = mkdir "/home/joey/lib/backup"
`requires` mkdir "/home/joey/lib"
@@ -505,13 +489,13 @@ obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs)
mkdir d = File.dirExists d
`before` File.ownerGroup d (User "joey") (Group "joey")
-podcatcher :: Property NoInfo
+podcatcher :: Property DebianLike
podcatcher = Cron.niceJob "podcatcher run hourly" (Cron.Times "55 * * * *")
(User "joey") "/home/joey/lib/sound/podcasts"
"xargs git-annex importfeed -c annex.genmetadata=true < feeds; mr --quiet update"
`requires` Apt.installed ["git-annex", "myrepos"]
-kiteMailServer :: Property HasInfo
+kiteMailServer :: Property (HasInfo + DebianLike)
kiteMailServer = propertyList "kitenet.net mail server" $ props
& Postfix.installed
& Apt.installed ["postfix-pcre"]
@@ -710,7 +694,7 @@ kiteMailServer = propertyList "kitenet.net mail server" $ props
-- Configures postfix to relay outgoing mail to kitenet.net, with
-- verification via tls cert.
-postfixClientRelay :: Context -> Property HasInfo
+postfixClientRelay :: Context -> Property (HasInfo + DebianLike)
postfixClientRelay ctx = Postfix.mainCfFile `File.containsLines`
-- Using smtps not smtp because more networks firewall smtp
[ "relayhost = kitenet.net:smtps"
@@ -727,7 +711,7 @@ postfixClientRelay ctx = Postfix.mainCfFile `File.containsLines`
`requires` hasPostfixCert ctx
-- Configures postfix to have the dkim milter, and no other milters.
-dkimMilter :: Property HasInfo
+dkimMilter :: Property (HasInfo + DebianLike)
dkimMilter = Postfix.mainCfFile `File.containsLines`
[ "smtpd_milters = inet:localhost:8891"
, "non_smtpd_milters = inet:localhost:8891"
@@ -740,7 +724,7 @@ dkimMilter = Postfix.mainCfFile `File.containsLines`
-- This does not configure postfix to use the dkim milter,
-- nor does it set up domainkey DNS.
-dkimInstalled :: Property HasInfo
+dkimInstalled :: Property (HasInfo + DebianLike)
dkimInstalled = go `onChange` Service.restarted "opendkim"
where
go = propertyList "opendkim installed" $ props
@@ -763,36 +747,25 @@ dkimInstalled = go `onChange` Service.restarted "opendkim"
domainKey :: (BindDomain, Record)
domainKey = (RelDomain "mail._domainkey", TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCc+/rfzNdt5DseBBmfB3C6sVM7FgVvf4h1FeCfyfwPpVcmPdW6M2I+NtJsbRkNbEICxiP6QY2UM0uoo9TmPqLgiCCG2vtuiG6XMsS0Y/gGwqKM7ntg/7vT1Go9vcquOFFuLa5PnzpVf8hB9+PMFdS4NPTvWL2c5xxshl/RJzICnQIDAQAB")
-hasJoeyCAChain :: Property HasInfo
+hasJoeyCAChain :: Property (HasInfo + UnixLike)
hasJoeyCAChain = "/etc/ssl/certs/joeyca.pem" `File.hasPrivContentExposed`
Context "joeyca.pem"
-hasPostfixCert :: Context -> Property HasInfo
-hasPostfixCert ctx = combineProperties "postfix tls cert installed"
- [ "/etc/ssl/certs/postfix.pem" `File.hasPrivContentExposed` ctx
- , "/etc/ssl/private/postfix.pem" `File.hasPrivContent` ctx
- ]
-
-kitenetHttps :: Property HasInfo
-kitenetHttps = propertyList "kitenet.net https certs" $ props
- & File.hasPrivContent "/etc/ssl/certs/web.pem" ctx
- & File.hasPrivContent "/etc/ssl/private/web.pem" ctx
- & File.hasPrivContent "/etc/ssl/certs/startssl.pem" ctx
- & Apache.modEnabled "ssl"
- where
- ctx = Context "kitenet.net"
+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
+legacyWebSites :: Property (HasInfo + DebianLike)
legacyWebSites = propertyList "legacy web sites" $ props
& Apt.serviceInstalledRunning "apache2"
& Apache.modEnabled "rewrite"
& Apache.modEnabled "cgi"
& Apache.modEnabled "speling"
& userDirHtml
- & kitenetHttps
- & apacheSite "kitenet.net" True
+ & Apache.httpsVirtualHost' "kitenet.net" "/var/www" letos
-- /var/www is empty
[ "DocumentRoot /var/www"
, "<Directory /var/www>"
@@ -880,7 +853,7 @@ legacyWebSites = propertyList "legacy web sites" $ props
, "rewriterule /~kyle/family/wiki(.*) http://macleawiki.branchable.com$1 [L]"
]
& alias "anna.kitenet.net"
- & apacheSite "anna.kitenet.net" False
+ & apacheSite "anna.kitenet.net"
[ "DocumentRoot /home/anna/html"
, "<Directory /home/anna/html/>"
, " Options Indexes ExecCGI"
@@ -890,7 +863,7 @@ legacyWebSites = propertyList "legacy web sites" $ props
]
& alias "sows-ear.kitenet.net"
& alias "www.sows-ear.kitenet.net"
- & apacheSite "sows-ear.kitenet.net" False
+ & apacheSite "sows-ear.kitenet.net"
[ "ServerAlias www.sows-ear.kitenet.net"
, "DocumentRoot /srv/web/sows-ear.kitenet.net"
, "<Directory /srv/web/sows-ear.kitenet.net>"
@@ -903,7 +876,7 @@ legacyWebSites = propertyList "legacy web sites" $ props
]
& alias "wortroot.kitenet.net"
& alias "www.wortroot.kitenet.net"
- & apacheSite "wortroot.kitenet.net" False
+ & apacheSite "wortroot.kitenet.net"
[ "ServerAlias www.wortroot.kitenet.net"
, "DocumentRoot /srv/web/wortroot.kitenet.net"
, "<Directory /srv/web/wortroot.kitenet.net>"
@@ -913,7 +886,7 @@ legacyWebSites = propertyList "legacy web sites" $ props
, "</Directory>"
]
& alias "creeksidepress.com"
- & apacheSite "creeksidepress.com" False
+ & apacheSite "creeksidepress.com"
[ "ServerAlias www.creeksidepress.com"
, "DocumentRoot /srv/web/www.creeksidepress.com"
, "<Directory /srv/web/www.creeksidepress.com>"
@@ -923,7 +896,7 @@ legacyWebSites = propertyList "legacy web sites" $ props
, "</Directory>"
]
& alias "joey.kitenet.net"
- & apacheSite "joey.kitenet.net" False
+ & apacheSite "joey.kitenet.net"
[ "DocumentRoot /var/www"
, "<Directory /var/www/>"
, " Options Indexes ExecCGI"
@@ -944,7 +917,7 @@ legacyWebSites = propertyList "legacy web sites" $ props
, "rewriterule (.*) http://joeyh.name$1 [r]"
]
-userDirHtml :: Property NoInfo
+userDirHtml :: Property DebianLike
userDirHtml = File.fileProperty "apache userdir is html" (map munge) conf
`onChange` Apache.reloaded
`requires` Apache.modEnabled "userdir"
@@ -956,10 +929,9 @@ userDirHtml = File.fileProperty "apache userdir is html" (map munge) conf
-- <http://joeyh.name/blog/entry/a_programmable_alarm_clock_using_systemd/>
--
-- oncalendar example value: "*-*-* 7:30"
-alarmClock :: String -> User -> String -> Property NoInfo
-alarmClock oncalendar (User user) command = combineProperties
- "goodmorning timer installed"
- [ "/etc/systemd/system/goodmorning.timer" `File.hasContent`
+alarmClock :: String -> User -> String -> Property DebianLike
+alarmClock oncalendar (User user) command = combineProperties "goodmorning timer installed" $ props
+ & "/etc/systemd/system/goodmorning.timer" `File.hasContent`
[ "[Unit]"
, "Description=good morning"
, ""
@@ -974,7 +946,7 @@ alarmClock oncalendar (User user) command = combineProperties
]
`onChange` (Systemd.daemonReloaded
`before` Systemd.restarted "goodmorning.timer")
- , "/etc/systemd/system/goodmorning.service" `File.hasContent`
+ & "/etc/systemd/system/goodmorning.service" `File.hasContent`
[ "[Unit]"
, "Description=good morning"
, "RefuseManualStart=true"
@@ -987,8 +959,7 @@ alarmClock oncalendar (User user) command = combineProperties
, "ExecStart=/bin/systemd-inhibit --what=handle-lid-switch --why=goodmorning /bin/su " ++ user ++ " -c \"" ++ command ++ "\""
]
`onChange` Systemd.daemonReloaded
- , Systemd.enabled "goodmorning.timer"
- , Systemd.started "goodmorning.timer"
- , "/etc/systemd/logind.conf" `ConfFile.containsIniSetting`
+ & Systemd.enabled "goodmorning.timer"
+ & Systemd.started "goodmorning.timer"
+ & "/etc/systemd/logind.conf" `ConfFile.containsIniSetting`
("Login", "LidSwitchIgnoreInhibited", "no")
- ]