Merge branch 'joeyconfig'
Conflicts: privdata.joey/privdata.gpg
This commit is contained in:
commit
5d3408d322
|
@ -7,4 +7,7 @@ Setup
|
||||||
Setup.hi
|
Setup.hi
|
||||||
Setup.o
|
Setup.o
|
||||||
docker
|
docker
|
||||||
|
chroot
|
||||||
propellor.1
|
propellor.1
|
||||||
|
.lock
|
||||||
|
.lastchecked
|
||||||
|
|
|
@ -76,7 +76,6 @@ darkstar = host "darkstar.kitenet.net"
|
||||||
& ipv6 "2001:4830:1600:187::2" -- sixxs tunnel
|
& ipv6 "2001:4830:1600:187::2" -- sixxs tunnel
|
||||||
|
|
||||||
& Apt.buildDep ["git-annex"] `period` Daily
|
& Apt.buildDep ["git-annex"] `period` Daily
|
||||||
& Docker.configured
|
|
||||||
|
|
||||||
& JoeySites.postfixClientRelay (Context "darkstar.kitenet.net")
|
& JoeySites.postfixClientRelay (Context "darkstar.kitenet.net")
|
||||||
& JoeySites.dkimMilter
|
& JoeySites.dkimMilter
|
||||||
|
@ -84,7 +83,6 @@ darkstar = host "darkstar.kitenet.net"
|
||||||
gnu :: Host
|
gnu :: Host
|
||||||
gnu = host "gnu.kitenet.net"
|
gnu = host "gnu.kitenet.net"
|
||||||
& Apt.buildDep ["git-annex"] `period` Daily
|
& Apt.buildDep ["git-annex"] `period` Daily
|
||||||
& Docker.configured
|
|
||||||
|
|
||||||
& JoeySites.postfixClientRelay (Context "gnu.kitenet.net")
|
& JoeySites.postfixClientRelay (Context "gnu.kitenet.net")
|
||||||
& JoeySites.dkimMilter
|
& JoeySites.dkimMilter
|
||||||
|
@ -98,18 +96,18 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64"
|
||||||
& Ssh.randomHostKeys
|
& Ssh.randomHostKeys
|
||||||
& Apt.unattendedUpgrades
|
& Apt.unattendedUpgrades
|
||||||
& Network.ipv6to4
|
& Network.ipv6to4
|
||||||
|
|
||||||
& Tor.isRelay
|
& Tor.isRelay
|
||||||
& Tor.named "kite1"
|
& Tor.named "kite1"
|
||||||
& Tor.bandwidthRate (Tor.PerMonth "400 GB")
|
& Tor.bandwidthRate (Tor.PerMonth "400 GB")
|
||||||
|
|
||||||
& Docker.configured
|
& Systemd.nspawned webserver
|
||||||
& Docker.garbageCollected `period` Daily
|
|
||||||
& Docker.docked webserver
|
|
||||||
& File.dirExists "/var/www/html"
|
& File.dirExists "/var/www/html"
|
||||||
& File.notPresent "/var/www/html/index.html"
|
& File.notPresent "/var/www/index.html"
|
||||||
& "/var/www/index.html" `File.hasContent` ["hello, world"]
|
& "/var/www/html/index.html" `File.hasContent` ["hello, world"]
|
||||||
& alias "helloworld.kitenet.net"
|
& alias "helloworld.kitenet.net"
|
||||||
& Docker.docked oldusenetShellBox
|
|
||||||
|
& Systemd.nspawned oldusenetShellBox
|
||||||
|
|
||||||
& JoeySites.scrollBox
|
& JoeySites.scrollBox
|
||||||
& alias "scroll.joeyh.name"
|
& alias "scroll.joeyh.name"
|
||||||
|
@ -133,9 +131,11 @@ orca = standardSystem "orca.kitenet.net" Unstable "amd64"
|
||||||
& Apt.serviceInstalledRunning "ntp"
|
& Apt.serviceInstalledRunning "ntp"
|
||||||
& Systemd.persistentJournal
|
& Systemd.persistentJournal
|
||||||
|
|
||||||
& Systemd.nspawned (GitAnnexBuilder.standardAutoBuilderContainer
|
& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer
|
||||||
|
GitAnnexBuilder.standardAutoBuilder
|
||||||
(System (Debian Testing) "amd64") fifteenpast "2h")
|
(System (Debian Testing) "amd64") fifteenpast "2h")
|
||||||
& Systemd.nspawned (GitAnnexBuilder.standardAutoBuilderContainer
|
& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer
|
||||||
|
GitAnnexBuilder.standardAutoBuilder
|
||||||
(System (Debian Testing) "i386") fifteenpast "2h")
|
(System (Debian Testing) "i386") fifteenpast "2h")
|
||||||
& Systemd.nspawned (GitAnnexBuilder.androidAutoBuilderContainer
|
& Systemd.nspawned (GitAnnexBuilder.androidAutoBuilderContainer
|
||||||
(Cron.Times "1 1 * * *") "3h")
|
(Cron.Times "1 1 * * *") "3h")
|
||||||
|
@ -151,15 +151,20 @@ honeybee = standardSystem "honeybee.kitenet.net" Testing "armhf"
|
||||||
-- (Also, system is not currently running a stock kernel,
|
-- (Also, system is not currently running a stock kernel,
|
||||||
-- although it should be able to.)
|
-- although it should be able to.)
|
||||||
& Postfix.satellite
|
& Postfix.satellite
|
||||||
& Apt.serviceInstalledRunning "ntp"
|
|
||||||
& Apt.serviceInstalledRunning "aiccu"
|
& Apt.serviceInstalledRunning "aiccu"
|
||||||
|
& Apt.serviceInstalledRunning "swapspace"
|
||||||
|
& Apt.serviceInstalledRunning "ntp"
|
||||||
|
|
||||||
-- Not using systemd-nspawn because it's broken (kernel issue?)
|
-- Not using systemd-nspawn because it's broken (kernel issue?)
|
||||||
-- & Systemd.nspawned (GitAnnexBuilder.standardAutoBuilderContainer
|
-- & Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer
|
||||||
-- osver Cron.Daily "22h")
|
-- GitAnnexBuilder.armAutoBuilder
|
||||||
|
-- builderos Cron.Daily "22h")
|
||||||
& Chroot.provisioned
|
& Chroot.provisioned
|
||||||
(Chroot.debootstrapped builderos mempty "/var/lib/container/armel-git-annex-builder"
|
(Chroot.debootstrapped builderos mempty "/var/lib/container/armel-git-annex-builder"
|
||||||
& GitAnnexBuilder.standardAutoBuilder builderos Cron.Daily "22h")
|
& "/etc/timezone" `File.hasContent` ["America/New_York"]
|
||||||
|
& GitAnnexBuilder.armAutoBuilder
|
||||||
|
builderos (Cron.Times "1 1 * * *") "12h"
|
||||||
|
)
|
||||||
where
|
where
|
||||||
-- Using unstable to get new enough ghc for TH on arm.
|
-- Using unstable to get new enough ghc for TH on arm.
|
||||||
builderos = System (Debian Unstable) "armel"
|
builderos = System (Debian Unstable) "armel"
|
||||||
|
@ -247,9 +252,6 @@ kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64"
|
||||||
, "zsh"
|
, "zsh"
|
||||||
]
|
]
|
||||||
|
|
||||||
& Docker.configured
|
|
||||||
& Docker.garbageCollected `period` Daily
|
|
||||||
|
|
||||||
& alias "nntp.olduse.net"
|
& alias "nntp.olduse.net"
|
||||||
& JoeySites.oldUseNetServer hosts
|
& JoeySites.oldUseNetServer hosts
|
||||||
|
|
||||||
|
@ -306,13 +308,14 @@ elephant = standardSystem "elephant.kitenet.net" Unstable "amd64"
|
||||||
& myDnsSecondary
|
& myDnsSecondary
|
||||||
|
|
||||||
& Docker.configured
|
& Docker.configured
|
||||||
& Docker.docked oldusenetShellBox
|
|
||||||
& Docker.docked openidProvider
|
& Docker.docked openidProvider
|
||||||
`requires` Apt.serviceInstalledRunning "ntp"
|
`requires` Apt.serviceInstalledRunning "ntp"
|
||||||
& Docker.docked ancientKitenet
|
& Docker.docked ancientKitenet
|
||||||
& Docker.docked jerryPlay
|
& Docker.docked jerryPlay
|
||||||
& Docker.garbageCollected `period` (Weekly (Just 1))
|
& Docker.garbageCollected `period` (Weekly (Just 1))
|
||||||
|
|
||||||
|
& Systemd.nspawned oldusenetShellBox
|
||||||
|
|
||||||
& JoeySites.scrollBox
|
& JoeySites.scrollBox
|
||||||
& alias "scroll.joeyh.name"
|
& alias "scroll.joeyh.name"
|
||||||
& alias "eu.scroll.joeyh.name"
|
& alias "eu.scroll.joeyh.name"
|
||||||
|
@ -320,7 +323,7 @@ elephant = standardSystem "elephant.kitenet.net" Unstable "amd64"
|
||||||
-- For https port 443, shellinabox with ssh login to
|
-- For https port 443, shellinabox with ssh login to
|
||||||
-- kitenet.net
|
-- kitenet.net
|
||||||
& alias "shell.kitenet.net"
|
& alias "shell.kitenet.net"
|
||||||
& Docker.docked kiteShellBox
|
& Systemd.nspawned kiteShellBox
|
||||||
-- Nothing is using http port 80, so listen on
|
-- Nothing is using http port 80, so listen on
|
||||||
-- that port for ssh, for traveling on bad networks that
|
-- that port for ssh, for traveling on bad networks that
|
||||||
-- block 22.
|
-- block 22.
|
||||||
|
@ -397,22 +400,21 @@ iabak = host "iabak.archiveteam.org"
|
||||||
--' __|II| ,.
|
--' __|II| ,.
|
||||||
---- __|II|II|__ ( \_,/\
|
---- __|II|II|__ ( \_,/\
|
||||||
--'-------'\o/-'-.-'-.-'-.- __|II|II|II|II|___/ __/ -'-.-'-.-'-.-'-.-'-.-'-
|
--'-------'\o/-'-.-'-.-'-.- __|II|II|II|II|___/ __/ -'-.-'-.-'-.-'-.-'-.-'-
|
||||||
-------------------------- | [Docker] / --------------------------
|
-------------------------- | [Containers] / --------------------------
|
||||||
-------------------------- : / ---------------------------
|
-------------------------- : / ---------------------------
|
||||||
--------------------------- \____, o ,' ----------------------------
|
--------------------------- \____, o ,' ----------------------------
|
||||||
---------------------------- '--,___________,' -----------------------------
|
---------------------------- '--,___________,' -----------------------------
|
||||||
|
|
||||||
-- Simple web server, publishing the outside host's /var/www
|
-- Simple web server, publishing the outside host's /var/www
|
||||||
webserver :: Docker.Container
|
webserver :: Systemd.Container
|
||||||
webserver = standardStableContainer "webserver"
|
webserver = standardStableContainer "webserver"
|
||||||
& Docker.publish "80:80"
|
& Systemd.bind "/var/www"
|
||||||
& Docker.volume "/var/www:/var/www"
|
|
||||||
& Apt.serviceInstalledRunning "apache2"
|
& Apt.serviceInstalledRunning "apache2"
|
||||||
|
|
||||||
-- My own openid provider. Uses php, so containerized for security
|
-- My own openid provider. Uses php, so containerized for security
|
||||||
-- and administrative sanity.
|
-- and administrative sanity.
|
||||||
openidProvider :: Docker.Container
|
openidProvider :: Docker.Container
|
||||||
openidProvider = standardStableContainer "openid-provider"
|
openidProvider = standardStableDockerContainer "openid-provider"
|
||||||
& alias "openid.kitenet.net"
|
& alias "openid.kitenet.net"
|
||||||
& Docker.publish "8081:80"
|
& Docker.publish "8081:80"
|
||||||
& OpenId.providerFor [User "joey", User "liw"]
|
& OpenId.providerFor [User "joey", User "liw"]
|
||||||
|
@ -420,32 +422,30 @@ openidProvider = standardStableContainer "openid-provider"
|
||||||
|
|
||||||
-- Exhibit: kite's 90's website.
|
-- Exhibit: kite's 90's website.
|
||||||
ancientKitenet :: Docker.Container
|
ancientKitenet :: Docker.Container
|
||||||
ancientKitenet = standardStableContainer "ancient-kitenet"
|
ancientKitenet = standardStableDockerContainer "ancient-kitenet"
|
||||||
& alias "ancient.kitenet.net"
|
& alias "ancient.kitenet.net"
|
||||||
& Docker.publish "1994:80"
|
& Docker.publish "1994:80"
|
||||||
& Apt.serviceInstalledRunning "apache2"
|
& Apt.serviceInstalledRunning "apache2"
|
||||||
& Git.cloned (User "root") "git://kitenet-net.branchable.com/" "/var/www"
|
& Git.cloned (User "root") "git://kitenet-net.branchable.com/" "/var/www/html"
|
||||||
(Just "remotes/origin/old-kitenet.net")
|
(Just "remotes/origin/old-kitenet.net")
|
||||||
|
|
||||||
oldusenetShellBox :: Docker.Container
|
oldusenetShellBox :: Systemd.Container
|
||||||
oldusenetShellBox = standardStableContainer "oldusenet-shellbox"
|
oldusenetShellBox = standardStableContainer "oldusenet-shellbox"
|
||||||
& alias "shell.olduse.net"
|
& alias "shell.olduse.net"
|
||||||
& Docker.publish "4200:4200"
|
|
||||||
& JoeySites.oldUseNetShellBox
|
& JoeySites.oldUseNetShellBox
|
||||||
|
|
||||||
jerryPlay :: Docker.Container
|
jerryPlay :: Docker.Container
|
||||||
jerryPlay = standardContainer "jerryplay" Unstable "amd64"
|
jerryPlay = standardDockerContainer "jerryplay" Unstable "amd64"
|
||||||
& alias "jerryplay.kitenet.net"
|
& alias "jerryplay.kitenet.net"
|
||||||
& Docker.publish "2202:22"
|
& Docker.publish "2202:22"
|
||||||
& Docker.publish "8001:80"
|
& Docker.publish "8001:80"
|
||||||
& Apt.installed ["ssh"]
|
& Apt.installed ["ssh"]
|
||||||
& User.hasSomePassword (User "root")
|
& User.hasSomePassword (User "root")
|
||||||
& Ssh.permitRootLogin True
|
& Ssh.permitRootLogin True
|
||||||
|
|
||||||
kiteShellBox :: Docker.Container
|
kiteShellBox :: Systemd.Container
|
||||||
kiteShellBox = standardStableContainer "kiteshellbox"
|
kiteShellBox = standardStableContainer "kiteshellbox"
|
||||||
& JoeySites.kiteShellBox
|
& JoeySites.kiteShellBox
|
||||||
& Docker.publish "443:443"
|
|
||||||
|
|
||||||
type Motd = [String]
|
type Motd = [String]
|
||||||
|
|
||||||
|
@ -476,12 +476,25 @@ standardSystemUnhardened hn suite arch motd = host hn
|
||||||
& 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
|
||||||
|
|
||||||
standardStableContainer :: Docker.ContainerName -> Docker.Container
|
-- This is my standard container setup, Featuring automatic upgrades.
|
||||||
|
standardContainer :: Systemd.MachineName -> DebianSuite -> Architecture -> Systemd.Container
|
||||||
|
standardContainer name suite arch = Systemd.container name chroot
|
||||||
|
& os system
|
||||||
|
& Apt.stdSourcesList `onChange` Apt.upgrade
|
||||||
|
& Apt.unattendedUpgrades
|
||||||
|
& Apt.cacheCleaned
|
||||||
|
where
|
||||||
|
system = System (Debian suite) arch
|
||||||
|
chroot = Chroot.debootstrapped system mempty
|
||||||
|
|
||||||
|
standardStableContainer :: Systemd.MachineName -> Systemd.Container
|
||||||
standardStableContainer name = standardContainer name (Stable "jessie") "amd64"
|
standardStableContainer name = standardContainer name (Stable "jessie") "amd64"
|
||||||
|
|
||||||
-- This is my standard container setup, Featuring automatic upgrades.
|
standardStableDockerContainer :: Docker.ContainerName -> Docker.Container
|
||||||
standardContainer :: Docker.ContainerName -> DebianSuite -> Architecture -> Docker.Container
|
standardStableDockerContainer name = standardDockerContainer name (Stable "jessie") "amd64"
|
||||||
standardContainer name suite arch = Docker.container name (dockerImage system)
|
|
||||||
|
standardDockerContainer :: Docker.ContainerName -> DebianSuite -> Architecture -> Docker.Container
|
||||||
|
standardDockerContainer name suite arch = Docker.container name (dockerImage system)
|
||||||
& os system
|
& os system
|
||||||
& Apt.stdSourcesList `onChange` Apt.upgrade
|
& Apt.stdSourcesList `onChange` Apt.upgrade
|
||||||
& Apt.unattendedUpgrades
|
& Apt.unattendedUpgrades
|
||||||
|
|
|
@ -8,13 +8,22 @@ propellor (2.5.0) UNRELEASED; urgency=medium
|
||||||
* createProcess from Propellor.Property.Cmd, so they are available
|
* createProcess from Propellor.Property.Cmd, so they are available
|
||||||
for use in constricting your own Properties when using propellor
|
for use in constricting your own Properties when using propellor
|
||||||
as a library.
|
as a library.
|
||||||
* Improve enter-machine scripts for nspawn containers to unset most
|
* Improve enter-machine scripts for systemd-nspawn containers to unset most
|
||||||
environment variables.
|
environment variables.
|
||||||
* Fix Postfix.satellite bug; the default relayhost was set to the
|
* Fix Postfix.satellite bug; the default relayhost was set to the
|
||||||
domain, not to smtp.domain as documented.
|
domain, not to smtp.domain as documented.
|
||||||
* Mount /proc inside a chroot before provisioning it, to work around #787227
|
* Mount /proc inside a chroot before provisioning it, to work around #787227
|
||||||
* --spin now works when given a short hostname that only resolves to an
|
* --spin now works when given a short hostname that only resolves to an
|
||||||
ipv6 address.
|
ipv6 address.
|
||||||
|
* Added publish property for systemd-spawn containers, for port publishing.
|
||||||
|
(Needs systemd version 220.)
|
||||||
|
* Added bind and bindRo properties for systemd-spawn containers.
|
||||||
|
* Firewall: Port was changed to a newtype, and the Port and PortRange
|
||||||
|
constructors of Rules were changed to DPort and DportRange, respectively.
|
||||||
|
(API change)
|
||||||
|
* Docker: volume and publish accept Bound FilePath and Bound Port,
|
||||||
|
respectively. They also continue to accept Strings, for backwards
|
||||||
|
compatability.
|
||||||
|
|
||||||
-- Joey Hess <id@joeyh.name> Thu, 07 May 2015 12:08:34 -0400
|
-- Joey Hess <id@joeyh.name> Thu, 07 May 2015 12:08:34 -0400
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,7 @@ Library
|
||||||
Propellor.Exception
|
Propellor.Exception
|
||||||
Propellor.Types
|
Propellor.Types
|
||||||
Propellor.Types.Chroot
|
Propellor.Types.Chroot
|
||||||
|
Propellor.Types.Container
|
||||||
Propellor.Types.Docker
|
Propellor.Types.Docker
|
||||||
Propellor.Types.Dns
|
Propellor.Types.Dns
|
||||||
Propellor.Types.Empty
|
Propellor.Types.Empty
|
||||||
|
|
|
@ -16,10 +16,10 @@ import Propellor
|
||||||
import Propellor.Types.CmdLine
|
import Propellor.Types.CmdLine
|
||||||
import Propellor.Types.Chroot
|
import Propellor.Types.Chroot
|
||||||
import Propellor.Property.Chroot.Util
|
import Propellor.Property.Chroot.Util
|
||||||
import Propellor.Property.Mount
|
|
||||||
import qualified Propellor.Property.Debootstrap as Debootstrap
|
import qualified Propellor.Property.Debootstrap as Debootstrap
|
||||||
import qualified Propellor.Property.Systemd.Core as Systemd
|
import qualified Propellor.Property.Systemd.Core as Systemd
|
||||||
import qualified Propellor.Shim as Shim
|
import qualified Propellor.Shim as Shim
|
||||||
|
import Propellor.Property.Mount
|
||||||
|
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Data.List.Utils
|
import Data.List.Utils
|
||||||
|
@ -70,7 +70,7 @@ provisioned' propigator c@(Chroot loc system builderconf _) systemdonly =
|
||||||
where
|
where
|
||||||
go desc a = propertyList (chrootDesc c desc) [a]
|
go desc a = propertyList (chrootDesc c desc) [a]
|
||||||
|
|
||||||
setup = propellChroot c (inChrootProcess c) systemdonly
|
setup = propellChroot c (inChrootProcess (not systemdonly) c) systemdonly
|
||||||
`requires` toProp built
|
`requires` toProp built
|
||||||
|
|
||||||
built = case (system, builderconf) of
|
built = case (system, builderconf) of
|
||||||
|
@ -95,7 +95,7 @@ chrootInfo (Chroot loc _ _ h) =
|
||||||
mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } }
|
mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } }
|
||||||
|
|
||||||
-- | Propellor is run inside the chroot to provision it.
|
-- | Propellor is run inside the chroot to provision it.
|
||||||
propellChroot :: Chroot -> ([String] -> CreateProcess) -> Bool -> Property NoInfo
|
propellChroot :: Chroot -> ([String] -> IO (CreateProcess, IO ())) -> Bool -> Property NoInfo
|
||||||
propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "provisioned") $ do
|
propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "provisioned") $ do
|
||||||
let d = localdir </> shimdir c
|
let d = localdir </> shimdir c
|
||||||
let me = localdir </> "propellor"
|
let me = localdir </> "propellor"
|
||||||
|
@ -103,7 +103,6 @@ propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "
|
||||||
( pure (Shim.file me d)
|
( pure (Shim.file me d)
|
||||||
, Shim.setup me Nothing d
|
, Shim.setup me Nothing d
|
||||||
)
|
)
|
||||||
liftIO mountproc
|
|
||||||
ifM (liftIO $ bindmount shim)
|
ifM (liftIO $ bindmount shim)
|
||||||
( chainprovision shim
|
( chainprovision shim
|
||||||
, return FailedChange
|
, return FailedChange
|
||||||
|
@ -119,25 +118,21 @@ propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "
|
||||||
, File localdir, File mntpnt
|
, File localdir, File mntpnt
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
-- /proc needs to be mounted in the chroot for the linker to use
|
|
||||||
-- /proc/self/exe which is necessary for some commands to work
|
|
||||||
mountproc = unlessM (elem procloc <$> mountPointsBelow loc) $
|
|
||||||
void $ mount "proc" "proc" procloc
|
|
||||||
procloc = loc </> "proc"
|
|
||||||
|
|
||||||
chainprovision shim = do
|
chainprovision shim = do
|
||||||
parenthost <- asks hostName
|
parenthost <- asks hostName
|
||||||
cmd <- liftIO $ toChain parenthost c systemdonly
|
cmd <- liftIO $ toChain parenthost c systemdonly
|
||||||
pe <- liftIO standardPathEnv
|
pe <- liftIO standardPathEnv
|
||||||
let p = mkproc
|
(p, cleanup) <- liftIO $ mkproc
|
||||||
[ shim
|
[ shim
|
||||||
, "--continue"
|
, "--continue"
|
||||||
, show cmd
|
, show cmd
|
||||||
]
|
]
|
||||||
let p' = p { env = Just pe }
|
let p' = p { env = Just pe }
|
||||||
liftIO $ withHandle StdoutHandle createProcessSuccess p'
|
r <- liftIO $ withHandle StdoutHandle createProcessSuccess p'
|
||||||
processChainOutput
|
processChainOutput
|
||||||
|
liftIO cleanup
|
||||||
|
return r
|
||||||
|
|
||||||
toChain :: HostName -> Chroot -> Bool -> IO CmdLine
|
toChain :: HostName -> Chroot -> Bool -> IO CmdLine
|
||||||
toChain parenthost (Chroot loc _ _ _) systemdonly = do
|
toChain parenthost (Chroot loc _ _ _) systemdonly = do
|
||||||
|
@ -164,8 +159,22 @@ chain hostlist (ChrootChain hn loc systemdonly onconsole) =
|
||||||
putStrLn $ "\n" ++ show r
|
putStrLn $ "\n" ++ show r
|
||||||
chain _ _ = errorMessage "bad chain command"
|
chain _ _ = errorMessage "bad chain command"
|
||||||
|
|
||||||
inChrootProcess :: Chroot -> [String] -> CreateProcess
|
inChrootProcess :: Bool -> Chroot -> [String] -> IO (CreateProcess, IO ())
|
||||||
inChrootProcess (Chroot loc _ _ _) cmd = proc "chroot" (loc:cmd)
|
inChrootProcess keepprocmounted (Chroot loc _ _ _) cmd = do
|
||||||
|
mountproc
|
||||||
|
return (proc "chroot" (loc:cmd), cleanup)
|
||||||
|
where
|
||||||
|
-- /proc needs to be mounted in the chroot for the linker to use
|
||||||
|
-- /proc/self/exe which is necessary for some commands to work
|
||||||
|
mountproc = unlessM (elem procloc <$> mountPointsBelow loc) $
|
||||||
|
void $ mount "proc" "proc" procloc
|
||||||
|
|
||||||
|
procloc = loc </> "proc"
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
| keepprocmounted = noop
|
||||||
|
| otherwise = whenM (elem procloc <$> mountPointsBelow loc) $
|
||||||
|
umountLazy procloc
|
||||||
|
|
||||||
provisioningLock :: FilePath -> FilePath
|
provisioningLock :: FilePath -> FilePath
|
||||||
provisioningLock containerloc = "chroot" </> mungeloc containerloc ++ ".lock"
|
provisioningLock containerloc = "chroot" </> mungeloc containerloc ++ ".lock"
|
||||||
|
|
|
@ -23,9 +23,11 @@ module Propellor.Property.Docker (
|
||||||
-- * Container configuration
|
-- * Container configuration
|
||||||
dns,
|
dns,
|
||||||
hostname,
|
hostname,
|
||||||
|
Publishable,
|
||||||
publish,
|
publish,
|
||||||
expose,
|
expose,
|
||||||
user,
|
user,
|
||||||
|
Mountable,
|
||||||
volume,
|
volume,
|
||||||
volumes_from,
|
volumes_from,
|
||||||
workdir,
|
workdir,
|
||||||
|
@ -43,6 +45,7 @@ module Propellor.Property.Docker (
|
||||||
|
|
||||||
import Propellor hiding (init)
|
import Propellor hiding (init)
|
||||||
import Propellor.Types.Docker
|
import Propellor.Types.Docker
|
||||||
|
import Propellor.Types.Container
|
||||||
import Propellor.Types.CmdLine
|
import Propellor.Types.CmdLine
|
||||||
import qualified Propellor.Property.File as File
|
import qualified Propellor.Property.File as File
|
||||||
import qualified Propellor.Property.Apt as Apt
|
import qualified Propellor.Property.Apt as Apt
|
||||||
|
@ -254,10 +257,19 @@ hostname = runProp "hostname"
|
||||||
name :: String -> Property HasInfo
|
name :: String -> Property HasInfo
|
||||||
name = runProp "name"
|
name = runProp "name"
|
||||||
|
|
||||||
|
class Publishable p where
|
||||||
|
toPublish :: p -> String
|
||||||
|
|
||||||
|
instance Publishable (Bound Port) where
|
||||||
|
toPublish p = show (hostSide p) ++ ":" ++ show (containerSide p)
|
||||||
|
|
||||||
|
-- | string format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
|
||||||
|
instance Publishable String where
|
||||||
|
toPublish = id
|
||||||
|
|
||||||
-- | Publish a container's port to the host
|
-- | Publish a container's port to the host
|
||||||
-- (format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort)
|
publish :: Publishable p => p -> Property HasInfo
|
||||||
publish :: String -> Property HasInfo
|
publish = runProp "publish" . toPublish
|
||||||
publish = runProp "publish"
|
|
||||||
|
|
||||||
-- | Expose a container's port without publishing it.
|
-- | Expose a container's port without publishing it.
|
||||||
expose :: String -> Property HasInfo
|
expose :: String -> Property HasInfo
|
||||||
|
@ -267,11 +279,21 @@ expose = runProp "expose"
|
||||||
user :: String -> Property HasInfo
|
user :: String -> Property HasInfo
|
||||||
user = runProp "user"
|
user = runProp "user"
|
||||||
|
|
||||||
-- | Mount a volume
|
class Mountable p where
|
||||||
-- Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]
|
toMount :: p -> String
|
||||||
|
|
||||||
|
instance Mountable (Bound FilePath) where
|
||||||
|
toMount p = hostSide p ++ ":" ++ containerSide p
|
||||||
|
|
||||||
|
-- | string format: [host-dir]:[container-dir]:[rw|ro]
|
||||||
|
--
|
||||||
-- With just a directory, creates a volume in the container.
|
-- With just a directory, creates a volume in the container.
|
||||||
volume :: String -> Property HasInfo
|
instance Mountable String where
|
||||||
volume = runProp "volume"
|
toMount = id
|
||||||
|
|
||||||
|
-- | Mount a volume
|
||||||
|
volume :: Mountable v => v -> Property HasInfo
|
||||||
|
volume = runProp "volume" . toMount
|
||||||
|
|
||||||
-- | Mount a volume from the specified container into the current
|
-- | Mount a volume from the specified container into the current
|
||||||
-- container.
|
-- container.
|
||||||
|
|
|
@ -9,7 +9,6 @@ module Propellor.Property.Firewall (
|
||||||
Target(..),
|
Target(..),
|
||||||
Proto(..),
|
Proto(..),
|
||||||
Rules(..),
|
Rules(..),
|
||||||
Port,
|
|
||||||
ConnectionState(..)
|
ConnectionState(..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
@ -45,8 +44,8 @@ toIpTable r = map Param $
|
||||||
toIpTableArg :: Rules -> [String]
|
toIpTableArg :: Rules -> [String]
|
||||||
toIpTableArg Everything = []
|
toIpTableArg Everything = []
|
||||||
toIpTableArg (Proto proto) = ["-p", map toLower $ show proto]
|
toIpTableArg (Proto proto) = ["-p", map toLower $ show proto]
|
||||||
toIpTableArg (Port port) = ["--dport", show port]
|
toIpTableArg (DPort port) = ["--dport", show port]
|
||||||
toIpTableArg (PortRange (f,t)) = ["--dport", show f ++ ":" ++ show t]
|
toIpTableArg (DPortRange (f,t)) = ["--dport", show f ++ ":" ++ show t]
|
||||||
toIpTableArg (IFace iface) = ["-i", iface]
|
toIpTableArg (IFace iface) = ["-i", iface]
|
||||||
toIpTableArg (Ctstate states) = ["-m", "conntrack","--ctstate", concat $ intersperse "," (map show states)]
|
toIpTableArg (Ctstate states) = ["-m", "conntrack","--ctstate", concat $ intersperse "," (map show states)]
|
||||||
toIpTableArg (r :- r') = toIpTableArg r <> toIpTableArg r'
|
toIpTableArg (r :- r') = toIpTableArg r <> toIpTableArg r'
|
||||||
|
@ -55,33 +54,31 @@ data Rule = Rule
|
||||||
{ ruleChain :: Chain
|
{ ruleChain :: Chain
|
||||||
, ruleTarget :: Target
|
, ruleTarget :: Target
|
||||||
, ruleRules :: Rules
|
, ruleRules :: Rules
|
||||||
} deriving (Eq, Show, Read)
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
data Chain = INPUT | OUTPUT | FORWARD
|
data Chain = INPUT | OUTPUT | FORWARD
|
||||||
deriving (Eq,Show,Read)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
data Target = ACCEPT | REJECT | DROP | LOG
|
data Target = ACCEPT | REJECT | DROP | LOG
|
||||||
deriving (Eq,Show,Read)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
data Proto = TCP | UDP | ICMP
|
data Proto = TCP | UDP | ICMP
|
||||||
deriving (Eq,Show,Read)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
type Port = Int
|
|
||||||
|
|
||||||
data ConnectionState = ESTABLISHED | RELATED | NEW | INVALID
|
data ConnectionState = ESTABLISHED | RELATED | NEW | INVALID
|
||||||
deriving (Eq,Show,Read)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
data Rules
|
data Rules
|
||||||
= Everything
|
= Everything
|
||||||
| Proto Proto
|
| Proto Proto
|
||||||
-- ^There is actually some order dependency between proto and port so this should be a specific
|
-- ^There is actually some order dependency between proto and port so this should be a specific
|
||||||
-- data type with proto + ports
|
-- data type with proto + ports
|
||||||
| Port Port
|
| DPort Port
|
||||||
| PortRange (Port,Port)
|
| DPortRange (Port,Port)
|
||||||
| IFace Network.Interface
|
| IFace Network.Interface
|
||||||
| Ctstate [ ConnectionState ]
|
| Ctstate [ ConnectionState ]
|
||||||
| Rules :- Rules -- ^Combine two rules
|
| Rules :- Rules -- ^Combine two rules
|
||||||
deriving (Eq,Show,Read)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
infixl 0 :-
|
infixl 0 :-
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,7 @@ import Propellor
|
||||||
import qualified Propellor.Property.Apt as Apt
|
import qualified Propellor.Property.Apt as Apt
|
||||||
import qualified Propellor.Property.User as User
|
import qualified Propellor.Property.User as User
|
||||||
import qualified Propellor.Property.Cron as Cron
|
import qualified Propellor.Property.Cron as Cron
|
||||||
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.Systemd as Systemd
|
import qualified Propellor.Property.Systemd as Systemd
|
||||||
import qualified Propellor.Property.Chroot as Chroot
|
import qualified Propellor.Property.Chroot as Chroot
|
||||||
import Propellor.Property.Cron (Times)
|
import Propellor.Property.Cron (Times)
|
||||||
|
@ -50,8 +48,6 @@ autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props
|
||||||
tree :: Architecture -> Property HasInfo
|
tree :: Architecture -> Property HasInfo
|
||||||
tree buildarch = combineProperties "gitannexbuilder tree" $ props
|
tree buildarch = combineProperties "gitannexbuilder tree" $ props
|
||||||
& Apt.installed ["git"]
|
& Apt.installed ["git"]
|
||||||
-- gitbuilderdir directory already exists when docker volume is used,
|
|
||||||
-- but with wrong owner.
|
|
||||||
& File.dirExists gitbuilderdir
|
& File.dirExists gitbuilderdir
|
||||||
& File.ownerGroup gitbuilderdir (User builduser) (Group builduser)
|
& File.ownerGroup gitbuilderdir (User builduser) (Group builduser)
|
||||||
& gitannexbuildercloned
|
& gitannexbuildercloned
|
||||||
|
@ -86,6 +82,13 @@ buildDepsNoHaskellLibs = Apt.installed
|
||||||
"alex", "happy", "c2hs"
|
"alex", "happy", "c2hs"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
haskellPkgsInstalled :: String -> Property NoInfo
|
||||||
|
haskellPkgsInstalled dir = flagFile go ("/haskellpkgsinstalled")
|
||||||
|
where
|
||||||
|
go = userScriptProperty (User builduser)
|
||||||
|
[ "cd " ++ builddir ++ " && ./standalone/ " ++ dir ++ "/install-haskell-packages"
|
||||||
|
]
|
||||||
|
|
||||||
-- Installs current versions of git-annex's deps from cabal, but only
|
-- Installs current versions of git-annex's deps from cabal, but only
|
||||||
-- does so once.
|
-- does so once.
|
||||||
cabalDeps :: Property NoInfo
|
cabalDeps :: Property NoInfo
|
||||||
|
@ -94,23 +97,36 @@ cabalDeps = flagFile go cabalupdated
|
||||||
go = userScriptProperty (User builduser) ["cabal update && cabal install git-annex --only-dependencies || true"]
|
go = userScriptProperty (User builduser) ["cabal update && cabal install git-annex --only-dependencies || true"]
|
||||||
cabalupdated = homedir </> ".cabal" </> "packages" </> "hackage.haskell.org" </> "00-index.cache"
|
cabalupdated = homedir </> ".cabal" </> "packages" </> "hackage.haskell.org" </> "00-index.cache"
|
||||||
|
|
||||||
standardAutoBuilderContainer :: System -> Times -> TimeOut -> Systemd.Container
|
autoBuilderContainer :: (System -> Property HasInfo) -> System -> Times -> TimeOut -> Systemd.Container
|
||||||
standardAutoBuilderContainer osver@(System _ arch) crontime timeout =
|
autoBuilderContainer mkprop osver@(System _ arch) crontime timeout =
|
||||||
Systemd.container name bootstrap
|
Systemd.container name bootstrap
|
||||||
& standardAutoBuilder osver crontime timeout
|
& mkprop osver
|
||||||
|
& buildDepsApt
|
||||||
|
& autobuilder arch crontime timeout
|
||||||
where
|
where
|
||||||
name = arch ++ "-git-annex-builder"
|
name = arch ++ "-git-annex-builder"
|
||||||
bootstrap = Chroot.debootstrapped osver mempty
|
bootstrap = Chroot.debootstrapped osver mempty
|
||||||
|
|
||||||
standardAutoBuilder :: System -> Times -> TimeOut -> Property HasInfo
|
standardAutoBuilder :: System -> Property HasInfo
|
||||||
standardAutoBuilder osver@(System _ arch) crontime timeout =
|
standardAutoBuilder osver@(System _ arch) =
|
||||||
propertyList "git-annex-builder" $ props
|
propertyList "standard git-annex autobuilder" $ props
|
||||||
& os osver
|
& os osver
|
||||||
& Apt.stdSourcesList
|
& Apt.stdSourcesList
|
||||||
& Apt.unattendedUpgrades
|
& Apt.unattendedUpgrades
|
||||||
& User.accountFor (User builduser)
|
& User.accountFor (User builduser)
|
||||||
& tree arch
|
& tree arch
|
||||||
& buildDepsApt
|
|
||||||
|
armAutoBuilder :: System -> Times -> TimeOut -> Property HasInfo
|
||||||
|
armAutoBuilder osver@(System _ arch) crontime timeout =
|
||||||
|
propertyList "arm git-annex autobuilder" $ props
|
||||||
|
& standardAutoBuilder osver
|
||||||
|
& buildDepsNoHaskellLibs
|
||||||
|
-- Works around ghc crash with parallel builds on arm.
|
||||||
|
& (homedir </> ".cabal" </> "config")
|
||||||
|
`File.lacksLine` "jobs: $ncpus"
|
||||||
|
-- Install patched haskell packages for portability to
|
||||||
|
-- arm NAS's using old kernel versions.
|
||||||
|
& haskellPkgsInstalled "linux"
|
||||||
& autobuilder arch crontime timeout
|
& autobuilder arch crontime timeout
|
||||||
|
|
||||||
androidAutoBuilderContainer :: Times -> TimeOut -> Systemd.Container
|
androidAutoBuilderContainer :: Times -> TimeOut -> Systemd.Container
|
||||||
|
@ -135,7 +151,7 @@ androidContainer name setupgitannexdir gitannexdir = Systemd.container name boot
|
||||||
& flagFile chrootsetup ("/chrootsetup")
|
& flagFile chrootsetup ("/chrootsetup")
|
||||||
`requires` setupgitannexdir
|
`requires` setupgitannexdir
|
||||||
& buildDepsApt
|
& buildDepsApt
|
||||||
& flagFile haskellpkgsinstalled ("/haskellpkgsinstalled")
|
& haskellPkgsInstalled "android"
|
||||||
where
|
where
|
||||||
-- Use git-annex's android chroot setup script, which will install
|
-- Use git-annex's android chroot setup script, which will install
|
||||||
-- ghc-android and the NDK, all build deps, etc, in the home
|
-- ghc-android and the NDK, all build deps, etc, in the home
|
||||||
|
@ -143,55 +159,5 @@ androidContainer name setupgitannexdir gitannexdir = Systemd.container name boot
|
||||||
chrootsetup = scriptProperty
|
chrootsetup = scriptProperty
|
||||||
[ "cd " ++ gitannexdir ++ " && ./standalone/android/buildchroot-inchroot"
|
[ "cd " ++ gitannexdir ++ " && ./standalone/android/buildchroot-inchroot"
|
||||||
]
|
]
|
||||||
haskellpkgsinstalled = userScriptProperty (User builduser)
|
|
||||||
[ "cd " ++ gitannexdir ++ " && ./standalone/android/install-haskell-packages"
|
|
||||||
]
|
|
||||||
osver = System (Debian Testing) "i386"
|
osver = System (Debian Testing) "i386"
|
||||||
bootstrap = Chroot.debootstrapped osver mempty
|
bootstrap = Chroot.debootstrapped osver mempty
|
||||||
|
|
||||||
-- armel builder has a companion container using amd64 that
|
|
||||||
-- runs the build first to get TH splices. They need
|
|
||||||
-- to have the same versions of all haskell libraries installed.
|
|
||||||
armelCompanionContainer :: (System -> Docker.Image) -> Docker.Container
|
|
||||||
armelCompanionContainer dockerImage = Docker.container "armel-git-annex-builder-companion"
|
|
||||||
(dockerImage $ System (Debian Unstable) "amd64")
|
|
||||||
& os (System (Debian Testing) "amd64")
|
|
||||||
& Apt.stdSourcesList
|
|
||||||
& Apt.installed ["systemd"]
|
|
||||||
-- This volume is shared with the armel builder.
|
|
||||||
& Docker.volume gitbuilderdir
|
|
||||||
& User.accountFor (User builduser)
|
|
||||||
-- Install current versions of build deps from cabal.
|
|
||||||
& tree "armel"
|
|
||||||
& buildDepsNoHaskellLibs
|
|
||||||
& cabalDeps
|
|
||||||
-- The armel builder can ssh to this companion.
|
|
||||||
& Docker.expose "22"
|
|
||||||
& Apt.serviceInstalledRunning "ssh"
|
|
||||||
& Ssh.authorizedKeys (User builduser) (Context "armel-git-annex-builder")
|
|
||||||
& Docker.tweaked
|
|
||||||
|
|
||||||
armelAutoBuilderContainer :: (System -> Docker.Image) -> Times -> TimeOut -> Docker.Container
|
|
||||||
armelAutoBuilderContainer dockerImage crontimes timeout = Docker.container "armel-git-annex-builder"
|
|
||||||
(dockerImage $ System (Debian Unstable) "armel")
|
|
||||||
& os (System (Debian Testing) "armel")
|
|
||||||
& Apt.stdSourcesList
|
|
||||||
& Apt.installed ["systemd"]
|
|
||||||
& Apt.installed ["openssh-client"]
|
|
||||||
& Docker.link "armel-git-annex-builder-companion" "companion"
|
|
||||||
& Docker.volumes_from "armel-git-annex-builder-companion"
|
|
||||||
& User.accountFor (User builduser)
|
|
||||||
-- TODO: automate installing haskell libs
|
|
||||||
-- (Currently have to run
|
|
||||||
-- git-annex/standalone/linux/install-haskell-packages
|
|
||||||
-- which is not fully automated.)
|
|
||||||
& buildDepsNoHaskellLibs
|
|
||||||
& autobuilder "armel" crontimes timeout
|
|
||||||
`requires` tree "armel"
|
|
||||||
& Ssh.keyImported SshRsa (User builduser) (Context "armel-git-annex-builder")
|
|
||||||
& trivial writecompanionaddress
|
|
||||||
& Docker.tweaked
|
|
||||||
where
|
|
||||||
writecompanionaddress = scriptProperty
|
|
||||||
[ "echo \"$COMPANION_PORT_22_TCP_ADDR\" > " ++ homedir </> "companion_address"
|
|
||||||
] `describe` "companion_address file"
|
|
||||||
|
|
|
@ -1,26 +1,46 @@
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
|
||||||
module Propellor.Property.Systemd (
|
module Propellor.Property.Systemd (
|
||||||
module Propellor.Property.Systemd.Core,
|
-- * Services
|
||||||
ServiceName,
|
ServiceName,
|
||||||
MachineName,
|
|
||||||
started,
|
started,
|
||||||
stopped,
|
stopped,
|
||||||
enabled,
|
enabled,
|
||||||
disabled,
|
disabled,
|
||||||
|
running,
|
||||||
restarted,
|
restarted,
|
||||||
persistentJournal,
|
networkd,
|
||||||
|
journald,
|
||||||
|
-- * Configuration
|
||||||
|
installed,
|
||||||
Option,
|
Option,
|
||||||
configured,
|
configured,
|
||||||
journaldConfigured,
|
|
||||||
daemonReloaded,
|
daemonReloaded,
|
||||||
|
-- * Journal
|
||||||
|
persistentJournal,
|
||||||
|
journaldConfigured,
|
||||||
|
-- * Containers
|
||||||
|
MachineName,
|
||||||
Container,
|
Container,
|
||||||
container,
|
container,
|
||||||
nspawned,
|
nspawned,
|
||||||
|
-- * Container configuration
|
||||||
containerCfg,
|
containerCfg,
|
||||||
resolvConfed,
|
resolvConfed,
|
||||||
|
linkJournal,
|
||||||
|
privateNetwork,
|
||||||
|
module Propellor.Types.Container,
|
||||||
|
Proto(..),
|
||||||
|
Publishable,
|
||||||
|
publish,
|
||||||
|
Bindable,
|
||||||
|
bind,
|
||||||
|
bindRo,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Propellor
|
import Propellor
|
||||||
import Propellor.Types.Chroot
|
import Propellor.Types.Chroot
|
||||||
|
import Propellor.Types.Container
|
||||||
import qualified Propellor.Property.Chroot as Chroot
|
import qualified Propellor.Property.Chroot as Chroot
|
||||||
import qualified Propellor.Property.Apt as Apt
|
import qualified Propellor.Property.Apt as Apt
|
||||||
import qualified Propellor.Property.File as File
|
import qualified Propellor.Property.File as File
|
||||||
|
@ -44,6 +64,9 @@ instance PropAccum Container where
|
||||||
getProperties (Container _ _ h) = hostProperties h
|
getProperties (Container _ _ h) = hostProperties h
|
||||||
|
|
||||||
-- | Starts a systemd service.
|
-- | Starts a systemd service.
|
||||||
|
--
|
||||||
|
-- Note that this does not configure systemd to start the service on boot,
|
||||||
|
-- it only ensures that the service is currently running.
|
||||||
started :: ServiceName -> Property NoInfo
|
started :: ServiceName -> Property NoInfo
|
||||||
started n = trivial $ cmdProperty "systemctl" ["start", n]
|
started n = trivial $ cmdProperty "systemctl" ["start", n]
|
||||||
`describe` ("service " ++ n ++ " started")
|
`describe` ("service " ++ n ++ " started")
|
||||||
|
@ -54,6 +77,9 @@ stopped n = trivial $ cmdProperty "systemctl" ["stop", n]
|
||||||
`describe` ("service " ++ n ++ " stopped")
|
`describe` ("service " ++ n ++ " stopped")
|
||||||
|
|
||||||
-- | Enables a systemd service.
|
-- | Enables a systemd service.
|
||||||
|
--
|
||||||
|
-- This does not ensure the service is started, it only configures systemd
|
||||||
|
-- to start it on boot.
|
||||||
enabled :: ServiceName -> Property NoInfo
|
enabled :: ServiceName -> Property NoInfo
|
||||||
enabled n = trivial $ cmdProperty "systemctl" ["enable", n]
|
enabled n = trivial $ cmdProperty "systemctl" ["enable", n]
|
||||||
`describe` ("service " ++ n ++ " enabled")
|
`describe` ("service " ++ n ++ " enabled")
|
||||||
|
@ -63,11 +89,23 @@ disabled :: ServiceName -> Property NoInfo
|
||||||
disabled n = trivial $ cmdProperty "systemctl" ["disable", n]
|
disabled n = trivial $ cmdProperty "systemctl" ["disable", n]
|
||||||
`describe` ("service " ++ n ++ " disabled")
|
`describe` ("service " ++ n ++ " disabled")
|
||||||
|
|
||||||
|
-- | Ensures that a service is both enabled and started
|
||||||
|
running :: ServiceName -> Property NoInfo
|
||||||
|
running n = trivial $ started n `requires` enabled n
|
||||||
|
|
||||||
-- | Restarts a systemd service.
|
-- | Restarts a systemd service.
|
||||||
restarted :: ServiceName -> Property NoInfo
|
restarted :: ServiceName -> Property NoInfo
|
||||||
restarted n = trivial $ cmdProperty "systemctl" ["restart", n]
|
restarted n = trivial $ cmdProperty "systemctl" ["restart", n]
|
||||||
`describe` ("service " ++ n ++ " restarted")
|
`describe` ("service " ++ n ++ " restarted")
|
||||||
|
|
||||||
|
-- | The systemd-networkd service.
|
||||||
|
networkd :: ServiceName
|
||||||
|
networkd = "systemd-networkd"
|
||||||
|
|
||||||
|
-- | The systemd-journald service.
|
||||||
|
journald :: ServiceName
|
||||||
|
journald = "systemd-journald"
|
||||||
|
|
||||||
-- | Enables persistent storage of the journal.
|
-- | Enables persistent storage of the journal.
|
||||||
persistentJournal :: Property NoInfo
|
persistentJournal :: Property NoInfo
|
||||||
persistentJournal = check (not <$> doesDirectoryExist dir) $
|
persistentJournal = check (not <$> doesDirectoryExist dir) $
|
||||||
|
@ -101,15 +139,15 @@ configured cfgfile option value = combineProperties desc
|
||||||
| setting `isPrefixOf` l = Nothing
|
| setting `isPrefixOf` l = Nothing
|
||||||
| otherwise = Just l
|
| otherwise = Just l
|
||||||
|
|
||||||
|
-- | Causes systemd to reload its configuration files.
|
||||||
|
daemonReloaded :: Property NoInfo
|
||||||
|
daemonReloaded = trivial $ cmdProperty "systemctl" ["daemon-reload"]
|
||||||
|
|
||||||
-- | Configures journald, restarting it so the changes take effect.
|
-- | Configures journald, restarting it so the changes take effect.
|
||||||
journaldConfigured :: Option -> String -> Property NoInfo
|
journaldConfigured :: Option -> String -> Property NoInfo
|
||||||
journaldConfigured option value =
|
journaldConfigured option value =
|
||||||
configured "/etc/systemd/journald.conf" option value
|
configured "/etc/systemd/journald.conf" option value
|
||||||
`onChange` restarted "systemd-journald"
|
`onChange` restarted journald
|
||||||
|
|
||||||
-- | Causes systemd to reload its configuration files.
|
|
||||||
daemonReloaded :: Property NoInfo
|
|
||||||
daemonReloaded = trivial $ cmdProperty "systemctl" ["daemon-reload"]
|
|
||||||
|
|
||||||
-- | Defines a container with a given machine name.
|
-- | Defines a container with a given machine name.
|
||||||
--
|
--
|
||||||
|
@ -122,6 +160,7 @@ container :: MachineName -> (FilePath -> Chroot.Chroot) -> Container
|
||||||
container name mkchroot = Container name c h
|
container name mkchroot = Container name c h
|
||||||
& os system
|
& os system
|
||||||
& resolvConfed
|
& resolvConfed
|
||||||
|
& linkJournal
|
||||||
where
|
where
|
||||||
c@(Chroot.Chroot _ system _ _) = mkchroot (containerDir name)
|
c@(Chroot.Chroot _ system _ _) = mkchroot (containerDir name)
|
||||||
h = Host name [] mempty
|
h = Host name [] mempty
|
||||||
|
@ -152,8 +191,7 @@ nspawned c@(Container name (Chroot.Chroot loc system builderconf _) h) =
|
||||||
-- Chroot provisioning is run in systemd-only mode,
|
-- Chroot provisioning is run in systemd-only mode,
|
||||||
-- which sets up the chroot and ensures systemd and dbus are
|
-- which sets up the chroot and ensures systemd and dbus are
|
||||||
-- installed, but does not handle the other provisions.
|
-- installed, but does not handle the other provisions.
|
||||||
chrootprovisioned = Chroot.provisioned'
|
chrootprovisioned = Chroot.provisioned' (Chroot.propigateChrootInfo chroot) chroot True
|
||||||
(Chroot.propigateChrootInfo chroot) chroot True
|
|
||||||
|
|
||||||
-- Use nsenter to enter container and and run propellor to
|
-- Use nsenter to enter container and and run propellor to
|
||||||
-- finish provisioning.
|
-- finish provisioning.
|
||||||
|
@ -177,8 +215,14 @@ nspawnService (Container name _ _) cfg = setup <!> teardown
|
||||||
return $ unlines $
|
return $ unlines $
|
||||||
"# deployed by propellor" : map addparams ls
|
"# deployed by propellor" : map addparams ls
|
||||||
addparams l
|
addparams l
|
||||||
| "ExecStart=" `isPrefixOf` l =
|
| "ExecStart=" `isPrefixOf` l = unwords $
|
||||||
l ++ " " ++ unwords (nspawnServiceParams cfg)
|
[ "ExecStart = /usr/bin/systemd-nspawn"
|
||||||
|
, "--quiet"
|
||||||
|
, "--keep-unit"
|
||||||
|
, "--boot"
|
||||||
|
, "--directory=" ++ containerDir name
|
||||||
|
, "--machine=%i"
|
||||||
|
] ++ nspawnServiceParams cfg
|
||||||
| otherwise = l
|
| otherwise = l
|
||||||
|
|
||||||
goodservicefile = (==)
|
goodservicefile = (==)
|
||||||
|
@ -237,8 +281,8 @@ enterScript c@(Container name _ _) = setup <!> teardown
|
||||||
enterScriptFile :: Container -> FilePath
|
enterScriptFile :: Container -> FilePath
|
||||||
enterScriptFile (Container name _ _ ) = "/usr/local/bin/enter-" ++ mungename name
|
enterScriptFile (Container name _ _ ) = "/usr/local/bin/enter-" ++ mungename name
|
||||||
|
|
||||||
enterContainerProcess :: Container -> [String] -> CreateProcess
|
enterContainerProcess :: Container -> [String] -> IO (CreateProcess, IO ())
|
||||||
enterContainerProcess = proc . enterScriptFile
|
enterContainerProcess c ps = pure (proc (enterScriptFile c) ps, noop)
|
||||||
|
|
||||||
nspawnServiceName :: MachineName -> ServiceName
|
nspawnServiceName :: MachineName -> ServiceName
|
||||||
nspawnServiceName name = "systemd-nspawn@" ++ name ++ ".service"
|
nspawnServiceName name = "systemd-nspawn@" ++ name ++ ".service"
|
||||||
|
@ -270,3 +314,68 @@ containerCfg p = RevertableProperty (mk True) (mk False)
|
||||||
-- This property is enabled by default. Revert it to disable it.
|
-- This property is enabled by default. Revert it to disable it.
|
||||||
resolvConfed :: RevertableProperty
|
resolvConfed :: RevertableProperty
|
||||||
resolvConfed = containerCfg "bind=/etc/resolv.conf"
|
resolvConfed = containerCfg "bind=/etc/resolv.conf"
|
||||||
|
|
||||||
|
-- | Link the container's journal to the host's if possible.
|
||||||
|
-- (Only works if the host has persistent journal enabled.)
|
||||||
|
--
|
||||||
|
-- This property is enabled by default. Revert it to disable it.
|
||||||
|
linkJournal :: RevertableProperty
|
||||||
|
linkJournal = containerCfg "link-journal=try-guest"
|
||||||
|
|
||||||
|
-- | Disconnect networking of the container from the host.
|
||||||
|
privateNetwork :: RevertableProperty
|
||||||
|
privateNetwork = containerCfg "private-network"
|
||||||
|
|
||||||
|
class Publishable a where
|
||||||
|
toPublish :: a -> String
|
||||||
|
|
||||||
|
instance Publishable Port where
|
||||||
|
toPublish (Port n) = show n
|
||||||
|
|
||||||
|
instance Publishable (Bound Port) where
|
||||||
|
toPublish v = toPublish (hostSide v) ++ ":" ++ toPublish (containerSide v)
|
||||||
|
|
||||||
|
data Proto = TCP | UDP
|
||||||
|
|
||||||
|
instance Publishable (Proto, Bound Port) where
|
||||||
|
toPublish (TCP, fp) = "tcp:" ++ toPublish fp
|
||||||
|
toPublish (UDP, fp) = "udp:" ++ toPublish fp
|
||||||
|
|
||||||
|
-- | Publish a port from the container to the host.
|
||||||
|
--
|
||||||
|
-- This feature was first added in systemd version 220.
|
||||||
|
--
|
||||||
|
-- This property is only needed (and will only work) if the container
|
||||||
|
-- is configured to use private networking. Also, networkd should be enabled
|
||||||
|
-- both inside the container, and on the host. For example:
|
||||||
|
--
|
||||||
|
-- > foo :: Host
|
||||||
|
-- > foo = host "foo.example.com"
|
||||||
|
-- > & Systemd.running Systemd.networkd
|
||||||
|
-- > & Systemd.nspawned webserver
|
||||||
|
-- >
|
||||||
|
-- > webserver :: Systemd.container
|
||||||
|
-- > webserver = Systemd.container "webserver" (Chroot.debootstrapped (System (Debian Testing) "amd64") mempty)
|
||||||
|
-- > & Systemd.privateNetwork
|
||||||
|
-- > & Systemd.running Systemd.networkd
|
||||||
|
-- > & Systemd.publish (Port 80 ->- Port 8080)
|
||||||
|
-- > & Apt.installedRunning "apache2"
|
||||||
|
publish :: Publishable p => p -> RevertableProperty
|
||||||
|
publish p = containerCfg $ "--port=" ++ toPublish p
|
||||||
|
|
||||||
|
class Bindable a where
|
||||||
|
toBind :: a -> String
|
||||||
|
|
||||||
|
instance Bindable FilePath where
|
||||||
|
toBind f = f
|
||||||
|
|
||||||
|
instance Bindable (Bound FilePath) where
|
||||||
|
toBind v = hostSide v ++ ":" ++ containerSide v
|
||||||
|
|
||||||
|
-- | Bind mount a file or directory from the host into the container.
|
||||||
|
bind :: Bindable p => p -> RevertableProperty
|
||||||
|
bind p = containerCfg $ "--bind=" ++ toBind p
|
||||||
|
|
||||||
|
-- | Read-only mind mount.
|
||||||
|
bindRo :: Bindable p => p -> RevertableProperty
|
||||||
|
bindRo p = containerCfg $ "--bind-ro=" ++ toBind p
|
||||||
|
|
|
@ -22,7 +22,8 @@ sshCachingParams hn = do
|
||||||
let ps =
|
let ps =
|
||||||
[ Param "-o"
|
[ Param "-o"
|
||||||
, Param ("ControlPath=" ++ socketfile)
|
, Param ("ControlPath=" ++ socketfile)
|
||||||
, Params "-o ControlMaster=auto -o ControlPersist=yes"
|
, Param "-o", Param "ControlMaster=auto"
|
||||||
|
, Param "-o", Param "ControlPersist=yes"
|
||||||
]
|
]
|
||||||
|
|
||||||
maybe noop (expireold ps socketfile)
|
maybe noop (expireold ps socketfile)
|
||||||
|
@ -37,7 +38,7 @@ sshCachingParams hn = do
|
||||||
then touchFile f
|
then touchFile f
|
||||||
else do
|
else do
|
||||||
void $ boolSystem "ssh" $
|
void $ boolSystem "ssh" $
|
||||||
[ Params "-O stop" ] ++ ps ++
|
[ Param "-O", Param "stop" ] ++ ps ++
|
||||||
[ Param "localhost" ]
|
[ Param "localhost" ]
|
||||||
nukeFile f
|
nukeFile f
|
||||||
tenminutes = 600
|
tenminutes = 600
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
|
||||||
|
module Propellor.Types.Container where
|
||||||
|
|
||||||
|
-- | A value that can be bound between the host and a container.
|
||||||
|
--
|
||||||
|
-- For example, a Bound Port is a Port on the container that is bound to
|
||||||
|
-- a Port on the host.
|
||||||
|
data Bound v = Bound
|
||||||
|
{ hostSide :: v
|
||||||
|
, containerSide :: v
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Create a Bound value, from two different values for the host and
|
||||||
|
-- container.
|
||||||
|
--
|
||||||
|
-- For example, @Port 8080 -<- Port 80@ means that port 8080 on the host
|
||||||
|
-- is bound to port 80 from the container.
|
||||||
|
(-<-) :: (hostv ~ v, containerv ~ v) => hostv -> containerv -> Bound v
|
||||||
|
(-<-) hostv containerv = Bound hostv containerv
|
||||||
|
|
||||||
|
-- | Flipped version of -<- with the container value first and host value
|
||||||
|
-- second.
|
||||||
|
(->-) :: (containerv ~ v, hostv ~ v) => hostv -> containerv -> Bound v
|
||||||
|
(->-) containerv hostv = Bound hostv containerv
|
||||||
|
|
||||||
|
-- | Create a Bound value, that is the same on both the host and container.
|
||||||
|
same :: v -> Bound v
|
||||||
|
same v = Bound v v
|
||||||
|
|
|
@ -10,6 +10,7 @@ module Propellor.Types.OS (
|
||||||
User(..),
|
User(..),
|
||||||
Group(..),
|
Group(..),
|
||||||
userGroup,
|
userGroup,
|
||||||
|
Port(..),
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Network.BSD (HostName)
|
import Network.BSD (HostName)
|
||||||
|
@ -42,3 +43,6 @@ newtype Group = Group String
|
||||||
-- | Makes a Group with the same name as the User.
|
-- | Makes a Group with the same name as the User.
|
||||||
userGroup :: User -> Group
|
userGroup :: User -> Group
|
||||||
userGroup (User u) = Group u
|
userGroup (User u) = Group u
|
||||||
|
|
||||||
|
newtype Port = Port Int
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
|
@ -19,25 +19,23 @@ import Prelude
|
||||||
|
|
||||||
-- | Parameters that can be passed to a shell command.
|
-- | Parameters that can be passed to a shell command.
|
||||||
data CommandParam
|
data CommandParam
|
||||||
= Params String -- ^ Contains multiple parameters, separated by whitespace
|
= Param String -- ^ A parameter
|
||||||
| Param String -- ^ A single parameter
|
|
||||||
| File FilePath -- ^ The name of a file
|
| File FilePath -- ^ The name of a file
|
||||||
deriving (Eq, Show, Ord)
|
deriving (Eq, Show, Ord)
|
||||||
|
|
||||||
-- | Used to pass a list of CommandParams to a function that runs
|
-- | Used to pass a list of CommandParams to a function that runs
|
||||||
-- a command and expects Strings. -}
|
-- a command and expects Strings. -}
|
||||||
toCommand :: [CommandParam] -> [String]
|
toCommand :: [CommandParam] -> [String]
|
||||||
toCommand = concatMap unwrap
|
toCommand = map unwrap
|
||||||
where
|
where
|
||||||
unwrap (Param s) = [s]
|
unwrap (Param s) = s
|
||||||
unwrap (Params s) = filter (not . null) (split " " s)
|
|
||||||
-- Files that start with a non-alphanumeric that is not a path
|
-- Files that start with a non-alphanumeric that is not a path
|
||||||
-- separator are modified to avoid the command interpreting them as
|
-- separator are modified to avoid the command interpreting them as
|
||||||
-- options or other special constructs.
|
-- options or other special constructs.
|
||||||
unwrap (File s@(h:_))
|
unwrap (File s@(h:_))
|
||||||
| isAlphaNum h || h `elem` pathseps = [s]
|
| isAlphaNum h || h `elem` pathseps = s
|
||||||
| otherwise = ["./" ++ s]
|
| otherwise = "./" ++ s
|
||||||
unwrap (File s) = [s]
|
unwrap (File s) = s
|
||||||
-- '/' is explicitly included because it's an alternative
|
-- '/' is explicitly included because it's an alternative
|
||||||
-- path separator on Windows.
|
-- path separator on Windows.
|
||||||
pathseps = pathSeparator:"./"
|
pathseps = pathSeparator:"./"
|
||||||
|
|
Loading…
Reference in New Issue