packages feed

propellor 5.12 → 5.13

raw patch · 12 files changed

+1015/−290 lines, 12 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Propellor: newtype Alt (f :: k -> Type) (a :: k) :: forall k. () => k -> Type -> k -> Type
- Propellor.Property.SiteSpecific.JoeySites: oldUseNetInstalled :: Package -> Property DebianLike
- Propellor.Property.SiteSpecific.JoeySites: oldUseNetServer :: [Host] -> Property (HasInfo + DebianLike)
- Propellor.Property.SiteSpecific.JoeySites: oldUseNetShellBox :: Property DebianLike
- Propellor.Types: instance forall a1 a2 (x :: [a2]) (y :: [a2]) (x' :: [a1]) (y' :: [a1]). (Propellor.Types.MetaTypes.CheckCombinable x y, Propellor.Types.MetaTypes.CheckCombinable x' y', Propellor.Types.Singletons.SingI (Propellor.Types.MetaTypes.Combine x y), Propellor.Types.Singletons.SingI (Propellor.Types.MetaTypes.Combine x' y')) => Propellor.Types.Combines (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes x) (Propellor.Types.MetaTypes.MetaTypes x')) (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes y) (Propellor.Types.MetaTypes.MetaTypes y'))
- Propellor.Types: instance forall k a (x :: [a]) (y :: [a]) (x' :: k). (Propellor.Types.MetaTypes.CheckCombinable x y, Propellor.Types.Singletons.SingI (Propellor.Types.MetaTypes.Combine x y)) => Propellor.Types.Combines (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes x) (Propellor.Types.MetaTypes.MetaTypes x')) (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes y))
- Propellor.Types: instance forall k a (x :: [a]) (y :: [a]) (y' :: k). (Propellor.Types.MetaTypes.CheckCombinable x y, Propellor.Types.Singletons.SingI (Propellor.Types.MetaTypes.Combine x y)) => Propellor.Types.Combines (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes x)) (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes y) (Propellor.Types.MetaTypes.MetaTypes y'))
- Propellor.Types: instance forall k1 k2 (setupmetatypes :: k2) (undometatypes :: k1). (GHC.Base.Monoid (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes setupmetatypes)), GHC.Base.Monoid (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes undometatypes)), Propellor.Types.Singletons.SingI setupmetatypes, Propellor.Types.Singletons.SingI undometatypes) => GHC.Base.Monoid (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes setupmetatypes) (Propellor.Types.MetaTypes.MetaTypes undometatypes))
- Propellor.Types: instance forall k1 k2 (setupmetatypes :: k2) (undometatypes :: k1). (GHC.Base.Semigroup (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes setupmetatypes)), GHC.Base.Semigroup (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes undometatypes)), Propellor.Types.Singletons.SingI setupmetatypes, Propellor.Types.Singletons.SingI undometatypes) => GHC.Base.Semigroup (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes setupmetatypes) (Propellor.Types.MetaTypes.MetaTypes undometatypes))
- Propellor.Types.MetaTypes: data DelayErrorFcf (a :: ErrorMessage) (b :: k) :: forall k. () => ErrorMessage -> k -> Type
- Propellor.Utilities: [SomeException] :: forall e. Exception e => e -> SomeException
+ Propellor: newtype Alt (f :: k -> Type) (a :: k)
+ Propellor: newtype Ap (f :: k -> Type) (a :: k)
+ Propellor.Property.Network: interfaceFileContains' :: FilePath -> [InterfaceStanza] -> Property DebianLike
+ Propellor.Property.Network: static'' :: Interface -> [(IPAddr, Maybe Gateway, InterfaceOptions)] -> Property DebianLike
+ Propellor.Property.Network: type InterfaceStanza = ([String], InterfaceOptions)
+ Propellor.Types: instance forall a k (x :: [a]) (y :: [a]) (x' :: k). (Propellor.Types.MetaTypes.CheckCombinable x y, Propellor.Types.Singletons.SingI (Propellor.Types.MetaTypes.Combine x y)) => Propellor.Types.Combines (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes x) (Propellor.Types.MetaTypes.MetaTypes x')) (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes y))
+ Propellor.Types: instance forall a k (x :: [a]) (y :: [a]) (y' :: k). (Propellor.Types.MetaTypes.CheckCombinable x y, Propellor.Types.Singletons.SingI (Propellor.Types.MetaTypes.Combine x y)) => Propellor.Types.Combines (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes x)) (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes y) (Propellor.Types.MetaTypes.MetaTypes y'))
+ Propellor.Types: instance forall a1 a2 (x :: [a1]) (y :: [a1]) (x' :: [a2]) (y' :: [a2]). (Propellor.Types.MetaTypes.CheckCombinable x y, Propellor.Types.MetaTypes.CheckCombinable x' y', Propellor.Types.Singletons.SingI (Propellor.Types.MetaTypes.Combine x y), Propellor.Types.Singletons.SingI (Propellor.Types.MetaTypes.Combine x' y')) => Propellor.Types.Combines (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes x) (Propellor.Types.MetaTypes.MetaTypes x')) (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes y) (Propellor.Types.MetaTypes.MetaTypes y'))
+ Propellor.Types: instance forall k1 k2 (setupmetatypes :: k1) (undometatypes :: k2). (GHC.Base.Monoid (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes setupmetatypes)), GHC.Base.Monoid (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes undometatypes)), Propellor.Types.Singletons.SingI setupmetatypes, Propellor.Types.Singletons.SingI undometatypes) => GHC.Base.Monoid (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes setupmetatypes) (Propellor.Types.MetaTypes.MetaTypes undometatypes))
+ Propellor.Types: instance forall k1 k2 (setupmetatypes :: k1) (undometatypes :: k2). (GHC.Base.Semigroup (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes setupmetatypes)), GHC.Base.Semigroup (Propellor.Types.Property (Propellor.Types.MetaTypes.MetaTypes undometatypes)), Propellor.Types.Singletons.SingI setupmetatypes, Propellor.Types.Singletons.SingI undometatypes) => GHC.Base.Semigroup (Propellor.Types.RevertableProperty (Propellor.Types.MetaTypes.MetaTypes setupmetatypes) (Propellor.Types.MetaTypes.MetaTypes undometatypes))
+ Propellor.Types.MetaTypes: data DelayErrorFcf (a :: ErrorMessage) (b :: k)
+ Propellor.Utilities: SomeException :: e -> SomeException
- Propellor: (!) :: CheckCombinableNote x z (NoteFor ( 'Text "!")) => Props (MetaTypes x) -> RevertableProperty (MetaTypes y) (MetaTypes z) -> Props (MetaTypes (Combine x z))
+ Propellor: (!) :: CheckCombinableNote x z (NoteFor ('Text "!")) => Props (MetaTypes x) -> RevertableProperty (MetaTypes y) (MetaTypes z) -> Props (MetaTypes (Combine x z))
- Propellor: (&) :: (IsProp p, MetaTypes y ~ GetMetaTypes p, CheckCombinableNote x y (NoteFor ( 'Text "&"))) => Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
+ Propellor: (&) :: (IsProp p, MetaTypes y ~ GetMetaTypes p, CheckCombinableNote x y (NoteFor ('Text "&"))) => Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
- Propellor: Alt :: f a -> Alt
+ Propellor: Alt :: f a -> Alt (f :: k -> Type) (a :: k)
- Propellor: Ap :: f a -> Ap
+ Propellor: Ap :: f a -> Ap (f :: k -> Type) (a :: k)
- Propellor: [getAlt] :: Alt -> f a
+ Propellor: [getAlt] :: Alt (f :: k -> Type) (a :: k) -> f a
- Propellor: [getAp] :: Ap -> f a
+ Propellor: [getAp] :: Ap (f :: k -> Type) (a :: k) -> f a
- Propellor.Base: withCurrentDirectory :: () => FilePath -> IO a -> IO a
+ Propellor.Base: withCurrentDirectory :: FilePath -> IO a -> IO a
- Propellor.Container: propagateContainer :: (IncludesInfo metatypes ~ 'True, IsContainer c) => String -> c -> (PropagateInfo -> Bool) -> Property metatypes -> Property metatypes
+ Propellor.Container: propagateContainer :: (IncludesInfo metatypes ~ 'True, IsContainer c) => String -> c -> (PropagateInfo -> Bool) -> Property metatypes -> Property metatypes
- Propellor.Info: addInfoProperty :: IncludesInfo metatypes ~ 'True => Property metatypes -> Info -> Property metatypes
+ Propellor.Info: addInfoProperty :: IncludesInfo metatypes ~ 'True => Property metatypes -> Info -> Property metatypes
- Propellor.PrivData: withPrivData :: (IsContext c, IsPrivDataSource s, IncludesInfo metatypes ~ 'True) => s -> c -> (((PrivData -> Propellor Result) -> Propellor Result) -> Property metatypes) -> Property metatypes
+ Propellor.PrivData: withPrivData :: (IsContext c, IsPrivDataSource s, IncludesInfo metatypes ~ 'True) => s -> c -> (((PrivData -> Propellor Result) -> Propellor Result) -> Property metatypes) -> Property metatypes
- Propellor.PrivData: withSomePrivData :: (IsContext c, IsPrivDataSource s, IncludesInfo metatypes ~ 'True) => [s] -> c -> ((((PrivDataField, PrivData) -> Propellor Result) -> Propellor Result) -> Property metatypes) -> Property metatypes
+ Propellor.PrivData: withSomePrivData :: (IsContext c, IsPrivDataSource s, IncludesInfo metatypes ~ 'True) => [s] -> c -> ((((PrivDataField, PrivData) -> Propellor Result) -> Propellor Result) -> Property metatypes) -> Property metatypes
- Propellor.PropAccum: (!) :: CheckCombinableNote x z (NoteFor ( 'Text "!")) => Props (MetaTypes x) -> RevertableProperty (MetaTypes y) (MetaTypes z) -> Props (MetaTypes (Combine x z))
+ Propellor.PropAccum: (!) :: CheckCombinableNote x z (NoteFor ('Text "!")) => Props (MetaTypes x) -> RevertableProperty (MetaTypes y) (MetaTypes z) -> Props (MetaTypes (Combine x z))
- Propellor.PropAccum: (&) :: (IsProp p, MetaTypes y ~ GetMetaTypes p, CheckCombinableNote x y (NoteFor ( 'Text "&"))) => Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
+ Propellor.PropAccum: (&) :: (IsProp p, MetaTypes y ~ GetMetaTypes p, CheckCombinableNote x y (NoteFor ('Text "&"))) => Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
- Propellor.PropAccum: (&^) :: (IsProp p, MetaTypes y ~ GetMetaTypes p, CheckCombinableNote x y (NoteFor ( 'Text "&^"))) => Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
+ Propellor.PropAccum: (&^) :: (IsProp p, MetaTypes y ~ GetMetaTypes p, CheckCombinableNote x y (NoteFor ('Text "&^"))) => Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
- Propellor.Property: pickOS :: HasCallStack => (SingKind ( 'KProxy :: KProxy ka), SingKind ( 'KProxy :: KProxy kb), DemoteRep ( 'KProxy :: KProxy ka) ~ [MetaType], DemoteRep ( 'KProxy :: KProxy kb) ~ [MetaType], SingI c) => Property (MetaTypes (a :: ka)) -> Property (MetaTypes (b :: kb)) -> Property (MetaTypes c)
+ Propellor.Property: pickOS :: HasCallStack => (SingKind ('KProxy :: KProxy ka), SingKind ('KProxy :: KProxy kb), DemoteRep ('KProxy :: KProxy ka) ~ [MetaType], DemoteRep ('KProxy :: KProxy kb) ~ [MetaType], SingI c) => Property (MetaTypes (a :: ka)) -> Property (MetaTypes (b :: kb)) -> Property (MetaTypes c)
- Propellor.Types: type ArchLinux = MetaTypes '[ 'Targeting 'OSArchLinux]
+ Propellor.Types: type ArchLinux = MetaTypes '[ 'Targeting 'OSArchLinux]
- Propellor.Types: type Buntish = MetaTypes '[ 'Targeting 'OSBuntish]
+ Propellor.Types: type Buntish = MetaTypes '[ 'Targeting 'OSBuntish]
- Propellor.Types: type Debian = MetaTypes '[ 'Targeting 'OSDebian]
+ Propellor.Types: type Debian = MetaTypes '[ 'Targeting 'OSDebian]
- Propellor.Types: type DebianLike = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
+ Propellor.Types: type DebianLike = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
- Propellor.Types: type FreeBSD = MetaTypes '[ 'Targeting 'OSFreeBSD]
+ Propellor.Types: type FreeBSD = MetaTypes '[ 'Targeting 'OSFreeBSD]
- Propellor.Types: type Linux = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish, 'Targeting 'OSArchLinux]
+ Propellor.Types: type Linux = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish, 'Targeting 'OSArchLinux]
- Propellor.Types: type UnixLike = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish, 'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
+ Propellor.Types: type UnixLike = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish, 'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
- Propellor.Types.MetaTypes: type ArchLinux = MetaTypes '[ 'Targeting 'OSArchLinux]
+ Propellor.Types.MetaTypes: type ArchLinux = MetaTypes '[ 'Targeting 'OSArchLinux]
- Propellor.Types.MetaTypes: type Buntish = MetaTypes '[ 'Targeting 'OSBuntish]
+ Propellor.Types.MetaTypes: type Buntish = MetaTypes '[ 'Targeting 'OSBuntish]
- Propellor.Types.MetaTypes: type Debian = MetaTypes '[ 'Targeting 'OSDebian]
+ Propellor.Types.MetaTypes: type Debian = MetaTypes '[ 'Targeting 'OSDebian]
- Propellor.Types.MetaTypes: type DebianLike = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
+ Propellor.Types.MetaTypes: type DebianLike = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish]
- Propellor.Types.MetaTypes: type DelayError (err :: ErrorMessage) = Eval (DelayErrorFcf err :: k -> Type)
+ Propellor.Types.MetaTypes: type DelayError (err :: ErrorMessage) = Eval DelayErrorFcf err :: k -> Type
- Propellor.Types.MetaTypes: type FreeBSD = MetaTypes '[ 'Targeting 'OSFreeBSD]
+ Propellor.Types.MetaTypes: type FreeBSD = MetaTypes '[ 'Targeting 'OSFreeBSD]
- Propellor.Types.MetaTypes: type Linux = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish, 'Targeting 'OSArchLinux]
+ Propellor.Types.MetaTypes: type Linux = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish, 'Targeting 'OSArchLinux]
- Propellor.Types.MetaTypes: type UnixLike = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish, 'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
+ Propellor.Types.MetaTypes: type UnixLike = MetaTypes '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish, 'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
- Propellor.Types.Singletons: class (kparam ~ 'KProxy) => SingKind (kparam :: KProxy k) where {
+ Propellor.Types.Singletons: class (kparam ~ 'KProxy) => SingKind (kparam :: KProxy k) where {
- Propellor.Utilities: withCreateProcess :: () => CreateProcess -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO a) -> IO a
+ Propellor.Utilities: withCreateProcess :: CreateProcess -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO a) -> IO a
- Propellor.Utilities: withCurrentDirectory :: () => FilePath -> IO a -> IO a
+ Propellor.Utilities: withCurrentDirectory :: FilePath -> IO a -> IO a

Files

CHANGELOG view
@@ -1,3 +1,18 @@+propellor (5.13) unstable; urgency=medium++  * Network: Added support for network interfaces with several address+    stanzas, eg ipv4 and ipv6.+    Thanks, Nicolas Schodet+  * Sudo.enabledFor: Deal with new @includedir syntax in sudoers file.+  * Apt.securityUpdates: Stop generating testing-security lines, as+    testing-security is unused per debian documentation.+  * Utility.HumanNumber: Fix rounding bug that could result in+    sometimes quite wrong values, eg "1.1 GB" when the input value was a+    few bytes less than 2 GB. Properties in Ccache and Journald that+    used it to generate config files were affected by this bug.++ -- Joey Hess <id@joeyh.name>  Fri, 30 Jul 2021 10:02:19 -0400+ propellor (5.12) unstable; urgency=medium    * Worked around a situation where ghc uses insane amounts of memory
config.hs view
@@ -1,29 +1,471 @@--- This is the main configuration file for Propellor, and is used to build--- the propellor program.+-- This is the live config file used by propellor's author.+-- https://propellor.branchable.com/+module Main where  import Propellor+import Propellor.Property.Scheduled+import Propellor.Property.DiskImage+import Propellor.Property.Chroot+import Propellor.Property.Machine+import Propellor.Property.Bootstrap import qualified Propellor.Property.File as File import qualified Propellor.Property.Apt as Apt+import qualified Propellor.Property.Network as Network+import qualified Propellor.Property.Ssh as Ssh import qualified Propellor.Property.Cron as Cron+import qualified Propellor.Property.Sudo as Sudo import qualified Propellor.Property.User as User--main :: IO ()-main = defaultMain hosts+import qualified Propellor.Property.Hostname as Hostname+import qualified Propellor.Property.Tor as Tor+import qualified Propellor.Property.Dns as Dns+import qualified Propellor.Property.Git as Git+import qualified Propellor.Property.Postfix as Postfix+import qualified Propellor.Property.Apache as Apache+import qualified Propellor.Property.LetsEncrypt as LetsEncrypt+import qualified Propellor.Property.Locale as Locale+import qualified Propellor.Property.Grub as Grub+import qualified Propellor.Property.Borg as Borg+import qualified Propellor.Property.OpenId as OpenId+import qualified Propellor.Property.Systemd as Systemd+import qualified Propellor.Property.Journald as Journald+import qualified Propellor.Property.Fail2Ban as Fail2Ban+import qualified Propellor.Property.Laptop as Laptop+import qualified Propellor.Property.LightDM as LightDM+import qualified Propellor.Property.HostingProvider.Linode as Linode+import qualified Propellor.Property.SiteSpecific.GitHome as GitHome+import qualified Propellor.Property.SiteSpecific.GitAnnexBuilder as GitAnnexBuilder+import qualified Propellor.Property.SiteSpecific.Branchable as Branchable+import qualified Propellor.Property.SiteSpecific.JoeySites as JoeySites --- The hosts propellor knows about.-hosts :: [Host]-hosts =-	[ mybox-	]+main :: IO ()           --     _         ______`|                       ,-.__+main = defaultMain hosts --  /   \___-=O`/|O`/__|                      (____.'+  {- Propellor            -- \          / | /    )          _.-"-._+     Deployed -}          --  `/-==__ _/__|/__=-|          (       \_+hosts :: [Host]          --   *             \ | |           '--------'+hosts =                 --                  (o)  `+	[ darkstar+	, dragon+	, oyster+	, orca+	, honeybee+	, kite+	, beaver+	, sow+	, mouse+	, peregrine+	, pell+	] ++ monsters --- An example host.-mybox :: Host-mybox = host "mybox.example.com" $ props+darkstar :: Host+darkstar = host "darkstar.kitenet.net" $ props 	& osDebian Unstable X86_64-	& Apt.stdSourcesList+	& ipv6 "2001:4830:1600:187::2"+	& Hostname.sane+	& Hostname.mailname+	& Apt.serviceInstalledRunning "swapspace"+	& Laptop.powertopAutoTuneOnBoot+	& Laptop.trimSSD+	& Grub.cmdline_Linux_default "i915.enable_psr=1"+	! Grub.cmdline_Linux_default "quiet"+	& User.hasGroup (User "joey") (Group "dialout")++	& JoeySites.dkimMilter+	& JoeySites.postfixSaslPasswordClient+	-- & JoeySites.alarmClock "*-*-* 7:30" (User "joey")+	--	"/usr/bin/timeout 45m /home/joey/bin/goodmorning"+	& JoeySites.laptopSoftware+	& JoeySites.userDirHtml+	& Ssh.userKeys (User "joey") hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICfFntnesZcYz2B2T41ay45igfckXRSh5uVffkuCQkLv joey@darkstar")+		]+	& imageBuiltFor honeybee+		(RawDiskImage "/srv/honeybee.img")+		(Debootstrapped mempty)++dragon :: Host+dragon = host "dragon.kitenet.net" $ props+	& ipv6 "2001:4830:1600:187::2"+	& JoeySites.dkimMilter+	& JoeySites.postfixSaslPasswordClient++oyster :: Host+oyster = host "oyster.kitenet.net" $ props+	& standardSystem (Stable "buster") X86_64+		["Unreliable server. Anything here may be lost at any time!" ]+	& ipv4 "45.138.157.89"++	& User.hasPassword (User "root") 	& Apt.unattendedUpgrades-	& Apt.installed ["etckeeper"]++orca :: Host+orca = host "orca.kitenet.net" $ props+	& standardSystem Unstable X86_64 [ "Main git-annex build box." ]+	& ipv4 "138.38.108.179"++	& Apt.unattendedUpgrades+	& Postfix.satellite+	& Apt.serviceInstalledRunning "ntp"+	& Systemd.persistentJournal++	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.standardAutoBuilder+		Unstable X86_64 Nothing (Cron.Times "15 * * * *") "2h")+	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.standardAutoBuilder+		Unstable X86_32 Nothing (Cron.Times "30 * * * *") "2h")+	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.stackAutoBuilder+		(Stable "jessie") X86_32 (Just "ancient") (Cron.Times "45 * * * *") "2h")+	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.standardAutoBuilder+		Testing ARM64 Nothing (Cron.Times "1 * * * *") "4h")++honeybee :: Host+honeybee = host "honeybee.kitenet.net" $ props+	& standardSystem Testing ARMHF+		[ "Home router and arm git-annex build box." ]+	& Apt.removed ["rsyslog"]+	+	& cubietech_Cubietruck+	& hasPartition+		( partition EXT3+			`mountedAt` "/"+			`setSize` MegaBytes 16000+		)+	& JoeySites.cubieTruckOneWire+	& Systemd.persistentJournal+	& Apt.installed ["firmware-misc-nonfree"] -- wifi+	& Apt.serviceInstalledRunning "ntp" -- no hardware clock+	& bootstrappedFrom GitRepoOutsideChroot+	& Ssh.hostKeys hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIS/hDYq1MAxfOBf49htym3BOYlx4Gk9SDpiHjv7u6IC")+		]+	& Ssh.userKeys (User "joey") hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAYgEgsDmN26goPBGPN0HIvtkZfxlc996nPfBPDWxGuh")+		]++	& JoeySites.house+		(User "joey")+		hosts+		(Context "house.joeyh.name")+		(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMAmVYddg/RgCbIj+cLcEiddeFXaYFnbEJ3uGj9G/EyV joey@honeybee")+	& JoeySites.homeRouter+	& JoeySites.homeNAS+	& Apt.installed ["mtr-tiny", "iftop", "screen"]+	& Postfix.satellite++	& check (not <$> hasContainerCapability Systemd.FilesystemContained) +		(setupRevertableProperty autobuilder)+	-- In case compiler needs more than available ram+	& Apt.serviceInstalledRunning "swapspace"+  where+	autobuilder = Systemd.nspawned $ GitAnnexBuilder.autoBuilderContainer+		(GitAnnexBuilder.armAutoBuilder GitAnnexBuilder.standardAutoBuilder)+		Testing ARMEL Nothing (Cron.Times "15 15 * * *") "10h"++-- This is not a complete description of kite, since it's a+-- multiuser system with eg, user passwords that are not deployed+-- with propellor.+kite :: Host+kite = host "kite.kitenet.net" $ props+	& standardSystemUnhardened Testing X86_64 [ "Welcome to kite!" ]+	& ipv4 "66.228.36.95"+	& ipv6 "2600:3c03::f03c:91ff:fe73:b0d2"+	& alias "kitenet.net"+	& Ssh.hostKeys (Context "kitenet.net")+		[ (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=")+		, (SshEcdsa, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLF+dzqBJZix+CWUkAd3Bd3cofFCKwHMNRIfwx1G7dL4XFe6fMKxmrNetQcodo2edyufwoPmCPr3NmnwON9vyh0=")+		, (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFZftKMnH/zH29BHMKbcBO4QsgTrstYFVhbrzrlRzBO3")+		]++	& Network.preserveStatic "eth0" `requires` Network.cleanInterfacesFile+	& Apt.installed ["linux-image-amd64"]+	& Apt.serviceInstalledRunning "swapspace"+	& Linode.serialGrub+	& Linode.mlocateEnabled+	& Apt.unattendedUpgrades+	& Systemd.installed+	& Systemd.persistentJournal+	& Journald.systemMaxUse "500MiB"+	& Ssh.passwordAuthentication True+	& Fail2Ban.installed -- since ssh password authentication is allowed+	-- Allow ssh -R to forward ports via kite+	& Ssh.setSshdConfig "GatewayPorts" "clientspecified"+	& Apt.serviceInstalledRunning "ntp"+	& "/etc/timezone" `File.hasContent` ["US/Eastern"]+	+	& Borg.backup "/" (JoeySites.rsyncNetBorgRepo "kite.borg" []) Cron.Daily+		[ "--exclude=/proc/*"+		, "--exclude=/sys/*"+		, "--exclude=/run/*"+		, "--exclude=/mnt/*"+		, "--exclude=/tmp/*"+		, "--exclude=/var/tmp/*"+		, "--exclude=/var/cache/*"+		, "--exclude=/var/lib/swapspace/*"+		, "--exclude=/var/lib/container/*"+		, "--exclude=/home/joey/lib"+		-- These directories are backed up and restored separately.+		, "--exclude=/srv/git"+		]+		[ Borg.KeepDays 7+		, Borg.KeepWeeks 4+		, Borg.KeepMonths 3+		]+		`requires` Ssh.knownHost hosts "usw-s002.rsync.net" (User "root")+		`requires` Ssh.userKeys (User "root")+			(Context "kite.kitenet.net")+			[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKyciu8E8qspcO8lnTSUBAxUdYfmk7FaFlvT5yxUaP+0 root@kite")+			]++	& alias "smtp.kitenet.net"+	& alias "imap.kitenet.net"+	& alias "pop.kitenet.net"+	& alias "mail.kitenet.net"+	& JoeySites.kiteMailServer++	& JoeySites.legacyWebSites+	& File.ownerGroup "/srv/web" (User "joey") (Group "joey")+	& Apt.installed ["analog"]++	& alias "git.kitenet.net"+	& alias "git.joeyh.name"+	& JoeySites.gitServer hosts++	& JoeySites.downloads+	& JoeySites.gitAnnexDistributor+	& JoeySites.tmp++	& Apt.installed+		[ "git-annex", "myrepos"+		, "build-essential", "make"+		, "rss2email", "archivemail"+		, "devscripts"+		-- Some users have zsh as their login shell.+		, "zsh"+		]++	& alias "znc.kitenet.net"+	& JoeySites.ircBouncer++	& alias "kgb.kitenet.net"+	& JoeySites.kgbServer+	+	& Systemd.nspawned ancientKitenet+	! Systemd.nspawned openidProvider+	+	& alias "podcatcher.kitenet.net"+	& JoeySites.podcatcher++	& JoeySites.scrollBox+	& alias "scroll.joeyh.name"+	& alias "us.scroll.joeyh.name"++	& alias "ns4.kitenet.net"+	& myDnsPrimary "kitenet.net"+		[ (RelDomain "mouse-onion", CNAME $ AbsDomain "htieo6yu2qtcn2j3.onion")+		, (RelDomain "beaver-onion", CNAME $ AbsDomain "tl4xsvaxryjylgxs.onion")+		, (RelDomain "peregrine-onion", CNAME $ AbsDomain "rsdwvaabir6ty2kdzblq7wdda26ib4fuc6hzxzwum75jbn6thqbojvid.onion")+		, (RelDomain "sow-onion", CNAME $ AbsDomain "urt4g2tq32qktgtp.onion")+		]+	& myDnsPrimary "joeyh.name" []+	& myDnsPrimary "ikiwiki.info" []+	& myDnsPrimary "olduse.net"+		[ (RelDomain "article", CNAME $ AbsDomain "virgil.koldfront.dk")+		]+	! myDnsPrimary "quarantimer.app" []+	& alias "ns4.branchable.com"+	& branchableSecondary+	& Dns.secondaryFor ["animx"] hosts "animx.eu.org"+	-- Use its own name server (amoung other things this avoids+	-- spamassassin URIBL_BLOCKED.+	& "/etc/resolv.conf" `File.hasContent`+		[ "nameserver 127.0.0.1"+		, "domain kitenet.net"+		, "search kitenet.net"+		]+	+	& alias "debug-me.joeyh.name"+	& Apt.installed ["debug-me", "debug-me-server"]+	& Systemd.enabled "debug-me"++	-- testing+	& Apache.httpsVirtualHost "letsencrypt.joeyh.name" "/var/www/html"+		(LetsEncrypt.AgreeTOS (Just "id@joeyh.name"))+	& alias "letsencrypt.joeyh.name"++beaver :: Host+beaver = host "beaver.kitenet.net" $ props 	& Apt.installed ["ssh"]+	& Ssh.hostPubKey SshDsa "ssh-dss AAAAB3NzaC1kc3MAAACBAIrLX260fY0Jjj/p0syNhX8OyR8hcr6feDPGOj87bMad0k/w/taDSOzpXe0Wet7rvUTbxUjH+Q5wPd4R9zkaSDiR/tCb45OdG6JsaIkmqncwe8yrU+pqSRCxttwbcFe+UU+4AAcinjVedZjVRDj2rRaFPc9BXkPt7ffk8GwEJ31/AAAAFQCG/gOjObsr86vvldUZHCteaJttNQAAAIB5nomvcqOk/TD07DLaWKyG7gAcW5WnfY3WtnvLRAFk09aq1EuiJ6Yba99Zkb+bsxXv89FWjWDg/Z3Psa22JMyi0HEDVsOevy/1sEQ96AGH5ijLzFInfXAM7gaJKXASD7hPbVdjySbgRCdwu0dzmQWHtH+8i1CMVmA2/a5Y/wtlJAAAAIAUZj2US2D378jBwyX1Py7e4sJfea3WSGYZjn4DLlsLGsB88POuh32aOChd1yzF6r6C2sdoPBHQcWBgNGXcx4gF0B5UmyVHg3lIX2NVSG1ZmfuLNJs9iKNu4cHXUmqBbwFYQJBvB69EEtrOw4jSbiTKwHFmqdA/mw1VsMB+khUaVw=="+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)++sow :: Host+sow = host "sow.kitenet.net" $ props+	& Apt.installed ["ssh"]+	& Ssh.hostPubKey SshDsa "ssh-dss AAAAB3NzaC1kc3MAAACBAIrLX260fY0Jjj/p0syNhX8OyR8hcr6feDPGOj87bMad0k/w/taDSOzpXe0Wet7rvUTbxUjH+Q5wPd4R9zkaSDiR/tCb45OdG6JsaIkmqncwe8yrU+pqSRCxttwbcFe+UU+4AAcinjVedZjVRDj2rRaFPc9BXkPt7ffk8GwEJ31/AAAAFQCG/gOjObsr86vvldUZHCteaJttNQAAAIB5nomvcqOk/TD07DLaWKyG7gAcW5WnfY3WtnvLRAFk09aq1EuiJ6Yba99Zkb+bsxXv89FWjWDg/Z3Psa22JMyi0HEDVsOevy/1sEQ96AGH5ijLzFInfXAM7gaJKXASD7hPbVdjySbgRCdwu0dzmQWHtH+8i1CMVmA2/a5Y/wtlJAAAAIAUZj2US2D378jBwyX1Py7e4sJfea3WSGYZjn4DLlsLGsB88POuh32aOChd1yzF6r6C2sdoPBHQcWBgNGXcx4gF0B5UmyVHg3lIX2NVSG1ZmfuLNJs9iKNu4cHXUmqBbwFYQJBvB69EEtrOw4jSbiTKwHFmqdA/mw1VsMB+khUaVw=="+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)++mouse :: Host+mouse = host "mouse.kitenet.net" $ props+	& ipv4 "67.223.19.96"+	& Apt.installed ["ssh"]+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)++peregrine :: Host+peregrine = host "peregrine.kitenet.net" $ props+	& Apt.installed ["ssh", "screen", "variety", "git-annex"]+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)+	& LightDM.autoLogin (User "desktop")++-- Branchable is not completely deployed with propellor yet.+pell :: Host+pell = host "pell.branchable.com" $ props+	& alias "branchable.com"+	& ipv4 "66.228.46.55"+	& ipv6 "2600:3c03::f03c:91ff:fedf:c0e5"++	-- All the websites I host at branchable that don't use+	-- branchable.com dns.+	& alias "olduse.net"+	& alias "www.olduse.net"+	& alias "www.kitenet.net"+	& alias "joeyh.name"+	& alias "www.joeyh.name"+	& alias "campaign.joeyh.name"+	& alias "ikiwiki.info"+	& alias "www.ikiwiki.info"+	& alias "git.ikiwiki.info"+	& alias "l10n.ikiwiki.info"+	& alias "dist-bugs.kitenet.net"+	& alias "family.kitenet.net"++	& osDebian (Stable "buster") X86_32+	& Apt.installed ["linux-image-686-pae"]+	& Apt.stdSourcesList `onChange` Apt.upgrade+	& Apt.unattendedUpgrades+	& Branchable.server hosts+	& Linode.serialGrub++++       --'                        __|II|      ,.+     ----                      __|II|II|__   (  \_,/\+--'-------'\o/-'-.-'-.-'-.- __|II|II|II|II|___/   __/ -'-.-'-.-'-.-'-.-'-.-'-+-------------------------- |   [Containers]      / --------------------------+-------------------------- :                    / ---------------------------+--------------------------- \____, o          ,' ----------------------------+---------------------------- '--,___________,'  -----------------------------++-- Exhibit: kite's 90's website on port 1994.+ancientKitenet :: Systemd.Container+ancientKitenet = Systemd.debContainer "ancient-kitenet" $ props+	& standardContainer (Stable "buster")+	& alias hn+	& Git.cloned (User "root") "git://kitenet-net.branchable.com/" "/var/www/html"+		(Just "remotes/origin/old-kitenet.net")+	& Apache.installed+	& Apache.listenPorts [p]+	& Apache.virtualHost hn p "/var/www/html"+	& Apache.siteDisabled "000-default"+  where+	p = Port 1994+	hn = "ancient.kitenet.net"++-- My own openid provider. Uses php, so containerized for security+-- and administrative sanity.+openidProvider :: Systemd.Container+openidProvider = Systemd.debContainer "openid-provider" $ props+	-- simpleid is not in buster+	& standardContainer (Stable "stretch")+	& alias hn+	& OpenId.providerFor [User "joey", User "liw"] hn (Just (Port 8086))+  where+	hn = "openid.kitenet.net"++type Motd = [String]++-- This is my standard system setup.+standardSystem :: DebianSuite -> Architecture -> Motd -> Property (HasInfo + Debian)+standardSystem suite arch motd =+	standardSystemUnhardened suite arch motd+		`before` Ssh.noPasswords++standardSystemUnhardened :: DebianSuite -> Architecture -> Motd -> Property (HasInfo + Debian)+standardSystemUnhardened suite arch motd = propertyList "standard system" $ props+	& osDebian suite arch+	& Hostname.sane+	& Hostname.mailname+	& Hostname.searchDomain+	& Locale.available "en_US.UTF-8"+	& File.hasContent "/etc/motd" ("":motd++[""])+	& Apt.stdSourcesList `onChange` Apt.upgrade+	& Apt.cacheCleaned+	& Apt.installed ["etckeeper"]+	& Apt.installed ["ssh", "mosh"]+	& GitHome.installedFor (User "root") 	& User.hasSomePassword (User "root")-	& File.dirExists "/var/www"+	& User.accountFor (User "joey")+	& User.hasSomePassword (User "joey")+	& Sudo.enabledFor (User "joey")+	& GitHome.installedFor (User "joey")+	& Apt.installed ["vim", "screen", "less"] 	& Cron.runPropellor (Cron.Times "30 * * * *")+	-- I use postfix, or no MTA.+	& JoeySites.noExim++-- This is my standard container setup, Featuring automatic upgrades.+standardContainer :: DebianSuite -> Property (HasInfo + Debian)+standardContainer suite = propertyList "standard container" $ props+	& osDebian suite X86_64+	-- Do not want to run mail daemon inside a random container..+	& JoeySites.noExim+	& Apt.stdSourcesList `onChange` Apt.upgrade+	& Apt.unattendedUpgrades+	& Apt.cacheCleaned++branchableSecondary :: RevertableProperty (HasInfo + DebianLike) DebianLike+branchableSecondary = Dns.secondaryFor ["branchable.com"] hosts "branchable.com"++-- Currently using kite (ns4) as primary with gandi as secondary+-- kite handles all mail.+myDnsPrimary :: Domain -> [(BindDomain, Record)] -> RevertableProperty (HasInfo + DebianLike) DebianLike+myDnsPrimary domain extras = Dns.signedPrimary (Weekly Nothing) hosts domain+	(Dns.mkSOA "ns4.kitenet.net" 100) $+	[ (RootDomain, NS $ AbsDomain "ns4.kitenet.net")+	, (RootDomain, NS $ AbsDomain "ns6.gandi.net")+	, (RootDomain, MX 0 $ AbsDomain "kitenet.net")+	, (RootDomain, TXT "v=spf1 a a:kitenet.net ~all")+	, JoeySites.domainKey+	] ++ extras++-- Systems I don't manage with propellor,+-- but do want to track their public keys etc.+monsters :: [Host]+monsters =+	[ host "usw-s002.rsync.net" $ props+		& Ssh.hostPubKey SshEd25519 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB7yTEBGfQYdwG/oeL+U9XPMIh/dW7XNs9T+M79YIOrd"+	, host "ns6.gandi.net" $ props+		& ipv4 "217.70.177.40"+	, host "animx" $ props+		& ipv4 "76.7.174.49"+	]++++                          --                                o+                          --             ___                 o              o+                       {-----\          / o \              ___o            o+                       {      \    __   \   /   _        (X___>--         __o+  _____________________{ ______\___  \__/ | \__/ \____                  |X__>+ <                                  \___//|\\___/\     \____________   _+  \                                  ___/ | \___    # #             \ (-)+   \    O      O      O             #     |     \ #                  >=)+    \______________________________# #   /       #__________________/ (-}++
debian/changelog view
@@ -1,3 +1,18 @@+propellor (5.13) unstable; urgency=medium++  * Network: Added support for network interfaces with several address+    stanzas, eg ipv4 and ipv6.+    Thanks, Nicolas Schodet+  * Sudo.enabledFor: Deal with new @includedir syntax in sudoers file.+  * Apt.securityUpdates: Stop generating testing-security lines, as+    testing-security is unused per debian documentation.+  * Utility.HumanNumber: Fix rounding bug that could result in+    sometimes quite wrong values, eg "1.1 GB" when the input value was a+    few bytes less than 2 GB. Properties in Ccache and Journald that+    used it to generate config files were affected by this bug.++ -- Joey Hess <id@joeyh.name>  Fri, 30 Jul 2021 10:02:19 -0400+ propellor (5.12) unstable; urgency=medium    * Worked around a situation where ghc uses insane amounts of memory
executables/propellor-config.hs view
@@ -1,29 +1,471 @@--- This is the main configuration file for Propellor, and is used to build--- the propellor program.+-- This is the live config file used by propellor's author.+-- https://propellor.branchable.com/+module Main where  import Propellor+import Propellor.Property.Scheduled+import Propellor.Property.DiskImage+import Propellor.Property.Chroot+import Propellor.Property.Machine+import Propellor.Property.Bootstrap import qualified Propellor.Property.File as File import qualified Propellor.Property.Apt as Apt+import qualified Propellor.Property.Network as Network+import qualified Propellor.Property.Ssh as Ssh import qualified Propellor.Property.Cron as Cron+import qualified Propellor.Property.Sudo as Sudo import qualified Propellor.Property.User as User--main :: IO ()-main = defaultMain hosts+import qualified Propellor.Property.Hostname as Hostname+import qualified Propellor.Property.Tor as Tor+import qualified Propellor.Property.Dns as Dns+import qualified Propellor.Property.Git as Git+import qualified Propellor.Property.Postfix as Postfix+import qualified Propellor.Property.Apache as Apache+import qualified Propellor.Property.LetsEncrypt as LetsEncrypt+import qualified Propellor.Property.Locale as Locale+import qualified Propellor.Property.Grub as Grub+import qualified Propellor.Property.Borg as Borg+import qualified Propellor.Property.OpenId as OpenId+import qualified Propellor.Property.Systemd as Systemd+import qualified Propellor.Property.Journald as Journald+import qualified Propellor.Property.Fail2Ban as Fail2Ban+import qualified Propellor.Property.Laptop as Laptop+import qualified Propellor.Property.LightDM as LightDM+import qualified Propellor.Property.HostingProvider.Linode as Linode+import qualified Propellor.Property.SiteSpecific.GitHome as GitHome+import qualified Propellor.Property.SiteSpecific.GitAnnexBuilder as GitAnnexBuilder+import qualified Propellor.Property.SiteSpecific.Branchable as Branchable+import qualified Propellor.Property.SiteSpecific.JoeySites as JoeySites --- The hosts propellor knows about.-hosts :: [Host]-hosts =-	[ mybox-	]+main :: IO ()           --     _         ______`|                       ,-.__+main = defaultMain hosts --  /   \___-=O`/|O`/__|                      (____.'+  {- Propellor            -- \          / | /    )          _.-"-._+     Deployed -}          --  `/-==__ _/__|/__=-|          (       \_+hosts :: [Host]          --   *             \ | |           '--------'+hosts =                 --                  (o)  `+	[ darkstar+	, dragon+	, oyster+	, orca+	, honeybee+	, kite+	, beaver+	, sow+	, mouse+	, peregrine+	, pell+	] ++ monsters --- An example host.-mybox :: Host-mybox = host "mybox.example.com" $ props+darkstar :: Host+darkstar = host "darkstar.kitenet.net" $ props 	& osDebian Unstable X86_64-	& Apt.stdSourcesList+	& ipv6 "2001:4830:1600:187::2"+	& Hostname.sane+	& Hostname.mailname+	& Apt.serviceInstalledRunning "swapspace"+	& Laptop.powertopAutoTuneOnBoot+	& Laptop.trimSSD+	& Grub.cmdline_Linux_default "i915.enable_psr=1"+	! Grub.cmdline_Linux_default "quiet"+	& User.hasGroup (User "joey") (Group "dialout")++	& JoeySites.dkimMilter+	& JoeySites.postfixSaslPasswordClient+	-- & JoeySites.alarmClock "*-*-* 7:30" (User "joey")+	--	"/usr/bin/timeout 45m /home/joey/bin/goodmorning"+	& JoeySites.laptopSoftware+	& JoeySites.userDirHtml+	& Ssh.userKeys (User "joey") hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICfFntnesZcYz2B2T41ay45igfckXRSh5uVffkuCQkLv joey@darkstar")+		]+	& imageBuiltFor honeybee+		(RawDiskImage "/srv/honeybee.img")+		(Debootstrapped mempty)++dragon :: Host+dragon = host "dragon.kitenet.net" $ props+	& ipv6 "2001:4830:1600:187::2"+	& JoeySites.dkimMilter+	& JoeySites.postfixSaslPasswordClient++oyster :: Host+oyster = host "oyster.kitenet.net" $ props+	& standardSystem (Stable "buster") X86_64+		["Unreliable server. Anything here may be lost at any time!" ]+	& ipv4 "45.138.157.89"++	& User.hasPassword (User "root") 	& Apt.unattendedUpgrades-	& Apt.installed ["etckeeper"]++orca :: Host+orca = host "orca.kitenet.net" $ props+	& standardSystem Unstable X86_64 [ "Main git-annex build box." ]+	& ipv4 "138.38.108.179"++	& Apt.unattendedUpgrades+	& Postfix.satellite+	& Apt.serviceInstalledRunning "ntp"+	& Systemd.persistentJournal++	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.standardAutoBuilder+		Unstable X86_64 Nothing (Cron.Times "15 * * * *") "2h")+	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.standardAutoBuilder+		Unstable X86_32 Nothing (Cron.Times "30 * * * *") "2h")+	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.stackAutoBuilder+		(Stable "jessie") X86_32 (Just "ancient") (Cron.Times "45 * * * *") "2h")+	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.standardAutoBuilder+		Testing ARM64 Nothing (Cron.Times "1 * * * *") "4h")++honeybee :: Host+honeybee = host "honeybee.kitenet.net" $ props+	& standardSystem Testing ARMHF+		[ "Home router and arm git-annex build box." ]+	& Apt.removed ["rsyslog"]+	+	& cubietech_Cubietruck+	& hasPartition+		( partition EXT3+			`mountedAt` "/"+			`setSize` MegaBytes 16000+		)+	& JoeySites.cubieTruckOneWire+	& Systemd.persistentJournal+	& Apt.installed ["firmware-misc-nonfree"] -- wifi+	& Apt.serviceInstalledRunning "ntp" -- no hardware clock+	& bootstrappedFrom GitRepoOutsideChroot+	& Ssh.hostKeys hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIS/hDYq1MAxfOBf49htym3BOYlx4Gk9SDpiHjv7u6IC")+		]+	& Ssh.userKeys (User "joey") hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAYgEgsDmN26goPBGPN0HIvtkZfxlc996nPfBPDWxGuh")+		]++	& JoeySites.house+		(User "joey")+		hosts+		(Context "house.joeyh.name")+		(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMAmVYddg/RgCbIj+cLcEiddeFXaYFnbEJ3uGj9G/EyV joey@honeybee")+	& JoeySites.homeRouter+	& JoeySites.homeNAS+	& Apt.installed ["mtr-tiny", "iftop", "screen"]+	& Postfix.satellite++	& check (not <$> hasContainerCapability Systemd.FilesystemContained) +		(setupRevertableProperty autobuilder)+	-- In case compiler needs more than available ram+	& Apt.serviceInstalledRunning "swapspace"+  where+	autobuilder = Systemd.nspawned $ GitAnnexBuilder.autoBuilderContainer+		(GitAnnexBuilder.armAutoBuilder GitAnnexBuilder.standardAutoBuilder)+		Testing ARMEL Nothing (Cron.Times "15 15 * * *") "10h"++-- This is not a complete description of kite, since it's a+-- multiuser system with eg, user passwords that are not deployed+-- with propellor.+kite :: Host+kite = host "kite.kitenet.net" $ props+	& standardSystemUnhardened Testing X86_64 [ "Welcome to kite!" ]+	& ipv4 "66.228.36.95"+	& ipv6 "2600:3c03::f03c:91ff:fe73:b0d2"+	& alias "kitenet.net"+	& Ssh.hostKeys (Context "kitenet.net")+		[ (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=")+		, (SshEcdsa, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLF+dzqBJZix+CWUkAd3Bd3cofFCKwHMNRIfwx1G7dL4XFe6fMKxmrNetQcodo2edyufwoPmCPr3NmnwON9vyh0=")+		, (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFZftKMnH/zH29BHMKbcBO4QsgTrstYFVhbrzrlRzBO3")+		]++	& Network.preserveStatic "eth0" `requires` Network.cleanInterfacesFile+	& Apt.installed ["linux-image-amd64"]+	& Apt.serviceInstalledRunning "swapspace"+	& Linode.serialGrub+	& Linode.mlocateEnabled+	& Apt.unattendedUpgrades+	& Systemd.installed+	& Systemd.persistentJournal+	& Journald.systemMaxUse "500MiB"+	& Ssh.passwordAuthentication True+	& Fail2Ban.installed -- since ssh password authentication is allowed+	-- Allow ssh -R to forward ports via kite+	& Ssh.setSshdConfig "GatewayPorts" "clientspecified"+	& Apt.serviceInstalledRunning "ntp"+	& "/etc/timezone" `File.hasContent` ["US/Eastern"]+	+	& Borg.backup "/" (JoeySites.rsyncNetBorgRepo "kite.borg" []) Cron.Daily+		[ "--exclude=/proc/*"+		, "--exclude=/sys/*"+		, "--exclude=/run/*"+		, "--exclude=/mnt/*"+		, "--exclude=/tmp/*"+		, "--exclude=/var/tmp/*"+		, "--exclude=/var/cache/*"+		, "--exclude=/var/lib/swapspace/*"+		, "--exclude=/var/lib/container/*"+		, "--exclude=/home/joey/lib"+		-- These directories are backed up and restored separately.+		, "--exclude=/srv/git"+		]+		[ Borg.KeepDays 7+		, Borg.KeepWeeks 4+		, Borg.KeepMonths 3+		]+		`requires` Ssh.knownHost hosts "usw-s002.rsync.net" (User "root")+		`requires` Ssh.userKeys (User "root")+			(Context "kite.kitenet.net")+			[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKyciu8E8qspcO8lnTSUBAxUdYfmk7FaFlvT5yxUaP+0 root@kite")+			]++	& alias "smtp.kitenet.net"+	& alias "imap.kitenet.net"+	& alias "pop.kitenet.net"+	& alias "mail.kitenet.net"+	& JoeySites.kiteMailServer++	& JoeySites.legacyWebSites+	& File.ownerGroup "/srv/web" (User "joey") (Group "joey")+	& Apt.installed ["analog"]++	& alias "git.kitenet.net"+	& alias "git.joeyh.name"+	& JoeySites.gitServer hosts++	& JoeySites.downloads+	& JoeySites.gitAnnexDistributor+	& JoeySites.tmp++	& Apt.installed+		[ "git-annex", "myrepos"+		, "build-essential", "make"+		, "rss2email", "archivemail"+		, "devscripts"+		-- Some users have zsh as their login shell.+		, "zsh"+		]++	& alias "znc.kitenet.net"+	& JoeySites.ircBouncer++	& alias "kgb.kitenet.net"+	& JoeySites.kgbServer+	+	& Systemd.nspawned ancientKitenet+	! Systemd.nspawned openidProvider+	+	& alias "podcatcher.kitenet.net"+	& JoeySites.podcatcher++	& JoeySites.scrollBox+	& alias "scroll.joeyh.name"+	& alias "us.scroll.joeyh.name"++	& alias "ns4.kitenet.net"+	& myDnsPrimary "kitenet.net"+		[ (RelDomain "mouse-onion", CNAME $ AbsDomain "htieo6yu2qtcn2j3.onion")+		, (RelDomain "beaver-onion", CNAME $ AbsDomain "tl4xsvaxryjylgxs.onion")+		, (RelDomain "peregrine-onion", CNAME $ AbsDomain "rsdwvaabir6ty2kdzblq7wdda26ib4fuc6hzxzwum75jbn6thqbojvid.onion")+		, (RelDomain "sow-onion", CNAME $ AbsDomain "urt4g2tq32qktgtp.onion")+		]+	& myDnsPrimary "joeyh.name" []+	& myDnsPrimary "ikiwiki.info" []+	& myDnsPrimary "olduse.net"+		[ (RelDomain "article", CNAME $ AbsDomain "virgil.koldfront.dk")+		]+	! myDnsPrimary "quarantimer.app" []+	& alias "ns4.branchable.com"+	& branchableSecondary+	& Dns.secondaryFor ["animx"] hosts "animx.eu.org"+	-- Use its own name server (amoung other things this avoids+	-- spamassassin URIBL_BLOCKED.+	& "/etc/resolv.conf" `File.hasContent`+		[ "nameserver 127.0.0.1"+		, "domain kitenet.net"+		, "search kitenet.net"+		]+	+	& alias "debug-me.joeyh.name"+	& Apt.installed ["debug-me", "debug-me-server"]+	& Systemd.enabled "debug-me"++	-- testing+	& Apache.httpsVirtualHost "letsencrypt.joeyh.name" "/var/www/html"+		(LetsEncrypt.AgreeTOS (Just "id@joeyh.name"))+	& alias "letsencrypt.joeyh.name"++beaver :: Host+beaver = host "beaver.kitenet.net" $ props 	& Apt.installed ["ssh"]+	& Ssh.hostPubKey SshDsa "ssh-dss AAAAB3NzaC1kc3MAAACBAIrLX260fY0Jjj/p0syNhX8OyR8hcr6feDPGOj87bMad0k/w/taDSOzpXe0Wet7rvUTbxUjH+Q5wPd4R9zkaSDiR/tCb45OdG6JsaIkmqncwe8yrU+pqSRCxttwbcFe+UU+4AAcinjVedZjVRDj2rRaFPc9BXkPt7ffk8GwEJ31/AAAAFQCG/gOjObsr86vvldUZHCteaJttNQAAAIB5nomvcqOk/TD07DLaWKyG7gAcW5WnfY3WtnvLRAFk09aq1EuiJ6Yba99Zkb+bsxXv89FWjWDg/Z3Psa22JMyi0HEDVsOevy/1sEQ96AGH5ijLzFInfXAM7gaJKXASD7hPbVdjySbgRCdwu0dzmQWHtH+8i1CMVmA2/a5Y/wtlJAAAAIAUZj2US2D378jBwyX1Py7e4sJfea3WSGYZjn4DLlsLGsB88POuh32aOChd1yzF6r6C2sdoPBHQcWBgNGXcx4gF0B5UmyVHg3lIX2NVSG1ZmfuLNJs9iKNu4cHXUmqBbwFYQJBvB69EEtrOw4jSbiTKwHFmqdA/mw1VsMB+khUaVw=="+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)++sow :: Host+sow = host "sow.kitenet.net" $ props+	& Apt.installed ["ssh"]+	& Ssh.hostPubKey SshDsa "ssh-dss AAAAB3NzaC1kc3MAAACBAIrLX260fY0Jjj/p0syNhX8OyR8hcr6feDPGOj87bMad0k/w/taDSOzpXe0Wet7rvUTbxUjH+Q5wPd4R9zkaSDiR/tCb45OdG6JsaIkmqncwe8yrU+pqSRCxttwbcFe+UU+4AAcinjVedZjVRDj2rRaFPc9BXkPt7ffk8GwEJ31/AAAAFQCG/gOjObsr86vvldUZHCteaJttNQAAAIB5nomvcqOk/TD07DLaWKyG7gAcW5WnfY3WtnvLRAFk09aq1EuiJ6Yba99Zkb+bsxXv89FWjWDg/Z3Psa22JMyi0HEDVsOevy/1sEQ96AGH5ijLzFInfXAM7gaJKXASD7hPbVdjySbgRCdwu0dzmQWHtH+8i1CMVmA2/a5Y/wtlJAAAAIAUZj2US2D378jBwyX1Py7e4sJfea3WSGYZjn4DLlsLGsB88POuh32aOChd1yzF6r6C2sdoPBHQcWBgNGXcx4gF0B5UmyVHg3lIX2NVSG1ZmfuLNJs9iKNu4cHXUmqBbwFYQJBvB69EEtrOw4jSbiTKwHFmqdA/mw1VsMB+khUaVw=="+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)++mouse :: Host+mouse = host "mouse.kitenet.net" $ props+	& ipv4 "67.223.19.96"+	& Apt.installed ["ssh"]+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)++peregrine :: Host+peregrine = host "peregrine.kitenet.net" $ props+	& Apt.installed ["ssh", "screen", "variety", "git-annex"]+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)+	& LightDM.autoLogin (User "desktop")++-- Branchable is not completely deployed with propellor yet.+pell :: Host+pell = host "pell.branchable.com" $ props+	& alias "branchable.com"+	& ipv4 "66.228.46.55"+	& ipv6 "2600:3c03::f03c:91ff:fedf:c0e5"++	-- All the websites I host at branchable that don't use+	-- branchable.com dns.+	& alias "olduse.net"+	& alias "www.olduse.net"+	& alias "www.kitenet.net"+	& alias "joeyh.name"+	& alias "www.joeyh.name"+	& alias "campaign.joeyh.name"+	& alias "ikiwiki.info"+	& alias "www.ikiwiki.info"+	& alias "git.ikiwiki.info"+	& alias "l10n.ikiwiki.info"+	& alias "dist-bugs.kitenet.net"+	& alias "family.kitenet.net"++	& osDebian (Stable "buster") X86_32+	& Apt.installed ["linux-image-686-pae"]+	& Apt.stdSourcesList `onChange` Apt.upgrade+	& Apt.unattendedUpgrades+	& Branchable.server hosts+	& Linode.serialGrub++++       --'                        __|II|      ,.+     ----                      __|II|II|__   (  \_,/\+--'-------'\o/-'-.-'-.-'-.- __|II|II|II|II|___/   __/ -'-.-'-.-'-.-'-.-'-.-'-+-------------------------- |   [Containers]      / --------------------------+-------------------------- :                    / ---------------------------+--------------------------- \____, o          ,' ----------------------------+---------------------------- '--,___________,'  -----------------------------++-- Exhibit: kite's 90's website on port 1994.+ancientKitenet :: Systemd.Container+ancientKitenet = Systemd.debContainer "ancient-kitenet" $ props+	& standardContainer (Stable "buster")+	& alias hn+	& Git.cloned (User "root") "git://kitenet-net.branchable.com/" "/var/www/html"+		(Just "remotes/origin/old-kitenet.net")+	& Apache.installed+	& Apache.listenPorts [p]+	& Apache.virtualHost hn p "/var/www/html"+	& Apache.siteDisabled "000-default"+  where+	p = Port 1994+	hn = "ancient.kitenet.net"++-- My own openid provider. Uses php, so containerized for security+-- and administrative sanity.+openidProvider :: Systemd.Container+openidProvider = Systemd.debContainer "openid-provider" $ props+	-- simpleid is not in buster+	& standardContainer (Stable "stretch")+	& alias hn+	& OpenId.providerFor [User "joey", User "liw"] hn (Just (Port 8086))+  where+	hn = "openid.kitenet.net"++type Motd = [String]++-- This is my standard system setup.+standardSystem :: DebianSuite -> Architecture -> Motd -> Property (HasInfo + Debian)+standardSystem suite arch motd =+	standardSystemUnhardened suite arch motd+		`before` Ssh.noPasswords++standardSystemUnhardened :: DebianSuite -> Architecture -> Motd -> Property (HasInfo + Debian)+standardSystemUnhardened suite arch motd = propertyList "standard system" $ props+	& osDebian suite arch+	& Hostname.sane+	& Hostname.mailname+	& Hostname.searchDomain+	& Locale.available "en_US.UTF-8"+	& File.hasContent "/etc/motd" ("":motd++[""])+	& Apt.stdSourcesList `onChange` Apt.upgrade+	& Apt.cacheCleaned+	& Apt.installed ["etckeeper"]+	& Apt.installed ["ssh", "mosh"]+	& GitHome.installedFor (User "root") 	& User.hasSomePassword (User "root")-	& File.dirExists "/var/www"+	& User.accountFor (User "joey")+	& User.hasSomePassword (User "joey")+	& Sudo.enabledFor (User "joey")+	& GitHome.installedFor (User "joey")+	& Apt.installed ["vim", "screen", "less"] 	& Cron.runPropellor (Cron.Times "30 * * * *")+	-- I use postfix, or no MTA.+	& JoeySites.noExim++-- This is my standard container setup, Featuring automatic upgrades.+standardContainer :: DebianSuite -> Property (HasInfo + Debian)+standardContainer suite = propertyList "standard container" $ props+	& osDebian suite X86_64+	-- Do not want to run mail daemon inside a random container..+	& JoeySites.noExim+	& Apt.stdSourcesList `onChange` Apt.upgrade+	& Apt.unattendedUpgrades+	& Apt.cacheCleaned++branchableSecondary :: RevertableProperty (HasInfo + DebianLike) DebianLike+branchableSecondary = Dns.secondaryFor ["branchable.com"] hosts "branchable.com"++-- Currently using kite (ns4) as primary with gandi as secondary+-- kite handles all mail.+myDnsPrimary :: Domain -> [(BindDomain, Record)] -> RevertableProperty (HasInfo + DebianLike) DebianLike+myDnsPrimary domain extras = Dns.signedPrimary (Weekly Nothing) hosts domain+	(Dns.mkSOA "ns4.kitenet.net" 100) $+	[ (RootDomain, NS $ AbsDomain "ns4.kitenet.net")+	, (RootDomain, NS $ AbsDomain "ns6.gandi.net")+	, (RootDomain, MX 0 $ AbsDomain "kitenet.net")+	, (RootDomain, TXT "v=spf1 a a:kitenet.net ~all")+	, JoeySites.domainKey+	] ++ extras++-- Systems I don't manage with propellor,+-- but do want to track their public keys etc.+monsters :: [Host]+monsters =+	[ host "usw-s002.rsync.net" $ props+		& Ssh.hostPubKey SshEd25519 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB7yTEBGfQYdwG/oeL+U9XPMIh/dW7XNs9T+M79YIOrd"+	, host "ns6.gandi.net" $ props+		& ipv4 "217.70.177.40"+	, host "animx" $ props+		& ipv4 "76.7.174.49"+	]++++                          --                                o+                          --             ___                 o              o+                       {-----\          / o \              ___o            o+                       {      \    __   \   /   _        (X___>--         __o+  _____________________{ ______\___  \__/ | \__/ \____                  |X__>+ <                                  \___//|\\___/\     \____________   _+  \                                  ___/ | \___    # #             \ (-)+   \    O      O      O             #     |     \ #                  >=)+    \______________________________# #   /       #__________________/ (-}++
joeyconfig.hs view
@@ -16,7 +16,6 @@ import qualified Propellor.Property.Sudo as Sudo import qualified Propellor.Property.User as User import qualified Propellor.Property.Hostname as Hostname-import qualified Propellor.Property.Fstab as Fstab import qualified Propellor.Property.Tor as Tor import qualified Propellor.Property.Dns as Dns import qualified Propellor.Property.Git as Git@@ -26,7 +25,6 @@ import qualified Propellor.Property.Locale as Locale import qualified Propellor.Property.Grub as Grub import qualified Propellor.Property.Borg as Borg-import qualified Propellor.Property.Gpg as Gpg import qualified Propellor.Property.OpenId as OpenId import qualified Propellor.Property.Systemd as Systemd import qualified Propellor.Property.Journald as Journald@@ -34,7 +32,6 @@ import qualified Propellor.Property.Laptop as Laptop import qualified Propellor.Property.LightDM as LightDM import qualified Propellor.Property.HostingProvider.Linode as Linode-import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean import qualified Propellor.Property.SiteSpecific.GitHome as GitHome import qualified Propellor.Property.SiteSpecific.GitAnnexBuilder as GitAnnexBuilder import qualified Propellor.Property.SiteSpecific.Branchable as Branchable@@ -48,9 +45,8 @@ hosts =                 --                  (o)  ` 	[ darkstar 	, dragon-	, clam+	, oyster 	, orca-	, baleen 	, honeybee 	, kite 	, beaver@@ -58,8 +54,6 @@ 	, mouse 	, peregrine 	, pell-	, keysafe-	, quarantimer 	] ++ monsters  darkstar :: Host@@ -87,9 +81,6 @@ 	& imageBuiltFor honeybee 		(RawDiskImage "/srv/honeybee.img") 		(Debootstrapped mempty)-	! imageBuiltFor banana-		(RawDiskImage "/srv/banana.img")-		(Debootstrapped mempty)  dragon :: Host dragon = host "dragon.kitenet.net" $ props@@ -97,46 +88,15 @@ 	& JoeySites.dkimMilter 	& JoeySites.postfixSaslPasswordClient -clam :: Host-clam = host "clam.kitenet.net" $ props+oyster :: Host+oyster = host "oyster.kitenet.net" $ props 	& standardSystem (Stable "buster") X86_64 		["Unreliable server. Anything here may be lost at any time!" ]-	& ipv4 "46.36.36.189"+	& ipv4 "45.138.157.89"  	& User.hasPassword (User "root")-	& Ssh.hostKeys hostContext-		[ (SshEcdsa, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPhfvcOuw0Yt+MnsFc4TI2gWkKi62Eajxz+TgbHMO/uRTYF8c5V8fOI3o+J/3m5+lT0S5o8j8a7xIC3COvi+AVw=")-		] 	& Apt.unattendedUpgrades -	-- & Tor.isRelay-	-- & Tor.named "kite1"-	-- & Tor.bandwidthRate (Tor.PerMonth "400 GB")-	-	& "/etc/resolv.conf" `File.hasContent`-		[ "nameserver 8.8.8.8"-		, "nameserver 8.8.4.4"-		, "nameserver 1.1.1.1"-		, "domain kitenet.net"-		, "search kitenet.net"-		]--baleen :: Host-baleen = host "baleen.kitenet.net" $ props-	& standardSystem Unstable X86_64 [ "New git-annex build box." ]--	-- Not on public network; ssh access via bounce host.-	& ipv4 "138.38.77.40"-	-	-- The root filesystem content may be lost if the VM is resized.-	-- /dev/vdb contains persistent storage.-	& Fstab.mounted "auto" "/dev/vdb" "/var/lib/container" mempty-	-	& Apt.unattendedUpgrades-	& Postfix.satellite-	& Apt.serviceInstalledRunning "ntp"-	& Systemd.persistentJournal- orca :: Host orca = host "orca.kitenet.net" $ props 	& standardSystem Unstable X86_64 [ "Main git-annex build box." ]@@ -160,17 +120,6 @@ 		GitAnnexBuilder.standardAutoBuilder 		Testing ARM64 Nothing (Cron.Times "1 * * * *") "4h") -banana :: Host-banana = host "banana.kitenet.net" $ props-	& lemaker_Banana_Pi-	& hasPartition-		( partition EXT4-			`mountedAt` "/"-			`setSize` MegaBytes 950-		)-	& osDebian Testing ARMHF-	& User.hasInsecurePassword (User "root") "root"- honeybee :: Host honeybee = host "honeybee.kitenet.net" $ props 	& standardSystem Testing ARMHF@@ -259,7 +208,6 @@ 		, "--exclude=/home/joey/lib" 		-- These directories are backed up and restored separately. 		, "--exclude=/srv/git"-		, "--exclude=/var/spool/oldusenet" 		] 		[ Borg.KeepDays 7 		, Borg.KeepWeeks 4@@ -298,10 +246,6 @@ 		, "zsh" 		] -	& alias "nntp.olduse.net"-	& JoeySites.oldUseNetServer hosts-	& Systemd.nspawned oldusenetShellBox-	 	& alias "znc.kitenet.net" 	& JoeySites.ircBouncer @@ -330,7 +274,7 @@ 	& myDnsPrimary "olduse.net" 		[ (RelDomain "article", CNAME $ AbsDomain "virgil.koldfront.dk") 		]-	& myDnsPrimary "quarantimer.app" []+	! myDnsPrimary "quarantimer.app" [] 	& alias "ns4.branchable.com" 	& branchableSecondary 	& Dns.secondaryFor ["animx"] hosts "animx.eu.org"@@ -343,7 +287,7 @@ 		] 	 	& alias "debug-me.joeyh.name"-	& Apt.installed ["debug-me"]+	& Apt.installed ["debug-me", "debug-me-server"] 	& Systemd.enabled "debug-me"  	-- testing@@ -408,91 +352,8 @@ 	& Branchable.server hosts 	& Linode.serialGrub --- See https://joeyh.name/code/keysafe/servers/ for requirements.-keysafe :: Host-keysafe = host "keysafe.joeyh.name" $ props-	& ipv4 "139.59.17.168"-	& Hostname.sane-	& Hostname.mailname-	& osDebian (Stable "buster") X86_64-	& Apt.stdSourcesList `onChange` Apt.upgrade-	& Apt.unattendedUpgrades-	& DigitalOcean.distroKernel-	-- This is a 500 mb VM, so need more ram to build propellor.-	& Apt.serviceInstalledRunning "swapspace"-	& Cron.runPropellor (Cron.Times "30 * * * *")-	& Apt.installed ["etckeeper", "sudo"]-	& JoeySites.noExim-	& Apt.removed ["nfs-common", "rsyslog", "acpid", "rpcbind", "at"] -	& User.hasSomePassword (User "root")-	& User.accountFor (User "joey")-	& User.hasSomePassword (User "joey")-	& Sudo.enabledFor (User "joey") -	& Ssh.installed-	& Ssh.randomHostKeys-	& User "root" `Ssh.authorizedKeysFrom` (User "joey", darkstar)-	& User "joey" `Ssh.authorizedKeysFrom` (User "joey", darkstar)-	& Ssh.noPasswords--	& Tor.installed-	& Tor.hiddenServiceAvailable "keysafe" (Port 4242)-		`requires` Tor.hiddenServiceData "keysafe" hostContext-	& Tor.bandwidthRate (Tor.PerMonth "750 GB")--	-- keysafe installed manually until package is available-	& Systemd.enabled "keysafe"--	& Gpg.keyImported (Gpg.GpgKeyId "CECE11AE") (User "root")-	& Ssh.knownHost hosts "usw-s002.rsync.net" (User "root")-	& Ssh.userKeys (User "root")-		(Context "keysafe.joeyh.name")-		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEx8bK9ZbXVEgEvxQeXLjnr9cGa/QvoB459aglP529My root@keysafe")-		]-	-- Note that this is not an incremental backup; it uploads the-	-- whole content every time. So, only run weekly.-	& Cron.niceJob "keysafe backup" Cron.Weekly (User "root") "/" backupcmd-		`requires` Apt.installed ["rsync"]-  where-	datadir = "/var/lib/keysafe"-	backupdir = "/var/backups/keysafe"-	rsyncnetbackup = "2318@usw-s002.rsync.net:keysafe"-	backupcmd = unwords-		[ "keysafe --store-directory", datadir, "--backup-server", backupdir-		, "&& rsync -a --delete --max-delete 3 ",  backupdir , rsyncnetbackup-		]--quarantimer :: Host-quarantimer = host "quarantimer.app" $ props-	& ipv4 "45.33.73.207"-	& Hostname.sane-	& Hostname.mailname-	& osDebian (Stable "buster") X86_64-	& Apt.stdSourcesList `onChange` Apt.upgrade-	& Apt.unattendedUpgrades-	& Cron.runPropellor (Cron.Times "30 * * * *")-	& Apt.installed ["etckeeper", "sudo"]-	& JoeySites.noExim--	& User.hasSomePassword (User "root")-	& User.accountFor (User "joey")-	& User.hasSomePassword (User "joey")-	& Sudo.enabledFor (User "joey")-	& Ssh.installed-	& Ssh.randomHostKeys-	& User "root" `Ssh.authorizedKeysFrom` (User "joey", darkstar)-	& User "joey" `Ssh.authorizedKeysFrom` (User "joey", darkstar)-	& Ssh.noPasswords--	& LetsEncrypt.letsEncrypt (LetsEncrypt.AgreeTOS (Just "id@joeyh.name"))-		"quarantimer.app" "/home/joey/quarantimer/static"-	& Apt.installed ["screen", "git", "ghc"]-	& Apt.installed ["zlib1g-dev", "imagemagick"]-	-- (Installing quarantimer not yet automated)---        --'                        __|II|      ,.      ----                      __|II|II|__   (  \_,/\ --'-------'\o/-'-.-'-.-'-.- __|II|II|II|II|___/   __/ -'-.-'-.-'-.-'-.-'-.-'-@@ -515,12 +376,6 @@   where 	p = Port 1994 	hn = "ancient.kitenet.net"--oldusenetShellBox :: Systemd.Container-oldusenetShellBox = Systemd.debContainer "oldusenet-shellbox" $ props-	& standardContainer (Stable "buster")-	& alias "shell.olduse.net"-	& JoeySites.oldUseNetShellBox  -- My own openid provider. Uses php, so containerized for security -- and administrative sanity.
propellor.cabal view
@@ -1,5 +1,5 @@ Name: propellor-Version: 5.12+Version: 5.13 Cabal-Version: 1.20 License: BSD2 Maintainer: Joey Hess <id@joeyh.name>@@ -39,7 +39,7 @@   Description: Build with type-errors library for better error messages and less memory use  Library-  Default-Language: Haskell98+  Default-Language: Haskell2010   GHC-Options: -Wall -fno-warn-tabs -O0   Default-Extensions: TypeOperators   Hs-Source-Dirs: src@@ -239,7 +239,7 @@     Paths_propellor  Executable propellor-config-  Default-Language: Haskell98+  Default-Language: Haskell2010   Hs-Source-Dirs: executables   Main-Is: propellor-config.hs   GHC-Options: -threaded -Wall -fno-warn-tabs@@ -247,7 +247,7 @@   Build-Depends: propellor, base  Executable propellor-  Default-Language: Haskell98+  Default-Language: Haskell2010   Hs-Source-Dirs: executables   Main-Is: wrapper.hs   GHC-Options: -threaded -Wall -fno-warn-tabs
src/Propellor/Property/Apt.hs view
@@ -107,16 +107,15 @@ stdArchiveLines :: Propellor SourcesGenerator stdArchiveLines = return . binandsrc =<< getMirror --- | Only available for Stable and Testing+-- | Only available for Stable suites, not for Testing or Unstable. securityUpdates :: SourcesGenerator securityUpdates suite-	| isStable suite || suite == Testing =+	| isStable suite = 		let l = "deb http://security.debian.org/debian-security " ++ securitysuite ++ " " ++ unwords stdSections 		in [l, srcLine l] 	| otherwise = []   where 	securitysuite-		| suite == Testing = "testing-security" 		| suite `elem` map Stable releasesusingoldname = 			showSuite suite ++ "/updates" 		| otherwise = showSuite suite ++ "-security"
src/Propellor/Property/Network.hs view
@@ -10,6 +10,9 @@ -- | Options to put in a stanza of an ifupdown interfaces file. type InterfaceOptions = [(String, String)] +-- | Stanza of an ifupdown interfaces file, with header lines and options.+type InterfaceStanza = ([String], InterfaceOptions)+ ifUp :: Interface -> Property DebianLike ifUp iface = tightenTargets $ cmdProperty "ifup" [iface] 	`assume` MadeChange@@ -52,22 +55,29 @@  static' :: Interface -> IPAddr -> Maybe Gateway -> InterfaceOptions -> Property DebianLike static' iface addr gateway options =-	interfaceFileContains (interfaceDFile iface) headerlines options'+	static'' iface [(addr, gateway, options)]++-- | Configures an interface with several stanzas (IPv4 and IPv6 for example).+static'' :: Interface -> [(IPAddr, Maybe Gateway, InterfaceOptions)] -> Property DebianLike+static'' iface confs =+	interfaceFileContains' (interfaceDFile iface) stanzas 	`describe` ("static IP address for " ++ iface) 	`requires` interfacesDEnabled   where-	headerlines =+	stanzas = map stanza confs+	stanza (addr, gateway, options) = (headerlines addr, options' addr gateway options)+	headerlines addr = 		[ "auto " ++ iface-		, "iface " ++ iface ++ " " ++ inet ++ " static"+		, "iface " ++ iface ++ " " ++ (inet addr) ++ " static" 		]-	options' = catMaybes+	options' addr gateway options = catMaybes 		[ Just $ ("address", val addr) 		, case gateway of-			Just (Gateway gaddr) -> +			Just (Gateway gaddr) -> 				Just ("gateway", val gaddr) 			Nothing -> Nothing 		] ++ options-	inet = case addr of+	inet addr = case addr of 		IPv4 _ -> "inet" 		IPv6 _ -> "inet6" @@ -149,8 +159,13 @@ 		`describe` "interfaces.d directory enabled"  interfaceFileContains :: FilePath -> [String] -> InterfaceOptions -> Property DebianLike-interfaceFileContains f headerlines options = tightenTargets $ hasContent f $-	warning : headerlines ++ map fmt options+interfaceFileContains f headerlines options =+	interfaceFileContains' f [(headerlines, options)]++interfaceFileContains' :: FilePath -> [InterfaceStanza] -> Property DebianLike+interfaceFileContains' f stanzas = tightenTargets $ hasContent f $+	warning : concatMap stanza stanzas   where+	stanza (headerlines, options) = headerlines ++ map fmt options 	fmt (k, v) = "\t" ++ k ++ " " ++ v 	warning = "# Deployed by propellor, do not edit."
src/Propellor/Property/SiteSpecific/Branchable.hs view
@@ -67,7 +67,6 @@ 	& Ssh.knownHost hosts "usw-s002.rsync.net" (User "root")  	& adminuser "joey"-	& adminuser "liw"   where 	adminuser u = propertyList ("admin user " ++ u) $ props 		& User.accountFor (User u)
src/Propellor/Property/SiteSpecific/JoeySites.hs view
@@ -97,86 +97,6 @@ 	s = d </> "login.sh" 	g = d </> "game.sh" -oldUseNetServer :: [Host] -> Property (HasInfo + DebianLike)-oldUseNetServer hosts = propertyList "olduse.net server" $ props-	& Apt.installed ["leafnode"]-	& oldUseNetInstalled "oldusenet-server"-	& oldUseNetBackup-	& spoolsymlink-	& "/etc/news/leafnode/config" `File.hasContent`-		[ "# olduse.net configuration (deployed by propellor)"-		, "expire = 1000000" -- no expiry via texpire-		, "server = " -- no upstream server-		, "debugmode = 1"-		, "allowSTRANGERS = 42" -- lets anyone connect-		, "nopost = 1" -- no new posting (just gather them)-		]-	& "/etc/hosts.deny" `File.lacksLine` "leafnode: ALL"-	& Apt.serviceInstalledRunning "openbsd-inetd"-	& File.notPresent "/etc/cron.daily/leafnode"-	& File.notPresent "/etc/cron.d/leafnode"-	& Cron.niceJob "oldusenet-expire" (Cron.Times "11 1 * * *") (User "news") newsspool expirecommand-	& Cron.niceJob "oldusenet-uucp" (Cron.Times "*/5 * * * *") (User "news") "/" uucpcommand-	& Apache.siteEnabled "nntp.olduse.net" nntpcfg-  where-	newsspool = "/var/spool/news"-	datadir = "/var/spool/oldusenet"-	expirecommand = intercalate ";"-		[ "find \\( -path ./out.going -or -path ./interesting.groups -or -path './*/.overview' \\) -prune -or -type f -ctime +60  -print | xargs --no-run-if-empty rm"-		, "find -type d -empty | xargs --no-run-if-empty rmdir"-		]-	uucpcommand = "/usr/bin/uucp " ++ datadir-	nntpcfg = apachecfg "nntp.olduse.net"-		[ "  DocumentRoot " ++ datadir ++ "/"-		, "  <Directory " ++ datadir ++ "/>"-		, "    Options Indexes FollowSymlinks"-		, "    AllowOverride None"-		, Apache.allowAll-		, "  </Directory>"-		]--	spoolsymlink :: Property UnixLike-	spoolsymlink = check (not . isSymbolicLink <$> getSymbolicLinkStatus newsspool)-		(property "olduse.net spool in place" $ makeChange $ do-			removeDirectoryRecursive newsspool-			createSymbolicLink (datadir </> "news") newsspool-		)--	oldUseNetBackup :: Property (HasInfo + DebianLike)-	oldUseNetBackup = Borg.backup datadir borgrepo -		(Cron.Times "33 4 * * *")-		[]-		[Borg.KeepDays 30]-		`requires` Ssh.userKeyAt (Just keyfile)-			(User "root")-			(Context "olduse.net")-			(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGtHhNuO/abNTrc5pyWkwXz/F8FAHw8VcET0Yh4mjgOk root@kite")-		`requires` Ssh.knownHost hosts "usw-s002.rsync.net" (User "root")-	borgrepo = rsyncNetBorgRepo "olduse.net.borg" [Borg.UseSshKey keyfile]-	keyfile = "/root/.ssh/olduse.net.key"--oldUseNetShellBox :: Property DebianLike-oldUseNetShellBox = propertyList "olduse.net shellbox" $ props-	& oldUseNetInstalled "oldusenet"-	& Service.running "shellinabox"--oldUseNetInstalled :: Apt.Package -> Property DebianLike-oldUseNetInstalled pkg = check (not <$> Apt.isInstalled pkg) $-	propertyList ("olduse.net " ++ pkg) $ props-		& Apt.installed (words "build-essential devscripts debhelper git libncursesw5-dev libpcre3-dev pkg-config bison libicu-dev libidn11-dev libcanlock2-dev libuu-dev ghc libghc-ifelse-dev libghc-hxt-dev libghc-utf8-string-dev libghc-missingh-dev libghc-sha-dev haskell-stack")-			`describe` "olduse.net build deps"-		& scriptProperty-			[ "rm -rf /root/tmp/oldusenet" -- idenpotency-			, "git clone git://olduse.net/ /root/tmp/oldusenet/source"-			, "cd /root/tmp/oldusenet/source/"-			, "HOME=/root dpkg-buildpackage -us -uc"-			, "dpkg -i ../" ++ pkg ++ "_*.deb || true"-			, "apt-get -fy install" -- dependencies-			, "rm -rf /root/tmp/oldusenet"-			]-			`assume` MadeChange-			`describe` "olduse.net built"- kgbServer :: Property (HasInfo + DebianLike) kgbServer = propertyList desc $ props 	& Apt.serviceInstalledRunning "kgb-bot"@@ -328,7 +248,7 @@ 	-- git-annex distribution signing key 	& Gpg.keyImported (Gpg.GpgKeyId "89C809CB") (User "joey") 	-- used for building rpms-	& Apt.installed ["rpm", "createrepo"]+	& Apt.installed ["rpm", "createrepo-c"]   where 	endpoint d = combineProperties ("endpoint " ++ d) $ props 		& File.dirExists d@@ -439,7 +359,7 @@ 	& Apt.serviceInstalledRunning "clamav-freshclam" 	-- Workaround https://bugs.debian.org/569150 	& Cron.niceJob "amavis-expire" Cron.Daily (User "root") "/"-		"find /var/lib/amavis/virusmails/ -type f -ctime +7 -delete"+		"find /var/lib/amavis/virusmails/ -type f -ctime +2 -delete"  	& dkimInstalled @@ -600,7 +520,10 @@ 		`onChange` (imapalpinescript `File.mode` 			combineModes (readModes ++ executeModes)) 		`describe` "imap script for pine"-	& Apt.serviceInstalledRunning "mailman"+	-- XXX temporarily disabled installing as it's not available in+	-- debian unstable any longer. Need to upgrade to mailman3+	-- at some point. (nontrivial)+	-- & Apt.serviceInstalledRunning "mailman" 	-- Override the default http url. (Only affects new lists.) 	& "/etc/mailman/mm_cfg.py" `File.containsLine` 		"DEFAULT_URL_PATTERN = 'https://%s/cgi-bin/mailman/'"@@ -1145,7 +1068,7 @@ laptopSoftware :: Property DebianLike laptopSoftware = Apt.installed 	[ "intel-microcode", "acpi"-	, "procmeter3", "xfce4", "procmeter3", "unclutter"+	, "procmeter3", "xfce4", "procmeter3", "unclutter-xfixes" 	, "mplayer", "fbreader", "firefox", "chromium" 	, "libdatetime-event-sunrise-perl", "libtime-duration-perl" 	, "network-manager", "network-manager-openvpn-gnome", "openvpn"@@ -1167,6 +1090,7 @@ 	, "vorbis-tools", "audacity" 	, "ekiga" 	, "bluez-firmware", "blueman", "pulseaudio-module-bluetooth"+	, "fwupd" 	, "xul-ext-ublock-origin", "xul-ext-pdf.js", "xul-ext-status4evar" 	, "vim-syntastic", "vim-fugitive" 	, "adb", "gthumb"@@ -1254,6 +1178,10 @@ 		(USBHubPort hubvendor 4) 		(USBDriveId wd "25a3") 		(Just "archive")+	& autoMountDrivePort "archive-14"+		(USBHubPort hubvendor 2)+		(USBDriveId wd "25a3")+		Nothing 	& autoMountDrive "passport" Nothing 	& Apt.installed ["git-annex", "borgbackup"]   where@@ -1280,7 +1208,7 @@ autoMountDrivePort label hp drive malias = propertyList desc $ props 	& File.hasContent ("/etc/systemd/system/" ++ hub) 		[ "[Unit]"-		, "Description=Startech usb hub port " ++ show (hubPort hp)+		, "Description=Startech usb hub port " ++ show (hubPort hp) ++ " vendor " ++ driveVendorId drive ++ " driveid " ++ driveProductId drive 		, "PartOf=" ++ mount 		, "[Service]" 		, "Type=oneshot"@@ -1307,7 +1235,7 @@ 	devfile = "/dev/disk/by-label/" ++ label 	mountpoint = "/media/joey/" ++ label 	desc = "auto mount with hub port power control " ++ mountpoint-	hub = "startech-hub-port-" ++ show (hubPort hp) ++ ".service"+	hub = "startech-hub-port-" ++ show (hubPort hp) ++ "-vendor-" ++ driveVendorId drive ++ "-drivedid-" ++ driveProductId drive ++ ".service" 	mount = svcbase ++ ".mount" 	svcbase = Systemd.escapePath mountpoint 	selecthubport = unwords
src/Propellor/Property/Sudo.hs view
@@ -27,7 +27,7 @@ 	setup = property' desc $ \w -> do 		locked <- liftIO $ isLockedPassword user 		ensureProperty w $ combineProperties desc $ props-			& containsLine sudoers "#includedir /etc/sudoers.d"+			& includessudoersd 			& fileProperty desc 				(modify locked . filter (wanted locked)) 				dfile@@ -43,8 +43,19 @@ 		desc = u ++ " is not sudoer" 	 	removeconflicting = fileProperty "remove conflicting" (filter notuserline)+	+	-- Not reverted because this line is included by default.+	includessudoersd = fileProperty (sudoers ++ " includes " ++ sudoersd) addl sudoers+	  where+		addl content = content ++ +			if l `notElem` content && oldl `notElem` content+				then [l]+				else []+		l = "@includedir /etc/sudoers.d"+		oldl = "#includedir /etc/sudoers.d"  	sudoers = "/etc/sudoers"+	sudoersd = "/etc/sudoers.d" 	dfile = "/etc/sudoers.d/000users" 	sudobaseline = u ++ " ALL=(ALL:ALL)" 	notuserline l = not (sudobaseline `isPrefixOf` l)
src/Utility/HumanNumber.hs view
@@ -1,21 +1,25 @@ {- numbers for humans  -- - Copyright 2012-2013 Joey Hess <id@joeyh.name>+ - Copyright 2012-2021 Joey Hess <id@joeyh.name>  -  - License: BSD-2-clause  -} -module Utility.HumanNumber where+module Utility.HumanNumber (showImprecise) where  {- Displays a fractional value as a string with a limited number  - of decimal digits. -} showImprecise :: RealFrac a => Int -> a -> String showImprecise precision n-	| precision == 0 || remainder == 0 = show (round n :: Integer)-	| otherwise = show int ++ "." ++ striptrailing0s (pad0s $ show remainder)+	| precision == 0 || remainder' == 0 = show (round n :: Integer)+	| otherwise = show int' ++ "." ++ striptrailing0s (pad0s $ show remainder')   where 	int :: Integer 	(int, frac) = properFraction n 	remainder = round (frac * 10 ^ precision) :: Integer+	(int', remainder')+		-- carry the 1+		| remainder == 10 ^ precision = (int + 1, 0)+		| otherwise = (int, remainder) 	pad0s s = replicate (precision - length s) '0' ++ s 	striptrailing0s = reverse . dropWhile (== '0') . reverse