diff options
| author | Joey Hess <joeyh@joeyh.name> | 2016-04-02 15:33:48 -0400 |
|---|---|---|
| committer | Joey Hess <joeyh@joeyh.name> | 2016-04-02 15:33:48 -0400 |
| commit | dce7e7bd72fa82ef7461535288b53d89db807566 (patch) | |
| tree | cf97100b90cddfd988d069059222df4bb8459bc5 /src/Propellor/Property/SiteSpecific | |
| parent | beba93baede04835687e1caeefead24f173d9048 (diff) | |
| parent | 48608a48bd91743776cf3d4abb2172b806d4b917 (diff) | |
Merge branch 'joeyconfig'
Diffstat (limited to 'src/Propellor/Property/SiteSpecific')
| -rw-r--r-- | src/Propellor/Property/SiteSpecific/Branchable.hs | 2 | ||||
| -rw-r--r-- | src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs | 103 | ||||
| -rw-r--r-- | src/Propellor/Property/SiteSpecific/GitHome.hs | 11 | ||||
| -rw-r--r-- | src/Propellor/Property/SiteSpecific/IABak.hs | 13 | ||||
| -rw-r--r-- | src/Propellor/Property/SiteSpecific/JoeySites.hs | 231 |
5 files changed, 169 insertions, 191 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 +apacheSite :: HostName -> Apache.ConfigFile -> RevertableProperty DebianLike DebianLike +apacheSite hn middle = Apache.siteEnabled hn $ apachecfg hn middle -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" +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") - ] |
