summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config-joey.hs155
-rw-r--r--debian/changelog13
-rw-r--r--privdata/privdata.gpg1180
-rw-r--r--propellor.cabal2
-rw-r--r--src/Propellor/Info.hs19
-rw-r--r--src/Propellor/Property/Apache.hs38
-rw-r--r--src/Propellor/Property/Cron.hs36
-rw-r--r--src/Propellor/Property/File.hs30
-rw-r--r--src/Propellor/Property/Hostname.hs24
-rw-r--r--src/Propellor/Property/Obnam.hs4
-rw-r--r--src/Propellor/Property/Postfix.hs110
-rw-r--r--src/Propellor/Property/SiteSpecific/JoeySites.hs388
-rw-r--r--src/Propellor/Types/Info.hs4
13 files changed, 1459 insertions, 544 deletions
diff --git a/config-joey.hs b/config-joey.hs
index 18f0a32b..b9a2bed2 100644
--- a/config-joey.hs
+++ b/config-joey.hs
@@ -8,6 +8,7 @@ import qualified Propellor.Property.File as File
import qualified Propellor.Property.Apt as Apt
import qualified Propellor.Property.Network as Network
import qualified Propellor.Property.Ssh as Ssh
+import qualified Propellor.Property.Gpg as Gpg
import qualified Propellor.Property.Cron as Cron
import qualified Propellor.Property.Sudo as Sudo
import qualified Propellor.Property.User as User
@@ -22,6 +23,7 @@ import qualified Propellor.Property.Apache as Apache
import qualified Propellor.Property.Postfix as Postfix
import qualified Propellor.Property.Service as Service
import qualified Propellor.Property.Grub as Grub
+import qualified Propellor.Property.Obnam as Obnam
import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean
import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost
import qualified Propellor.Property.HostingProvider.Linode as Linode
@@ -41,7 +43,7 @@ hosts = -- (o) `
& Apt.buildDep ["git-annex"] `period` Daily
& Docker.configured
- & Docker.docked hosts "android-git-annex"
+ ! Docker.docked hosts "android-git-annex"
, standardSystem "clam.kitenet.net" Unstable "amd64"
[ "Unreliable server. Anything here may be lost at any time!" ]
@@ -61,38 +63,70 @@ hosts = -- (o) `
[ "Main git-annex build box." ]
& ipv4 "138.38.108.179"
- & Hostname.sane
& Apt.unattendedUpgrades
& Postfix.satellite
& Docker.configured
& Docker.docked hosts "amd64-git-annex-builder"
& Docker.docked hosts "i386-git-annex-builder"
- & Docker.docked hosts "armel-git-annex-builder-companion"
- & Docker.docked hosts "armel-git-annex-builder"
& Docker.docked hosts "android-git-annex-builder"
+ -- not currently working
+ ! Docker.docked hosts "armel-git-annex-builder-companion"
+ ! Docker.docked hosts "armel-git-annex-builder"
& Docker.garbageCollected `period` Daily
& Apt.buildDep ["git-annex"] `period` Daily
- , standardSystem "kite.kitenet.net" Unstable "amd64"
+ -- This is not a complete description of kite, since it's a
+ -- multiuser system with eg, user passwords that are not deployed
+ -- with propellor.
+ , standardSystemUnhardened "kite.kitenet.net" Unstable "amd64"
[ "Welcome to the new kitenet.net server!"
, "This is still under construction and not yet live.."
]
& ipv4 "66.228.36.95"
& ipv6 "2600:3c03::f03c:91ff:fe73:b0d2"
+ -- & alias "kitenet.net" -- not yet live!
& Apt.installed ["linux-image-amd64"]
& Linode.chainPVGrub 5
- & Hostname.sane
& Apt.unattendedUpgrades
& Apt.installed ["systemd"]
& Ssh.hostKeys (Context "kitenet.net")
-
+ -- Since ssh password authentication is allowed:
+ & Apt.serviceInstalledRunning "fail2ban"
+ & Obnam.backup "/" "33 1 * * *"
+ [ "--repository=sftp://joey@eubackup.kitenet.net/~/lib/backup/kite.obnam"
+ , "--client-name=kitenet.net"
+ , "--encrypt-with="
+ , "--exclude=/var/cache"
+ , "--exclude=/var/tmp"
+ , "--exclude=/home/joey/lib"
+ , "--exclude=.*/tmp/"
+ , "--one-file-system"
+ ] Obnam.OnlyClient
+ `requires` Gpg.keyImported "98147487" "root"
+ `requires` Ssh.keyImported SshRsa "root"
+ (Context "kite.kitenet.net")
+ `requires` Ssh.knownHost hosts "eubackup.kitenet.net" "root"
+
+ -- & alias "smtp.kitenet.net" -- not yet live!
+ -- & alias "imap.kitenet.net" -- not yet live!
+ -- & alias "mail.kitenet.net" -- not yet live!
+ & JoeySites.kiteMailServer
+
+ & JoeySites.legacyWebSites
+
+ & Apt.installed
+ ["git-annex", "myrepos"
+ , "build-essential", "make"
+ -- Some users have zsh as their login shell.
+ , "zsh"
+ ]
+
, standardSystem "diatom.kitenet.net" Stable "amd64"
[ "Important stuff that needs not too much memory or CPU." ]
& ipv4 "107.170.31.195"
& DigitalOcean.distroKernel
- & Hostname.sane
& Ssh.hostKeys (Context "diatom.kitenet.net")
& Apt.unattendedUpgrades
& Apt.serviceInstalledRunning "ntp"
@@ -103,10 +137,7 @@ hosts = -- (o) `
& Apt.serviceInstalledRunning "swapspace"
& Apt.serviceInstalledRunning "apache2"
- & File.hasPrivContent "/etc/ssl/certs/web.pem" (Context "kitenet.net")
- & File.hasPrivContent "/etc/ssl/private/web.pem" (Context "kitenet.net")
- & File.hasPrivContent "/etc/ssl/certs/startssl.pem" (Context "kitenet.net")
- & Apache.modEnabled "ssl"
+ & JoeySites.kitenetHttps
& Apache.multiSSL
& File.ownerGroup "/srv/web" "joey" "joey"
& Apt.installed ["analog"]
@@ -116,14 +147,16 @@ hosts = -- (o) `
& JoeySites.gitServer hosts
& alias "downloads.kitenet.net"
- & JoeySites.annexWebSite hosts "/srv/git/downloads.git"
+ & JoeySites.annexWebSite "/srv/git/downloads.git"
"downloads.kitenet.net"
"840760dc-08f0-11e2-8c61-576b7e66acfd"
- [("turtle", "ssh://turtle.kitenet.net/~/lib/downloads/")]
+ [("usbackup", "ssh://usbackup.kitenet.net/~/lib/downloads/")]
+ `requires` Ssh.keyImported SshRsa "joey" (Context "downloads.kitenet.net")
+ `requires` Ssh.knownHost hosts "usbackup.kitenet.net" "joey"
& JoeySites.gitAnnexDistributor
& alias "tmp.kitenet.net"
- & JoeySites.annexWebSite hosts "/srv/git/joey/tmp.git"
+ & JoeySites.annexWebSite "/srv/git/joey/tmp.git"
"tmp.kitenet.net"
"26fd6e38-1226-11e2-a75f-ff007033bdba"
[]
@@ -148,25 +181,28 @@ hosts = -- (o) `
, let ctx = Context "elephant.kitenet.net"
in standardSystem "elephant.kitenet.net" Unstable "amd64"
- [ "Storage, big data, and backups, omnomnom!" ]
+ [ "Storage, big data, and backups, omnomnom!"
+ , "(Encrypt all data stored here.)"
+ ]
& ipv4 "193.234.225.114"
& Grub.chainPVGrub "hd0,0" "xen/xvda1" 30
- & Hostname.sane
& Postfix.satellite
& Apt.unattendedUpgrades
& Ssh.hostKeys ctx
+ & sshPubKey "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAJkoPRhUGT8EId6m37uBdYEtq42VNwslKnc9mmO+89ody066q6seHKeFY6ImfwjcyIjM30RTzEwftuVNQnbEB0="
& Ssh.keyImported SshRsa "joey" ctx
& Apt.serviceInstalledRunning "swapspace"
& alias "eubackup.kitenet.net"
& Apt.installed ["obnam", "sshfs", "rsync"]
+ & JoeySites.obnamRepos ["wren", "pell", "kite"]
& JoeySites.githubBackup
- & JoeySites.obnamRepos ["wren", "pell"]
- & Ssh.knownHost hosts "usw-s002.rsync.net" "joey"
+ & JoeySites.rsyncNetBackup hosts
+ & JoeySites.backupsBackedupTo hosts "usbackup.kitenet.net" "lib/backup/eubackup"
& alias "podcatcher.kitenet.net"
- & Apt.installed ["git-annex"]
+ & JoeySites.podcatcher
& alias "znc.kitenet.net"
& JoeySites.ircBouncer
@@ -201,9 +237,9 @@ hosts = -- (o) `
`onChange` Service.restarted "ssh"
-- temp
- & Docker.docked hosts "amd64-git-annex-builder"
- & Docker.docked hosts "i386-git-annex-builder"
- & Docker.docked hosts "android-git-annex-builder"
+ ! Docker.docked hosts "amd64-git-annex-builder"
+ ! Docker.docked hosts "i386-git-annex-builder"
+ ! Docker.docked hosts "android-git-annex-builder"
--' __|II| ,.
@@ -261,8 +297,17 @@ type Motd = [String]
-- This is my standard system setup.
standardSystem :: HostName -> DebianSuite -> Architecture -> Motd -> Host
-standardSystem hn suite arch motd = host hn
+standardSystem hn suite arch motd = standardSystemUnhardened hn suite arch motd
+ -- Harden the system, but only once root's authorized_keys
+ -- is safely in place.
+ & check (Ssh.hasAuthorizedKeys "root")
+ (Ssh.passwordAuthentication False)
+
+standardSystemUnhardened :: HostName -> DebianSuite -> Architecture -> Motd -> Host
+standardSystemUnhardened hn suite arch motd = host hn
& os (System (Debian suite) arch)
+ & Hostname.sane
+ & Hostname.searchDomain
& File.hasContent "/etc/motd" ("":motd++[""])
& Apt.stdSourcesList `onChange` Apt.upgrade
& Apt.cacheCleaned
@@ -270,10 +315,6 @@ standardSystem hn suite arch motd = host hn
& Apt.installed ["ssh"]
& GitHome.installedFor "root"
& User.hasSomePassword "root" (Context hn)
- -- Harden the system, but only once root's authorized_keys
- -- is safely in place.
- & check (Ssh.hasAuthorizedKeys "root")
- (Ssh.passwordAuthentication False)
& User.accountFor "joey"
& User.hasSomePassword "joey" (Context hn)
& Sudo.enabledFor "joey"
@@ -350,6 +391,7 @@ monsters = -- but do want to track their public keys etc.
& ipv4 "67.223.19.96"
& ipv6 "2001:4978:f:2d9::2"
& alias "backup.kitenet.net"
+ & alias "usbackup.kitenet.net"
& sshPubKey "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAokMXQiX/NZjA1UbhMdgAscnS5dsmy+Q7bWrQ6tsTZ/o+6N/T5cbjoBHOdpypXJI3y/PiJTDJaQtXIhLa8gFg/EvxMnMz/KG9skADW1361JmfCc4BxicQIO2IOOe6eilPr+YsnOwiHwL0vpUnuty39cppuMWVD25GzxXlS6KQsLCvXLzxLLuNnGC43UAM0q4UwQxDtAZEK1dH2o3HMWhgMP2qEQupc24dbhpO3ecxh2C9678a3oGDuDuNf7mLp3s7ptj5qF3onitpJ82U5o7VajaHoygMaSRFeWxP2c13eM57j3bLdLwxVXFhePcKXARu1iuFTLS5uUf3hN6MkQcOGw=="
, host "wren.kitenet.net"
& ipv4 "80.68.85.49"
@@ -359,37 +401,46 @@ monsters = -- but do want to track their public keys etc.
& alias "ftp.kitenet.net"
& alias "mail.kitenet.net"
& alias "smtp.kitenet.net"
- & alias "sows-ear.kitenet.net"
- & alias "www.sows-ear.kitenet.net"
- & alias "wortroot.kitenet.net"
- & alias "www.wortroot.kitenet.net"
- & alias "joey.kitenet.net"
- & alias "anna.kitenet.net"
& alias "bitlbee.kitenet.net"
{- Remaining services on kite:
+ -
+ - / = ready to go on kite.kitenet.net
-
- mail
- - postfix
- - postgrey
+ - /postfix
+ - /postgrey
- mailman
- - spamassassin
- - sqwebmail
- - courier
- - imap
- - tls
- - apache
- - some static websites
- - bitlbee
- - prosody
- - (used by daddy's git-annex)
- - named
- - (branchable is still pushing to here
- - (thinking it's ns2.branchable.com), but it's no
- - longer a primary or secondary for anything)
+ - /spamassassin
+ - sqwebmail (cannot use this with dovecot, alternatives?)
+ - /imap server
+ - /pop server
+ - /apache
+ - (need to re-rsync /srv/web to new kite.kitenet.net
+ - server before decommissioning)
+ - bitlbee (EOL?)
+ - prosody (EOL?)
- ftpd (EOL)
-
- - user shell stuff:
- - pine, zsh, make, git-annex, myrepos, ...
+ - Pre-transition:
+ - - re-rsync /home (skip ~joey and .pine*)
+ -
+ - Transition plan:
+ - - on darkstar: offlineimap run & disable cron job
+ - & move offlineimap files to tmp
+ - - take down wren pstfix, imap, pop servers
+ - - log all users out of wren
+ - - final /home rsync (skip ~joey and .pine*)
+ - - rsync /var/mail
+ - - rsync mailman and mailman list archives dirs
+ - - switch kitenet.net dns and enable pop.kitenet.net etc aliass
+ - - point wren.kitenet.net at kite.kitenet.net temporarily
+ - (make real-wren.kitenet.net alias)
+ - - reconfigure errol's email client to use new server
+ - - re-run offlinimap against new server
+ - - test mail
+ - - test virus filtering
+ - - test http://kitenet.net/~kyle/ (user home dirs)
+ - - migrate user cron jobs
-}
, host "mouse.kitenet.net"
& ipv6 "2001:4830:1600:492::2"
diff --git a/debian/changelog b/debian/changelog
index 54923662..29dec10c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,16 @@
+propellor (0.8.2) unstable; urgency=medium
+
+ * Fix bug in File.containsLines that caused lines that were already in the
+ file to sometimes be appended to the end.
+ * Hostname.sane also configures /etc/mailname.
+ * Fixed Postfix.satellite to really configure relayhost = smtp.domain.
+ * Avoid reconfiguring postfix unncessarily when it already has a relayhost.
+ * Deal with apache 2.4's change in the name of site-available config files.
+ * Hostname aliases can now be used in several places, including --spin
+ and Ssh.knownHost.
+
+ -- Joey Hess <joeyh@debian.org> Mon, 04 Aug 2014 01:12:19 -0400
+
propellor (0.8.1) unstable; urgency=medium
* Run apt-get update in initial bootstrap.
diff --git a/privdata/privdata.gpg b/privdata/privdata.gpg
index afafeee5..f8c08d86 100644
--- a/privdata/privdata.gpg
+++ b/privdata/privdata.gpg
@@ -1,439 +1,749 @@
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
-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
-7pa2HSH3ZFmSC8g5gt5ZA3TSQv8iY/7xD5cMsbk=
-=6HOm
+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
+o6jRkc4=
+=fEUC
-----END PGP MESSAGE-----
diff --git a/propellor.cabal b/propellor.cabal
index 50067b8d..878113c1 100644
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -1,5 +1,5 @@
Name: propellor
-Version: 0.8.1
+Version: 0.8.2
Cabal-Version: >= 1.6
License: BSD3
Maintainer: Joey Hess <joey@kitenet.net>
diff --git a/src/Propellor/Info.hs b/src/Propellor/Info.hs
index 00f1b0e9..1b89c008 100644
--- a/src/Propellor/Info.hs
+++ b/src/Propellor/Info.hs
@@ -43,11 +43,15 @@ ipv6 = addDNS . Address . IPv6
-- problems with CNAMEs, and also means that when multiple hosts have the
-- same alias, a DNS round-robin is automatically set up.
alias :: Domain -> Property
-alias = addDNS . CNAME . AbsDomain
+alias d = pureInfoProperty ("alias " ++ d) $ mempty
+ { _aliases = S.singleton d
+ -- A CNAME is added here, but the DNS setup code converts it to an
+ -- IP address when that makes sense.
+ , _dns = S.singleton $ CNAME $ AbsDomain d
+ }
addDNS :: Record -> Property
-addDNS r = pureInfoProperty (rdesc r) $
- mempty { _dns = S.singleton r }
+addDNS r = pureInfoProperty (rdesc r) $ mempty { _dns = S.singleton r }
where
rdesc (CNAME d) = unwords ["alias", ddesc d]
rdesc (Address (IPv4 addr)) = unwords ["ipv4", addr]
@@ -71,8 +75,15 @@ getSshPubKey = askInfo _sshPubKey
hostMap :: [Host] -> M.Map HostName Host
hostMap l = M.fromList $ zip (map hostName l) l
+aliasMap :: [Host] -> M.Map HostName Host
+aliasMap = M.fromList . concat .
+ map (\h -> map (\aka -> (aka, h)) $ S.toList $ _aliases $ hostInfo h)
+
findHost :: [Host] -> HostName -> Maybe Host
-findHost l hn = M.lookup hn (hostMap l)
+findHost l hn = maybe (findAlias l hn) Just (M.lookup hn (hostMap l))
+
+findAlias :: [Host] -> HostName -> Maybe Host
+findAlias l hn = M.lookup hn (aliasMap l)
getAddresses :: Info -> [IPAddr]
getAddresses = mapMaybe getIPAddr . S.toList . _dns
diff --git a/src/Propellor/Property/Apache.hs b/src/Propellor/Property/Apache.hs
index cf3e62cc..e6930893 100644
--- a/src/Propellor/Property/Apache.hs
+++ b/src/Propellor/Property/Apache.hs
@@ -10,20 +10,21 @@ type ConfigFile = [String]
siteEnabled :: HostName -> ConfigFile -> RevertableProperty
siteEnabled hn cf = RevertableProperty enable disable
where
- enable = trivial $ cmdProperty "a2ensite" ["--quiet", hn]
+ enable = trivial (cmdProperty "a2ensite" ["--quiet", hn])
`describe` ("apache site enabled " ++ hn)
`requires` siteAvailable hn cf
`requires` installed
`onChange` reloaded
- disable = trivial $ File.notPresent (siteCfg hn)
- `describe` ("apache site disabled " ++ hn)
+ disable = trivial $ combineProperties
+ ("apache site disabled " ++ hn)
+ (map File.notPresent (siteCfg hn))
`onChange` cmdProperty "a2dissite" ["--quiet", hn]
`requires` installed
`onChange` reloaded
siteAvailable :: HostName -> ConfigFile -> Property
-siteAvailable hn cf = siteCfg hn `File.hasContent` (comment:cf)
- `describe` ("apache site available " ++ hn)
+siteAvailable hn cf = combineProperties ("apache site available " ++ hn) $
+ map (`File.hasContent` (comment:cf)) (siteCfg hn)
where
comment = "# deployed with propellor, do not modify"
@@ -39,8 +40,15 @@ modEnabled modname = RevertableProperty enable disable
`requires` installed
`onChange` reloaded
-siteCfg :: HostName -> FilePath
-siteCfg hn = "/etc/apache2/sites-available/" ++ hn
+-- This is a list of config files because different versions of apache
+-- use different filenames. Propellor simply writen them all.
+siteCfg :: HostName -> [FilePath]
+siteCfg hn =
+ -- Debian pre-2.4
+ [ "/etc/apache2/sites-available/" ++ hn
+ -- Debian 2.4+
+ , "/etc/apache2/sites-available/" ++ hn ++ ".conf"
+ ]
installed :: Property
installed = Apt.installed ["apache2"]
@@ -60,3 +68,19 @@ multiSSL = "/etc/apache2/conf.d/ssl" `File.hasContent`
]
`describe` "apache SNI enabled"
`onChange` 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 :: String
+allowAll = unlines
+ [ "<IfVersion < 2.4>"
+ , "Order allow,deny"
+ , "allow from all"
+ , "</IfVersion>"
+ , "<IfVersion >= 2.4>"
+ , "Require all granted"
+ , "</IfVersion>"
+ ]
diff --git a/src/Propellor/Property/Cron.hs b/src/Propellor/Property/Cron.hs
index 5b070eff..d55c3dbb 100644
--- a/src/Propellor/Property/Cron.hs
+++ b/src/Propellor/Property/Cron.hs
@@ -4,6 +4,7 @@ import Propellor
import qualified Propellor.Property.File as File
import qualified Propellor.Property.Apt as Apt
import Utility.SafeCommand
+import Utility.FileMode
import Data.Char
@@ -19,22 +20,33 @@ type CronTimes = String
--
-- The cron job's output will only be emailed if it exits nonzero.
job :: Desc -> CronTimes -> UserName -> FilePath -> String -> Property
-job desc times user cddir command = cronjobfile `File.hasContent`
- [ "# Generated by propellor"
- , ""
- , "SHELL=/bin/sh"
- , "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
- , ""
- , times ++ "\t" ++ user ++ "\t"
- ++ "chronic flock -n " ++ shellEscape cronjobfile
- ++ " sh -c " ++ shellEscape cmdline
+job desc times user cddir command = combineProperties ("cronned " ++ desc)
+ [ cronjobfile `File.hasContent`
+ [ "# Generated by propellor"
+ , ""
+ , "SHELL=/bin/sh"
+ , "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
+ , ""
+ , times ++ "\t" ++ user ++ "\tchronic " ++ shellEscape scriptfile
+ ]
+ -- Use a separate script because it makes the cron job name
+ -- prettier in emails, and also allows running the job manually.
+ , scriptfile `File.hasContent`
+ [ "#!/bin/sh"
+ , "# Generated by propellor"
+ , "set -e"
+ , "flock -n " ++ shellEscape cronjobfile
+ ++ " sh -c " ++ shellEscape cmdline
+ ]
+ , scriptfile `File.mode` combineModes (readModes ++ executeModes)
]
`requires` Apt.serviceInstalledRunning "cron"
`requires` Apt.installed ["util-linux", "moreutils"]
- `describe` ("cronned " ++ desc)
where
cmdline = "cd " ++ cddir ++ " && ( " ++ command ++ " )"
- cronjobfile = "/etc/cron.d/" ++ map sanitize desc
+ cronjobfile = "/etc/cron.d/" ++ name
+ scriptfile = "/usr/local/bin/" ++ name ++ "_cronjob"
+ name = map sanitize desc
sanitize c
| isAlphaNum c = c
| otherwise = '_'
@@ -42,7 +54,7 @@ job desc times user cddir command = cronjobfile `File.hasContent`
-- | Installs a cron job, and runs it niced and ioniced.
niceJob :: Desc -> CronTimes -> UserName -> FilePath -> String -> Property
niceJob desc times user cddir command = job desc times user cddir
- ("nice ionice -c 3 " ++ command)
+ ("nice ionice -c 3 sh -c " ++ shellEscape command)
-- | Installs a cron job to run propellor.
runPropellor :: CronTimes -> Property
diff --git a/src/Propellor/Property/File.hs b/src/Propellor/Property/File.hs
index 0e738f25..bc499e07 100644
--- a/src/Propellor/Property/File.hs
+++ b/src/Propellor/Property/File.hs
@@ -18,28 +18,32 @@ f `hasContent` newcontent = fileProperty ("replace " ++ f)
-- The file's permissions are preserved if the file already existed.
-- Otherwise, they're set to 600.
hasPrivContent :: FilePath -> Context -> Property
-hasPrivContent f context = withPrivData (PrivFile f) context $ \getcontent ->
- property desc $ getcontent $ \privcontent ->
- ensureProperty $ fileProperty' writeFileProtected desc
- (\_oldcontent -> lines privcontent) f
- where
- desc = "privcontent " ++ f
+hasPrivContent = hasPrivContent' writeFileProtected
--- | Leaves the file world-readable.
+-- | Leaves the file at its default or current mode,
+-- allowing "private" data to be read.
+--
+-- Use with caution!
hasPrivContentExposed :: FilePath -> Context -> Property
-hasPrivContentExposed f context = hasPrivContent f context `onChange`
- mode f (combineModes (ownerWriteMode:readModes))
+hasPrivContentExposed = hasPrivContent' writeFile
+
+hasPrivContent' :: (String -> FilePath -> IO ()) -> FilePath -> Context -> Property
+hasPrivContent' writer f context =
+ withPrivData (PrivFile f) context $ \getcontent ->
+ property desc $ getcontent $ \privcontent ->
+ ensureProperty $ fileProperty' writer desc
+ (\_oldcontent -> lines privcontent) f
+ where
+ desc = "privcontent " ++ f
-- | Ensures that a line is present in a file, adding it to the end if not.
containsLine :: FilePath -> Line -> Property
f `containsLine` l = f `containsLines` [l]
containsLines :: FilePath -> [Line] -> Property
-f `containsLines` l = fileProperty (f ++ " contains:" ++ show l) go f
+f `containsLines` ls = fileProperty (f ++ " contains:" ++ show ls) go f
where
- go ls
- | all (`elem` ls) l = ls
- | otherwise = ls++l
+ go content = content ++ filter (`notElem` content) ls
-- | Ensures that a line is not present in a file.
-- Note that the file is ensured to exist, so if it doesn't, an empty
diff --git a/src/Propellor/Property/Hostname.hs b/src/Propellor/Property/Hostname.hs
index 1cce4e60..c489e2fb 100644
--- a/src/Propellor/Property/Hostname.hs
+++ b/src/Propellor/Property/Hostname.hs
@@ -3,10 +3,14 @@ module Propellor.Property.Hostname where
import Propellor
import qualified Propellor.Property.File as File
+import Data.List
+
-- | Ensures that the hostname is set using best practices.
--
-- Configures /etc/hostname and the current hostname.
--
+-- Configures /etc/mailname with the domain part of the hostname.
+--
-- /etc/hosts is also configured, with an entry for 127.0.1.1, which is
-- standard at least on Debian to set the FDQN.
--
@@ -29,6 +33,8 @@ setTo hn = combineProperties desc go
else Just $ trivial $ hostsline "127.0.1.1" [hn, basehost]
, Just $ trivial $ hostsline "127.0.0.1" ["localhost"]
, Just $ trivial $ cmdProperty "hostname" [basehost]
+ , Just $ "/etc/mailname" `File.hasContent`
+ [if null domain then hn else domain]
]
hostsline ip names = File.fileProperty desc
@@ -37,3 +43,21 @@ setTo hn = combineProperties desc go
addhostsline ip names ls =
(ip ++ "\t" ++ (unwords names)) : filter (not . hasip ip) ls
hasip ip l = headMaybe (words l) == Just ip
+
+-- | Makes /etc/resolv.conf contain search and domain lines for
+-- the domain that the hostname is in.
+searchDomain :: Property
+searchDomain = property desc (ensureProperty . go =<< asks hostName)
+ where
+ desc = "resolv.conf search and domain configured"
+ go hn =
+ let (_basehost, domain) = separate (== '.') hn
+ in File.fileProperty desc (use domain) "/etc/resolv.conf"
+ use domain ls = filter wanted $ nub (ls ++ cfgs)
+ where
+ cfgs = ["domain " ++ domain, "search " ++ domain]
+ wanted l
+ | l `elem` cfgs = True
+ | "domain " `isPrefixOf` l = False
+ | "search " `isPrefixOf` l = False
+ | otherwise = True
diff --git a/src/Propellor/Property/Obnam.hs b/src/Propellor/Property/Obnam.hs
index 15a8494c..b5c6d776 100644
--- a/src/Propellor/Property/Obnam.hs
+++ b/src/Propellor/Property/Obnam.hs
@@ -33,8 +33,8 @@ data NumClients = OnlyClient | MultipleClients
-- > [ "--repository=sftp://2318@usw-s002.rsync.net/~/mygitrepos.obnam"
-- > , "--encrypt-with=1B169BE1"
-- > ] Obnam.OnlyClient
--- > `requires` Gpg.keyImported "1B169BE1" "root"
--- > `requires` Ssh.keyImported SshRsa "root"
+-- > `requires` Gpg.keyImported "1B169BE1" "root"
+-- > `requires` Ssh.keyImported SshRsa "root" (Context hostname)
--
-- How awesome is that?
backup :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Property
diff --git a/src/Propellor/Property/Postfix.hs b/src/Propellor/Property/Postfix.hs
index ef96e086..b3d12727 100644
--- a/src/Propellor/Property/Postfix.hs
+++ b/src/Propellor/Property/Postfix.hs
@@ -2,24 +2,120 @@ module Propellor.Property.Postfix where
import Propellor
import qualified Propellor.Property.Apt as Apt
+import Propellor.Property.File
+import qualified Propellor.Property.Service as Service
+
+import qualified Data.Map as M
+import Data.List
+import Data.Char
installed :: Property
installed = Apt.serviceInstalledRunning "postfix"
+restarted :: Property
+restarted = Service.restarted "postfix"
+
+reloaded :: Property
+reloaded = Service.reloaded "postfix"
+
-- | Configures postfix as a satellite system, which
--- relats all mail through a relay host, which defaults to smtp.domain.
+-- relays all mail through a relay host, which defaults to smtp.domain.
--
-- The smarthost may refuse to relay mail on to other domains, without
-- futher coniguration/keys. But this should be enough to get cron job
-- mail flowing to a place where it will be seen.
satellite :: Property
-satellite = setup `requires` installed
+satellite = check (not <$> mainCfIsSet "relayhost") setup
+ `requires` installed
where
setup = trivial $ property "postfix satellite system" $ do
hn <- asks hostName
- ensureProperty $ Apt.reConfigure "postfix"
- [ ("postfix/main_mailer_type", "select", "Satellite system")
- , ("postfix/root_address", "string", "root")
- , ("postfix/destinations", "string", " ")
- , ("postfix/mailname", "string", hn)
+ let (_, domain) = separate (== '.') hn
+ ensureProperties
+ [ Apt.reConfigure "postfix"
+ [ ("postfix/main_mailer_type", "select", "Satellite system")
+ , ("postfix/root_address", "string", "root")
+ , ("postfix/destinations", "string", " ")
+ , ("postfix/mailname", "string", hn)
+ ]
+ , mainCf ("relayhost", domain)
+ `onChange` reloaded
]
+
+-- | Sets up a file by running a property (which the filename is passed
+-- to). If the setup property makes a change, postmap will be run on the
+-- file, and postfix will be reloaded.
+mappedFile :: FilePath -> (FilePath -> Property) -> Property
+mappedFile f setup = setup f
+ `onChange` cmdProperty "postmap" [f]
+
+-- | Run newaliases command, which should be done after changing
+-- /etc/aliases.
+newaliases :: Property
+newaliases = trivial $ cmdProperty "newaliases" []
+
+-- | The main config file for postfix.
+mainCfFile :: FilePath
+mainCfFile = "/etc/postfix/main.cf"
+
+-- | Sets a main.cf name=value pair. Does not reload postfix immediately.
+mainCf :: (String, String) -> Property
+mainCf (name, value) = check notset set
+ `describe` ("postfix main.cf " ++ setting)
+ where
+ setting = name ++ "=" ++ value
+ notset = (/= Just value) <$> getMainCf name
+ set = cmdProperty "postconf" ["-e", setting]
+
+-- | Gets a man.cf setting.
+getMainCf :: String -> IO (Maybe String)
+getMainCf name = parse . lines <$> readProcess "postconf" [name]
+ where
+ parse (l:_) = Just $
+ case separate (== '=') l of
+ (_, (' ':v)) -> v
+ (_, v) -> v
+ parse [] = Nothing
+
+-- | Checks if a main.cf field is set. A field that is set to ""
+-- is considered not set.
+mainCfIsSet :: String -> IO Bool
+mainCfIsSet name = do
+ v <- getMainCf name
+ return $ v /= Nothing && v /= Just ""
+
+-- | Parses main.cf, and removes any initial configuration lines that are
+-- overridden to other values later in the file.
+--
+-- For example, to add some settings, removing any old settings:
+--
+-- > mainCf `File.containsLines`
+-- > [ "# I like bars."
+-- > , "foo = bar"
+-- > ] `onChange` dedupMainCf
+--
+-- Note that multiline configurations that continue onto the next line
+-- are not currently supported.
+dedupMainCf :: Property
+dedupMainCf = fileProperty "postfix main.cf dedupped" dedupCf mainCfFile
+
+dedupCf :: [String] -> [String]
+dedupCf ls =
+ let parsed = map parse ls
+ in dedup [] (keycounts $ rights parsed) parsed
+ where
+ parse l
+ | "#" `isPrefixOf` l = Left l
+ | "=" `isInfixOf` l =
+ let (k, v) = separate (== '=') l
+ in Right ((filter (not . isSpace) k), v)
+ | otherwise = Left l
+ fmt k v = k ++ " =" ++ v
+
+ keycounts = M.fromListWith (+) . map (\(k, _v) -> (k, (1 :: Integer)))
+
+ dedup c _ [] = reverse c
+ dedup c kc ((Left v):rest) = dedup (v:c) kc rest
+ dedup c kc ((Right (k, v)):rest) = case M.lookup k kc of
+ Just n | n > 1 -> dedup c (M.insert k (n - 1) kc) rest
+ _ -> dedup (fmt k v:c) kc rest
diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs
index c770907b..fa8773de 100644
--- a/src/Propellor/Property/SiteSpecific/JoeySites.hs
+++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs
@@ -14,12 +14,14 @@ import qualified Propellor.Property.Service as Service
import qualified Propellor.Property.User as User
import qualified Propellor.Property.Obnam as Obnam
import qualified Propellor.Property.Apache as Apache
+import qualified Propellor.Property.Postfix as Postfix
import Utility.SafeCommand
import Utility.FileMode
import Utility.Path
import Data.List
import System.Posix.Files
+import Data.String.Utils
oldUseNetServer :: [Host] -> Property
oldUseNetServer hosts = propertyList ("olduse.net server")
@@ -59,9 +61,7 @@ oldUseNetServer hosts = propertyList ("olduse.net server")
, " <Directory " ++ datadir ++ "/>"
, " Options Indexes FollowSymlinks"
, " AllowOverride None"
- -- I had this in the file before.
- -- This may be needed by a newer version of apache?
- --, " Require all granted"
+ , Apache.allowAll
, " </Directory>"
]
]
@@ -114,11 +114,11 @@ mumbleServer hosts = combineProperties hn
[ Apt.serviceInstalledRunning "mumble-server"
, Obnam.latestVersion
, Obnam.backup "/var/lib/mumble-server" "55 5 * * *"
- [ "--repository=sftp://joey@turtle.kitenet.net/~/lib/backup/" ++ hn ++ ".obnam"
+ [ "--repository=sftp://joey@usbackup.kitenet.net/~/lib/backup/" ++ hn ++ ".obnam"
, "--client-name=mumble"
] Obnam.OnlyClient
`requires` Ssh.keyImported SshRsa "root" (Context hn)
- `requires` Ssh.knownHost hosts "turtle.kitenet.net" "root"
+ `requires` Ssh.knownHost hosts "usbackup.kitenet.net" "root"
, trivial $ cmdProperty "chown" ["-R", "mumble-server:mumble-server", "/var/lib/mumble-server"]
]
where
@@ -142,7 +142,7 @@ gitServer hosts = propertyList "git.kitenet.net setup"
, Obnam.backup "/srv/git" "33 3 * * *"
[ "--repository=sftp://2318@usw-s002.rsync.net/~/git.kitenet.net"
, "--encrypt-with=1B169BE1"
- , "--client-name=wren"
+ , "--client-name=wren" -- historical
] Obnam.OnlyClient
`requires` Gpg.keyImported "1B169BE1" "root"
`requires` Ssh.keyImported SshRsa "root" (Context "git.kitenet.net")
@@ -191,8 +191,8 @@ gitServer hosts = propertyList "git.kitenet.net setup"
type AnnexUUID = String
-- | A website, with files coming from a git-annex repository.
-annexWebSite :: [Host] -> Git.RepoUrl -> HostName -> AnnexUUID -> [(String, Git.RepoUrl)] -> Property
-annexWebSite hosts origin hn uuid remotes = propertyList (hn ++" website using git-annex")
+annexWebSite :: Git.RepoUrl -> HostName -> AnnexUUID -> [(String, Git.RepoUrl)] -> Property
+annexWebSite origin hn uuid remotes = propertyList (hn ++" website using git-annex")
[ Git.cloned "joey" origin dir Nothing
`onChange` setup
, postupdatehook `File.hasContent`
@@ -206,8 +206,6 @@ annexWebSite hosts origin hn uuid remotes = propertyList (hn ++" website using g
dir = "/srv/web/" ++ hn
postupdatehook = dir </> ".git/hooks/post-update"
setup = userScriptProperty "joey" setupscript
- `requires` Ssh.keyImported SshRsa "joey" (Context hn)
- `requires` Ssh.knownHost hosts "turtle.kitenet.net" "joey"
setupscript =
[ "cd " ++ shellEscape dir
, "git config annex.uuid " ++ shellEscape uuid
@@ -348,8 +346,27 @@ githubBackup = propertyList "github-backup box"
, let f = "/home/joey/.github-keys"
in File.hasPrivContent f anyContext
`onChange` File.ownerGroup f "joey" "joey"
+ , Cron.niceJob "github-backup run" "30 4 * * *" "joey"
+ "/home/joey/lib/backup" $ intercalate "&&"
+ [ "mkdir -p github"
+ , "cd github"
+ , ". $HOME/.github-keys && github-backup joeyh"
+ ]
]
+rsyncNetBackup :: [Host] -> Property
+rsyncNetBackup hosts = Cron.niceJob "rsync.net copied in daily" "30 5 * * *"
+ "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" "joey"
+
+backupsBackedupTo :: [Host] -> HostName -> FilePath -> Property
+backupsBackedupTo hosts desthost destdir = Cron.niceJob desc
+ "1 1 * * 3" "joey" "/" cmd
+ `requires` Ssh.knownHost hosts desthost "joey"
+ where
+ desc = "backups copied to " ++ desthost ++ " weekly"
+ cmd = "rsync -az --delete /home/joey/lib/backup " ++ desthost ++ ":" ++ destdir
+
obnamRepos :: [String] -> Property
obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs)
(mkbase : map mkrepo rs)
@@ -360,3 +377,354 @@ obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs)
mkdir d = File.dirExists d
`before` File.ownerGroup d "joey" "joey"
+podcatcher :: Property
+podcatcher = Cron.niceJob "podcatcher run hourly" "55 * * * *"
+ "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
+kiteMailServer = propertyList "kitenet.net mail server"
+ [ Postfix.installed
+ , Apt.installed ["postfix-pcre"]
+ , Apt.serviceInstalledRunning "postgrey"
+
+ , Apt.serviceInstalledRunning "spamassassin"
+ , "/etc/default/spamassassin" `File.containsLines`
+ [ "# Propellor deployed"
+ , "ENABLED=1"
+ , "CRON=1"
+ , "OPTIONS=\"--create-prefs --max-children 5 --helper-home-dir\""
+ , "CRON=1"
+ , "NICE=\"--nicelevel 15\""
+ ] `onChange` Service.restarted "spamassassin"
+ `describe` "spamd enabled"
+ `requires` Apt.serviceInstalledRunning "cron"
+
+ , Apt.serviceInstalledRunning "spamass-milter"
+ -- Add -m to prevent modifying messages Subject or body.
+ , "/etc/default/spamass-milter" `File.containsLine`
+ "OPTIONS=\"-m -u spamass-milter -i 127.0.0.1\""
+ `onChange` Service.restarted "spamass-milter"
+ `describe` "spamass-milter configured"
+
+ , Apt.serviceInstalledRunning "amavisd-milter"
+ , "/etc/default/amavisd-milter" `File.containsLines`
+ [ "# Propellor deployed"
+ , "MILTERSOCKET=/var/spool/postfix/amavis/amavis.sock"
+ , "MILTERSOCKETOWNER=\"postfix:postfix\""
+ , "MILTERSOCKETMODE=\"0660\""
+ ]
+ `onChange` Service.restarted "amavisd-milter"
+ `describe` "amavisd-milter configured for postfix"
+ , Apt.serviceInstalledRunning "clamav-freshclam"
+
+ , Apt.installed ["maildrop"]
+ , "/etc/maildroprc" `File.hasContent`
+ [ "# Global maildrop filter file (deployed with propellor)"
+ , "DEFAULT=\"$HOME/Maildir\""
+ , "MAILBOX=\"$DEFAULT/.\""
+ , "# Filter spam to a spam folder, unless .keepspam exists"
+ , "if (/^X-Spam-Status: Yes/)"
+ , "{"
+ , " `test -e \"$HOME/.keepspam\"`"
+ , " if ( $RETURNCODE != 0 )"
+ , " to ${MAILBOX}spam"
+ , "}"
+ ]
+ `describe` "maildrop configured"
+
+ , "/etc/aliases" `File.hasPrivContentExposed` ctx
+ `onChange` Postfix.newaliases
+ , hasJoeyCAChain
+ , "/etc/ssl/certs/postfix.pem" `File.hasPrivContentExposed` ctx
+ , "/etc/ssl/private/postfix.pem" `File.hasPrivContent` ctx
+
+ , "/etc/postfix/mydomain" `File.containsLines`
+ [ "/.*\\.kitenet\\.net/\tOK"
+ , "/ikiwiki\\.info/\tOK"
+ , "/joeyh\\.name/\tOK"
+ ]
+ `onChange` Postfix.reloaded
+ `describe` "postfix mydomain file configured"
+ , "/etc/postfix/obscure_client_relay.pcre" `File.containsLine`
+ "/^Received: from ([^.]+)\\.kitenet\\.net.*using TLS.*by kitenet\\.net \\(([^)]+)\\) with (E?SMTPS?A?) id ([A-F[:digit:]]+)(.*)/ IGNORE"
+ `onChange` Postfix.reloaded
+ `describe` "postfix obscure_client_relay file configured"
+ , Postfix.mappedFile "/etc/postfix/virtual"
+ (flip File.containsLines
+ [ "# *@joeyh.name to joey"
+ , "@joeyh.name\tjoey"
+ ]
+ ) `describe` "postfix virtual file configured"
+ `onChange` Postfix.reloaded
+ , Postfix.mappedFile "/etc/postfix/relay_clientcerts" $
+ flip File.hasPrivContentExposed ctx
+ , Postfix.mainCfFile `File.containsLines`
+ [ "myhostname = kitenet.net"
+ , "mydomain = $myhostname"
+ , "append_dot_mydomain = no"
+ , "myorigin = kitenet.net"
+ , "mydestination = $myhostname, localhost.$mydomain, $mydomain, kite.$mydomain., localhost, regexp:$config_directory/mydomain"
+ , "mailbox_command = maildrop"
+ , "virtual_alias_maps = hash:/etc/postfix/virtual"
+
+ , "# Allow clients with trusted certs to relay mail through."
+ , "relay_clientcerts = hash:/etc/postfix/relay_clientcerts"
+ , "smtpd_relay_restrictions = permit_mynetworks,permit_tls_clientcerts,permit_sasl_authenticated,reject_unauth_destination"
+
+ , "# Filter out client relay lines from headers."
+ , "header_checks = pcre:$config_directory/obscure_client_relay.pcre"
+
+ , "# Enable postgrey."
+ , "smtpd_recipient_restrictions = permit_mynetworks,reject_unauth_destination,check_policy_service inet:127.0.0.1:10023"
+
+ , "# Enable spamass-milter and amavis-milter."
+ , "smtpd_milters = unix:/spamass/spamass.sock unix:amavis/amavis.sock"
+ , "milter_connect_macros = j {daemon_name} v {if_name} _"
+
+ , "# TLS setup -- server"
+ , "smtpd_tls_CAfile = /etc/ssl/certs/joeyca.pem"
+ , "smtpd_tls_cert_file = /etc/ssl/certs/postfix.pem"
+ , "smtpd_tls_key_file = /etc/ssl/private/postfix.pem"
+ , "smtpd_tls_loglevel = 1"
+ , "smtpd_tls_received_header = yes"
+ , "smtpd_use_tls = yes"
+ , "smtpd_tls_ask_ccert = yes"
+ , "smtpd_tls_session_cache_database = sdbm:/etc/postfix/smtpd_scache"
+
+ , "# TLS setup -- client"
+ , "smtp_tls_CAfile = /etc/ssl/certs/joeyca.pem"
+ , "smtp_tls_cert_file = /etc/ssl/certs/postfix.pem"
+ , "smtp_tls_key_file = /etc/ssl/private/postfix.pem"
+ , "smtp_tls_loglevel = 1"
+ , "smtp_use_tls = yes"
+ , "smtp_tls_session_cache_database = sdbm:/etc/postfix/smtp_scache"
+ ]
+ `onChange` Postfix.dedupMainCf
+ `onChange` Postfix.reloaded
+ `describe` "postfix configured"
+
+ , Apt.serviceInstalledRunning "dovecot-imapd"
+ , Apt.serviceInstalledRunning "dovecot-pop3d"
+ , "/etc/dovecot/conf.d/10-mail.conf" `File.containsLine`
+ "mail_location = maildir:~/Maildir"
+ `onChange` Service.reloaded "dovecot"
+ `describe` "dovecot mail.conf"
+ , "/etc/dovecot/conf.d/10-auth.conf" `File.containsLine`
+ "!include auth-passwdfile.conf.ext"
+ `onChange` Service.restarted "dovecot"
+ `describe` "dovecot auth.conf"
+ , File.hasPrivContent dovecotusers ctx
+ `onChange` (dovecotusers `File.mode`
+ combineModes [ownerReadMode, groupReadMode])
+ , File.ownerGroup dovecotusers "root" "dovecot"
+
+ , Apt.installed ["mutt", "bsd-mailx", "alpine"]
+
+ , pinescript `File.hasContent`
+ [ "#!/bin/sh"
+ , "# deployed with propellor"
+ , "set -e"
+ , "pass=$HOME/.pine-password"
+ , "if [ ! -e $pass ]; then"
+ , "\ttouch $pass"
+ , "fi"
+ , "chmod 600 $pass"
+ , "exec alpine -passfile $pass \"$@\""
+ ]
+ `onChange` (pinescript `File.mode`
+ combineModes (readModes ++ executeModes))
+ `describe` "pine wrapper script"
+ , "/etc/pine.conf" `File.containsLines`
+ [ "inbox-path={localhost/novalidate-cert}inbox"
+ ]
+ `describe` "pine configured to use local imap server"
+ ]
+ where
+ ctx = Context "kitenet.net"
+ pinescript = "/usr/local/bin/pine"
+ dovecotusers = "/etc/dovecot/users"
+
+hasJoeyCAChain :: Property
+hasJoeyCAChain = "/etc/ssl/certs/joeyca.pem" `File.hasPrivContentExposed`
+ Context "joeyca.pem"
+
+kitenetHttps :: Property
+kitenetHttps = propertyList "kitenet.net https certs"
+ [ File.hasPrivContent "/etc/ssl/certs/web.pem" ctx
+ , File.hasPrivContent "/etc/ssl/private/web.pem" ctx
+ , File.hasPrivContent "/etc/ssl/certs/startssl.pem" ctx
+ , toProp $ Apache.modEnabled "ssl"
+ ]
+ where
+ ctx = Context "kitenet.net"
+
+-- Legacy static web sites and redirections from kitenet.net to newer
+-- sites.
+legacyWebSites :: Property
+legacyWebSites = propertyList "legacy web sites"
+ [ Apt.serviceInstalledRunning "apache2"
+ , toProp $ Apache.modEnabled "rewrite"
+ , toProp $ Apache.modEnabled "cgi"
+ , toProp $ Apache.modEnabled "speling"
+ , userDirHtml
+ , kitenetHttps
+ , toProp $ Apache.siteEnabled "kitenet.net" $ apachecfg "kitenet.net" True
+ -- /var/www is empty
+ [ "DocumentRoot /var/www"
+ , "<Directory /var/www>"
+ , " Options Indexes FollowSymLinks MultiViews ExecCGI Includes"
+ , " AllowOverride None"
+ , Apache.allowAll
+ , "</Directory>"
+ , "ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/"
+
+ -- for mailman cgi scripts
+ , "<Directory /usr/lib/cgi-bin>"
+ , " AllowOverride None"
+ , " Options ExecCGI"
+ , Apache.allowAll
+ , "</Directory>"
+ , "Alias /pipermail/ /var/lib/mailman/archives/public/"
+ , "<Directory /var/lib/mailman/archives/public/>"
+ , " Options Indexes MultiViews FollowSymlinks"
+ , " AllowOverride None"
+ , Apache.allowAll
+ , "</Directory>"
+ , "Alias /images/ /usr/share/images/"
+ , "<Directory /usr/share/images/>"
+ , " Options Indexes MultiViews"
+ , " AllowOverride None"
+ , Apache.allowAll
+ , "</Directory>"
+
+ , "RewriteEngine On"
+ , "# Force hostname to kitenet.net"
+ , "RewriteCond %{HTTP_HOST} !^kitenet\\.net [NC]"
+ , "RewriteCond %{HTTP_HOST} !^$"
+ , "RewriteRule ^/(.*) http://kitenet\\.net/$1 [L,R]"
+
+ , "# Moved pages"
+ , "RewriteRule /programs/debhelper http://joeyh.name/code/debhelper/ [L]"
+ , "RewriteRule /programs/satutils http://joeyh.name/code/satutils/ [L]"
+ , "RewriteRule /programs/filters http://joeyh.name/code/filters/ [L]"
+ , "RewriteRule /programs/ticker http://joeyh.name/code/ticker/ [L]"
+ , "RewriteRule /programs/pdmenu http://joeyh.name/code/pdmenu/ [L]"
+ , "RewriteRule /programs/sleepd http://joeyh.name/code/sleepd/ [L]"
+ , "RewriteRule /programs/Lingua::EN::Words2Nums http://joeyh.name/code/Words2Nums/ [L]"
+ , "RewriteRule /programs/wmbattery http://joeyh.name/code/wmbattery/ [L]"
+ , "RewriteRule /programs/dpkg-repack http://joeyh.name/code/dpkg-repack/ [L]"
+ , "RewriteRule /programs/debconf http://joeyh.name/code/debconf/ [L]"
+ , "RewriteRule /programs/perlmoo http://joeyh.name/code/perlmoo/ [L]"
+ , "RewriteRule /programs/alien http://joeyh.name/code/alien/ [L]"
+ , "RewriteRule /~joey/blog/entry/(.+)-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9].html http://joeyh.name/blog/entry/$1/ [L]"
+ , "RewriteRule /~anna/.* http://waldeneffect\\.org/ [R]"
+ , "RewriteRule /~anna/.* http://waldeneffect\\.org/ [R]"
+ , "RewriteRule /~anna http://waldeneffect\\.org/ [R]"
+ , "RewriteRule /simpleid/ http://openid.kitenet.net:8081/simpleid/"
+ , "# Even the kite home page is not here any more!"
+ , "RewriteRule ^/$ http://www.kitenet.net/ [R]"
+ , "RewriteRule ^/index.html http://www.kitenet.net/ [R]"
+ , "RewriteRule ^/joey http://www.kitenet.net/joey/ [R]"
+ , "RewriteRule ^/joey/index.html http://www.kitenet.net/joey/ [R]"
+ , "RewriteRule ^/wifi http://www.kitenet.net/wifi/ [R]"
+ , "RewriteRule ^/wifi/index.html http://www.kitenet.net/wifi/ [R]"
+
+ , "# Old ikiwiki filenames for kitenet.net wiki."
+ , "rewritecond $1 !^/~"
+ , "rewritecond $1 !^/doc/"
+ , "rewritecond $1 !^/pipermail/"
+ , "rewritecond $1 !^/cgi-bin/"
+ , "rewritecond $1 !.*/index$"
+ , "rewriterule (.+).html$ $1/ [r]"
+
+ , "# Old ikiwiki filenames for joey's wiki."
+ , "rewritecond $1 ^/~joey/"
+ , "rewritecond $1 !.*/index$"
+ , "rewriterule (.+).html$ http://kitenet.net/$1/ [L,R]"
+
+ , "# ~joey to joeyh.name"
+ , "rewriterule /~joey/(.*) http://joeyh.name/$1 [L]"
+
+ , "# Old familywiki location."
+ , "rewriterule /~family/(.*).html http://family.kitenet.net/$1 [L]"
+ , "rewriterule /~family/(.*).rss http://family.kitenet.net/$1/index.rss [L]"
+ , "rewriterule /~family(.*) http://family.kitenet.net$1 [L]"
+
+ , "rewriterule /~kyle/bywayofscience(.*) http://bywayofscience.branchable.com$1 [L]"
+ , "rewriterule /~kyle/family/wiki/(.*).html http://macleawiki.branchable.com/$1 [L]"
+ , "rewriterule /~kyle/family/wiki/(.*).rss http://macleawiki.branchable.com/$1/index.rss [L]"
+ , "rewriterule /~kyle/family/wiki(.*) http://macleawiki.branchable.com$1 [L]"
+ ]
+ , alias "anna.kitenet.net"
+ , toProp $ Apache.siteEnabled "anna.kitenet.net" $ apachecfg "anna.kitenet.net" False
+ [ "DocumentRoot /home/anna/html"
+ , "<Directory /home/anna/html/>"
+ , " Options Indexes ExecCGI"
+ , " AllowOverride None"
+ , Apache.allowAll
+ , "</Directory>"
+ ]
+ , alias "sows-ear.kitenet.net"
+ , alias "www.sows-ear.kitenet.net"
+ , toProp $ Apache.siteEnabled "sows-ear.kitenet.net" $ apachecfg "sows-ear.kitenet.net" False
+ [ "ServerAlias www.sows-ear.kitenet.net"
+ , "DocumentRoot /srv/web/sows-ear.kitenet.net"
+ , "<Directory /srv/web/sows-ear.kitenet.net>"
+ , " Options FollowSymLinks"
+ , " AllowOverride None"
+ , Apache.allowAll
+ , "</Directory>"
+ ]
+ , alias "wortroot.kitenet.net"
+ , alias "www.wortroot.kitenet.net"
+ , toProp $ Apache.siteEnabled "wortroot.kitenet.net" $ apachecfg "wortroot.kitenet.net" False
+ [ "ServerAlias www.wortroot.kitenet.net"
+ , "DocumentRoot /srv/web/wortroot.kitenet.net"
+ , "<Directory /srv/web/wortroot.kitenet.net>"
+ , " Options FollowSymLinks"
+ , " AllowOverride None"
+ , Apache.allowAll
+ , "</Directory>"
+ ]
+ , alias "creeksidepress.com"
+ , toProp $ Apache.siteEnabled "creeksidepress.com" $ apachecfg "creeksidepress.com" False
+ [ "ServerAlias www.creeksidepress.com"
+ , "DocumentRoot /srv/web/www.creeksidepress.com"
+ , "<Directory /srv/web/www.creeksidepress.com>"
+ , " Options FollowSymLinks"
+ , " AllowOverride None"
+ , Apache.allowAll
+ , "</Directory>"
+ ]
+ , alias "joey.kitenet.net"
+ , toProp $ Apache.siteEnabled "joey.kitenet.net" $ apachecfg "joey.kitenet.net" False
+ [ "DocumentRoot /home/joey/html"
+ , "<Directory /home/joey/html/>"
+ , " Options Indexes ExecCGI"
+ , " AllowOverride None"
+ , Apache.allowAll
+ , "</Directory>"
+
+ , "RewriteEngine On"
+
+ , "# Old ikiwiki filenames for joey's wiki."
+ , "rewritecond $1 !.*/index$"
+ , "rewriterule (.+).html$ http://joeyh.name/$1/ [l]"
+
+ , "rewritecond $1 !.*/index$"
+ , "rewriterule (.+).rss$ http://joeyh.name/$1/index.rss [l]"
+
+ , "# Redirect all to joeyh.name."
+ , "rewriterule (.*) http://joeyh.name$1 [r]"
+ ]
+ ]
+
+userDirHtml :: Property
+userDirHtml = File.fileProperty "apache userdir is html" (map munge) conf
+ `onChange` Apache.reloaded
+ `requires` (toProp $ Apache.modEnabled "userdir")
+ where
+ munge = replace "public_html" "html"
+ conf = "/etc/apache2/mods-available/userdir.conf"
diff --git a/src/Propellor/Types/Info.hs b/src/Propellor/Types/Info.hs
index 8856e06f..de072aa0 100644
--- a/src/Propellor/Types/Info.hs
+++ b/src/Propellor/Types/Info.hs
@@ -12,6 +12,7 @@ data Info = Info
{ _os :: Val System
, _privDataFields :: S.Set (PrivDataField, Context)
, _sshPubKey :: Val String
+ , _aliases :: S.Set HostName
, _dns :: S.Set Dns.Record
, _namedconf :: Dns.NamedConfMap
, _dockerinfo :: DockerInfo
@@ -19,11 +20,12 @@ data Info = Info
deriving (Eq, Show)
instance Monoid Info where
- mempty = Info mempty mempty mempty mempty mempty mempty
+ mempty = Info mempty mempty mempty mempty mempty mempty mempty
mappend old new = Info
{ _os = _os old <> _os new
, _privDataFields = _privDataFields old <> _privDataFields new
, _sshPubKey = _sshPubKey old <> _sshPubKey new
+ , _aliases = _aliases old <> _aliases new
, _dns = _dns old <> _dns new
, _namedconf = _namedconf old <> _namedconf new
, _dockerinfo = _dockerinfo old <> _dockerinfo new