packages feed

propellor 5.2.0 → 5.3.0

raw patch · 20 files changed

+1522/−82 lines, 20 filesdep ~base

Dependency ranges changed: base

Files

CHANGELOG view
@@ -1,3 +1,22 @@+propellor (5.3.0) unstable; urgency=medium++  * Avoid bogus warning about new upstream version when /usr/bin/propellor+    is run on a Debian system, but ~/.propellor was not cloned from the+    Debian git bundle.+  * Parted: Allow partitions to have no filesystem, for eg, GPT BIOS boot+    partitions. (API change)+  * Added rawPartition to PartSpec, for specifying partitions with no+    filesystem.+  * Added BiosGrubFlag to PartFlag.+  * Add HasCallStack constraint to pickOS and unsupportedOS, so the+    call stack includes the caller.+  * Run su with --login, to avoid inheriting some problematic environment+    variables, such as TMP, from the caller.+  * Grub: Added properties to configure /etc/default/grub.+  * Laptop: New module, starting with powertopAutoTuneOnBoot.++ -- Joey Hess <id@joeyh.name>  Thu, 01 Feb 2018 12:27:01 -0400+ propellor (5.2.0) unstable; urgency=medium    [ Joey Hess ]
config.hs view
@@ -1,29 +1,658 @@--- 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.Service as Service+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+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.OpenId as OpenId+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.FlashKernel as FlashKernel+import qualified Propellor.Property.Borg as Borg+import qualified Propellor.Property.Gpg as Gpg+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.OS as OS+import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost+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+import qualified Propellor.Property.SiteSpecific.JoeySites as JoeySites -main :: IO ()-main = defaultMain hosts+main :: IO ()           --     _         ______`|                       ,-.__+main = defaultMain hosts --  /   \___-=O`/|O`/__|                      (____.'+  {- Propellor            -- \          / | /    )          _.-"-._+     Deployed -}          --  `/-==__ _/__|/__=-|          (       \_+hosts :: [Host]          --   *             \ | |           '--------'+hosts =                 --                  (o)  `+	[ darkstar+	, gnu+	, dragon+	, clam+	, orca+	, baleen+	, honeybee+	, kite+	, elephant+	, beaver+	, mouse+	, peregrine+	, pell+	, keysafe+	] ++ monsters --- The hosts propellor knows about.-hosts :: [Host]-hosts =-	[ mybox-	]+testvm :: Host+testvm = host "testvm.kitenet.net" $ props+	& osDebian Unstable X86_64+	& OS.cleanInstallOnce (OS.Confirmed "testvm.kitenet.net")+	 	`onChange` postinstall+	& Hostname.sane+	& Hostname.searchDomain+	& Apt.installed ["linux-image-amd64"]+	& Apt.installed ["ssh"]+	& User.hasPassword (User "root")+  where+	postinstall :: Property (HasInfo + DebianLike)+	postinstall = propertyList "fixing up after clean install" $ props+		& OS.preserveRootSshAuthorized+		& OS.preserveResolvConf+		& Apt.update+		& Grub.boots "/dev/sda"+			`requires` Grub.installed Grub.PC --- 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+	& Apt.serviceInstalledRunning "swapspace"+	& Laptop.powertopAutoTuneOnBoot+	& Grub.cmdline_Linux_default "i915.enable_psr=1"+	! Grub.cmdline_Linux_default "quiet"++	& 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+		[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1YoyHxZwG5Eg0yiMTJLSWJ/+dMM6zZkZiR4JJ0iUfP+tT2bm/lxYompbSqBeiCq+PYcSC67mALxp1vfmdOV//LWlbXfotpxtyxbdTcQbHhdz4num9rJQz1tjsOsxTEheX5jKirFNC5OiKhqwIuNydKWDS9qHGqsKcZQ8p+n1g9Lr3nJVGY7eRRXzw/HopTpwmGmAmb9IXY6DC2k91KReRZAlOrk0287LaK3eCe1z0bu7LYzqqS+w99iXZ/Qs0m9OqAPnHZjWQQ0fN4xn5JQpZSJ7sqO38TBAimM+IHPmy2FTNVVn9zGM+vN1O2xr3l796QmaUG1+XLL0shfR/OZbb joey@darkstar")+		]+	-- & imageBuiltFor honeybee+	--	(RawDiskImage "/srv/honeybee.img")+	--	(Debootstrapped mempty)++gnu :: Host+gnu = host "gnu.kitenet.net" $ props+	& Postfix.satellite++dragon :: Host+dragon = host "dragon.kitenet.net" $ props+	& ipv6 "2001:4830:1600:187::2"+	& JoeySites.dkimMilter+	& JoeySites.postfixSaslPasswordClient++clam :: Host+clam = host "clam.kitenet.net" $ props+	& standardSystem Unstable X86_64+		["Unreliable server. Anything here may be lost at any time!" ]+	& ipv4 "45.62.211.94"++	& CloudAtCost.decruft+	& Ssh.hostKeys hostContext+		[ (SshDsa, "ssh-dss AAAAB3NzaC1kc3MAAACBAI3WUq0RaigLlcUivgNG4sXpso2ORZkMvfqKz6zkc60L6dpxvWDNmZVEH8hEjxRSYG07NehcuOgQqeyFnS++xw1hdeGjf37JqCUH49i02lra3Zxv8oPpRxyeqe5MmuzUJhlWvBdlc3O/nqZ4bTUfnxMzSYWyy6++s/BpSHttZplNAAAAFQC1DE0vzgVeNAv9smHLObQWZFe2VQAAAIBECtpJry3GC8NVTFsTHDGWksluoFPIbKiZUFFztZGdM0AO2VwAbiJ6Au6M3VddGFANgTlni6d2/9yS919zO90TaFoIjywZeXhxE2CSuRfU7sx2hqDBk73jlycem/ER0sanFhzpHVpwmLfWneTXImWyq37vhAxatJANOtbj81vQ3AAAAIBV3lcyTT9xWg1Q4vERJbvyF8mCliwZmnIPa7ohveKkxlcgUk5d6dnaqFfjVaiXBPN3Qd08WXoQ/a9k3chBPT9nW2vWgzzM8l36j2MbHLmaxGwevAc9+vx4MXqvnGHzd2ex950mC33ct3j0fzMZlO6vqEsgD4CYmiASxhfefj+JCQ==")+		, (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJybAjUPUWIhvVMmer8K5ZgdfI54DM6vc8Mzw+5KmVKL0TwkvzbR1HAB4heyMGtN1F8YzkWhsI3/Txh+MQUJ+i4u8SvSYc6D1q3j3ZyCi06wZ3DJS25tZrOM/thOOA1DFA4Hhb0uI/1Kg8PguNNNSMXn8F7q3F6cFQizYgszs6z6ktiST/BTC+IXWovhcnn2vQXXU8FTcTsqBFqA5dEjZbp1WDzqp3km84ZyXGmoVlpqzXeMvlkWTIshYiQjXIwPOkALzlGYjp1lw1OaxPVI1IGFcgCbIWQQWoCReb+genX2VaR+odAYXjaOdRx0lQj7UCPTBCpqMyzBMLtT5Yiaqh")+		, (SshEcdsa, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPhfvcOuw0Yt+MnsFc4TI2gWkKi62Eajxz+TgbHMO/uRTYF8c5V8fOI3o+J/3m5+lT0S5o8j8a7xIC3COvi+AVw=")+		] 	& Apt.unattendedUpgrades-	& Apt.installed ["etckeeper"]+	& Systemd.persistentJournal+	& Journald.systemMaxUse "50MiB"+	& Apt.serviceInstalledRunning "swapspace"++	& Tor.isRelay+	& Tor.named "kite1"+	& Tor.bandwidthRate (Tor.PerMonth "400 GB")++	& Systemd.nspawned oldusenetShellBox++	& JoeySites.scrollBox+	& alias "scroll.joeyh.name"+	& alias "us.scroll.joeyh.name"++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." ]+	& 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.androidAutoBuilderContainer+		(Cron.Times "1 1 * * *") "3h")++honeybee :: Host+honeybee = host "honeybee.kitenet.net" $ props+	& standardSystem Testing ARMHF+		[ "Home router and arm git-annex build box." ]+	+	& cubietech_Cubietruck+	& hasPartition+		( partition EXT4+			`mountedAt` "/"+			`setSize` MegaBytes 8000+		)+	& File.hasPrivContentExposed "/etc/flash-kernel/dtbs/sun7i-a20-cubietruck.dtb"+		(Context "cubietruck gpio")+		`onChange` FlashKernel.flashKernel+	+	& Apt.installed ["firmware-brcm80211"]+		-- Workaround for https://bugs.debian.org/844056+		`requires` File.hasPrivContent "/lib/firmware/brcm/brcmfmac43362-sdio.txt" anyContext+		`requires` File.dirExists "/lib/firmware/brcm"+	& "/etc/default/rcS" `File.containsLine` "FSCKFIX=yes"+	& Apt.serviceInstalledRunning "ntp" -- no hardware clock+	& bootstrappedFrom GitRepoOutsideChroot+	& Ssh.hostKeys hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIS/hDYq1MAxfOBf49htym3BOYlx4Gk9SDpiHjv7u6IC")+		]++	& JoeySites.homePowerMonitor+		(User "joey")+		hosts+		(Context "homepower.joeyh.name")+		(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMAmVYddg/RgCbIj+cLcEiddeFXaYFnbEJ3uGj9G/EyV joey@honeybee")+	& JoeySites.homeRouter+	& Apt.installed ["mtr-tiny", "iftop", "screen"]+	& Postfix.satellite++	& check (not <$> inChroot) (setupRevertableProperty autobuilder)+	-- In case compiler needs more than available ram+	& Apt.serviceInstalledRunning "swapspace"+  where+	autobuilder = Systemd.nspawned $ GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.armAutoBuilder+		Unstable ARMEL Nothing (Cron.Times "15 10 * * *") "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"+	& alias "wren.kitenet.net" -- temporary+	& 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"]+	& 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 "/" (Borg.BorgRepo "joey@eubackup.kitenet.net:/home/joey/lib/backup/kite/kite.borg") Cron.Daily+		[ "--exclude=/proc/*"+		, "--exclude=/sys/*"+		, "--exclude=/run/*"+		, "--exclude=/tmp/*"+		, "--exclude=/var/tmp/*"+		, "--exclude=/var/cache/*"+		, "--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+		, Borg.KeepMonths 6+		]+		`requires` Ssh.knownHost hosts "eubackup.kitenet.net" (User "root")+		`requires` Ssh.userKeys (User "root")+			(Context "kite.kitenet.net")+			[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5Gza2sNqSKfNtUN4dN/Z3rlqw18nijmXFx6df2GtBoZbkIak73uQfDuZLP+AXlyfHocwdkdHEf/zrxgXS4EokQMGLZhJ37Pr3edrEn/NEnqroiffw7kyd7EqaziA6UOezcLTjWGv+Zqg9JhitYs4WWTpNzrPH3yQf1V9FunZnkzb4gJGndts13wGmPEwSuf+QHbgQvjMOMCJwWSNcJGdhDR66hFlxfG26xx50uIczXYAbgLfHp5W6WuR/lcaS9J6i7HAPwcsPDA04XDinrcpl29QwsMW1HyGS/4FSCgrDqNZ2jzP49Bka78iCLRqfl1efyYas/Zo1jQ0x+pxq2RMr 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 hosts+	& JoeySites.gitAnnexDistributor+	& JoeySites.tmp++	& alias "bitlbee.kitenet.net"+	& Apt.serviceInstalledRunning "bitlbee"+	& "/etc/bitlbee/bitlbee.conf" `File.hasContent`+		[ "[settings]"+		, "User = bitlbee"+		, "AuthMode = Registered"+		, "[defaults]"+		]+		`onChange` Service.restarted "bitlbee"+	& "/etc/default/bitlbee" `File.containsLine` "BITLBEE_PORT=\"6767\""+		`onChange` Service.restarted "bitlbee"++	& Apt.installed+		[ "git-annex", "myrepos"+		, "build-essential", "make"+		, "rss2email", "archivemail"+		, "devscripts"+		-- Some users have zsh as their login shell.+		, "zsh"+		]++	& alias "nntp.olduse.net"+	& JoeySites.oldUseNetServer hosts++	& alias "ns4.kitenet.net"+	& myDnsPrimary True "kitenet.net"+		[ (RelDomain "mouse-onion", CNAME $ AbsDomain "htieo6yu2qtcn2j3.onion")+		, (RelDomain "beaver-onion", CNAME $ AbsDomain "tl4xsvaxryjylgxs.onion")+		, (RelDomain "peregrine-onion", CNAME $ AbsDomain "ahw47zqw6qszoufl.onion")+		]+	& myDnsPrimary True "joeyh.name" []+	& myDnsPrimary True "ikiwiki.info" []+	& myDnsPrimary True "olduse.net"+		[ (RelDomain "article", CNAME $ AbsDomain "virgil.koldfront.dk")+		]+	& 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"+	-- debug-me installed manually until package is available+	& Systemd.enabled "debug-me"++	-- testing+	& Apache.httpsVirtualHost "letsencrypt.joeyh.name" "/var/www/html"+		(LetsEncrypt.AgreeTOS (Just "id@joeyh.name"))+	& alias "letsencrypt.joeyh.name"+  where++elephant :: Host+elephant = host "elephant.kitenet.net" $ props+	& standardSystem Unstable X86_64+		[ "Storage, big data, and backups, omnomnom!"+		, "(Encrypt all data stored here.)"+		]+	& ipv4 "193.234.225.114"+	& Ssh.hostKeys hostContext+		[ (SshDsa, "ssh-dss AAAAB3NzaC1kc3MAAACBANxXGWac0Yz58akI3UbLkphAa8VPDCGswTS0CT3D5xWyL9OeArISAi/OKRIvxA4c+9XnWtNXS7nYVFDJmzzg8v3ZMx543AxXK82kXCfvTOc/nAlVz9YKJAA+FmCloxpmOGrdiTx1k36FE+uQgorslGW/QTxnOcO03fDZej/ppJifAAAAFQCnenyJIw6iJB1+zuF/1TSLT8UAeQAAAIEA1WDrI8rKnxnh2rGaQ0nk+lOcVMLEr7AxParnZjgC4wt2mm/BmkF/feI1Fjft2z4D+V1W7MJHOqshliuproxhFUNGgX9fTbstFJf66p7h7OLAlwK8ZkpRk/uV3h5cIUPel6aCwjL5M2gN6/yq+gcCTXeHLq9OPyUTmlN77SBL71UAAACBAJJiCHWxPAGooe7Vv3W7EIBbsDyf7b2kDH3bsIlo+XFcKIN6jysBu4kn9utjFlrlPeHUDzGQHe+DmSqTUQQ0JPCRGcAcuJL8XUqhJi6A6ye51M9hVt51cJMXmERx9TjLOP/adkEuxpv3Fj20FxRUr1HOmvRvewSHrJ1GeA1bjbYL")+		, (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrEQ7aNmRYyLKY7xHILQsyV/w0B3++D98vn5IvjHkDnitrUWjB+vPxlS7LYKLzN9Jx7Hb14R2lg7+wdgtFMxLZZukA8b0tqFpTdRFBvBYGh8IM8Id1iE/6io/NZl+hTQEDp0LJP+RljH1CLfz7J3qtc+v6NbfTP5cOgH104mWYoLWzJGaZ4p53jz6THRWnVXy5nPO3dSBr2f/SQgRuJQWHNIh0jicRGD8H2kzOQzilpo+Y46PWtkufl3Yu3UsP5UMAyLRIXwZ6nNRZqRiVWrX44hoNfDbooTdFobbHlqMl+y6291bOXaOA6PACk8B4IVcC89/gmc9Oe4EaDuszU5kD")+		, (SshEcdsa, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAJkoPRhUGT8EId6m37uBdYEtq42VNwslKnc9mmO+89ody066q6seHKeFY6ImfwjcyIjM30RTzEwftuVNQnbEB0=")+		, (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB6VtXi0uygxZeCo26n6PuCTlSFCBcwRifv6N8HdWh2Z")+		]++	& Grub.chainPVGrub "hd0,0" "xen/xvda1" 30+	& Postfix.satellite+	& Apt.unattendedUpgrades+	& Systemd.installed+	& Systemd.persistentJournal+	& Ssh.userKeys (User "joey") hostContext+		[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4wJuQEGno+nJvtE75IKL6JQ08sJHZ9Bzs9Dvu0zuxSEZE30MWK98/twNwCH9PVf2N9m4apfN7f9GHgHTUongfo8xnLAk4PuBSTV74YgKyOCvNYqANuKKa+76PsS/vFf/or3ct++uTEWsRyYD29cQndufwKA4rthAqHG+fifbLDC53AjcldI0zI1RckpPzT+AMazlnSBFMlpKvGD2uzSXALVRXa3vSqWkWd0z7qmIkpmpq0AAgbDLwrGBcUGV/h0rOa2s8zSeirA0tLmHNROl4cZsX0T/6VBGfBRkrHSxL67xJziATw4WPq6spYlxg84pC/5qJVr9SC5HosppbDqgj joey@elephant")+		]+	& Apt.serviceInstalledRunning "swapspace"++	& alias "eubackup.kitenet.net"+	& Apt.installed ["sshfs", "rsync", "borgbackup"]+	& JoeySites.githubBackup+	& JoeySites.rsyncNetBackup hosts++	& alias "podcatcher.kitenet.net"+	& JoeySites.podcatcher++	& alias "znc.kitenet.net"+	& JoeySites.ircBouncer+	& alias "kgb.kitenet.net"+	& JoeySites.kgbServer++	& alias "ns3.kitenet.net"+	& myDnsSecondary++	& Systemd.nspawned oldusenetShellBox+	& Systemd.nspawned ancientKitenet+	& Systemd.nspawned openidProvider+	 	`requires` Apt.serviceInstalledRunning "ntp"++	& JoeySites.scrollBox+	& alias "scroll.joeyh.name"+	& alias "eu.scroll.joeyh.name"++	-- For https port 443, shellinabox with ssh login to+	-- kitenet.net+	& alias "shell.kitenet.net"+	& Systemd.nspawned kiteShellBox+	-- Nothing is using http port 80, so listen on+	-- that port for ssh, for traveling on bad networks that+	-- block 22.+	& Ssh.listenPort (Port 80)++beaver :: Host+beaver = host "beaver.kitenet.net" $ props+	& ipv6 "2001:4830:1600:195::2" 	& 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)+	& alias "usbackup.kitenet.net"+	& JoeySites.backupsBackedupFrom hosts "eubackup.kitenet.net" "/home/joey/lib/backup"+	& Apt.serviceInstalledRunning "anacron"+	& Cron.niceJob "system disk backed up" Cron.Weekly (User "root") "/"+		"rsync -a -x / /home/joey/lib/backup/beaver.kitenet.net/"++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"]+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)++-- 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 "stretch") X86_64+	& Apt.installed ["linux-image-686-pae"]+	& Apt.unattendedUpgrades+	& 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+	& osDebian (Stable "stretch") 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"]+	& Apt.removed ["nfs-common", "exim4", "exim4-base", "exim4-daemon-light", "rsyslog", "acpid", "rpcbind", "at"]+ 	& User.hasSomePassword (User "root")-	& File.dirExists "/var/www"+	& 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+		]++       --'                        __|II|      ,.+     ----                      __|II|II|__   (  \_,/\+--'-------'\o/-'-.-'-.-'-.- __|II|II|II|II|___/   __/ -'-.-'-.-'-.-'-.-'-.-'-+-------------------------- |   [Containers]      / --------------------------+-------------------------- :                    / ---------------------------+--------------------------- \____, o          ,' ----------------------------+---------------------------- '--,___________,'  -----------------------------++-- My own openid provider. Uses php, so containerized for security+-- and administrative sanity.+openidProvider :: Systemd.Container+openidProvider = Systemd.debContainer "openid-provider" $ props+	& standardContainer (Stable "stretch")+	& alias hn+	& OpenId.providerFor [User "joey", User "liw"] hn (Just (Port 8081))+  where+	hn = "openid.kitenet.net"++-- Exhibit: kite's 90's website on port 1994.+ancientKitenet :: Systemd.Container+ancientKitenet = Systemd.debContainer "ancient-kitenet" $ props+	& standardContainer (Stable "stretch")+	& 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"++oldusenetShellBox :: Systemd.Container+oldusenetShellBox = Systemd.debContainer "oldusenet-shellbox" $ props+	& standardContainer (Stable "stretch")+	& alias "shell.olduse.net"+	& JoeySites.oldUseNetShellBox++kiteShellBox :: Systemd.Container+kiteShellBox = Systemd.debContainer "kiteshellbox" $ props+	& standardContainer (Stable "stretch")+	& JoeySites.kiteShellBox++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.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")+	& 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.+	& Apt.removed ["exim4", "exim4-daemon-light", "exim4-config", "exim4-base"]+		`onChange` Apt.autoRemove+	-- At least until system integration catches up, revert+	-- systemd 230's behavior of enabling this property by default.+	! Systemd.killUserProcesses++-- This is my standard container setup, Featuring automatic upgrades.+standardContainer :: DebianSuite -> Property (HasInfo + Debian)+standardContainer suite = propertyList "standard container" $ props+	& osDebian suite X86_64+	& Apt.stdSourcesList `onChange` Apt.upgrade+	& Apt.unattendedUpgrades+	& Apt.cacheCleaned++myDnsSecondary :: Property (HasInfo + DebianLike)+myDnsSecondary = propertyList "dns secondary for all my domains" $ props+	& Dns.secondary hosts "kitenet.net"+	& Dns.secondary hosts "joeyh.name"+	& Dns.secondary hosts "ikiwiki.info"+	& Dns.secondary hosts "olduse.net"++branchableSecondary :: RevertableProperty (HasInfo + DebianLike) DebianLike+branchableSecondary = Dns.secondaryFor ["branchable.com"] hosts "branchable.com"++-- Currently using kite (ns4) as primary with secondaries+-- elephant (ns3) and gandi.+-- kite handles all mail.+myDnsPrimary :: Bool -> Domain -> [(BindDomain, Record)] -> RevertableProperty (HasInfo + DebianLike) DebianLike+myDnsPrimary dnssec domain extras = (if dnssec then Dns.signedPrimary (Weekly Nothing) else Dns.primary) hosts domain+	(Dns.mkSOA "ns4.kitenet.net" 100) $+	[ (RootDomain, NS $ AbsDomain "ns4.kitenet.net")+	, (RootDomain, NS $ AbsDomain "ns3.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+++monsters :: [Host]    -- Systems I don't manage with propellor,+monsters =            -- but do want to track their public keys etc.+	[ host "usw-s002.rsync.net" $ props+		& Ssh.hostPubKey SshEd25519 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB7yTEBGfQYdwG/oeL+U9XPMIh/dW7XNs9T+M79YIOrd"+	, host "github.com" $ props+		& Ssh.hostPubKey SshRsa "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="+	, host "gitlab.com" $ props+		& Ssh.hostPubKey SshEcdsa "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY="+	, host "ns6.gandi.net" $ props+		& ipv4 "217.70.177.40"+	, host "animx" $ props+		& ipv4 "76.7.162.186"+		& ipv4 "76.7.162.187"+	]++++                          --                                o+                          --             ___                 o              o+                       {-----\          / o \              ___o            o+                       {      \    __   \   /   _        (X___>--         __o+  _____________________{ ______\___  \__/ | \__/ \____                  |X__>+ <                                  \___//|\\___/\     \____________   _+  \                                  ___/ | \___    # #             \ (-)+   \    O      O      O             #     |     \ #                  >=)+    \______________________________# #   /       #__________________/ (-}++
debian/changelog view
@@ -1,3 +1,22 @@+propellor (5.3.0) unstable; urgency=medium++  * Avoid bogus warning about new upstream version when /usr/bin/propellor+    is run on a Debian system, but ~/.propellor was not cloned from the+    Debian git bundle.+  * Parted: Allow partitions to have no filesystem, for eg, GPT BIOS boot+    partitions. (API change)+  * Added rawPartition to PartSpec, for specifying partitions with no+    filesystem.+  * Added BiosGrubFlag to PartFlag.+  * Add HasCallStack constraint to pickOS and unsupportedOS, so the+    call stack includes the caller.+  * Run su with --login, to avoid inheriting some problematic environment+    variables, such as TMP, from the caller.+  * Grub: Added properties to configure /etc/default/grub.+  * Laptop: New module, starting with powertopAutoTuneOnBoot.++ -- Joey Hess <id@joeyh.name>  Thu, 01 Feb 2018 12:27:01 -0400+ propellor (5.2.0) unstable; urgency=medium    [ Joey Hess ]
joeyconfig.hs view
@@ -27,11 +27,13 @@ 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.FlashKernel as FlashKernel import qualified Propellor.Property.Borg as Borg import qualified Propellor.Property.Gpg as Gpg 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.OS as OS import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost import qualified Propellor.Property.HostingProvider.Linode as Linode@@ -58,6 +60,7 @@ 	, elephant 	, beaver 	, mouse+	, peregrine 	, pell 	, keysafe 	] ++ monsters@@ -87,12 +90,16 @@ 	& ipv6 "2001:4830:1600:187::2" 	& Hostname.sane 	& Apt.serviceInstalledRunning "swapspace"+	& Laptop.powertopAutoTuneOnBoot+	& Grub.cmdline_Linux_default "i915.enable_psr=1"+	! Grub.cmdline_Linux_default "quiet"  	& 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 		[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1YoyHxZwG5Eg0yiMTJLSWJ/+dMM6zZkZiR4JJ0iUfP+tT2bm/lxYompbSqBeiCq+PYcSC67mALxp1vfmdOV//LWlbXfotpxtyxbdTcQbHhdz4num9rJQz1tjsOsxTEheX5jKirFNC5OiKhqwIuNydKWDS9qHGqsKcZQ8p+n1g9Lr3nJVGY7eRRXzw/HopTpwmGmAmb9IXY6DC2k91KReRZAlOrk0287LaK3eCe1z0bu7LYzqqS+w99iXZ/Qs0m9OqAPnHZjWQQ0fN4xn5JQpZSJ7sqO38TBAimM+IHPmy2FTNVVn9zGM+vN1O2xr3l796QmaUG1+XLL0shfR/OZbb joey@darkstar") 		]@@ -114,7 +121,7 @@ clam = host "clam.kitenet.net" $ props 	& standardSystem Unstable X86_64 		["Unreliable server. Anything here may be lost at any time!" ]-	& ipv4 "45.62.211.6"+	& ipv4 "45.62.211.94"  	& CloudAtCost.decruft 	& Ssh.hostKeys hostContext@@ -186,6 +193,9 @@ 			`mountedAt` "/" 			`setSize` MegaBytes 8000 		)+	& File.hasPrivContentExposed "/etc/flash-kernel/dtbs/sun7i-a20-cubietruck.dtb"+		(Context "cubietruck gpio")+		`onChange` FlashKernel.flashKernel 	 	& Apt.installed ["firmware-brcm80211"] 		-- Workaround for https://bugs.debian.org/844056@@ -315,6 +325,7 @@ 	& myDnsPrimary True "kitenet.net" 		[ (RelDomain "mouse-onion", CNAME $ AbsDomain "htieo6yu2qtcn2j3.onion") 		, (RelDomain "beaver-onion", CNAME $ AbsDomain "tl4xsvaxryjylgxs.onion")+		, (RelDomain "peregrine-onion", CNAME $ AbsDomain "ahw47zqw6qszoufl.onion") 		] 	& myDnsPrimary True "joeyh.name" [] 	& myDnsPrimary True "ikiwiki.info" []@@ -415,6 +426,12 @@ 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"] 	& Tor.installed 	& Tor.hiddenServiceAvailable "ssh" (Port 22)
propellor.cabal view
@@ -1,5 +1,5 @@ Name: propellor-Version: 5.2.0+Version: 5.3.0 Cabal-Version: >= 1.20 License: BSD2 Maintainer: Joey Hess <id@joeyh.name>@@ -126,6 +126,7 @@     Propellor.Property.Installer.Target     Propellor.Property.Journald     Propellor.Property.Kerberos+    Propellor.Property.Laptop     Propellor.Property.LetsEncrypt     Propellor.Property.List     Propellor.Property.LightDM
src/Propellor/DotDir.hs view
@@ -358,7 +358,7 @@ 		withQuietOutput createProcessSuccess $ 			proc "git" ["log", headrev] 	if (headknown == Nothing)-		then setupUpstreamMaster headrev+		then updateUpstreamMaster headrev 		else do 			theirhead <- getCurrentGitSha1 =<< getCurrentBranchRef 			when (theirhead /= headrev) $ do@@ -372,26 +372,30 @@ 		d <- dotPropellor 		doesFileExist (d </> "propellor.cabal") --- Makes upstream/master in dotPropellor be a usefully mergeable branch.+-- Updates upstream/master in dotPropellor so merging from it will update+-- to the latest distrepo. ----- We cannot just use origin/master, because in the case of a distrepo,--- it only contains 1 commit. So, trying to merge with it will result--- in lots of merge conflicts, since git cannot find a common parent--- commit.+-- We cannot just fetch the distrepo because the distrepo contains only +-- 1 commit. So, trying to merge with it will result in lots of merge+-- conflicts, since git cannot find a common parent commit. ----- Instead, the upstream/master branch is created by taking the--- upstream/master branch (which must be an old version of propellor,+-- Instead, the new upstream/master branch is updated by taking the+-- current upstream/master branch (which must be an old version of propellor, -- as distributed), and diffing from it to the current origin/master, -- and committing the result. This is done in a temporary clone of the -- repository, giving it a new master branch. That new branch is fetched -- into the user's repository, as if fetching from a upstream remote, -- yielding a new upstream/master branch.-setupUpstreamMaster :: String -> IO ()-setupUpstreamMaster newref = do+--+-- If there's no upstream/master, the user is not using the distrepo,+-- so do nothing. And, if there's a remote named "upstream", the user+-- must have set that up is not using the distrepo, so do nothing.+updateUpstreamMaster :: String -> IO ()+updateUpstreamMaster newref = unlessM (hasRemote "upstream") $ do 	changeWorkingDirectory =<< dotPropellor 	go =<< catchMaybeIO getoldrev   where-	go Nothing = warnoutofdate False+	go Nothing = return () 	go (Just oldref) = do 		let tmprepo = ".git/propellordisttmp" 		let cleantmprepo = void $ catchMaybeIO $ removeDirectoryRecursive tmprepo@@ -427,7 +431,7 @@ warnoutofdate :: Bool -> IO () warnoutofdate havebranch = do 	warningMessage ("** Your ~/.propellor/ is out of date..")-	let also s = hPutStrLn stderr ("   " ++ s)+	let also s = infoMessage ["   " ++ s] 	also ("A newer upstream version is available in " ++ distrepo) 	if havebranch 		then also ("To merge it, run: git merge " ++ upstreambranch)
src/Propellor/Git.hs view
@@ -23,9 +23,12 @@ 	<$> readProcess "git" ["show-ref", "--hash", branchref]  hasOrigin :: IO Bool-hasOrigin = catchDefaultIO False $ do+hasOrigin = hasRemote "origin"++hasRemote :: String -> IO Bool+hasRemote remotename = catchDefaultIO False $ do 	rs <- lines <$> readProcess "git" ["remote"]-	return $ "origin" `elem` rs+	return $ remotename `elem` rs  hasGitRepo :: IO Bool hasGitRepo = doesFileExist ".git/HEAD"
src/Propellor/Property.hs view
@@ -55,6 +55,7 @@ import Data.List import Data.Hashable import Control.Applicative+import GHC.Stack import Prelude  import Propellor.Types@@ -283,6 +284,7 @@ -- fail that way. pickOS 	::+		HasCallStack => 		( SingKind ('KProxy :: KProxy ka) 		, SingKind ('KProxy :: KProxy kb) 		, DemoteRep ('KProxy :: KProxy ka) ~ [MetaType]@@ -344,7 +346,7 @@  -- | Throws an error, for use in `withOS` when a property is lacking -- support for an OS.-unsupportedOS' :: Propellor Result+unsupportedOS' :: HasCallStack => Propellor Result unsupportedOS' = go =<< getOS 	  where 		go Nothing = error "Unknown host OS is not supported by this property."
src/Propellor/Property/Cmd.hs view
@@ -94,6 +94,7 @@ -- | A property that can satisfied by running a script -- as user (cd'd to their home directory). userScriptProperty :: User -> Script -> UncheckedProperty UnixLike-userScriptProperty (User user) script = cmdProperty "su" ["--shell", "/bin/sh", "-c", shellcmd, user]+userScriptProperty (User user) script = cmdProperty "su"+	["--login", "--shell", "/bin/sh", "-c", shellcmd, user]   where 	shellcmd = intercalate " ; " ("set -e" : "cd" : script)
src/Propellor/Property/DiskImage.hs view
@@ -420,7 +420,7 @@ 	orderedmntsdevs = sortBy (compare `on` fst) $ zip mnts (zip mntopts devs)  	swaps = map (SwapPartition . partitionLoopDev . snd) $-		filter ((== LinuxSwap) . partFs . fst) $+		filter ((== Just LinuxSwap) . partFs . fst) $ 			zip parts devs  	mountall top = forM_ orderedmntsdevs $ \(mp, (mopts, loopdev)) -> case mp of
src/Propellor/Property/DiskImage/PartSpec.hs view
@@ -9,6 +9,7 @@ 	partition, 	-- * PartSpec combinators 	swapPartition,+	rawPartition, 	mountedAt, 	addFreeSpace, 	setSize,@@ -48,11 +49,15 @@ -- The partition is not mounted anywhere by default; use the combinators -- below to configure it. partition :: Monoid t => Fs -> PartSpec t-partition fs = (Nothing, mempty, mkPartition fs, mempty)+partition fs = (Nothing, mempty, mkPartition (Just fs), mempty)  -- | Specifies a swap partition of a given size. swapPartition :: Monoid t => PartSize -> PartSpec t-swapPartition sz = (Nothing, mempty, const (mkPartition LinuxSwap sz), mempty)+swapPartition sz = (Nothing, mempty, const (mkPartition (Just LinuxSwap) sz), mempty)++-- | Specifies a partition without any filesystem, of a given size.+rawPartition :: Monoid t => PartSize -> PartSpec t+rawPartition sz = (Nothing, mempty, const (mkPartition Nothing sz), mempty)  -- | Specifies where to mount a partition. mountedAt :: PartSpec t -> MountPoint -> PartSpec t
src/Propellor/Property/FlashKernel.hs view
@@ -23,9 +23,14 @@ installed machine = setInfoProperty go (toInfo [FlashKernelInstalled])   where 	go = "/etc/flash-kernel/machine" `File.hasContent` [machine]-		`onChange` (cmdProperty "flash-kernel" [] `assume` MadeChange)+		`onChange` flashKernel 		`requires` File.dirExists "/etc/flash-kernel" 		`requires` Apt.installed ["flash-kernel"]++-- | Runs flash-kernel with whatever machine `installed` configured.+flashKernel :: Property DebianLike+flashKernel = tightenTargets $+	cmdProperty "flash-kernel" [] `assume` MadeChange  -- | Runs flash-kernel in the system mounted at a particular directory. flashKernelMounted :: FilePath -> Property Linux
src/Propellor/Property/Gpg.hs view
@@ -33,7 +33,7 @@ 			ifM (liftIO $ hasGpgKey (parse keylines)) 				( return NoChange 				, makeChange $ withHandle StdinHandle createProcessSuccess-					(proc "su" ["-c", "gpg --import", u]) $ \h -> do+					(proc "su" ["--login", "-c", "gpg --import", u]) $ \h -> do 						hPutStr h (unlines keylines) 						hClose h 				)@@ -49,11 +49,11 @@  hasPrivKey :: GpgKeyId -> User -> IO Bool hasPrivKey (GpgKeyId keyid) (User u) = catchBoolIO $-	snd <$> processTranscript "su" ["-c", "gpg --list-secret-keys " ++ shellEscape keyid, u] Nothing+	snd <$> processTranscript "su" ["--login", "-c", "gpg --list-secret-keys " ++ shellEscape keyid, u] Nothing  hasPubKey :: GpgKeyId -> User -> IO Bool hasPubKey (GpgKeyId keyid) (User u) = catchBoolIO $-	snd <$> processTranscript "su" ["-c", "gpg --list-public-keys " ++ shellEscape keyid, u] Nothing+	snd <$> processTranscript "su" ["--login", "-c", "gpg --list-public-keys " ++ shellEscape keyid, u] Nothing  dotDir :: User -> IO FilePath dotDir (User u) = do
src/Propellor/Property/Grub.hs view
@@ -5,6 +5,8 @@ 	installed, 	mkConfig, 	installed',+	configured,+	cmdline_Linux_default, 	boots, 	bootsMounted, 	TimeoutSecs,@@ -13,12 +15,16 @@  import Propellor.Base import qualified Propellor.Property.File as File+import qualified Propellor.Property.ConfFile as ConfFile import qualified Propellor.Property.Apt as Apt import Propellor.Property.Mount import Propellor.Property.Chroot (inChroot) import Propellor.Types.Info import Propellor.Types.Bootloader+import Utility.SafeCommand +import Data.List+ -- | Eg, \"hd0,0\" or \"xen/xvda1\" type GrubDevice = String @@ -52,6 +58,65 @@ 		EFI32 -> "grub-efi-ia32" 		Coreboot -> "grub-coreboot" 		Xen -> "grub-xen"++-- | Sets a simple confguration value, using grub-mkconfig to update+-- the grub boot menu accordingly. On Debian, these are written to+-- </etc/default/grub>+--+-- Example:+--+-- >	& Grub.configured "GRUB_TIMEOUT" "10"+-- >	& Grub.configured "GRUB_TERMINAL_INPUT" "console serial"+configured :: String -> String -> Property DebianLike+configured k v = ConfFile.adjustSection +	("grub configured with " ++ k ++ "=" ++ v)+	isline+	(not . isline)+	(const [l])+	(const [l])+	simpleConfigFile+	`onChange` mkConfig+  where+	isline s = (k ++ "=") `isPrefixOf` s+	l = k ++ "=" ++ shellEscape v++simpleConfigFile :: FilePath+simpleConfigFile = "/etc/default/grub"++-- | Adds a word to the default linux command line.+-- Any other words in the command line will be left unchanged.+--+-- Example:+--+-- > 	& Grub.cmdline_Linux_default "i915.enable_psr=1"+-- > 	! Grub.cmdline_Linux_default "quiet"+cmdline_Linux_default :: String -> RevertableProperty DebianLike DebianLike+cmdline_Linux_default w = setup <!> undo+  where+	setup = ConfFile.adjustSection+		("linux command line includes " ++ w)+		isline+		(not . isline)+		(map (mkline . addw . getws))+		(++ [mkline [w]])+		simpleConfigFile+		`onChange` mkConfig+	undo = ConfFile.adjustSection+		("linux command line does not include " ++ w)+		isline+		(not . isline)+		(map (mkline . rmw . getws))+		(++ [mkline [""]])+		simpleConfigFile+		`onChange` mkConfig+	k = "GRUB_CMDLINE_LINUX_DEFAULT"+	isline s = (k ++ "=") `isPrefixOf` s+	mkline ws = k ++ "=" ++ shellEscape (unwords ws)+	getws = concatMap words . shellUnEscape . drop 1 . dropWhile (/= '=')+	addw ws+		| w `elem` ws = ws+		| otherwise = ws ++ [w]+	rmw = filter (/= w)  -- | Installs grub onto a device's boot loader,  -- so the system can boot from that device.
src/Propellor/Property/Installer/Target.hs view
@@ -68,15 +68,19 @@ -- see <https://git.joeyh.name/index.cgi/secret-project.git/>  module Propellor.Property.Installer.Target (+	-- * Main interface 	TargetPartTable(..), 	targetInstalled,-	mountTarget, 	fstabLists,+	-- * Additional properties+	mountTarget, 	targetBootable, 	partitionTargetDisk,+	-- * Utility functions 	targetDir, 	probeDisk, 	findDiskDevices,+	-- * Installation progress tracking 	TargetFilled, 	TargetFilledHandle, 	prepTargetFilled,@@ -110,6 +114,7 @@ import Data.Ratio import System.Process (readProcess) +-- | Partition table for the target disk. data TargetPartTable = TargetPartTable TableType [PartSpec DiskPart]  -- | Property that installs the target system to the TargetDiskDevice@@ -179,6 +184,7 @@ 		umountaside = cmdProperty "umount" ["-l", "/mnt"] 			`assume` MadeChange +-- | Gets the target mounted. mountTarget 	:: UserInput i 	=> i@@ -240,10 +246,10 @@ 	 	partitions = map (\(mp, _, mkpart, _) -> (mp, mkpart mempty)) partspecs 	mnts = mapMaybe fst $-		filter (\(_, p) -> partFs p /= LinuxSwap) partitions+		filter (\(_, p) -> partFs p /= Just LinuxSwap && partFs p /= Nothing) partitions 	swaps targetdev =  		map (Fstab.SwapPartition . diskPartition targetdev . snd) $-			filter (\((_, p), _) -> partFs p == LinuxSwap)+			filter (\((_, p), _) -> partFs p == Just LinuxSwap) 				(zip partitions partNums)  -- | Make the target bootable using whatever bootloader is installed on it.@@ -271,6 +277,7 @@ 				warningMessage $ "don't know how to enable bootloader(s) " ++ show l 				return FailedChange +-- | Partitions the target disk. partitionTargetDisk 	:: UserInput i 	=> i@@ -424,10 +431,10 @@ 	parse _ = Nothing  -- | How much of the target disks are used, compared with the size of the--- installer's root device. Since the main part of an installation --- is rsyncing the latter to the former, this allows roughly estimating--- the percent done while an install is running, and can be used in some--- sort of progress display.+-- installer's root device. Since the main part of an installation+-- is `targetInstalled` rsyncing the latter to the former, this allows+-- roughly estimating the percent done while an install is running,+-- and can be used in some sort of progress display. data TargetFilled = TargetFilled (Ratio Integer) 	deriving (Show, Eq) @@ -437,6 +444,7 @@  newtype TargetFilledHandle = TargetFilledHandle Integer +-- | Prepare for getting `TargetFilled`. prepTargetFilled :: IO TargetFilledHandle prepTargetFilled = go =<< getMountSource "/"   where@@ -446,6 +454,8 @@ 		return (TargetFilledHandle sz) 	go Nothing = return (TargetFilledHandle 0) +-- | Get the current `TargetFilled` value. This is fast enough to be run+-- multiple times per second without using much CPU. checkTargetFilled :: TargetFilledHandle -> IO TargetFilled checkTargetFilled (TargetFilledHandle installsz) = do 	targetsz <- sum . map snd . filter (isTargetMountPoint . fst)
+ src/Propellor/Property/Laptop.hs view
@@ -0,0 +1,28 @@+module Propellor.Property.Laptop where++import Propellor.Base+import qualified Propellor.Property.File as File+import qualified Propellor.Property.Apt as Apt+import qualified Propellor.Property.Systemd as Systemd++-- | Makes powertop auto-tune the system for optimal power consumption on+-- boot.+powertopAutoTuneOnBoot :: RevertableProperty DebianLike DebianLike+powertopAutoTuneOnBoot = setup <!> undo+	`describe` "powertop auto-tune on boot"+  where+	setup = Systemd.enabled "powertop"+		`requires` Apt.installed ["powertop"]+		`requires` File.hasContent servicefile+			[ "[Unit]"+			, "Description=Powertop tunings"+			, "[Service]"+			, "ExecStart=/usr/sbin/powertop --auto-tune"+			, "RemainAfterExit=true"+			, "[Install]"+			, "WantedBy=multi-user.target"+			]+	undo = tightenTargets $ File.notPresent servicefile+		`requires` check (doesFileExist servicefile)+			(Systemd.disabled "powertop")+	servicefile = "/etc/systemd/system/powertop.service"
src/Propellor/Property/Parted.hs view
@@ -62,8 +62,10 @@   where 	desc = disk ++ " partitioned" 	formatl devs = combineProperties desc (toProps $ map format (zip parts devs))-	format (p, dev) = Partition.formatted' (partMkFsOpts p)-		Partition.YesReallyFormatPartition (partFs p) dev+	format (p, dev) = case partFs p of+		Just fs -> Partition.formatted' (partMkFsOpts p)+			Partition.YesReallyFormatPartition fs dev+		Nothing -> doNothing  -- | Gets the total size of the disk specified by the partition table. partTableSize :: PartTable -> ByteSize@@ -81,12 +83,12 @@ 		, pval f 		, pval b 		]-	mkpart partnum startpos endpos p =-		[ "mkpart"-		, pval (partType p)-		, pval (partFs p)-		, partposexact startpos-		, partposfuzzy endpos+	mkpart partnum startpos endpos p = catMaybes+		[ Just "mkpart"+		, Just $ pval (partType p)+		, fmap pval (partFs p)+		, Just $ partposexact startpos+		, Just $ partposfuzzy endpos 		] ++ case partName p of 			Just n -> ["name", show partnum, n] 			Nothing -> []
src/Propellor/Property/Parted/Types.hs view
@@ -31,7 +31,7 @@ data Partition = Partition 	{ partType :: PartType 	, partSize :: PartSize-	, partFs :: Partition.Fs+	, partFs :: Maybe Partition.Fs 	, partMkFsOpts :: Partition.MkfsOpts 	, partFlags :: [(PartFlag, Bool)] -- ^ flags can be set or unset (parted may set some flags by default) 	, partName :: Maybe String -- ^ optional name for partition (only works for GPT, PC98, MAC)@@ -39,7 +39,7 @@ 	deriving (Show)  -- | Makes a Partition with defaults for non-important values.-mkPartition :: Partition.Fs -> PartSize -> Partition+mkPartition :: Maybe Partition.Fs -> PartSize -> Partition mkPartition fs sz = Partition 	{ partType = Primary 	, partSize = sz@@ -105,7 +105,7 @@ fromAlignment (Alignment n) = n  -- | Flags that can be set on a partition.-data PartFlag = BootFlag | RootFlag | SwapFlag | HiddenFlag | RaidFlag | LvmFlag | LbaFlag | LegacyBootFlag | IrstFlag | EspFlag | PaloFlag+data PartFlag = BootFlag | RootFlag | SwapFlag | HiddenFlag | RaidFlag | LvmFlag | LbaFlag | LegacyBootFlag | IrstFlag | EspFlag | PaloFlag | BiosGrubFlag 	deriving (Show)  instance PartedVal PartFlag where@@ -120,6 +120,7 @@ 	pval IrstFlag = "irst" 	pval EspFlag = "esp" 	pval PaloFlag = "palo"+	pval BiosGrubFlag = "bios_grub"  instance PartedVal Bool where 	pval True = "on"
src/Propellor/Property/SiteSpecific/JoeySites.hs view
@@ -948,10 +948,9 @@ 		, "[Install]" 		, "WantedBy=multi-user.target" 		]-	-- Only upload when eth0 is up; eg the satellite internet is up. 	-- Any changes to the rsync command will need my .authorized_keys 	-- rsync server command to be updated too.-	rsynccommand = "if ip route | grep '^default' | grep -q eth0; then rsync -e 'ssh -i" ++ sshkeyfile ++ "' -avz rrds/recent/ joey@kitenet.net:/srv/web/homepower.joeyh.name/rrds/recent/; fi"+	rsynccommand = "rsync -e 'ssh -i" ++ sshkeyfile ++ "' -avz rrds/recent/ joey@kitenet.net:/srv/web/homepower.joeyh.name/rrds/recent/"  -- My home router, running hostapd and dnsmasq for wlan0, -- with eth0 connected to a satellite modem, and a fallback ppp connection.@@ -998,7 +997,7 @@ 	& Apt.installed ["ppp"] 		`before` File.hasContent "/etc/ppp/peers/provider" 			[ "user \"joeyh@arczip.com\""-			, "connect \"/usr/sbin/chat -v -f /etc/chatscripts/pap -T 9734111\""+			, "connect \"/usr/sbin/chat -v -f /etc/chatscripts/pap -T 3825441\"" 			, "/dev/ttyACM0" 			, "115200" 			, "noipdefault"@@ -1037,23 +1036,25 @@  laptopSoftware :: Property DebianLike laptopSoftware = Apt.installed-	[ "procmeter3", "xfce4", "procmeter3", "unclutter"+	[ "intel-microcode"+	, "procmeter3", "xfce4", "procmeter3", "unclutter" 	, "mplayer", "fbreader", "firefox", "chromium" 	, "libdatetime-event-sunrise-perl", "libtime-duration-perl"-	, "iftop", "network-manager", "gtk-redshift", "powertop"+	, "network-manager", "gtk-redshift", "powertop" 	, "gimp", "gthumb", "inkscape", "sozi", "xzgv", "hugin" 	, "mpc", "mpd", "ncmpc", "sonata", "mpdtoys"-	, "bsdgames", "nethack"+	, "bsdgames", "nethack-console" 	, "xmonad", "libghc-xmonad-dev", "libghc-xmonad-contrib-dev" 	, "ttf-bitstream-vera" 	, "mairix", "offlineimap", "mutt"-	, "nmap"+	, "nmap", "whois", "wireshark", "tcpdump", "iftop" 	, "udevil", "pmount" 	, "arbtt", "hledger", "bc" 	, "apache2", "ikiwiki", "libhighlight-perl" 	, "pal" 	, "yeahconsole", "xkbset", "xinput"-	, "assword", "pumpa", "vorbis-tools"+	, "assword", "pumpa"+	, "vorbis-tools", "audacity" 	, "xul-ext-ublock-origin", "xul-ext-pdf.js", "xul-ext-status4evar" 	, "vim-syntastic", "vim-fugitive" 	, "adb", "gthumb"@@ -1076,5 +1077,4 @@ 	, "hothasktags", "hdevtools", "hlint" 	, "gdb", "dpkg-repack", "lintian" 	, "pristine-tar", "github-backup"-	, "kvm" 	]
src/propellor-config.hs view
@@ -1,29 +1,658 @@--- 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.Service as Service+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+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.OpenId as OpenId+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.FlashKernel as FlashKernel+import qualified Propellor.Property.Borg as Borg+import qualified Propellor.Property.Gpg as Gpg+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.OS as OS+import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost+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+import qualified Propellor.Property.SiteSpecific.JoeySites as JoeySites -main :: IO ()-main = defaultMain hosts+main :: IO ()           --     _         ______`|                       ,-.__+main = defaultMain hosts --  /   \___-=O`/|O`/__|                      (____.'+  {- Propellor            -- \          / | /    )          _.-"-._+     Deployed -}          --  `/-==__ _/__|/__=-|          (       \_+hosts :: [Host]          --   *             \ | |           '--------'+hosts =                 --                  (o)  `+	[ darkstar+	, gnu+	, dragon+	, clam+	, orca+	, baleen+	, honeybee+	, kite+	, elephant+	, beaver+	, mouse+	, peregrine+	, pell+	, keysafe+	] ++ monsters --- The hosts propellor knows about.-hosts :: [Host]-hosts =-	[ mybox-	]+testvm :: Host+testvm = host "testvm.kitenet.net" $ props+	& osDebian Unstable X86_64+	& OS.cleanInstallOnce (OS.Confirmed "testvm.kitenet.net")+	 	`onChange` postinstall+	& Hostname.sane+	& Hostname.searchDomain+	& Apt.installed ["linux-image-amd64"]+	& Apt.installed ["ssh"]+	& User.hasPassword (User "root")+  where+	postinstall :: Property (HasInfo + DebianLike)+	postinstall = propertyList "fixing up after clean install" $ props+		& OS.preserveRootSshAuthorized+		& OS.preserveResolvConf+		& Apt.update+		& Grub.boots "/dev/sda"+			`requires` Grub.installed Grub.PC --- 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+	& Apt.serviceInstalledRunning "swapspace"+	& Laptop.powertopAutoTuneOnBoot+	& Grub.cmdline_Linux_default "i915.enable_psr=1"+	! Grub.cmdline_Linux_default "quiet"++	& 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+		[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1YoyHxZwG5Eg0yiMTJLSWJ/+dMM6zZkZiR4JJ0iUfP+tT2bm/lxYompbSqBeiCq+PYcSC67mALxp1vfmdOV//LWlbXfotpxtyxbdTcQbHhdz4num9rJQz1tjsOsxTEheX5jKirFNC5OiKhqwIuNydKWDS9qHGqsKcZQ8p+n1g9Lr3nJVGY7eRRXzw/HopTpwmGmAmb9IXY6DC2k91KReRZAlOrk0287LaK3eCe1z0bu7LYzqqS+w99iXZ/Qs0m9OqAPnHZjWQQ0fN4xn5JQpZSJ7sqO38TBAimM+IHPmy2FTNVVn9zGM+vN1O2xr3l796QmaUG1+XLL0shfR/OZbb joey@darkstar")+		]+	-- & imageBuiltFor honeybee+	--	(RawDiskImage "/srv/honeybee.img")+	--	(Debootstrapped mempty)++gnu :: Host+gnu = host "gnu.kitenet.net" $ props+	& Postfix.satellite++dragon :: Host+dragon = host "dragon.kitenet.net" $ props+	& ipv6 "2001:4830:1600:187::2"+	& JoeySites.dkimMilter+	& JoeySites.postfixSaslPasswordClient++clam :: Host+clam = host "clam.kitenet.net" $ props+	& standardSystem Unstable X86_64+		["Unreliable server. Anything here may be lost at any time!" ]+	& ipv4 "45.62.211.94"++	& CloudAtCost.decruft+	& Ssh.hostKeys hostContext+		[ (SshDsa, "ssh-dss AAAAB3NzaC1kc3MAAACBAI3WUq0RaigLlcUivgNG4sXpso2ORZkMvfqKz6zkc60L6dpxvWDNmZVEH8hEjxRSYG07NehcuOgQqeyFnS++xw1hdeGjf37JqCUH49i02lra3Zxv8oPpRxyeqe5MmuzUJhlWvBdlc3O/nqZ4bTUfnxMzSYWyy6++s/BpSHttZplNAAAAFQC1DE0vzgVeNAv9smHLObQWZFe2VQAAAIBECtpJry3GC8NVTFsTHDGWksluoFPIbKiZUFFztZGdM0AO2VwAbiJ6Au6M3VddGFANgTlni6d2/9yS919zO90TaFoIjywZeXhxE2CSuRfU7sx2hqDBk73jlycem/ER0sanFhzpHVpwmLfWneTXImWyq37vhAxatJANOtbj81vQ3AAAAIBV3lcyTT9xWg1Q4vERJbvyF8mCliwZmnIPa7ohveKkxlcgUk5d6dnaqFfjVaiXBPN3Qd08WXoQ/a9k3chBPT9nW2vWgzzM8l36j2MbHLmaxGwevAc9+vx4MXqvnGHzd2ex950mC33ct3j0fzMZlO6vqEsgD4CYmiASxhfefj+JCQ==")+		, (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJybAjUPUWIhvVMmer8K5ZgdfI54DM6vc8Mzw+5KmVKL0TwkvzbR1HAB4heyMGtN1F8YzkWhsI3/Txh+MQUJ+i4u8SvSYc6D1q3j3ZyCi06wZ3DJS25tZrOM/thOOA1DFA4Hhb0uI/1Kg8PguNNNSMXn8F7q3F6cFQizYgszs6z6ktiST/BTC+IXWovhcnn2vQXXU8FTcTsqBFqA5dEjZbp1WDzqp3km84ZyXGmoVlpqzXeMvlkWTIshYiQjXIwPOkALzlGYjp1lw1OaxPVI1IGFcgCbIWQQWoCReb+genX2VaR+odAYXjaOdRx0lQj7UCPTBCpqMyzBMLtT5Yiaqh")+		, (SshEcdsa, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPhfvcOuw0Yt+MnsFc4TI2gWkKi62Eajxz+TgbHMO/uRTYF8c5V8fOI3o+J/3m5+lT0S5o8j8a7xIC3COvi+AVw=")+		] 	& Apt.unattendedUpgrades-	& Apt.installed ["etckeeper"]+	& Systemd.persistentJournal+	& Journald.systemMaxUse "50MiB"+	& Apt.serviceInstalledRunning "swapspace"++	& Tor.isRelay+	& Tor.named "kite1"+	& Tor.bandwidthRate (Tor.PerMonth "400 GB")++	& Systemd.nspawned oldusenetShellBox++	& JoeySites.scrollBox+	& alias "scroll.joeyh.name"+	& alias "us.scroll.joeyh.name"++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." ]+	& 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.androidAutoBuilderContainer+		(Cron.Times "1 1 * * *") "3h")++honeybee :: Host+honeybee = host "honeybee.kitenet.net" $ props+	& standardSystem Testing ARMHF+		[ "Home router and arm git-annex build box." ]+	+	& cubietech_Cubietruck+	& hasPartition+		( partition EXT4+			`mountedAt` "/"+			`setSize` MegaBytes 8000+		)+	& File.hasPrivContentExposed "/etc/flash-kernel/dtbs/sun7i-a20-cubietruck.dtb"+		(Context "cubietruck gpio")+		`onChange` FlashKernel.flashKernel+	+	& Apt.installed ["firmware-brcm80211"]+		-- Workaround for https://bugs.debian.org/844056+		`requires` File.hasPrivContent "/lib/firmware/brcm/brcmfmac43362-sdio.txt" anyContext+		`requires` File.dirExists "/lib/firmware/brcm"+	& "/etc/default/rcS" `File.containsLine` "FSCKFIX=yes"+	& Apt.serviceInstalledRunning "ntp" -- no hardware clock+	& bootstrappedFrom GitRepoOutsideChroot+	& Ssh.hostKeys hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIS/hDYq1MAxfOBf49htym3BOYlx4Gk9SDpiHjv7u6IC")+		]++	& JoeySites.homePowerMonitor+		(User "joey")+		hosts+		(Context "homepower.joeyh.name")+		(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMAmVYddg/RgCbIj+cLcEiddeFXaYFnbEJ3uGj9G/EyV joey@honeybee")+	& JoeySites.homeRouter+	& Apt.installed ["mtr-tiny", "iftop", "screen"]+	& Postfix.satellite++	& check (not <$> inChroot) (setupRevertableProperty autobuilder)+	-- In case compiler needs more than available ram+	& Apt.serviceInstalledRunning "swapspace"+  where+	autobuilder = Systemd.nspawned $ GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.armAutoBuilder+		Unstable ARMEL Nothing (Cron.Times "15 10 * * *") "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"+	& alias "wren.kitenet.net" -- temporary+	& 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"]+	& 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 "/" (Borg.BorgRepo "joey@eubackup.kitenet.net:/home/joey/lib/backup/kite/kite.borg") Cron.Daily+		[ "--exclude=/proc/*"+		, "--exclude=/sys/*"+		, "--exclude=/run/*"+		, "--exclude=/tmp/*"+		, "--exclude=/var/tmp/*"+		, "--exclude=/var/cache/*"+		, "--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+		, Borg.KeepMonths 6+		]+		`requires` Ssh.knownHost hosts "eubackup.kitenet.net" (User "root")+		`requires` Ssh.userKeys (User "root")+			(Context "kite.kitenet.net")+			[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5Gza2sNqSKfNtUN4dN/Z3rlqw18nijmXFx6df2GtBoZbkIak73uQfDuZLP+AXlyfHocwdkdHEf/zrxgXS4EokQMGLZhJ37Pr3edrEn/NEnqroiffw7kyd7EqaziA6UOezcLTjWGv+Zqg9JhitYs4WWTpNzrPH3yQf1V9FunZnkzb4gJGndts13wGmPEwSuf+QHbgQvjMOMCJwWSNcJGdhDR66hFlxfG26xx50uIczXYAbgLfHp5W6WuR/lcaS9J6i7HAPwcsPDA04XDinrcpl29QwsMW1HyGS/4FSCgrDqNZ2jzP49Bka78iCLRqfl1efyYas/Zo1jQ0x+pxq2RMr 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 hosts+	& JoeySites.gitAnnexDistributor+	& JoeySites.tmp++	& alias "bitlbee.kitenet.net"+	& Apt.serviceInstalledRunning "bitlbee"+	& "/etc/bitlbee/bitlbee.conf" `File.hasContent`+		[ "[settings]"+		, "User = bitlbee"+		, "AuthMode = Registered"+		, "[defaults]"+		]+		`onChange` Service.restarted "bitlbee"+	& "/etc/default/bitlbee" `File.containsLine` "BITLBEE_PORT=\"6767\""+		`onChange` Service.restarted "bitlbee"++	& Apt.installed+		[ "git-annex", "myrepos"+		, "build-essential", "make"+		, "rss2email", "archivemail"+		, "devscripts"+		-- Some users have zsh as their login shell.+		, "zsh"+		]++	& alias "nntp.olduse.net"+	& JoeySites.oldUseNetServer hosts++	& alias "ns4.kitenet.net"+	& myDnsPrimary True "kitenet.net"+		[ (RelDomain "mouse-onion", CNAME $ AbsDomain "htieo6yu2qtcn2j3.onion")+		, (RelDomain "beaver-onion", CNAME $ AbsDomain "tl4xsvaxryjylgxs.onion")+		, (RelDomain "peregrine-onion", CNAME $ AbsDomain "ahw47zqw6qszoufl.onion")+		]+	& myDnsPrimary True "joeyh.name" []+	& myDnsPrimary True "ikiwiki.info" []+	& myDnsPrimary True "olduse.net"+		[ (RelDomain "article", CNAME $ AbsDomain "virgil.koldfront.dk")+		]+	& 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"+	-- debug-me installed manually until package is available+	& Systemd.enabled "debug-me"++	-- testing+	& Apache.httpsVirtualHost "letsencrypt.joeyh.name" "/var/www/html"+		(LetsEncrypt.AgreeTOS (Just "id@joeyh.name"))+	& alias "letsencrypt.joeyh.name"+  where++elephant :: Host+elephant = host "elephant.kitenet.net" $ props+	& standardSystem Unstable X86_64+		[ "Storage, big data, and backups, omnomnom!"+		, "(Encrypt all data stored here.)"+		]+	& ipv4 "193.234.225.114"+	& Ssh.hostKeys hostContext+		[ (SshDsa, "ssh-dss AAAAB3NzaC1kc3MAAACBANxXGWac0Yz58akI3UbLkphAa8VPDCGswTS0CT3D5xWyL9OeArISAi/OKRIvxA4c+9XnWtNXS7nYVFDJmzzg8v3ZMx543AxXK82kXCfvTOc/nAlVz9YKJAA+FmCloxpmOGrdiTx1k36FE+uQgorslGW/QTxnOcO03fDZej/ppJifAAAAFQCnenyJIw6iJB1+zuF/1TSLT8UAeQAAAIEA1WDrI8rKnxnh2rGaQ0nk+lOcVMLEr7AxParnZjgC4wt2mm/BmkF/feI1Fjft2z4D+V1W7MJHOqshliuproxhFUNGgX9fTbstFJf66p7h7OLAlwK8ZkpRk/uV3h5cIUPel6aCwjL5M2gN6/yq+gcCTXeHLq9OPyUTmlN77SBL71UAAACBAJJiCHWxPAGooe7Vv3W7EIBbsDyf7b2kDH3bsIlo+XFcKIN6jysBu4kn9utjFlrlPeHUDzGQHe+DmSqTUQQ0JPCRGcAcuJL8XUqhJi6A6ye51M9hVt51cJMXmERx9TjLOP/adkEuxpv3Fj20FxRUr1HOmvRvewSHrJ1GeA1bjbYL")+		, (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrEQ7aNmRYyLKY7xHILQsyV/w0B3++D98vn5IvjHkDnitrUWjB+vPxlS7LYKLzN9Jx7Hb14R2lg7+wdgtFMxLZZukA8b0tqFpTdRFBvBYGh8IM8Id1iE/6io/NZl+hTQEDp0LJP+RljH1CLfz7J3qtc+v6NbfTP5cOgH104mWYoLWzJGaZ4p53jz6THRWnVXy5nPO3dSBr2f/SQgRuJQWHNIh0jicRGD8H2kzOQzilpo+Y46PWtkufl3Yu3UsP5UMAyLRIXwZ6nNRZqRiVWrX44hoNfDbooTdFobbHlqMl+y6291bOXaOA6PACk8B4IVcC89/gmc9Oe4EaDuszU5kD")+		, (SshEcdsa, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAJkoPRhUGT8EId6m37uBdYEtq42VNwslKnc9mmO+89ody066q6seHKeFY6ImfwjcyIjM30RTzEwftuVNQnbEB0=")+		, (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB6VtXi0uygxZeCo26n6PuCTlSFCBcwRifv6N8HdWh2Z")+		]++	& Grub.chainPVGrub "hd0,0" "xen/xvda1" 30+	& Postfix.satellite+	& Apt.unattendedUpgrades+	& Systemd.installed+	& Systemd.persistentJournal+	& Ssh.userKeys (User "joey") hostContext+		[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4wJuQEGno+nJvtE75IKL6JQ08sJHZ9Bzs9Dvu0zuxSEZE30MWK98/twNwCH9PVf2N9m4apfN7f9GHgHTUongfo8xnLAk4PuBSTV74YgKyOCvNYqANuKKa+76PsS/vFf/or3ct++uTEWsRyYD29cQndufwKA4rthAqHG+fifbLDC53AjcldI0zI1RckpPzT+AMazlnSBFMlpKvGD2uzSXALVRXa3vSqWkWd0z7qmIkpmpq0AAgbDLwrGBcUGV/h0rOa2s8zSeirA0tLmHNROl4cZsX0T/6VBGfBRkrHSxL67xJziATw4WPq6spYlxg84pC/5qJVr9SC5HosppbDqgj joey@elephant")+		]+	& Apt.serviceInstalledRunning "swapspace"++	& alias "eubackup.kitenet.net"+	& Apt.installed ["sshfs", "rsync", "borgbackup"]+	& JoeySites.githubBackup+	& JoeySites.rsyncNetBackup hosts++	& alias "podcatcher.kitenet.net"+	& JoeySites.podcatcher++	& alias "znc.kitenet.net"+	& JoeySites.ircBouncer+	& alias "kgb.kitenet.net"+	& JoeySites.kgbServer++	& alias "ns3.kitenet.net"+	& myDnsSecondary++	& Systemd.nspawned oldusenetShellBox+	& Systemd.nspawned ancientKitenet+	& Systemd.nspawned openidProvider+	 	`requires` Apt.serviceInstalledRunning "ntp"++	& JoeySites.scrollBox+	& alias "scroll.joeyh.name"+	& alias "eu.scroll.joeyh.name"++	-- For https port 443, shellinabox with ssh login to+	-- kitenet.net+	& alias "shell.kitenet.net"+	& Systemd.nspawned kiteShellBox+	-- Nothing is using http port 80, so listen on+	-- that port for ssh, for traveling on bad networks that+	-- block 22.+	& Ssh.listenPort (Port 80)++beaver :: Host+beaver = host "beaver.kitenet.net" $ props+	& ipv6 "2001:4830:1600:195::2" 	& 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)+	& alias "usbackup.kitenet.net"+	& JoeySites.backupsBackedupFrom hosts "eubackup.kitenet.net" "/home/joey/lib/backup"+	& Apt.serviceInstalledRunning "anacron"+	& Cron.niceJob "system disk backed up" Cron.Weekly (User "root") "/"+		"rsync -a -x / /home/joey/lib/backup/beaver.kitenet.net/"++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"]+	& Tor.installed+	& Tor.hiddenServiceAvailable "ssh" (Port 22)++-- 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 "stretch") X86_64+	& Apt.installed ["linux-image-686-pae"]+	& Apt.unattendedUpgrades+	& 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+	& osDebian (Stable "stretch") 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"]+	& Apt.removed ["nfs-common", "exim4", "exim4-base", "exim4-daemon-light", "rsyslog", "acpid", "rpcbind", "at"]+ 	& User.hasSomePassword (User "root")-	& File.dirExists "/var/www"+	& 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+		]++       --'                        __|II|      ,.+     ----                      __|II|II|__   (  \_,/\+--'-------'\o/-'-.-'-.-'-.- __|II|II|II|II|___/   __/ -'-.-'-.-'-.-'-.-'-.-'-+-------------------------- |   [Containers]      / --------------------------+-------------------------- :                    / ---------------------------+--------------------------- \____, o          ,' ----------------------------+---------------------------- '--,___________,'  -----------------------------++-- My own openid provider. Uses php, so containerized for security+-- and administrative sanity.+openidProvider :: Systemd.Container+openidProvider = Systemd.debContainer "openid-provider" $ props+	& standardContainer (Stable "stretch")+	& alias hn+	& OpenId.providerFor [User "joey", User "liw"] hn (Just (Port 8081))+  where+	hn = "openid.kitenet.net"++-- Exhibit: kite's 90's website on port 1994.+ancientKitenet :: Systemd.Container+ancientKitenet = Systemd.debContainer "ancient-kitenet" $ props+	& standardContainer (Stable "stretch")+	& 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"++oldusenetShellBox :: Systemd.Container+oldusenetShellBox = Systemd.debContainer "oldusenet-shellbox" $ props+	& standardContainer (Stable "stretch")+	& alias "shell.olduse.net"+	& JoeySites.oldUseNetShellBox++kiteShellBox :: Systemd.Container+kiteShellBox = Systemd.debContainer "kiteshellbox" $ props+	& standardContainer (Stable "stretch")+	& JoeySites.kiteShellBox++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.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")+	& 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.+	& Apt.removed ["exim4", "exim4-daemon-light", "exim4-config", "exim4-base"]+		`onChange` Apt.autoRemove+	-- At least until system integration catches up, revert+	-- systemd 230's behavior of enabling this property by default.+	! Systemd.killUserProcesses++-- This is my standard container setup, Featuring automatic upgrades.+standardContainer :: DebianSuite -> Property (HasInfo + Debian)+standardContainer suite = propertyList "standard container" $ props+	& osDebian suite X86_64+	& Apt.stdSourcesList `onChange` Apt.upgrade+	& Apt.unattendedUpgrades+	& Apt.cacheCleaned++myDnsSecondary :: Property (HasInfo + DebianLike)+myDnsSecondary = propertyList "dns secondary for all my domains" $ props+	& Dns.secondary hosts "kitenet.net"+	& Dns.secondary hosts "joeyh.name"+	& Dns.secondary hosts "ikiwiki.info"+	& Dns.secondary hosts "olduse.net"++branchableSecondary :: RevertableProperty (HasInfo + DebianLike) DebianLike+branchableSecondary = Dns.secondaryFor ["branchable.com"] hosts "branchable.com"++-- Currently using kite (ns4) as primary with secondaries+-- elephant (ns3) and gandi.+-- kite handles all mail.+myDnsPrimary :: Bool -> Domain -> [(BindDomain, Record)] -> RevertableProperty (HasInfo + DebianLike) DebianLike+myDnsPrimary dnssec domain extras = (if dnssec then Dns.signedPrimary (Weekly Nothing) else Dns.primary) hosts domain+	(Dns.mkSOA "ns4.kitenet.net" 100) $+	[ (RootDomain, NS $ AbsDomain "ns4.kitenet.net")+	, (RootDomain, NS $ AbsDomain "ns3.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+++monsters :: [Host]    -- Systems I don't manage with propellor,+monsters =            -- but do want to track their public keys etc.+	[ host "usw-s002.rsync.net" $ props+		& Ssh.hostPubKey SshEd25519 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB7yTEBGfQYdwG/oeL+U9XPMIh/dW7XNs9T+M79YIOrd"+	, host "github.com" $ props+		& Ssh.hostPubKey SshRsa "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="+	, host "gitlab.com" $ props+		& Ssh.hostPubKey SshEcdsa "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY="+	, host "ns6.gandi.net" $ props+		& ipv4 "217.70.177.40"+	, host "animx" $ props+		& ipv4 "76.7.162.186"+		& ipv4 "76.7.162.187"+	]++++                          --                                o+                          --             ___                 o              o+                       {-----\          / o \              ___o            o+                       {      \    __   \   /   _        (X___>--         __o+  _____________________{ ______\___  \__/ | \__/ \____                  |X__>+ <                                  \___//|\\___/\     \____________   _+  \                                  ___/ | \___    # #             \ (-)+   \    O      O      O             #     |     \ #                  >=)+    \______________________________# #   /       #__________________/ (-}++