Merge branch 'joeyconfig'
Conflicts: privdata.joey/privdata.gpg
This commit is contained in:
commit
cb67eb1d08
126
config-joey.hs
126
config-joey.hs
|
@ -19,7 +19,6 @@ import qualified Propellor.Property.Dns as Dns
|
||||||
import qualified Propellor.Property.OpenId as OpenId
|
import qualified Propellor.Property.OpenId as OpenId
|
||||||
import qualified Propellor.Property.Docker as Docker
|
import qualified Propellor.Property.Docker as Docker
|
||||||
import qualified Propellor.Property.Git as Git
|
import qualified Propellor.Property.Git as Git
|
||||||
import qualified Propellor.Property.Apache as Apache
|
|
||||||
import qualified Propellor.Property.Postfix as Postfix
|
import qualified Propellor.Property.Postfix as Postfix
|
||||||
import qualified Propellor.Property.Grub as Grub
|
import qualified Propellor.Property.Grub as Grub
|
||||||
import qualified Propellor.Property.Obnam as Obnam
|
import qualified Propellor.Property.Obnam as Obnam
|
||||||
|
@ -27,7 +26,6 @@ import qualified Propellor.Property.Gpg as Gpg
|
||||||
import qualified Propellor.Property.Systemd as Systemd
|
import qualified Propellor.Property.Systemd as Systemd
|
||||||
import qualified Propellor.Property.Journald as Journald
|
import qualified Propellor.Property.Journald as Journald
|
||||||
import qualified Propellor.Property.OS as OS
|
import qualified Propellor.Property.OS as OS
|
||||||
import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean
|
|
||||||
import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost
|
import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost
|
||||||
import qualified Propellor.Property.HostingProvider.Linode as Linode
|
import qualified Propellor.Property.HostingProvider.Linode as Linode
|
||||||
import qualified Propellor.Property.SiteSpecific.GitHome as GitHome
|
import qualified Propellor.Property.SiteSpecific.GitHome as GitHome
|
||||||
|
@ -47,6 +45,7 @@ hosts = -- (o) `
|
||||||
, kite
|
, kite
|
||||||
, diatom
|
, diatom
|
||||||
, elephant
|
, elephant
|
||||||
|
, beaver
|
||||||
] ++ monsters
|
] ++ monsters
|
||||||
|
|
||||||
testvm :: Host
|
testvm :: Host
|
||||||
|
@ -86,7 +85,7 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64"
|
||||||
& Ssh.randomHostKeys
|
& Ssh.randomHostKeys
|
||||||
& Apt.unattendedUpgrades
|
& Apt.unattendedUpgrades
|
||||||
& Network.ipv6to4
|
& Network.ipv6to4
|
||||||
& Tor.isBridge
|
& Tor.named "kite1" Tor.isRelay'
|
||||||
& Postfix.satellite
|
& Postfix.satellite
|
||||||
|
|
||||||
& Docker.configured
|
& Docker.configured
|
||||||
|
@ -118,8 +117,8 @@ orca = standardSystem "orca.kitenet.net" Unstable "amd64"
|
||||||
& Docker.docked (GitAnnexBuilder.standardAutoBuilderContainer dockerImage "amd64" 15 "2h")
|
& Docker.docked (GitAnnexBuilder.standardAutoBuilderContainer dockerImage "amd64" 15 "2h")
|
||||||
& Docker.docked (GitAnnexBuilder.standardAutoBuilderContainer dockerImage "i386" 45 "2h")
|
& Docker.docked (GitAnnexBuilder.standardAutoBuilderContainer dockerImage "i386" 45 "2h")
|
||||||
& Docker.docked (GitAnnexBuilder.armelCompanionContainer dockerImage)
|
& Docker.docked (GitAnnexBuilder.armelCompanionContainer dockerImage)
|
||||||
& Docker.docked (GitAnnexBuilder.armelAutoBuilderContainer dockerImage "1 3 * * *" "5h")
|
& Docker.docked (GitAnnexBuilder.armelAutoBuilderContainer dockerImage (Cron.Times "1 3 * * *") "5h")
|
||||||
& Docker.docked (GitAnnexBuilder.androidAutoBuilderContainer dockerImage "1 1 * * *" "3h")
|
& Docker.docked (GitAnnexBuilder.androidAutoBuilderContainer dockerImage (Cron.Times "1 1 * * *") "3h")
|
||||||
& Docker.garbageCollected `period` Daily
|
& Docker.garbageCollected `period` Daily
|
||||||
& Apt.buildDep ["git-annex"] `period` Daily
|
& Apt.buildDep ["git-annex"] `period` Daily
|
||||||
|
|
||||||
|
@ -128,7 +127,7 @@ orca = standardSystem "orca.kitenet.net" Unstable "amd64"
|
||||||
-- with propellor.
|
-- with propellor.
|
||||||
kite :: Host
|
kite :: Host
|
||||||
kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64"
|
kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64"
|
||||||
[ "Welcome to the new kitenet.net server!" ]
|
[ "Welcome to kite!" ]
|
||||||
& ipv4 "66.228.36.95"
|
& ipv4 "66.228.36.95"
|
||||||
& ipv6 "2600:3c03::f03c:91ff:fe73:b0d2"
|
& ipv6 "2600:3c03::f03c:91ff:fe73:b0d2"
|
||||||
& alias "kitenet.net"
|
& alias "kitenet.net"
|
||||||
|
@ -143,6 +142,7 @@ kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64"
|
||||||
& Network.static "eth0" `requires` Network.cleanInterfacesFile
|
& Network.static "eth0" `requires` Network.cleanInterfacesFile
|
||||||
& Apt.installed ["linux-image-amd64"]
|
& Apt.installed ["linux-image-amd64"]
|
||||||
& Linode.chainPVGrub 5
|
& Linode.chainPVGrub 5
|
||||||
|
& Linode.mlocateEnabled
|
||||||
& Apt.unattendedUpgrades
|
& Apt.unattendedUpgrades
|
||||||
& Systemd.installed
|
& Systemd.installed
|
||||||
& Systemd.persistentJournal
|
& Systemd.persistentJournal
|
||||||
|
@ -150,7 +150,7 @@ kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64"
|
||||||
& Ssh.passwordAuthentication True
|
& Ssh.passwordAuthentication True
|
||||||
-- Since ssh password authentication is allowed:
|
-- Since ssh password authentication is allowed:
|
||||||
& Apt.serviceInstalledRunning "fail2ban"
|
& Apt.serviceInstalledRunning "fail2ban"
|
||||||
& Obnam.backupEncrypted "/" "33 1 * * *"
|
& Obnam.backupEncrypted "/" (Cron.Times "33 1 * * *")
|
||||||
[ "--repository=sftp://joey@eubackup.kitenet.net/~/lib/backup/kite.obnam"
|
[ "--repository=sftp://joey@eubackup.kitenet.net/~/lib/backup/kite.obnam"
|
||||||
, "--client-name=kitenet.net"
|
, "--client-name=kitenet.net"
|
||||||
, "--exclude=/var/cache"
|
, "--exclude=/var/cache"
|
||||||
|
@ -171,12 +171,18 @@ kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64"
|
||||||
& alias "mail.kitenet.net"
|
& alias "mail.kitenet.net"
|
||||||
& JoeySites.kiteMailServer
|
& JoeySites.kiteMailServer
|
||||||
|
|
||||||
& alias "ns4.kitenet.net"
|
& JoeySites.kitenetHttps
|
||||||
& myDnsSecondary
|
|
||||||
& alias "ns4.branchable.com"
|
|
||||||
& branchableSecondary
|
|
||||||
|
|
||||||
& JoeySites.legacyWebSites
|
& JoeySites.legacyWebSites
|
||||||
|
& File.ownerGroup "/srv/web" "joey" "joey"
|
||||||
|
& Apt.installed ["analog"]
|
||||||
|
|
||||||
|
& alias "git.kitenet.net"
|
||||||
|
& alias "git.joeyh.name"
|
||||||
|
& JoeySites.gitServer hosts
|
||||||
|
|
||||||
|
& JoeySites.downloads hosts
|
||||||
|
& JoeySites.gitAnnexDistributor
|
||||||
|
& JoeySites.tmp
|
||||||
|
|
||||||
& alias "bitlbee.kitenet.net"
|
& alias "bitlbee.kitenet.net"
|
||||||
& Apt.serviceInstalledRunning "bitlbee"
|
& Apt.serviceInstalledRunning "bitlbee"
|
||||||
|
@ -201,73 +207,32 @@ kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64"
|
||||||
|
|
||||||
& Docker.configured
|
& Docker.configured
|
||||||
& Docker.garbageCollected `period` Daily
|
& Docker.garbageCollected `period` Daily
|
||||||
& Docker.docked oldusenetShellBox
|
! Docker.docked oldusenetShellBox
|
||||||
|
|
||||||
diatom :: Host
|
|
||||||
diatom = standardSystem "diatom.kitenet.net" (Stable "wheezy") "amd64"
|
|
||||||
[ "Important stuff that needs not too much memory or CPU." ]
|
|
||||||
& ipv4 "107.170.31.195"
|
|
||||||
& Ssh.hostKeys hostContext
|
|
||||||
[ (SshDsa, "ssh-dss AAAAB3NzaC1kc3MAAACBAO9tnPUT4p+9z7K6/OYuiBNHaij4Nzv5YVBih1vMl+ALz0gYAj8RWJzXmqp5buFAyfgOoLw+H9s1bBS01Sy3i07Dm6cx1fWG4RXL/E/3w1tavX99GD2bBxDBu890ebA5Tp+eFRJkS9+JwSvFiF6CP7NbVjifCagoUO56Ig048RwDAAAAFQDPY2xM3q6KwsVQliel23nrd0rV2QAAAIEAga3hj1hL00rYPNnAUzT8GAaSP62S4W68lusErH+KPbsMwFBFY/Ib1FVf8k6Zn6dZLh/HH/RtJi0JwdzPI1IFW+lwVbKfwBvhQ1lw9cH2rs1UIVgi7Wxdgfy8gEWxf+QIqn62wG+Ulf/HkWGvTrRpoJqlYRNS/gnOWj9Z/4s99koAAACBAM/uJIo2I0nK15wXiTYs/NYUZA7wcErugFn70TRbSgduIFH6U/CQa3rgHJw9DCPCQJLq7pwCnFH7too/qaK+czDk04PsgqV0+Jc7957gU5miPg50d60eJMctHV4eQ1FpwmGGfXxRBR9k2ZvikWYatYir3L6/x1ir7M0bA9IzNU45")
|
|
||||||
, (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA2QAJEuvbTmaN9ex9i9bjPhMGj+PHUYq2keIiaIImJ+8mo+yKSaGUxebG4tpuDPx6KZjdycyJt74IXfn1voGUrfzwaEY9NkqOP3v6OWTC3QeUGqDCeJ2ipslbEd9Ep9XBp+/ldDQm60D0XsIZdmDeN6MrHSbKF4fXv1bqpUoUILk=")
|
|
||||||
]
|
|
||||||
|
|
||||||
& DigitalOcean.distroKernel
|
|
||||||
& Apt.unattendedUpgrades
|
|
||||||
& Apt.serviceInstalledRunning "ntp"
|
|
||||||
& Postfix.satellite
|
|
||||||
|
|
||||||
-- Diatom has 500 mb of memory, so tune for that.
|
|
||||||
& JoeySites.obnamLowMem
|
|
||||||
& Apt.serviceInstalledRunning "swapspace"
|
|
||||||
|
|
||||||
& Apt.serviceInstalledRunning "apache2"
|
|
||||||
& JoeySites.kitenetHttps
|
|
||||||
& Apache.multiSSL
|
|
||||||
& File.ownerGroup "/srv/web" "joey" "joey"
|
|
||||||
& Apt.installed ["analog"]
|
|
||||||
|
|
||||||
& alias "git.kitenet.net"
|
|
||||||
& alias "git.joeyh.name"
|
|
||||||
& JoeySites.gitServer hosts
|
|
||||||
|
|
||||||
& JoeySites.annexWebSite "/srv/git/downloads.git"
|
|
||||||
"downloads.kitenet.net"
|
|
||||||
"840760dc-08f0-11e2-8c61-576b7e66acfd"
|
|
||||||
[("eubackup", "ssh://eubackup.kitenet.net/~/lib/downloads/")]
|
|
||||||
`requires` Ssh.keyImported SshRsa "joey" (Context "downloads.kitenet.net")
|
|
||||||
`requires` Ssh.knownHost hosts "eubackup.kitenet.net" "joey"
|
|
||||||
& JoeySites.gitAnnexDistributor
|
|
||||||
|
|
||||||
& JoeySites.annexWebSite "/srv/git/joey/tmp.git"
|
|
||||||
"tmp.kitenet.net"
|
|
||||||
"26fd6e38-1226-11e2-a75f-ff007033bdba"
|
|
||||||
[]
|
|
||||||
& JoeySites.twitRss
|
|
||||||
& JoeySites.pumpRss
|
|
||||||
|
|
||||||
& JoeySites.annexWebSite "/srv/git/user-liberation.git"
|
|
||||||
"user-liberation.joeyh.name"
|
|
||||||
"da89f112-808b-420a-b468-d990ae2e5b52"
|
|
||||||
[]
|
|
||||||
|
|
||||||
& alias "nntp.olduse.net"
|
& alias "nntp.olduse.net"
|
||||||
& alias "resources.olduse.net"
|
|
||||||
& JoeySites.oldUseNetServer hosts
|
& JoeySites.oldUseNetServer hosts
|
||||||
|
|
||||||
& alias "ns2.kitenet.net"
|
& alias "ns4.kitenet.net"
|
||||||
& myDnsPrimary True "kitenet.net" []
|
& myDnsPrimary True "kitenet.net" []
|
||||||
& myDnsPrimary True "joeyh.name" []
|
& myDnsPrimary True "joeyh.name" []
|
||||||
& myDnsPrimary True "ikiwiki.info" []
|
& myDnsPrimary True "ikiwiki.info" []
|
||||||
& myDnsPrimary True "olduse.net"
|
& myDnsPrimary True "olduse.net"
|
||||||
[ (RelDomain "article", CNAME $ AbsDomain "virgil.koldfront.dk")
|
[ (RelDomain "article", CNAME $ AbsDomain "virgil.koldfront.dk")
|
||||||
]
|
]
|
||||||
|
& alias "ns4.branchable.com"
|
||||||
& alias "ns3.branchable.com"
|
|
||||||
& branchableSecondary
|
& branchableSecondary
|
||||||
|
|
||||||
& Dns.secondaryFor ["animx"] hosts "animx.eu.org"
|
& Dns.secondaryFor ["animx"] hosts "animx.eu.org"
|
||||||
|
|
||||||
|
diatom :: Host
|
||||||
|
diatom = standardSystem "diatom.kitenet.net" (Stable "wheezy") "amd64"
|
||||||
|
[ "dying" ]
|
||||||
|
& ipv4 "107.170.31.195"
|
||||||
|
& Ssh.hostKeys hostContext
|
||||||
|
[ (SshDsa, "ssh-dss AAAAB3NzaC1kc3MAAACBAO9tnPUT4p+9z7K6/OYuiBNHaij4Nzv5YVBih1vMl+ALz0gYAj8RWJzXmqp5buFAyfgOoLw+H9s1bBS01Sy3i07Dm6cx1fWG4RXL/E/3w1tavX99GD2bBxDBu890ebA5Tp+eFRJkS9+JwSvFiF6CP7NbVjifCagoUO56Ig048RwDAAAAFQDPY2xM3q6KwsVQliel23nrd0rV2QAAAIEAga3hj1hL00rYPNnAUzT8GAaSP62S4W68lusErH+KPbsMwFBFY/Ib1FVf8k6Zn6dZLh/HH/RtJi0JwdzPI1IFW+lwVbKfwBvhQ1lw9cH2rs1UIVgi7Wxdgfy8gEWxf+QIqn62wG+Ulf/HkWGvTrRpoJqlYRNS/gnOWj9Z/4s99koAAACBAM/uJIo2I0nK15wXiTYs/NYUZA7wcErugFn70TRbSgduIFH6U/CQa3rgHJw9DCPCQJLq7pwCnFH7too/qaK+czDk04PsgqV0+Jc7957gU5miPg50d60eJMctHV4eQ1FpwmGGfXxRBR9k2ZvikWYatYir3L6/x1ir7M0bA9IzNU45")
|
||||||
|
, (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA2QAJEuvbTmaN9ex9i9bjPhMGj+PHUYq2keIiaIImJ+8mo+yKSaGUxebG4tpuDPx6KZjdycyJt74IXfn1voGUrfzwaEY9NkqOP3v6OWTC3QeUGqDCeJ2ipslbEd9Ep9XBp+/ldDQm60D0XsIZdmDeN6MrHSbKF4fXv1bqpUoUILk=")
|
||||||
|
]
|
||||||
|
& alias "ns2.kitenet.net"
|
||||||
|
|
||||||
elephant :: Host
|
elephant :: Host
|
||||||
elephant = standardSystem "elephant.kitenet.net" Unstable "amd64"
|
elephant = standardSystem "elephant.kitenet.net" Unstable "amd64"
|
||||||
[ "Storage, big data, and backups, omnomnom!"
|
[ "Storage, big data, and backups, omnomnom!"
|
||||||
|
@ -294,7 +259,6 @@ elephant = standardSystem "elephant.kitenet.net" Unstable "amd64"
|
||||||
& JoeySites.obnamRepos ["wren", "pell", "kite"]
|
& JoeySites.obnamRepos ["wren", "pell", "kite"]
|
||||||
& JoeySites.githubBackup
|
& JoeySites.githubBackup
|
||||||
& JoeySites.rsyncNetBackup hosts
|
& JoeySites.rsyncNetBackup hosts
|
||||||
& JoeySites.backupsBackedupTo hosts "usbackup.kitenet.net" "lib/backup/eubackup"
|
|
||||||
|
|
||||||
& alias "podcatcher.kitenet.net"
|
& alias "podcatcher.kitenet.net"
|
||||||
& JoeySites.podcatcher
|
& JoeySites.podcatcher
|
||||||
|
@ -328,6 +292,18 @@ elephant = standardSystem "elephant.kitenet.net" Unstable "amd64"
|
||||||
-- block 22.
|
-- block 22.
|
||||||
& Ssh.listenPort 80
|
& Ssh.listenPort 80
|
||||||
|
|
||||||
|
beaver :: Host
|
||||||
|
beaver = host "beaver.kitenet.net"
|
||||||
|
& ipv6 "2001:4830:1600:195::2"
|
||||||
|
& Apt.serviceInstalledRunning "aiccu"
|
||||||
|
& Apt.installed ["ssh"]
|
||||||
|
& Ssh.pubKey SshDsa "ssh-dss AAAAB3NzaC1kc3MAAACBAIrLX260fY0Jjj/p0syNhX8OyR8hcr6feDPGOj87bMad0k/w/taDSOzpXe0Wet7rvUTbxUjH+Q5wPd4R9zkaSDiR/tCb45OdG6JsaIkmqncwe8yrU+pqSRCxttwbcFe+UU+4AAcinjVedZjVRDj2rRaFPc9BXkPt7ffk8GwEJ31/AAAAFQCG/gOjObsr86vvldUZHCteaJttNQAAAIB5nomvcqOk/TD07DLaWKyG7gAcW5WnfY3WtnvLRAFk09aq1EuiJ6Yba99Zkb+bsxXv89FWjWDg/Z3Psa22JMyi0HEDVsOevy/1sEQ96AGH5ijLzFInfXAM7gaJKXASD7hPbVdjySbgRCdwu0dzmQWHtH+8i1CMVmA2/a5Y/wtlJAAAAIAUZj2US2D378jBwyX1Py7e4sJfea3WSGYZjn4DLlsLGsB88POuh32aOChd1yzF6r6C2sdoPBHQcWBgNGXcx4gF0B5UmyVHg3lIX2NVSG1ZmfuLNJs9iKNu4cHXUmqBbwFYQJBvB69EEtrOw4jSbiTKwHFmqdA/mw1VsMB+khUaVw=="
|
||||||
|
& alias "usbackup.kitenet.net"
|
||||||
|
& JoeySites.backupsBackedupFrom hosts "eubackup.kitenet.net" "/home/joey/lib/backup"
|
||||||
|
& Apt.serviceInstalledRunning "anacron"
|
||||||
|
& Cron.niceJob "system disk backed up" Cron.Weekly "root" "/"
|
||||||
|
"rsync -a -x / /home/joey/lib/backup/beaver.kitenet.net/"
|
||||||
|
|
||||||
|
|
||||||
--' __|II| ,.
|
--' __|II| ,.
|
||||||
---- __|II|II|__ ( \_,/\
|
---- __|II|II|__ ( \_,/\
|
||||||
|
@ -411,7 +387,7 @@ standardSystemUnhardened hn suite arch motd = host hn
|
||||||
& Sudo.enabledFor "joey"
|
& Sudo.enabledFor "joey"
|
||||||
& GitHome.installedFor "joey"
|
& GitHome.installedFor "joey"
|
||||||
& Apt.installed ["vim", "screen", "less"]
|
& Apt.installed ["vim", "screen", "less"]
|
||||||
& Cron.runPropellor "30 * * * *"
|
& Cron.runPropellor (Cron.Times "30 * * * *")
|
||||||
-- I use postfix, or no MTA.
|
-- I use postfix, or no MTA.
|
||||||
& Apt.removed ["exim4", "exim4-daemon-light", "exim4-config", "exim4-base"]
|
& Apt.removed ["exim4", "exim4-daemon-light", "exim4-config", "exim4-base"]
|
||||||
`onChange` Apt.autoRemove
|
`onChange` Apt.autoRemove
|
||||||
|
@ -447,15 +423,14 @@ myDnsSecondary = propertyList "dns secondary for all my domains" $ props
|
||||||
branchableSecondary :: RevertableProperty
|
branchableSecondary :: RevertableProperty
|
||||||
branchableSecondary = Dns.secondaryFor ["branchable.com"] hosts "branchable.com"
|
branchableSecondary = Dns.secondaryFor ["branchable.com"] hosts "branchable.com"
|
||||||
|
|
||||||
-- Currently using diatom (ns2) as primary with secondaries
|
-- Currently using kite (ns4) as primary with secondaries
|
||||||
-- elephant (ns3), kite (ns4) and gandi.
|
-- elephant (ns3) and gandi.
|
||||||
-- kite handles all mail.
|
-- kite handles all mail.
|
||||||
myDnsPrimary :: Bool -> Domain -> [(BindDomain, Record)] -> RevertableProperty
|
myDnsPrimary :: Bool -> Domain -> [(BindDomain, Record)] -> RevertableProperty
|
||||||
myDnsPrimary dnssec domain extras = (if dnssec then Dns.signedPrimary (Weekly Nothing) else Dns.primary) hosts domain
|
myDnsPrimary dnssec domain extras = (if dnssec then Dns.signedPrimary (Weekly Nothing) else Dns.primary) hosts domain
|
||||||
(Dns.mkSOA "ns2.kitenet.net" 100) $
|
(Dns.mkSOA "ns4.kitenet.net" 100) $
|
||||||
[ (RootDomain, NS $ AbsDomain "ns2.kitenet.net")
|
[ (RootDomain, NS $ AbsDomain "ns4.kitenet.net")
|
||||||
, (RootDomain, NS $ AbsDomain "ns3.kitenet.net")
|
, (RootDomain, NS $ AbsDomain "ns3.kitenet.net")
|
||||||
, (RootDomain, NS $ AbsDomain "ns4.kitenet.net")
|
|
||||||
, (RootDomain, NS $ AbsDomain "ns6.gandi.net")
|
, (RootDomain, NS $ AbsDomain "ns6.gandi.net")
|
||||||
, (RootDomain, MX 0 $ AbsDomain "kitenet.net")
|
, (RootDomain, MX 0 $ AbsDomain "kitenet.net")
|
||||||
, (RootDomain, TXT "v=spf1 a a:kitenet.net ~all")
|
, (RootDomain, TXT "v=spf1 a a:kitenet.net ~all")
|
||||||
|
@ -474,13 +449,8 @@ monsters = -- but do want to track their public keys etc.
|
||||||
, host "turtle.kitenet.net"
|
, host "turtle.kitenet.net"
|
||||||
& ipv4 "67.223.19.96"
|
& ipv4 "67.223.19.96"
|
||||||
& ipv6 "2001:4978:f:2d9::2"
|
& ipv6 "2001:4978:f:2d9::2"
|
||||||
& alias "backup.kitenet.net"
|
|
||||||
& alias "usbackup.kitenet.net"
|
|
||||||
& Ssh.pubKey SshRsa "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAokMXQiX/NZjA1UbhMdgAscnS5dsmy+Q7bWrQ6tsTZ/o+6N/T5cbjoBHOdpypXJI3y/PiJTDJaQtXIhLa8gFg/EvxMnMz/KG9skADW1361JmfCc4BxicQIO2IOOe6eilPr+YsnOwiHwL0vpUnuty39cppuMWVD25GzxXlS6KQsLCvXLzxLLuNnGC43UAM0q4UwQxDtAZEK1dH2o3HMWhgMP2qEQupc24dbhpO3ecxh2C9678a3oGDuDuNf7mLp3s7ptj5qF3onitpJ82U5o7VajaHoygMaSRFeWxP2c13eM57j3bLdLwxVXFhePcKXARu1iuFTLS5uUf3hN6MkQcOGw=="
|
|
||||||
, host "mouse.kitenet.net"
|
, host "mouse.kitenet.net"
|
||||||
& ipv6 "2001:4830:1600:492::2"
|
& ipv6 "2001:4830:1600:492::2"
|
||||||
, host "beaver.kitenet.net"
|
|
||||||
& ipv6 "2001:4830:1600:195::2"
|
|
||||||
, host "branchable.com"
|
, host "branchable.com"
|
||||||
& ipv4 "66.228.46.55"
|
& ipv4 "66.228.46.55"
|
||||||
& ipv6 "2600:3c03::f03c:91ff:fedf:c0e5"
|
& ipv6 "2600:3c03::f03c:91ff:fedf:c0e5"
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
propellor (2.1.0) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
|
* Additional tor properties, including support for making relays,
|
||||||
|
and naming bridges, relays, etc.
|
||||||
|
* New Cron.Times data type, which allows Cron.job to install
|
||||||
|
daily/monthly/weekly jobs that anacron can run. (API change)
|
||||||
|
* Fix Git.daemonRunning to restart inetd after enabling the git server.
|
||||||
|
* Ssh.authorizedKey: Make the authorized_keys file and .ssh directory
|
||||||
|
be owned by the user, not root.
|
||||||
|
* Ssh.knownHost: Make the .ssh directory be owned by the user, not root.
|
||||||
|
|
||||||
|
-- Joey Hess <id@joeyh.name> Thu, 29 Jan 2015 01:41:07 -0400
|
||||||
|
|
||||||
propellor (2.0.0) unstable; urgency=medium
|
propellor (2.0.0) unstable; urgency=medium
|
||||||
|
|
||||||
* Property has been converted to a GADT, and will be Property NoInfo
|
* Property has been converted to a GADT, and will be Property NoInfo
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Name: propellor
|
Name: propellor
|
||||||
Version: 2.0.0
|
Version: 2.1.0
|
||||||
Cabal-Version: >= 1.6
|
Cabal-Version: >= 1.6
|
||||||
License: BSD3
|
License: BSD3
|
||||||
Maintainer: Joey Hess <id@joeyh.name>
|
Maintainer: Joey Hess <id@joeyh.name>
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
{-# LANGUAGE PackageImports #-}
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
|
||||||
module Propellor.PropAccum where
|
module Propellor.PropAccum
|
||||||
|
( host
|
||||||
|
, props
|
||||||
|
, PropAccum(..)
|
||||||
|
, (!)
|
||||||
|
, PropList
|
||||||
|
, propigateContainer
|
||||||
|
) where
|
||||||
|
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
|
|
||||||
|
@ -47,9 +54,9 @@ instance PropAccum Host where
|
||||||
data PropList = PropList [Property HasInfo]
|
data PropList = PropList [Property HasInfo]
|
||||||
|
|
||||||
instance PropAccum PropList where
|
instance PropAccum PropList where
|
||||||
PropList l & p = PropList (l ++ [toProp p])
|
PropList l & p = PropList (toProp p : l)
|
||||||
PropList l &^ p = PropList ([toProp p] ++ l)
|
PropList l &^ p = PropList (l ++ [toProp p])
|
||||||
getProperties (PropList l) = l
|
getProperties (PropList l) = reverse l
|
||||||
|
|
||||||
-- | Adds a property in reverted form.
|
-- | Adds a property in reverted form.
|
||||||
(!) :: PropAccum h => h -> RevertableProperty -> h
|
(!) :: PropAccum h => h -> RevertableProperty -> h
|
||||||
|
|
|
@ -70,13 +70,17 @@ reloaded = Service.reloaded "apache2"
|
||||||
|
|
||||||
-- | Configure apache to use SNI to differentiate between
|
-- | Configure apache to use SNI to differentiate between
|
||||||
-- https hosts.
|
-- https hosts.
|
||||||
|
--
|
||||||
|
-- This was off by default in apache 2.2.22. Newver versions enable
|
||||||
|
-- it by default. This property uses the filename used by the old version.
|
||||||
multiSSL :: Property NoInfo
|
multiSSL :: Property NoInfo
|
||||||
multiSSL = "/etc/apache2/conf.d/ssl" `File.hasContent`
|
multiSSL = check (doesDirectoryExist "/etc/apache2/conf.d") $
|
||||||
[ "NameVirtualHost *:443"
|
"/etc/apache2/conf.d/ssl" `File.hasContent`
|
||||||
, "SSLStrictSNIVHostCheck off"
|
[ "NameVirtualHost *:443"
|
||||||
]
|
, "SSLStrictSNIVHostCheck off"
|
||||||
`describe` "apache SNI enabled"
|
]
|
||||||
`onChange` reloaded
|
`describe` "apache SNI enabled"
|
||||||
|
`onChange` reloaded
|
||||||
|
|
||||||
-- | Config file fragment that can be inserted into a <Directory>
|
-- | Config file fragment that can be inserted into a <Directory>
|
||||||
-- stanza to allow global read access to the directory.
|
-- stanza to allow global read access to the directory.
|
||||||
|
|
|
@ -8,18 +8,26 @@ import Utility.FileMode
|
||||||
|
|
||||||
import Data.Char
|
import Data.Char
|
||||||
|
|
||||||
type CronTimes = String
|
-- | When to run a cron job.
|
||||||
|
--
|
||||||
|
-- The Daily, Monthly, and Weekly options allow the cron job to be run
|
||||||
|
-- by anacron, which is useful for non-servers.
|
||||||
|
data Times
|
||||||
|
= Times String -- ^ formatted as in crontab(5)
|
||||||
|
| Daily
|
||||||
|
| Weekly
|
||||||
|
| Monthly
|
||||||
|
|
||||||
-- | Installs a cron job, run as a specified user, in a particular
|
-- | Installs a cron job, that will run as a specified user in a particular
|
||||||
-- directory. Note that the Desc must be unique, as it is used for the
|
-- directory. Note that the Desc must be unique, as it is used for the
|
||||||
-- cron.d/ filename.
|
-- cron job filename.
|
||||||
--
|
--
|
||||||
-- Only one instance of the cron job is allowed to run at a time, no matter
|
-- Only one instance of the cron job is allowed to run at a time, no matter
|
||||||
-- how long it runs. This is accomplished using flock locking of the cron
|
-- how long it runs. This is accomplished using flock locking of the cron
|
||||||
-- job file.
|
-- job file.
|
||||||
--
|
--
|
||||||
-- The cron job's output will only be emailed if it exits nonzero.
|
-- The cron job's output will only be emailed if it exits nonzero.
|
||||||
job :: Desc -> CronTimes -> UserName -> FilePath -> String -> Property NoInfo
|
job :: Desc -> Times -> UserName -> FilePath -> String -> Property NoInfo
|
||||||
job desc times user cddir command = combineProperties ("cronned " ++ desc)
|
job desc times user cddir command = combineProperties ("cronned " ++ desc)
|
||||||
[ cronjobfile `File.hasContent`
|
[ cronjobfile `File.hasContent`
|
||||||
[ "# Generated by propellor"
|
[ "# Generated by propellor"
|
||||||
|
@ -27,8 +35,15 @@ job desc times user cddir command = combineProperties ("cronned " ++ desc)
|
||||||
, "SHELL=/bin/sh"
|
, "SHELL=/bin/sh"
|
||||||
, "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
|
, "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
|
||||||
, ""
|
, ""
|
||||||
, times ++ "\t" ++ user ++ "\tchronic " ++ shellEscape scriptfile
|
, case times of
|
||||||
|
Times t -> t ++ "\t" ++ user ++ "\tchronic " ++ shellEscape scriptfile
|
||||||
|
_ -> case user of
|
||||||
|
"root" -> "chronic " ++ shellEscape scriptfile
|
||||||
|
_ -> "chronic su " ++ user ++ " -c " ++ shellEscape scriptfile
|
||||||
]
|
]
|
||||||
|
, case times of
|
||||||
|
Times _ -> doNothing
|
||||||
|
_ -> cronjobfile `File.mode` combineModes (readModes ++ executeModes)
|
||||||
-- Use a separate script because it makes the cron job name
|
-- Use a separate script because it makes the cron job name
|
||||||
-- prettier in emails, and also allows running the job manually.
|
-- prettier in emails, and also allows running the job manually.
|
||||||
, scriptfile `File.hasContent`
|
, scriptfile `File.hasContent`
|
||||||
|
@ -44,7 +59,12 @@ job desc times user cddir command = combineProperties ("cronned " ++ desc)
|
||||||
`requires` Apt.installed ["util-linux", "moreutils"]
|
`requires` Apt.installed ["util-linux", "moreutils"]
|
||||||
where
|
where
|
||||||
cmdline = "cd " ++ cddir ++ " && ( " ++ command ++ " )"
|
cmdline = "cd " ++ cddir ++ " && ( " ++ command ++ " )"
|
||||||
cronjobfile = "/etc/cron.d/" ++ name
|
cronjobfile = "/etc" </> cronjobdir </> name
|
||||||
|
cronjobdir = case times of
|
||||||
|
Times _ -> "cron.d"
|
||||||
|
Daily -> "cron.daily"
|
||||||
|
Weekly -> "cron.weekly"
|
||||||
|
Monthly -> "cron.monthly"
|
||||||
scriptfile = "/usr/local/bin/" ++ name ++ "_cronjob"
|
scriptfile = "/usr/local/bin/" ++ name ++ "_cronjob"
|
||||||
name = map sanitize desc
|
name = map sanitize desc
|
||||||
sanitize c
|
sanitize c
|
||||||
|
@ -52,10 +72,10 @@ job desc times user cddir command = combineProperties ("cronned " ++ desc)
|
||||||
| otherwise = '_'
|
| otherwise = '_'
|
||||||
|
|
||||||
-- | Installs a cron job, and runs it niced and ioniced.
|
-- | Installs a cron job, and runs it niced and ioniced.
|
||||||
niceJob :: Desc -> CronTimes -> UserName -> FilePath -> String -> Property NoInfo
|
niceJob :: Desc -> Times -> UserName -> FilePath -> String -> Property NoInfo
|
||||||
niceJob desc times user cddir command = job desc times user cddir
|
niceJob desc times user cddir command = job desc times user cddir
|
||||||
("nice ionice -c 3 sh -c " ++ shellEscape command)
|
("nice ionice -c 3 sh -c " ++ shellEscape command)
|
||||||
|
|
||||||
-- | Installs a cron job to run propellor.
|
-- | Installs a cron job to run propellor.
|
||||||
runPropellor :: CronTimes -> Property NoInfo
|
runPropellor :: Times -> Property NoInfo
|
||||||
runPropellor times = niceJob "propellor" times "root" localdir "./propellor"
|
runPropellor times = niceJob "propellor" times "root" localdir "./propellor"
|
||||||
|
|
|
@ -21,7 +21,7 @@ hasPrivContent :: IsContext c => FilePath -> c -> Property HasInfo
|
||||||
hasPrivContent f = hasPrivContentFrom (PrivDataSourceFile (PrivFile f) f) f
|
hasPrivContent f = hasPrivContentFrom (PrivDataSourceFile (PrivFile f) f) f
|
||||||
|
|
||||||
-- | Like hasPrivContent, but allows specifying a source
|
-- | Like hasPrivContent, but allows specifying a source
|
||||||
-- for PrivData, rather than using PrivDataSourceFile.
|
-- for PrivData, rather than using PrivDataSourceFile .
|
||||||
hasPrivContentFrom :: (IsContext c, IsPrivDataSource s) => s -> FilePath -> c -> Property HasInfo
|
hasPrivContentFrom :: (IsContext c, IsPrivDataSource s) => s -> FilePath -> c -> Property HasInfo
|
||||||
hasPrivContentFrom = hasPrivContent' writeFileProtected
|
hasPrivContentFrom = hasPrivContent' writeFileProtected
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ daemonRunning exportdir = setup <!> unsetup
|
||||||
`requires`
|
`requires`
|
||||||
Apt.serviceInstalledRunning "openbsd-inetd"
|
Apt.serviceInstalledRunning "openbsd-inetd"
|
||||||
`onChange`
|
`onChange`
|
||||||
Service.running "openbsd-inetd"
|
Service.reloaded "openbsd-inetd"
|
||||||
`describe` ("git-daemon exporting " ++ exportdir)
|
`describe` ("git-daemon exporting " ++ exportdir)
|
||||||
unsetup = lacksLine conf (mkl "tcp4")
|
unsetup = lacksLine conf (mkl "tcp4")
|
||||||
`requires`
|
`requires`
|
||||||
|
|
|
@ -2,9 +2,18 @@ module Propellor.Property.HostingProvider.Linode where
|
||||||
|
|
||||||
import Propellor
|
import Propellor
|
||||||
import qualified Propellor.Property.Grub as Grub
|
import qualified Propellor.Property.Grub as Grub
|
||||||
|
import qualified Propellor.Property.File as File
|
||||||
|
import Utility.FileMode
|
||||||
|
|
||||||
-- | Linode's pv-grub-x86_64 does not currently support booting recent
|
-- | Linode's pv-grub-x86_64 does not currently support booting recent
|
||||||
-- Debian kernels compressed with xz. This sets up pv-grub chaing to enable
|
-- Debian kernels compressed with xz. This sets up pv-grub chaing to enable
|
||||||
-- it.
|
-- it.
|
||||||
chainPVGrub :: Grub.TimeoutSecs -> Property NoInfo
|
chainPVGrub :: Grub.TimeoutSecs -> Property NoInfo
|
||||||
chainPVGrub = Grub.chainPVGrub "hd0" "xen/xvda"
|
chainPVGrub = Grub.chainPVGrub "hd0" "xen/xvda"
|
||||||
|
|
||||||
|
-- | Linode disables mlocate's cron job's execute permissions,
|
||||||
|
-- presumably to avoid disk IO. This ensures it's executable.
|
||||||
|
mlocateEnabled :: Property NoInfo
|
||||||
|
mlocateEnabled = "/etc/cron.daily/mlocate"
|
||||||
|
`File.mode` combineModes (readModes ++ executeModes)
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ data NumClients = OnlyClient | MultipleClients
|
||||||
-- > `requires` Ssh.keyImported SshRsa "root" (Context hostname)
|
-- > `requires` Ssh.keyImported SshRsa "root" (Context hostname)
|
||||||
--
|
--
|
||||||
-- How awesome is that?
|
-- How awesome is that?
|
||||||
backup :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Property NoInfo
|
backup :: FilePath -> Cron.Times -> [ObnamParam] -> NumClients -> Property NoInfo
|
||||||
backup dir crontimes params numclients =
|
backup dir crontimes params numclients =
|
||||||
backup' dir crontimes params numclients
|
backup' dir crontimes params numclients
|
||||||
`requires` restored dir params
|
`requires` restored dir params
|
||||||
|
@ -46,7 +46,7 @@ backup dir crontimes params numclients =
|
||||||
--
|
--
|
||||||
-- The gpg secret key will be automatically imported
|
-- The gpg secret key will be automatically imported
|
||||||
-- into root's keyring using Propellor.Property.Gpg.keyImported
|
-- into root's keyring using Propellor.Property.Gpg.keyImported
|
||||||
backupEncrypted :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Gpg.GpgKeyId -> Property HasInfo
|
backupEncrypted :: FilePath -> Cron.Times -> [ObnamParam] -> NumClients -> Gpg.GpgKeyId -> Property HasInfo
|
||||||
backupEncrypted dir crontimes params numclients keyid =
|
backupEncrypted dir crontimes params numclients keyid =
|
||||||
backup dir crontimes params' numclients
|
backup dir crontimes params' numclients
|
||||||
`requires` Gpg.keyImported keyid "root"
|
`requires` Gpg.keyImported keyid "root"
|
||||||
|
@ -54,7 +54,7 @@ backupEncrypted dir crontimes params numclients keyid =
|
||||||
params' = ("--encrypt-with=" ++ Gpg.getGpgKeyId keyid) : params
|
params' = ("--encrypt-with=" ++ Gpg.getGpgKeyId keyid) : params
|
||||||
|
|
||||||
-- | Does a backup, but does not automatically restore.
|
-- | Does a backup, but does not automatically restore.
|
||||||
backup' :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Property NoInfo
|
backup' :: FilePath -> Cron.Times -> [ObnamParam] -> NumClients -> Property NoInfo
|
||||||
backup' dir crontimes params numclients = cronjob `describe` desc
|
backup' dir crontimes params numclients = cronjob `describe` desc
|
||||||
where
|
where
|
||||||
desc = dir ++ " backed up by obnam"
|
desc = dir ++ " backed up by obnam"
|
||||||
|
|
|
@ -4,8 +4,9 @@ module Propellor.Property.Postfix where
|
||||||
|
|
||||||
import Propellor
|
import Propellor
|
||||||
import qualified Propellor.Property.Apt as Apt
|
import qualified Propellor.Property.Apt as Apt
|
||||||
import Propellor.Property.File
|
import qualified Propellor.Property.File as File
|
||||||
import qualified Propellor.Property.Service as Service
|
import qualified Propellor.Property.Service as Service
|
||||||
|
import qualified Propellor.Property.User as User
|
||||||
|
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Data.List
|
import Data.List
|
||||||
|
@ -103,7 +104,7 @@ mainCfIsSet name = do
|
||||||
-- Note that multiline configurations that continue onto the next line
|
-- Note that multiline configurations that continue onto the next line
|
||||||
-- are not currently supported.
|
-- are not currently supported.
|
||||||
dedupMainCf :: Property NoInfo
|
dedupMainCf :: Property NoInfo
|
||||||
dedupMainCf = fileProperty "postfix main.cf dedupped" dedupCf mainCfFile
|
dedupMainCf = File.fileProperty "postfix main.cf dedupped" dedupCf mainCfFile
|
||||||
|
|
||||||
dedupCf :: [String] -> [String]
|
dedupCf :: [String] -> [String]
|
||||||
dedupCf ls =
|
dedupCf ls =
|
||||||
|
@ -125,3 +126,33 @@ dedupCf ls =
|
||||||
dedup c kc ((Right (k, v)):rest) = case M.lookup k kc of
|
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
|
Just n | n > 1 -> dedup c (M.insert k (n - 1) kc) rest
|
||||||
_ -> dedup (fmt k v:c) kc rest
|
_ -> dedup (fmt k v:c) kc rest
|
||||||
|
|
||||||
|
-- | Installs saslauthd and configures it for postfix, authenticating
|
||||||
|
-- against PAM.
|
||||||
|
--
|
||||||
|
-- Does not configure postfix to use it; eg smtpd_sasl_auth_enable = yes
|
||||||
|
-- needs to be set to enable use. See
|
||||||
|
-- https://wiki.debian.org/PostfixAndSASL
|
||||||
|
saslAuthdInstalled :: Property NoInfo
|
||||||
|
saslAuthdInstalled = setupdaemon
|
||||||
|
`requires` Service.running "saslauthd"
|
||||||
|
`requires` postfixgroup
|
||||||
|
`requires` dirperm
|
||||||
|
`requires` Apt.installed ["sasl2-bin"]
|
||||||
|
`requires` smtpdconf
|
||||||
|
where
|
||||||
|
setupdaemon = "/etc/default/saslauthd" `File.containsLines`
|
||||||
|
[ "START=yes"
|
||||||
|
, "OPTIONS=\"-c -m " ++ dir ++ "\""
|
||||||
|
]
|
||||||
|
`onChange` Service.restarted "saslauthd"
|
||||||
|
smtpdconf = "/etc/postfix/sasl/smtpd.conf" `File.containsLines`
|
||||||
|
[ "pwcheck_method: saslauthd"
|
||||||
|
, "mech_list: PLAIN LOGIN"
|
||||||
|
]
|
||||||
|
dirperm = check (not <$> doesDirectoryExist dir) $
|
||||||
|
cmdProperty "dpkg-statoverride"
|
||||||
|
[ "--add", "root", "sasl", "710", dir ]
|
||||||
|
postfixgroup = "postfix" `User.hasGroup` "sasl"
|
||||||
|
`onChange` restarted
|
||||||
|
dir = "/var/spool/postfix/var/run/saslauthd"
|
||||||
|
|
|
@ -9,7 +9,7 @@ import qualified Propellor.Property.Cron as Cron
|
||||||
import qualified Propellor.Property.Ssh as Ssh
|
import qualified Propellor.Property.Ssh as Ssh
|
||||||
import qualified Propellor.Property.File as File
|
import qualified Propellor.Property.File as File
|
||||||
import qualified Propellor.Property.Docker as Docker
|
import qualified Propellor.Property.Docker as Docker
|
||||||
import Propellor.Property.Cron (CronTimes)
|
import Propellor.Property.Cron (Times)
|
||||||
|
|
||||||
builduser :: UserName
|
builduser :: UserName
|
||||||
builduser = "builder"
|
builduser = "builder"
|
||||||
|
@ -25,7 +25,7 @@ builddir = gitbuilderdir </> "build"
|
||||||
|
|
||||||
type TimeOut = String -- eg, 5h
|
type TimeOut = String -- eg, 5h
|
||||||
|
|
||||||
autobuilder :: Architecture -> CronTimes -> TimeOut -> Property HasInfo
|
autobuilder :: Architecture -> Times -> TimeOut -> Property HasInfo
|
||||||
autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props
|
autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props
|
||||||
& Apt.serviceInstalledRunning "cron"
|
& Apt.serviceInstalledRunning "cron"
|
||||||
& Cron.niceJob "gitannexbuilder" crontimes builduser gitbuilderdir
|
& Cron.niceJob "gitannexbuilder" crontimes builduser gitbuilderdir
|
||||||
|
@ -102,10 +102,10 @@ standardAutoBuilderContainer dockerImage arch buildminute timeout = Docker.conta
|
||||||
& User.accountFor builduser
|
& User.accountFor builduser
|
||||||
& tree arch
|
& tree arch
|
||||||
& buildDepsApt
|
& buildDepsApt
|
||||||
& autobuilder arch (show buildminute ++ " * * * *") timeout
|
& autobuilder arch (Cron.Times $ show buildminute ++ " * * * *") timeout
|
||||||
& Docker.tweaked
|
& Docker.tweaked
|
||||||
|
|
||||||
androidAutoBuilderContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Docker.Container
|
androidAutoBuilderContainer :: (System -> Docker.Image) -> Times -> TimeOut -> Docker.Container
|
||||||
androidAutoBuilderContainer dockerImage crontimes timeout =
|
androidAutoBuilderContainer dockerImage crontimes timeout =
|
||||||
androidContainer dockerImage "android-git-annex-builder" (tree "android") builddir
|
androidContainer dockerImage "android-git-annex-builder" (tree "android") builddir
|
||||||
& Apt.unattendedUpgrades
|
& Apt.unattendedUpgrades
|
||||||
|
@ -166,7 +166,7 @@ armelCompanionContainer dockerImage = Docker.container "armel-git-annex-builder-
|
||||||
& Ssh.authorizedKeys builduser (Context "armel-git-annex-builder")
|
& Ssh.authorizedKeys builduser (Context "armel-git-annex-builder")
|
||||||
& Docker.tweaked
|
& Docker.tweaked
|
||||||
|
|
||||||
armelAutoBuilderContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Docker.Container
|
armelAutoBuilderContainer :: (System -> Docker.Image) -> Times -> TimeOut -> Docker.Container
|
||||||
armelAutoBuilderContainer dockerImage crontimes timeout = Docker.container "armel-git-annex-builder"
|
armelAutoBuilderContainer dockerImage crontimes timeout = Docker.container "armel-git-annex-builder"
|
||||||
(dockerImage $ System (Debian Unstable) "armel")
|
(dockerImage $ System (Debian Unstable) "armel")
|
||||||
& os (System (Debian Testing) "armel")
|
& os (System (Debian Testing) "armel")
|
||||||
|
|
|
@ -24,6 +24,7 @@ import Data.String.Utils
|
||||||
|
|
||||||
oldUseNetServer :: [Host] -> Property HasInfo
|
oldUseNetServer :: [Host] -> Property HasInfo
|
||||||
oldUseNetServer hosts = propertyList "olduse.net server" $ props
|
oldUseNetServer hosts = propertyList "olduse.net server" $ props
|
||||||
|
& Apt.installed ["leafnode"]
|
||||||
& oldUseNetInstalled "oldusenet-server"
|
& oldUseNetInstalled "oldusenet-server"
|
||||||
& Obnam.latestVersion
|
& Obnam.latestVersion
|
||||||
& oldUseNetBackup
|
& oldUseNetBackup
|
||||||
|
@ -32,7 +33,6 @@ oldUseNetServer hosts = propertyList "olduse.net server" $ props
|
||||||
removeDirectoryRecursive newsspool
|
removeDirectoryRecursive newsspool
|
||||||
createSymbolicLink (datadir </> "news") newsspool
|
createSymbolicLink (datadir </> "news") newsspool
|
||||||
)
|
)
|
||||||
& Apt.installed ["leafnode"]
|
|
||||||
& "/etc/news/leafnode/config" `File.hasContent`
|
& "/etc/news/leafnode/config" `File.hasContent`
|
||||||
[ "# olduse.net configuration (deployed by propellor)"
|
[ "# olduse.net configuration (deployed by propellor)"
|
||||||
, "expire = 1000000" -- no expiry via texpire
|
, "expire = 1000000" -- no expiry via texpire
|
||||||
|
@ -45,8 +45,8 @@ oldUseNetServer hosts = propertyList "olduse.net server" $ props
|
||||||
& Apt.serviceInstalledRunning "openbsd-inetd"
|
& Apt.serviceInstalledRunning "openbsd-inetd"
|
||||||
& File.notPresent "/etc/cron.daily/leafnode"
|
& File.notPresent "/etc/cron.daily/leafnode"
|
||||||
& File.notPresent "/etc/cron.d/leafnode"
|
& File.notPresent "/etc/cron.d/leafnode"
|
||||||
& Cron.niceJob "oldusenet-expire" "11 1 * * *" "news" newsspool expirecommand
|
& Cron.niceJob "oldusenet-expire" (Cron.Times "11 1 * * *") "news" newsspool expirecommand
|
||||||
& Cron.niceJob "oldusenet-uucp" "*/5 * * * *" "news" "/" uucpcommand
|
& Cron.niceJob "oldusenet-uucp" (Cron.Times "*/5 * * * *") "news" "/" uucpcommand
|
||||||
& Apache.siteEnabled "nntp.olduse.net" nntpcfg
|
& Apache.siteEnabled "nntp.olduse.net" nntpcfg
|
||||||
where
|
where
|
||||||
newsspool = "/var/spool/news"
|
newsspool = "/var/spool/news"
|
||||||
|
@ -65,12 +65,14 @@ oldUseNetServer hosts = propertyList "olduse.net server" $ props
|
||||||
, " </Directory>"
|
, " </Directory>"
|
||||||
]
|
]
|
||||||
|
|
||||||
oldUseNetBackup = Obnam.backup datadir "33 4 * * *"
|
oldUseNetBackup = Obnam.backup datadir (Cron.Times "33 4 * * *")
|
||||||
[ "--repository=sftp://2318@usw-s002.rsync.net/~/olduse.net"
|
[ "--repository=sftp://2318@usw-s002.rsync.net/~/olduse.net"
|
||||||
, "--client-name=spool"
|
, "--client-name=spool"
|
||||||
|
, "--ssh-key=" ++ keyfile
|
||||||
] Obnam.OnlyClient
|
] Obnam.OnlyClient
|
||||||
`requires` Ssh.keyImported SshRsa "root" (Context "olduse.net")
|
`requires` Ssh.keyImported' (Just keyfile) SshRsa "root" (Context "olduse.net")
|
||||||
`requires` Ssh.knownHost hosts "usw-s002.rsync.net" "root"
|
`requires` Ssh.knownHost hosts "usw-s002.rsync.net" "root"
|
||||||
|
keyfile = "/root/.ssh/olduse.net.key"
|
||||||
|
|
||||||
oldUseNetShellBox :: Property HasInfo
|
oldUseNetShellBox :: Property HasInfo
|
||||||
oldUseNetShellBox = propertyList "olduse.net shellbox" $ props
|
oldUseNetShellBox = propertyList "olduse.net shellbox" $ props
|
||||||
|
@ -113,12 +115,12 @@ mumbleServer :: [Host] -> Property HasInfo
|
||||||
mumbleServer hosts = combineProperties hn $ props
|
mumbleServer hosts = combineProperties hn $ props
|
||||||
& Apt.serviceInstalledRunning "mumble-server"
|
& Apt.serviceInstalledRunning "mumble-server"
|
||||||
& Obnam.latestVersion
|
& Obnam.latestVersion
|
||||||
& Obnam.backup "/var/lib/mumble-server" "55 5 * * *"
|
& Obnam.backup "/var/lib/mumble-server" (Cron.Times "55 5 * * *")
|
||||||
[ "--repository=sftp://joey@usbackup.kitenet.net/~/lib/backup/" ++ hn ++ ".obnam"
|
[ "--repository=sftp://2318@usw-s002.rsync.net/~/" ++ hn ++ ".obnam"
|
||||||
, "--client-name=mumble"
|
, "--client-name=mumble"
|
||||||
] Obnam.OnlyClient
|
] Obnam.OnlyClient
|
||||||
`requires` Ssh.keyImported SshRsa "root" (Context hn)
|
`requires` Ssh.keyImported SshRsa "root" (Context hn)
|
||||||
`requires` Ssh.knownHost hosts "usbackup.kitenet.net" "root"
|
`requires` Ssh.knownHost hosts "usw-s002.rsync.net" "root"
|
||||||
& trivial (cmdProperty "chown" ["-R", "mumble-server:mumble-server", "/var/lib/mumble-server"])
|
& trivial (cmdProperty "chown" ["-R", "mumble-server:mumble-server", "/var/lib/mumble-server"])
|
||||||
where
|
where
|
||||||
hn = "mumble.debian.net"
|
hn = "mumble.debian.net"
|
||||||
|
@ -129,8 +131,8 @@ obnamLowMem = combineProperties "obnam tuned for low memory use"
|
||||||
, "/etc/obnam.conf" `File.containsLines`
|
, "/etc/obnam.conf" `File.containsLines`
|
||||||
[ "[config]"
|
[ "[config]"
|
||||||
, "# Suggested by liw to keep Obnam memory consumption down (at some speed cost)."
|
, "# Suggested by liw to keep Obnam memory consumption down (at some speed cost)."
|
||||||
, "upload-queue-size = 128"
|
, "upload-queue-size = 96"
|
||||||
, "lru-size = 128"
|
, "lru-size = 96"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -138,20 +140,20 @@ obnamLowMem = combineProperties "obnam tuned for low memory use"
|
||||||
gitServer :: [Host] -> Property HasInfo
|
gitServer :: [Host] -> Property HasInfo
|
||||||
gitServer hosts = propertyList "git.kitenet.net setup" $ props
|
gitServer hosts = propertyList "git.kitenet.net setup" $ props
|
||||||
& Obnam.latestVersion
|
& Obnam.latestVersion
|
||||||
& Obnam.backupEncrypted "/srv/git" "33 3 * * *"
|
& Obnam.backupEncrypted "/srv/git" (Cron.Times "33 3 * * *")
|
||||||
[ "--repository=sftp://2318@usw-s002.rsync.net/~/git.kitenet.net"
|
[ "--repository=sftp://2318@usw-s002.rsync.net/~/git.kitenet.net"
|
||||||
|
, "--ssh-key=" ++ sshkey
|
||||||
, "--client-name=wren" -- historical
|
, "--client-name=wren" -- historical
|
||||||
] Obnam.OnlyClient (Gpg.GpgKeyId "1B169BE1")
|
] Obnam.OnlyClient (Gpg.GpgKeyId "1B169BE1")
|
||||||
`requires` Ssh.keyImported SshRsa "root" (Context "git.kitenet.net")
|
`requires` Ssh.keyImported' (Just sshkey) SshRsa "root" (Context "git.kitenet.net")
|
||||||
`requires` Ssh.knownHost hosts "usw-s002.rsync.net" "root"
|
`requires` Ssh.knownHost hosts "usw-s002.rsync.net" "root"
|
||||||
`requires` Ssh.authorizedKeys "family" (Context "git.kitenet.net")
|
`requires` Ssh.authorizedKeys "family" (Context "git.kitenet.net")
|
||||||
`requires` User.accountFor "family"
|
`requires` User.accountFor "family"
|
||||||
& Apt.installed ["git", "rsync", "gitweb"]
|
& Apt.installed ["git", "rsync", "gitweb"]
|
||||||
-- backport avoids channel flooding on branch merge
|
& Apt.installed ["git-annex"]
|
||||||
& Apt.installedBackport ["kgb-client"]
|
& Apt.installed ["kgb-client"]
|
||||||
-- backport supports ssh event notification
|
|
||||||
& Apt.installedBackport ["git-annex"]
|
|
||||||
& File.hasPrivContentExposed "/etc/kgb-bot/kgb-client.conf" anyContext
|
& File.hasPrivContentExposed "/etc/kgb-bot/kgb-client.conf" anyContext
|
||||||
|
`requires` File.dirExists "/etc/kgb-bot/"
|
||||||
& Git.daemonRunning "/srv/git"
|
& Git.daemonRunning "/srv/git"
|
||||||
& "/etc/gitweb.conf" `File.containsLines`
|
& "/etc/gitweb.conf" `File.containsLines`
|
||||||
[ "$projectroot = '/srv/git';"
|
[ "$projectroot = '/srv/git';"
|
||||||
|
@ -168,6 +170,7 @@ gitServer hosts = propertyList "git.kitenet.net setup" $ props
|
||||||
& website "git.joeyh.name"
|
& website "git.joeyh.name"
|
||||||
& Apache.modEnabled "cgi"
|
& Apache.modEnabled "cgi"
|
||||||
where
|
where
|
||||||
|
sshkey = "/root/.ssh/git.kitenet.net.key"
|
||||||
website hn = apacheSite hn True
|
website hn = apacheSite hn True
|
||||||
[ " DocumentRoot /srv/web/git.kitenet.net/"
|
[ " DocumentRoot /srv/web/git.kitenet.net/"
|
||||||
, " <Directory /srv/web/git.kitenet.net/>"
|
, " <Directory /srv/web/git.kitenet.net/>"
|
||||||
|
@ -175,6 +178,7 @@ gitServer hosts = propertyList "git.kitenet.net setup" $ props
|
||||||
, " AllowOverride None"
|
, " AllowOverride None"
|
||||||
, " AddHandler cgi-script .cgi"
|
, " AddHandler cgi-script .cgi"
|
||||||
, " DirectoryIndex index.cgi"
|
, " DirectoryIndex index.cgi"
|
||||||
|
, Apache.allowAll
|
||||||
, " </Directory>"
|
, " </Directory>"
|
||||||
, ""
|
, ""
|
||||||
, " ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/"
|
, " ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/"
|
||||||
|
@ -204,7 +208,7 @@ annexWebSite origin hn uuid remotes = propertyList (hn ++" website using git-ann
|
||||||
setup = userScriptProperty "joey" setupscript
|
setup = userScriptProperty "joey" setupscript
|
||||||
setupscript =
|
setupscript =
|
||||||
[ "cd " ++ shellEscape dir
|
[ "cd " ++ shellEscape dir
|
||||||
, "git config annex.uuid " ++ shellEscape uuid
|
, "git annex reinit " ++ shellEscape uuid
|
||||||
] ++ map addremote remotes ++
|
] ++ map addremote remotes ++
|
||||||
[ "git annex get"
|
[ "git annex get"
|
||||||
, "git update-server-info"
|
, "git update-server-info"
|
||||||
|
@ -217,14 +221,14 @@ annexWebSite origin hn uuid remotes = propertyList (hn ++" website using git-ann
|
||||||
, " <Directory /srv/web/"++hn++">"
|
, " <Directory /srv/web/"++hn++">"
|
||||||
, " Options FollowSymLinks"
|
, " Options FollowSymLinks"
|
||||||
, " AllowOverride None"
|
, " AllowOverride None"
|
||||||
|
, Apache.allowAll
|
||||||
, " </Directory>"
|
, " </Directory>"
|
||||||
, " <Directory /srv/web/"++hn++">"
|
, " <Directory /srv/web/"++hn++">"
|
||||||
, " Options Indexes FollowSymLinks ExecCGI"
|
, " Options Indexes FollowSymLinks ExecCGI"
|
||||||
, " AllowOverride None"
|
, " AllowOverride None"
|
||||||
, " AddHandler cgi-script .cgi"
|
, " AddHandler cgi-script .cgi"
|
||||||
, " DirectoryIndex index.html index.cgi"
|
, " DirectoryIndex index.html index.cgi"
|
||||||
, " Order allow,deny"
|
, Apache.allowAll
|
||||||
, " allow from all"
|
|
||||||
, " </Directory>"
|
, " </Directory>"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -252,8 +256,7 @@ apachecfg hn withssl middle
|
||||||
, " <Directory \"/usr/share/apache2/icons\">"
|
, " <Directory \"/usr/share/apache2/icons\">"
|
||||||
, " Options Indexes MultiViews"
|
, " Options Indexes MultiViews"
|
||||||
, " AllowOverride None"
|
, " AllowOverride None"
|
||||||
, " Order allow,deny"
|
, Apache.allowAll
|
||||||
, " Allow from all"
|
|
||||||
, " </Directory>"
|
, " </Directory>"
|
||||||
, "</VirtualHost>"
|
, "</VirtualHost>"
|
||||||
]
|
]
|
||||||
|
@ -288,6 +291,22 @@ gitAnnexDistributor = combineProperties "git-annex distributor, including rsync
|
||||||
, File.ownerGroup d "joey" "joey"
|
, File.ownerGroup d "joey" "joey"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
downloads :: [Host] -> Property HasInfo
|
||||||
|
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" "joey"
|
||||||
|
|
||||||
|
tmp :: Property HasInfo
|
||||||
|
tmp = propertyList "tmp.kitenet.net" $ props
|
||||||
|
& annexWebSite "/srv/git/joey/tmp.git"
|
||||||
|
"tmp.kitenet.net"
|
||||||
|
"26fd6e38-1226-11e2-a75f-ff007033bdba"
|
||||||
|
[]
|
||||||
|
& twitRss
|
||||||
|
& pumpRss
|
||||||
|
|
||||||
-- Twitter, you kill us.
|
-- Twitter, you kill us.
|
||||||
twitRss :: Property HasInfo
|
twitRss :: Property HasInfo
|
||||||
twitRss = combineProperties "twitter rss" $ props
|
twitRss = combineProperties "twitter rss" $ props
|
||||||
|
@ -297,7 +316,7 @@ twitRss = combineProperties "twitter rss" $ props
|
||||||
& feed "http://twitter.com/search/realtime?q=olduse+OR+git-annex+OR+debhelper+OR+etckeeper+OR+ikiwiki+-ashley_ikiwiki" "twittergrep"
|
& feed "http://twitter.com/search/realtime?q=olduse+OR+git-annex+OR+debhelper+OR+etckeeper+OR+ikiwiki+-ashley_ikiwiki" "twittergrep"
|
||||||
where
|
where
|
||||||
dir = "/srv/web/tmp.kitenet.net/twitrss"
|
dir = "/srv/web/tmp.kitenet.net/twitrss"
|
||||||
crontime = "15 * * * *"
|
crontime = Cron.Times "15 * * * *"
|
||||||
feed url desc = Cron.job desc crontime "joey" dir $
|
feed url desc = Cron.job desc crontime "joey" dir $
|
||||||
"./twitRss " ++ shellEscape url ++ " > " ++ shellEscape ("../" ++ desc ++ ".rss")
|
"./twitRss " ++ shellEscape url ++ " > " ++ shellEscape ("../" ++ desc ++ ".rss")
|
||||||
compiled = userScriptProperty "joey"
|
compiled = userScriptProperty "joey"
|
||||||
|
@ -311,9 +330,8 @@ twitRss = combineProperties "twitter rss" $ props
|
||||||
]
|
]
|
||||||
|
|
||||||
-- Work around for expired ssl cert.
|
-- Work around for expired ssl cert.
|
||||||
-- (no longer expired, TODO remove this and change urls)
|
|
||||||
pumpRss :: Property NoInfo
|
pumpRss :: Property NoInfo
|
||||||
pumpRss = Cron.job "pump rss" "15 * * * *" "joey" "/srv/web/tmp.kitenet.net/"
|
pumpRss = Cron.job "pump rss" (Cron.Times "15 * * * *") "joey" "/srv/web/tmp.kitenet.net/"
|
||||||
"wget https://pump2rss.com/feed/joeyh@identi.ca.atom -O pump.atom --no-check-certificate 2>/dev/null"
|
"wget https://pump2rss.com/feed/joeyh@identi.ca.atom -O pump.atom --no-check-certificate 2>/dev/null"
|
||||||
|
|
||||||
ircBouncer :: Property HasInfo
|
ircBouncer :: Property HasInfo
|
||||||
|
@ -323,7 +341,7 @@ ircBouncer = propertyList "IRC bouncer" $ props
|
||||||
& File.dirExists (takeDirectory conf)
|
& File.dirExists (takeDirectory conf)
|
||||||
& File.hasPrivContent conf anyContext
|
& File.hasPrivContent conf anyContext
|
||||||
& File.ownerGroup conf "znc" "znc"
|
& File.ownerGroup conf "znc" "znc"
|
||||||
& Cron.job "znconboot" "@reboot" "znc" "~" "znc"
|
& Cron.job "znconboot" (Cron.Times "@reboot") "znc" "~" "znc"
|
||||||
-- ensure running if it was not already
|
-- ensure running if it was not already
|
||||||
& trivial (userScriptProperty "znc" ["znc || true"])
|
& trivial (userScriptProperty "znc" ["znc || true"])
|
||||||
`describe` "znc running"
|
`describe` "znc running"
|
||||||
|
@ -347,9 +365,9 @@ githubBackup :: Property HasInfo
|
||||||
githubBackup = propertyList "github-backup box" $ props
|
githubBackup = propertyList "github-backup box" $ props
|
||||||
& Apt.installed ["github-backup", "moreutils"]
|
& Apt.installed ["github-backup", "moreutils"]
|
||||||
& githubKeys
|
& githubKeys
|
||||||
& Cron.niceJob "github-backup run" "30 4 * * *" "joey"
|
& Cron.niceJob "github-backup run" (Cron.Times "30 4 * * *") "joey"
|
||||||
"/home/joey/lib/backup" backupcmd
|
"/home/joey/lib/backup" backupcmd
|
||||||
& Cron.niceJob "gitriddance" "30 4 * * *" "joey"
|
& Cron.niceJob "gitriddance" (Cron.Times "30 4 * * *") "joey"
|
||||||
"/home/joey/lib/backup" gitriddancecmd
|
"/home/joey/lib/backup" gitriddancecmd
|
||||||
where
|
where
|
||||||
backupcmd = intercalate "&&" $
|
backupcmd = intercalate "&&" $
|
||||||
|
@ -385,17 +403,17 @@ githubMirrors =
|
||||||
plzuseurl u = "please submit changes to " ++ u ++ " instead of using github pull requests"
|
plzuseurl u = "please submit changes to " ++ u ++ " instead of using github pull requests"
|
||||||
|
|
||||||
rsyncNetBackup :: [Host] -> Property NoInfo
|
rsyncNetBackup :: [Host] -> Property NoInfo
|
||||||
rsyncNetBackup hosts = Cron.niceJob "rsync.net copied in daily" "30 5 * * *"
|
rsyncNetBackup hosts = Cron.niceJob "rsync.net copied in daily" (Cron.Times "30 5 * * *")
|
||||||
"joey" "/home/joey/lib/backup" "mkdir -p rsync.net && rsync --delete -az 2318@usw-s002.rsync.net: rsync.net"
|
"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"
|
`requires` Ssh.knownHost hosts "usw-s002.rsync.net" "joey"
|
||||||
|
|
||||||
backupsBackedupTo :: [Host] -> HostName -> FilePath -> Property NoInfo
|
backupsBackedupFrom :: [Host] -> HostName -> FilePath -> Property NoInfo
|
||||||
backupsBackedupTo hosts desthost destdir = Cron.niceJob desc
|
backupsBackedupFrom hosts srchost destdir = Cron.niceJob desc
|
||||||
"1 1 * * 3" "joey" "/" cmd
|
(Cron.Times "@reboot") "joey" "/" cmd
|
||||||
`requires` Ssh.knownHost hosts desthost "joey"
|
`requires` Ssh.knownHost hosts srchost "joey"
|
||||||
where
|
where
|
||||||
desc = "backups copied to " ++ desthost ++ " weekly"
|
desc = "backups copied from " ++ srchost ++ " on boot"
|
||||||
cmd = "rsync -az --delete /home/joey/lib/backup " ++ desthost ++ ":" ++ destdir
|
cmd = "rsync -az --bwlimit=300K --partial --delete " ++ srchost ++ ":lib/backup/ " ++ destdir </> srchost
|
||||||
|
|
||||||
obnamRepos :: [String] -> Property NoInfo
|
obnamRepos :: [String] -> Property NoInfo
|
||||||
obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs)
|
obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs)
|
||||||
|
@ -408,7 +426,7 @@ obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs)
|
||||||
`before` File.ownerGroup d "joey" "joey"
|
`before` File.ownerGroup d "joey" "joey"
|
||||||
|
|
||||||
podcatcher :: Property NoInfo
|
podcatcher :: Property NoInfo
|
||||||
podcatcher = Cron.niceJob "podcatcher run hourly" "55 * * * *"
|
podcatcher = Cron.niceJob "podcatcher run hourly" (Cron.Times "55 * * * *")
|
||||||
"joey" "/home/joey/lib/sound/podcasts"
|
"joey" "/home/joey/lib/sound/podcasts"
|
||||||
"xargs git-annex importfeed -c annex.genmetadata=true < feeds; mr --quiet update"
|
"xargs git-annex importfeed -c annex.genmetadata=true < feeds; mr --quiet update"
|
||||||
`requires` Apt.installed ["git-annex", "myrepos"]
|
`requires` Apt.installed ["git-annex", "myrepos"]
|
||||||
|
@ -450,6 +468,8 @@ kiteMailServer = propertyList "kitenet.net mail server" $ props
|
||||||
|
|
||||||
& dkimInstalled
|
& dkimInstalled
|
||||||
|
|
||||||
|
& Postfix.saslAuthdInstalled
|
||||||
|
|
||||||
& Apt.installed ["maildrop"]
|
& Apt.installed ["maildrop"]
|
||||||
& "/etc/maildroprc" `File.hasContent`
|
& "/etc/maildroprc" `File.hasContent`
|
||||||
[ "# Global maildrop filter file (deployed with propellor)"
|
[ "# Global maildrop filter file (deployed with propellor)"
|
||||||
|
@ -514,8 +534,13 @@ kiteMailServer = propertyList "kitenet.net mail server" $ props
|
||||||
, "# Filter out client relay lines from headers."
|
, "# Filter out client relay lines from headers."
|
||||||
, "header_checks = pcre:$config_directory/obscure_client_relay.pcre"
|
, "header_checks = pcre:$config_directory/obscure_client_relay.pcre"
|
||||||
|
|
||||||
|
, "# Password auth for relaying (used by errol)"
|
||||||
|
, "smtpd_sasl_auth_enable = yes"
|
||||||
|
, "smtpd_sasl_security_options = noanonymous"
|
||||||
|
, "smtpd_sasl_local_domain = kitenet.net"
|
||||||
|
|
||||||
, "# Enable postgrey."
|
, "# Enable postgrey."
|
||||||
, "smtpd_recipient_restrictions = permit_tls_clientcerts,permit_mynetworks,reject_unauth_destination,check_policy_service inet:127.0.0.1:10023"
|
, "smtpd_recipient_restrictions = permit_tls_clientcerts,permit_sasl_authenticated,,permit_mynetworks,reject_unauth_destination,check_policy_service inet:127.0.0.1:10023"
|
||||||
|
|
||||||
, "# Enable spamass-milter, amavis-milter, opendkim"
|
, "# Enable spamass-milter, amavis-milter, opendkim"
|
||||||
, "smtpd_milters = unix:/spamass/spamass.sock unix:amavis/amavis.sock inet:localhost:8891"
|
, "smtpd_milters = unix:/spamass/spamass.sock unix:amavis/amavis.sock inet:localhost:8891"
|
||||||
|
|
|
@ -12,6 +12,7 @@ module Propellor.Property.Ssh (
|
||||||
pubKey,
|
pubKey,
|
||||||
getPubKey,
|
getPubKey,
|
||||||
keyImported,
|
keyImported,
|
||||||
|
keyImported',
|
||||||
knownHost,
|
knownHost,
|
||||||
authorizedKeys,
|
authorizedKeys,
|
||||||
listenPort
|
listenPort
|
||||||
|
@ -147,13 +148,25 @@ getPubKey = asks (_sshPubKey . hostInfo)
|
||||||
|
|
||||||
-- | Sets up a user with a ssh private key and public key pair from the
|
-- | Sets up a user with a ssh private key and public key pair from the
|
||||||
-- PrivData.
|
-- PrivData.
|
||||||
|
--
|
||||||
|
-- If the user already has a private/public key, it is left unchanged.
|
||||||
keyImported :: IsContext c => SshKeyType -> UserName -> c -> Property HasInfo
|
keyImported :: IsContext c => SshKeyType -> UserName -> c -> Property HasInfo
|
||||||
keyImported keytype user context = combineProperties desc
|
keyImported = keyImported' Nothing
|
||||||
|
|
||||||
|
-- | A file can be speficied to write the key to somewhere other than
|
||||||
|
-- usual. Allows a user to have multiple keys for different roles.
|
||||||
|
keyImported' :: IsContext c => Maybe FilePath -> SshKeyType -> UserName -> c -> Property HasInfo
|
||||||
|
keyImported' dest keytype user context = combineProperties desc
|
||||||
[ installkey (SshPubKey keytype user) (install writeFile ".pub")
|
[ installkey (SshPubKey keytype user) (install writeFile ".pub")
|
||||||
, installkey (SshPrivKey keytype user) (install writeFileProtected "")
|
, installkey (SshPrivKey keytype user) (install writeFileProtected "")
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
desc = user ++ " has ssh key (" ++ fromKeyType keytype ++ ")"
|
desc = unwords $ catMaybes
|
||||||
|
[ Just user
|
||||||
|
, Just "has ssh key"
|
||||||
|
, dest
|
||||||
|
, Just $ "(" ++ fromKeyType keytype ++ ")"
|
||||||
|
]
|
||||||
installkey p a = withPrivData p context $ \getkey ->
|
installkey p a = withPrivData p context $ \getkey ->
|
||||||
property desc $ getkey a
|
property desc $ getkey a
|
||||||
install writer ext key = do
|
install writer ext key = do
|
||||||
|
@ -168,9 +181,11 @@ keyImported keytype user context = combineProperties desc
|
||||||
, File.ownerGroup (takeDirectory f) user user
|
, File.ownerGroup (takeDirectory f) user user
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
keyfile ext = do
|
keyfile ext = case dest of
|
||||||
home <- homeDirectory <$> getUserEntryForName user
|
Nothing -> do
|
||||||
return $ home </> ".ssh" </> "id_" ++ fromKeyType keytype ++ ext
|
home <- homeDirectory <$> getUserEntryForName user
|
||||||
|
return $ home </> ".ssh" </> "id_" ++ fromKeyType keytype ++ ext
|
||||||
|
Just f -> return $ f ++ ext
|
||||||
|
|
||||||
fromKeyType :: SshKeyType -> String
|
fromKeyType :: SshKeyType -> String
|
||||||
fromKeyType SshRsa = "rsa"
|
fromKeyType SshRsa = "rsa"
|
||||||
|
@ -178,7 +193,7 @@ fromKeyType SshDsa = "dsa"
|
||||||
fromKeyType SshEcdsa = "ecdsa"
|
fromKeyType SshEcdsa = "ecdsa"
|
||||||
fromKeyType SshEd25519 = "ed25519"
|
fromKeyType SshEd25519 = "ed25519"
|
||||||
|
|
||||||
-- | Puts some host's ssh public key(s), as set using 'pubKey',
|
-- | Puts some host's ssh public key(s), as set using 'pubKey' or 'hostKey'
|
||||||
-- into the known_hosts file for a user.
|
-- into the known_hosts file for a user.
|
||||||
knownHost :: [Host] -> HostName -> UserName -> Property NoInfo
|
knownHost :: [Host] -> HostName -> UserName -> Property NoInfo
|
||||||
knownHost hosts hn user = property desc $
|
knownHost hosts hn user = property desc $
|
||||||
|
@ -192,6 +207,7 @@ knownHost hosts hn user = property desc $
|
||||||
, f `File.containsLines`
|
, f `File.containsLines`
|
||||||
(map (\k -> hn ++ " " ++ k) (M.elems m))
|
(map (\k -> hn ++ " " ++ k) (M.elems m))
|
||||||
, File.ownerGroup f user user
|
, File.ownerGroup f user user
|
||||||
|
, File.ownerGroup (takeDirectory f) user user
|
||||||
]
|
]
|
||||||
go _ = do
|
go _ = do
|
||||||
warningMessage $ "no configred pubKey for " ++ hn
|
warningMessage $ "no configred pubKey for " ++ hn
|
||||||
|
@ -215,12 +231,17 @@ authorizedKeys user context = withPrivData (SshAuthorizedKeys user) context $ \g
|
||||||
-- | Ensures that a user's authorized_keys contains a line.
|
-- | Ensures that a user's authorized_keys contains a line.
|
||||||
-- Any other lines in the file are preserved as-is.
|
-- Any other lines in the file are preserved as-is.
|
||||||
authorizedKey :: UserName -> String -> Property NoInfo
|
authorizedKey :: UserName -> String -> Property NoInfo
|
||||||
authorizedKey user l = property (user ++ " has autorized_keys line " ++ l) $ do
|
authorizedKey user l = property desc $ do
|
||||||
f <- liftIO $ dotFile "authorized_keys" user
|
f <- liftIO $ dotFile "authorized_keys" user
|
||||||
ensureProperty $
|
ensureProperty $ combineProperties desc
|
||||||
f `File.containsLine` l
|
[ f `File.containsLine` l
|
||||||
`requires` File.dirExists (takeDirectory f)
|
`requires` File.dirExists (takeDirectory f)
|
||||||
`onChange` File.mode f (combineModes [ownerWriteMode, ownerReadMode])
|
`onChange` File.mode f (combineModes [ownerWriteMode, ownerReadMode])
|
||||||
|
, File.ownerGroup f user user
|
||||||
|
, File.ownerGroup (takeDirectory f) user user
|
||||||
|
]
|
||||||
|
where
|
||||||
|
desc = user ++ " has autorized_keys line " ++ l
|
||||||
|
|
||||||
-- | Makes the ssh server listen on a given port, in addition to any other
|
-- | Makes the ssh server listen on a given port, in addition to any other
|
||||||
-- ports it is configured to listen on.
|
-- ports it is configured to listen on.
|
||||||
|
|
|
@ -7,19 +7,78 @@ import qualified Propellor.Property.Service as Service
|
||||||
import Utility.FileMode
|
import Utility.FileMode
|
||||||
|
|
||||||
import System.Posix.Files
|
import System.Posix.Files
|
||||||
|
import Data.Char
|
||||||
|
|
||||||
type HiddenServiceName = String
|
type HiddenServiceName = String
|
||||||
|
|
||||||
|
type NodeName = String
|
||||||
|
|
||||||
|
-- | Sets up a tor bridge. (Not a relay or exit node.)
|
||||||
|
--
|
||||||
|
-- Uses port 443
|
||||||
isBridge :: Property NoInfo
|
isBridge :: Property NoInfo
|
||||||
isBridge = setup `requires` Apt.installed ["tor"]
|
isBridge = isBridge' []
|
||||||
|
|
||||||
|
isBridge' :: [String] -> Property NoInfo
|
||||||
|
isBridge' extraconfig = server config
|
||||||
`describe` "tor bridge"
|
`describe` "tor bridge"
|
||||||
where
|
where
|
||||||
setup = mainConfig `File.hasContent`
|
config =
|
||||||
[ "SocksPort 0"
|
[ "BridgeRelay 1"
|
||||||
, "ORPort 443"
|
|
||||||
, "BridgeRelay 1"
|
|
||||||
, "Exitpolicy reject *:*"
|
, "Exitpolicy reject *:*"
|
||||||
] `onChange` restarted
|
, "ORPort 443"
|
||||||
|
] ++ extraconfig
|
||||||
|
|
||||||
|
-- | Sets up a tor relay.
|
||||||
|
--
|
||||||
|
-- Uses port 443
|
||||||
|
isRelay :: Property NoInfo
|
||||||
|
isRelay = isRelay' []
|
||||||
|
|
||||||
|
isRelay' :: [String] -> Property NoInfo
|
||||||
|
isRelay' extraconfig = server config
|
||||||
|
`describe` "tor relay"
|
||||||
|
where
|
||||||
|
config =
|
||||||
|
[ "BridgeRelay 0"
|
||||||
|
, "Exitpolicy reject *:*"
|
||||||
|
, "ORPort 443"
|
||||||
|
] ++ extraconfig
|
||||||
|
|
||||||
|
-- | Converts a property like isBridge' or isRelay' to be a named
|
||||||
|
-- node, with a known private key.
|
||||||
|
--
|
||||||
|
-- This can be moved to a different IP without needing to wait to
|
||||||
|
-- accumulate trust.
|
||||||
|
--
|
||||||
|
-- The base property can be used to start out and then upgraded to
|
||||||
|
-- a named property later.
|
||||||
|
named :: NodeName -> ([String] -> Property NoInfo) -> Property HasInfo
|
||||||
|
named n basep = p `describe` (getDesc p ++ " " ++ n)
|
||||||
|
where
|
||||||
|
p = basep ["Nickname " ++ saneNickname n]
|
||||||
|
`requires` torPrivKey (Context ("tor " ++ n))
|
||||||
|
|
||||||
|
-- | A tor server (bridge, relay, or exit)
|
||||||
|
-- Don't use if you just want to run tor for personal use.
|
||||||
|
server :: [String] -> Property NoInfo
|
||||||
|
server extraconfig = setup
|
||||||
|
`requires` Apt.installed ["tor", "ntp"]
|
||||||
|
`describe` "tor server"
|
||||||
|
where
|
||||||
|
setup = mainConfig `File.hasContent` config
|
||||||
|
`onChange` restarted
|
||||||
|
config =
|
||||||
|
[ "SocksPort 0"
|
||||||
|
] ++ extraconfig
|
||||||
|
|
||||||
|
torPrivKey :: Context -> Property HasInfo
|
||||||
|
torPrivKey context = f `File.hasPrivContent` context
|
||||||
|
`onChange` File.ownerGroup f user user
|
||||||
|
-- install tor first, so the directory exists with right perms
|
||||||
|
`requires` Apt.installed ["tor"]
|
||||||
|
where
|
||||||
|
f = "/var/lib/tor/keys/secret_id_key"
|
||||||
|
|
||||||
hiddenServiceAvailable :: HiddenServiceName -> Int -> Property NoInfo
|
hiddenServiceAvailable :: HiddenServiceName -> Int -> Property NoInfo
|
||||||
hiddenServiceAvailable hn port = hiddenServiceHostName prop
|
hiddenServiceAvailable hn port = hiddenServiceHostName prop
|
||||||
|
@ -80,3 +139,14 @@ varRun = "/var/run/tor"
|
||||||
|
|
||||||
user :: UserName
|
user :: UserName
|
||||||
user = "debian-tor"
|
user = "debian-tor"
|
||||||
|
|
||||||
|
type NickName = String
|
||||||
|
|
||||||
|
-- | Convert String to a valid tor NickName.
|
||||||
|
saneNickname :: String -> NickName
|
||||||
|
saneNickname s
|
||||||
|
| null n = "unnamed"
|
||||||
|
| otherwise = n
|
||||||
|
where
|
||||||
|
legal c = isNumber c || isAsciiUpper c || isAsciiLower c
|
||||||
|
n = take 19 $ filter legal s
|
||||||
|
|
Loading…
Reference in New Issue