This was the last public version of rsiddharth's propellor config (2020-04-29).
-- This is the main configuration file for Propellor, and is used to build -- the propellor program. https://propellor.branchable.com/ -- Copyright © 2019 rsiddharth <s@ricketyspace.net> -- License: BSD2 -- -- _________ -- < s' lazy > -- --------- -- \ ., -- \ . .TR d' -- \ k,l .R.b .t .Je -- \ .P q. a|.b .f .Z% -- .b .h .E` # J: 2` . -- .,.a .E ,L.M' ?:b `| ..J9!`., -- q,.h.M` `.., ..,""` ..2"` -- .M, J8` `: ` 3; -- . Jk ..., `^7"90c. -- j, ,! .7"'`j,.| .n. ... -- j, 7' .r` 4: L `... -- ..,m. J` ..,|.. J` 7TWi -- ..JJ,.: % oo ,. ...., -- .,E 3 7`g.M: P 41 -- JT7"' O. .J,; `` V"7N. -- G. ""Q+ .Zu.,!` Z` -- .9.. . J&..J! . ,: -- 7"9a JM"! -- .5J. .. ..F` -- 78a.. ` ..2' -- J9Ksaw0"' -- .EJ?A...a. -- q...g...gi -- .m...qa..,y: -- .HQFNB&...mm -- ,Z|,m.a.,dp -- .,?f` ,E?:"^7b -- `A| . .F^^7'^4, -- .MMMMMMMMMMMQzna, -- ...f"A.JdT J: Jp, -- `JNa..........A....af` -- `^^^^^'` import Propellor import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.Cron as Cron import qualified Propellor.Property.Dns as Dns import qualified Propellor.Property.Fail2Ban as Fail2Ban import qualified Propellor.Property.File as File import qualified Propellor.Property.Group as Group import qualified Propellor.Property.Locale as Locale import qualified Propellor.Property.Nginx as Nginx import qualified Propellor.Property.Postfix as Postfix import qualified Propellor.Property.Service as Service import qualified Propellor.Property.Ssh as Ssh import qualified Propellor.Property.Sudo as Sudo import qualified Propellor.Property.User as User main :: IO () main = defaultMain hosts -- The hosts propellor knows about. hosts :: [Host] hosts = publicHosts ++ [ grus ] publicHosts :: [Host] publicHosts = [ lyra, virgo, ara ] ++ [ vela ] ++ m31 -- keys. sCanonicalSshPubKey :: [Char] sCanonicalSshPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDd7kT6tpH4zZ/hFlRmSVH1oJZZJJUvoMd89AiskXAq5rBrvZC90WVOF12OTQVQqslUVV2ze7BCC13UEfK5F2xP+7F6FDqSFApV4lBsJWLNbtDlZY23lTYqi/L6muq3x5tbqJLQjUK5ItORe0Ecqqz1ymSy+Zk+kHmHfnqyoWAQ7Z5GJkRu1B4J9uT3LJDIgLE8m4nJEOoCJ5vnycJfs0LCwHNZ67H38FV3Uw/sGibCNyCSJHQcG+nkKGYzABDcbXmWXedUq0MlRY2TjU22cOzjaAH0mf6M7m6KQCQeXjdxyyLaI3lNOzhBOU7j8/H9GqdRDH8pZ5e4xp+AG3tcrWi2E+47Qp4J9qv0YPgfj7JZ4oJhvCKGkgldOQZ8mkvjDLvAMGte0zpk2SPDlfJeFgfDHMre3nxAAzIfmhaIX2j86LdUh717BmcXDYD//9SubRLdAZrOKh4Iapcotm0STOFUlDa6nvh27DuKIIvq7v/+ID6P4fSNb4h1ktC/3lrhI21ei8ZjBulonJ9XV+BPGlnIzmWL7g5j4dMm90AqZXRRKQMAX9UIizLoCh58KR5gESszQ/8MSrELclI1fUwiY4Wxlvf6ZsGsg3c22xumxlnc85eiAYQ1LEPWNghcyqE96yrIhXrph3unLRsEbZcGxgXw/dcUtjIL9tjDO9zSN6ZuOQ== rsd@grus" sAraSshPubKey :: [Char] sAraSshPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTn+zicq75blG6yWY0GIkba93FDbWHOo95k2oqrUVr3llmpuRnYCdp6F7LIiRF4NxDA6hBL5JAlxwS0mKgpbzJjbav7S7XxV1HxrtbO/bQqbcH3pvGCuSvltpZg072pB/g1Uhcv9S2FiOHJsedqlGiqUfucuFdRINYk3a8cQVTZ6XB7AxpqGLova3b+1rdhF6c5DSxgMscvZ+zGANN8tmv/0iGERRRdpvePR7iKZp7ZpqrsS4zXHJO537T6Z05lhaD+Fk/sgz5AUT/fkxIVvsNYL23mVS2fQg1htBAZi4vZ7joZn643bc1w6B7oa8nKEagRu4EWw+LbMeKzecIv0pB s@cygnus.ricketyspace.net" sLyraSshPubKey :: [Char] sLyraSshPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0UdjqvAo5lICg0BwGv6aQVSO+Ew6ZXFwbwpZiXhZ03+P/Wk98mJJUln+NaKC9lbjQnAShviBy5BIPbexQJ21vvP6mh13Z6xPPtHWRYUy+Y0GYvnc8yKfsnJ2bDaXobpAprfwWpwhW01ZC2xehaZxE+w8dwdAP4v53w5XlLU733f19vRqis4Y0/jyse2BMpsVGzWiLRLprjeLOgdcDB+yLP+EnM46Yj5z0xchbO2uCozloX1yhExDJ2Z4MITx397+/3GYaPEytcMVD/YmIScU4y4nqwa8O/sg5miamD6HUzAWKOHkHgf1HosDbz4JHcEwJqgSvqTeVJ5UWWuPK7YfJ s@cygnus.ricketyspace.net" -- configure ara grus :: Host grus = host "grus.ricketyspace.net" $props & osDebian Unstable X86_64 & Locale.available "en_US.UTF-8" & File.hasContent "/etc/motd" (["At grus."]) & dockerCEInstalled -- configure ara ara :: Host ara = host "ara.ricketyspace.net" $props & osDebian (Stable "buster") X86_64 & Locale.available "en_US.UTF-8" & ipv4 "207.246.85.24" & File.hasContent "/etc/motd" (["At ara."]) -- apt & Apt.stdSourcesList & Apt.unattendedUpgrades & Apt.safeUpgrade & Apt.installed ["htop", "tmux", "git"] -- sshd & Ssh.passwordAuthentication False -- system -- & Fail2Ban.installed -- root config & File.hasContent "/root/.tmux.conf" tmuxConf & Ssh.authorizedKey (User "root") sCanonicalSshPubKey & Ssh.authorizedKey (User "root") sAraSshPubKey & Ssh.userKeyAt (Just "/root/.ssh/id_rsa") (User "root") hostContext (SshRsa, sAraSshPubKey) & File.hasPrivContent "/root/switchblade.ovpn" (Context "ara.ricketyspace.net") -- s config & User.accountFor(User "s") & User.hasPassword (User "s") & User.hasLoginShell (User "s") "/bin/bash" & Sudo.enabledFor (User "s") & Ssh.authorizedKey (User "s") sCanonicalSshPubKey & Ssh.userKeyAt (Just "/home/s/.ssh/id_rsa") (User "s") hostContext (SshRsa, sAraSshPubKey) & File.hasContent "/home/s/.tmux.conf" tmuxConf & File.ownerGroup "/home/s" (User "s") (Group "s") -- configure virgo virgo :: Host virgo = host "virgo.ricketyspace.net" $props & osDebian (Stable "buster") X86_64 & ipv4 "207.246.94.218" & Locale.available "en_US.UTF-8" & File.hasContent "/etc/motd" (["At virgo."]) -- apt & Apt.stdSourcesList & Apt.unattendedUpgrades & Apt.safeUpgrade & Apt.installed ["htop", "tmux"] -- sshd & Ssh.passwordAuthentication False -- system & Fail2Ban.installed --- nginx & Apt.removed ["apache2"] & Nginx.installed & ricketyspaceNetDhparamPem & ricketyspaceNetCert `onChange` Nginx.restarted & ricketyspaceNetCertKey & ricketyspaceNetGitCert & ricketyspaceNetGitCertKey & ricketyspaceNetLyraCert & ricketyspaceNetLyraCertKey & Nginx.siteEnabled "ricketyspace.net" ricketyspaceNetNginx & Nginx.siteEnabled "git.ricketyspace.net" ricketyspaceNetGitNginx -- crons & stagitGenCron -- web & Group.exists (Group "pubs") Nothing -- web - root & File.dirExists "/var/www/root" & File.ownerGroup "/var/www/root" (User "www-data") (Group "pubs") & File.mode "/var/www/root/" 0O0770 -- web - git & File.dirExists "/var/www/git.rs" & File.ownerGroup "/var/www/git.rs" (User "www-data") (Group "pubs") & File.mode "/var/www/git.rs/" 0O0770 -- www-data config & User.hasGroup (User "www-data") (Group "pubs") -- root config & File.hasContent "/root/.tmux.conf" tmuxConf & Ssh.authorizedKey (User "root") sCanonicalSshPubKey -- g config & User.accountFor (User "g") & User.hasGroup (User "g") (Group "pubs") & Ssh.authorizedKey (User "g") sCanonicalSshPubKey & Ssh.authorizedKey (User "g") sAraSshPubKey --- c dir config & File.dirExists "/home/g/c" & File.ownerGroup "/home/g/c" (User "g") (Group "pubs") & File.mode "/home/g/c" 0O0770 -- s config & User.accountFor (User "s") & User.hasPassword (User "s") & Sudo.enabledFor (User "s") & Ssh.authorizedKey (User "s") sCanonicalSshPubKey -- git-daemon -- & rsGitDaemonDefaults `onChange` Service.restarted "git-daemon" -- opendkim -- & File.dirExists "/etc/opendkim" -- & File.containsLines "/etc/opendkim.conf" ricketyspaceNetOpenDkimConf -- & File.containsLines "/etc/opendkim/KeyTable" ricketyspaceNetOpenDkimKeyTable -- & File.containsLines "/etc/opendkim/SigningTable" ricketyspaceNetOpenDkimSigningTable -- & File.containsLines "/etc/opendkim/TrustedHosts" ricketyspaceNetOpenDkimTrustedHosts -- & File.dirExists "/etc/dkimkeys/ricketyspace.net" -- & File.ownerGroup "/etc/dkimkeys/ricketyspace.net" (User "opendkim") (Group "opendkim") -- & File.hasPrivContent "/etc/dkimkeys/ricketyspace.net/mail.private" (Context "ricketyspace.net") -- & File.ownerGroup "/etc/dkimkeys/ricketyspace.net/mail.private" -- (User "opendkim") (Group "opendkim") -- postfix & rsMailAliases & rsPostfixHeaderChecks & rsPostfixRBLOverride & File.hasContent "/etc/postfix/main.cf" rsPostfixMainCf & File.hasContent "/etc/postfix/master.cf" rsPostfixMasterCf `onChange` Postfix.reloaded -- configure lyra lyra :: Host lyra = host "lyra.ricketyspace.net" $props & osDebian (Stable "stretch") X86_64 & Locale.available "en_US.UTF-8" & ipv4 "159.89.229.91" & ipv6 "2604:a880:400:d1::77f:8001" & alias "ricketyspace.net" & alias "git.ricketyspace.net" & alias "dingy.space" & alias "nfsw.dingy.space" & File.hasContent "/etc/motd" (["At lyra."]) -- apt & Apt.stdSourcesList & Apt.unattendedUpgrades & Apt.safeUpgrade & Apt.installed ["git", "etckeeper" , "htop", "sudo", "zsh", "tmux" , "emacs", "rsync", "git-annex" , "cgit", "fcgiwrap", "git-daemon-sysvinit" , "bind9", "bind9-doc" , "opendkim", "opendkim-tools", "postfix", "postfix-doc" , "postfix-policyd-spf-python", "postfix-pcre" , "dovecot-imapd", "python3-markdown", "python3-docutils" , "pandoc", "cvs" , "libgit2-dev", "musl-dev", "make" ] -- sshd & Ssh.passwordAuthentication False -- system & Fail2Ban.installed --- nginx & Apt.removed ["apache2"] & Nginx.installed & Nginx.siteEnabled "ricketyspace.net" ricketyspaceNetNginx & Nginx.siteEnabled "git.ricketyspace.net" ricketyspaceNetGitNginx & Nginx.siteEnabled "dingy.space" dingySpaceNginx & Nginx.siteEnabled "nfsw.dingy.space" nfswDingySpaceNginx & ricketyspaceNetDhparamPem & ricketyspaceNetCert `onChange` Nginx.restarted & ricketyspaceNetCertKey & ricketyspaceNetGitCert & ricketyspaceNetGitCertKey & ricketyspaceNetLyraCert & ricketyspaceNetLyraCertKey & dingySpaceCert & dingySpaceCertKey & nfswDingySpaceCert & nfswDingySpaceCertKey -- git-daemon & rsGitDaemonDefaults `onChange` Service.restarted "git-daemon" -- opendkim & File.dirExists "/etc/opendkim" & File.containsLines "/etc/opendkim.conf" ricketyspaceNetOpenDkimConf & File.containsLines "/etc/opendkim/KeyTable" ricketyspaceNetOpenDkimKeyTable & File.containsLines "/etc/opendkim/SigningTable" ricketyspaceNetOpenDkimSigningTable & File.containsLines "/etc/opendkim/TrustedHosts" ricketyspaceNetOpenDkimTrustedHosts --- opendkim for ricketyspace.net & File.dirExists "/etc/dkimkeys/ricketyspace.net" & File.ownerGroup "/etc/dkimkeys/ricketyspace.net" (User "opendkim") (Group "opendkim") & File.hasPrivContent "/etc/dkimkeys/ricketyspace.net/mail.private" (Context "ricketyspace.net") & File.ownerGroup "/etc/dkimkeys/ricketyspace.net/mail.private" (User "opendkim") (Group "opendkim") --- opendkim for dingy.space & File.dirExists "/etc/dkimkeys/dingy.space" & File.ownerGroup "/etc/dkimkeys/dingy.space" (User "opendkim") (Group "opendkim") & File.hasPrivContent "/etc/dkimkeys/dingy.space/mail.private" (Context "dingy.space") & File.ownerGroup "/etc/dkimkeys/dingy.space/mail.private" (User "opendkim") (Group "opendkim") -- postfix & rsMailAliases & rsPostfixHeaderChecks & rsPostfixRBLOverride & File.hasContent "/etc/postfix/main.cf" rsPostfixMainCf & File.hasContent "/etc/postfix/master.cf" rsPostfixMasterCf `onChange` Postfix.reloaded & File.dirExists "/etc/postfix/virtual" & rsPostfixVirtualAddresses & rsPostfixVirtualDomains -- dovecot & File.hasContent "/etc/dovecot/dovecot.conf" rsDovecotConf `onChange` Service.restarted "dovecot" -- bind & Dns.primary publicHosts "ricketyspace.net" (Dns.mkSOA "lyra.ricketyspace.net" 20180129) [ (RootDomain, NS $ RelDomain "lyra") , (RootDomain, NS $ AbsDomain "ns6.gandi.net") , (RootDomain, MX 0 $ AbsDomain "lyra.ricketyspace.net") , (RootDomain, TXT "v=spf1 mx -all") , (RelDomain "_dmarc", TXT "v=DMARC1; p=none; rua=mailto:root@ricketyspace.net") , (RelDomain "mail._domainkey", TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6ClUrJTSt/UISOTEoZy36SfCjuyuajJVGEzYrhuysn2CA3MNt6y3dsHrjalA04Bix02KySMVEHcbScsd54MHhvk364pOkapuAEFIAmvY9SiZGRWsKMK5tgq/aSgH6xFg6M1CupV4QHWFgk193juiEdnB8uwXKTxOdKP/P/xbU3h98MFvXmNzT8sEr5VMZHiTdzqcxCLLfhx27iwjFJh4td6y+0n5YO/M2zf3n9ikXIof/dw4lA5Xo2icI3G88LMl9Tk4vcY0UVXXXulKmrnrn96Nyow0zU31kB/NUb1HbOxaVLz7KJThS+U9NV/66vZ5blwg7aExJXkPfVEtLTca+wIDAQAB") ] & Dns.primary publicHosts "dingy.space" (Dns.mkSOA "lyra.ricketyspace.net" 20191028) [ (RootDomain, NS $ AbsDomain "lyra.ricketyspace.net") , (RootDomain, NS $ AbsDomain "ns6.gandi.net") , (RootDomain, MX 0 $ AbsDomain "lyra.ricketyspace.net") , (RootDomain, TXT "v=spf1 mx -all") , (RelDomain "_dmarc", TXT "v=DMARC1; p=reject; rua=mailto:root@dingy.space") , (RelDomain "mail._domainkey", TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyxnjDmXyu4Z+RKCDobnebr9Sp+w20Dmn7KFhjgVtKGirQGnemMZTxlXrO+5Ro8T0Ecq+D472EKxQbXPUr5GG7zxIeqldjU3kOChjAoOE8TUsR9pxShdp2qJylGdqvZqPTMApbzKJPXJC8j7yBA9DspLyaPluj50o8XqmbrWkZaZ4/+05E3MfjqbTJsqr0yDl/3/KoB4Qut3LqTCWrpzvGG4Ixu0wUz5FLPq6U6m7xiEnDMtTMnRDuz2XLcNtQXwHtxrkB9TdViDPA//FQONTtnXtaQjwuEh3FMScElkcYAl3tZr+ZRfgzZanH2YIDf80Og0ZQZkD06i1HQxWrM4SQwIDAQAB") ] -- crons & stagitGenCron -- web & Group.exists (Group "pubs") Nothing -- web - root & File.dirExists "/var/www/root" & File.ownerGroup "/var/www/root" (User "www-data") (Group "pubs") & File.mode "/var/www/root/" 0O0770 -- web - git & File.dirExists "/var/www/git.rs" & File.ownerGroup "/var/www/git.rs" (User "www-data") (Group "pubs") & File.mode "/var/www/git.rs/" 0O0770 -- root config & Ssh.authorizedKey (User "root") sCanonicalSshPubKey & File.hasContent "/root/.tmux.conf" tmuxConf -- www-data config & User.hasGroup (User "www-data") (Group "pubs") -- gitdaemon config & User.hasGroup (User "gitdaemon") (Group "pubs") -- w config & User.accountFor (User "w") & User.hasGroup (User "w") (Group "pubs") & Ssh.authorizedKey (User "w") sCanonicalSshPubKey -- g config & User.accountFor (User "g") & User.hasGroup (User "g") (Group "pubs") & Ssh.authorizedKey (User "g") sCanonicalSshPubKey & Ssh.authorizedKey (User "g") sAraSshPubKey -- c dir config & File.dirExists "/home/g/c" & File.ownerGroup "/home/g/c" (User "g") (Group "pubs") & File.mode "/home/g/c" 0O0770 -- s config & User.accountFor (User "s") & User.hasPassword (User "s") & Sudo.enabledFor (User "s") & Ssh.authorizedKey (User "s") sCanonicalSshPubKey & Ssh.authorizedKey (User "s") sAraSshPubKey & Ssh.userKeyAt (Just "/home/s/.ssh/id_rsa") (User "s") hostContext (SshRsa, sLyraSshPubKey) vela :: Host vela = host "vela.dingy.space" $props & ipv4 "45.77.145.168" --- nginx ricketyspaceNetNginx :: [String] ricketyspaceNetNginx = [ "# Adapted from https://gist.github.com/konklone/6532544" , "" , "server {" , " listen 80;" , " listen [::]:80;" , " listen 443 ssl http2;" , " listen [::]:443 ssl http2;" , " server_name lyra.ricketyspace.net;" , " return 301 https://ricketyspace.net;" , "" , " ssl_certificate /etc/ssl/certs/lyra.rs.net.chained.le.pem;" , " ssl_certificate_key /etc/ssl/private/lyra.rs.net.d.le.key;" , "}" , "" , "server {" , " listen 80;" , " listen [::]:80;" , " server_name ricketyspace.net;" , " return 301 https://$host$request_uri;" , "}" , "" , "# The 'spdy' at the end of the listen command below turns on SPDY support." , "" , "server {" , " listen 443 ssl http2;" , " listen [::]:443 ssl http2;" , " server_name ricketyspace.net;" , "" , " root /var/www/root;" , " error_page 404 /404.html;" , " error_page 403 /403.html;" , " default_type text/plain;" , "" , " rewrite /gpg.txt /pgp/ permanent;" , "" , " location /git-difme/releases/ {" , " autoindex on;" , " }" , "" , " location /nsfw/ {" , " autoindex on;" , " }" , "" , " location /nfsw/ {" , " autoindex on;" , " }" , "" , " location /tmp/x200/ {" , " autoindex on;" , " }" , "" , " # Path to certificate and private key." , " # The .crt may omit the root CA cert, if it's a standard CA that ships with clients." , " ssl_certificate /etc/ssl/certs/rs.net.chained.le.pem;" , " ssl_certificate_key /etc/ssl/private/rs.net.d.le.key;" , "" , " add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';" , "" , " ssl_prefer_server_ciphers on;" , " ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';" , "" , " ssl_protocols TLSv1.2 TLSv1.1 TLSv1;" , "" , " # as recommended by http://nginx.org/en/docs/http/configuring_https_servers.html" , " ssl_session_cache shared:SSL:10m;" , " ssl_session_timeout 10m;" , " keepalive_timeout 70;" , "" , " # nginx 1.5.9+ ONLY" , " ssl_buffer_size 1400; " , "" , " #" , " # Generated by OpenSSL with the following command:" , " # openssl dhparam -outform pem -out dhparam2048.pem 2048" , " ssl_dhparam /etc/ssl/certs/dhparam4096.pem;" , "}" ] ricketyspaceNetGitNginx :: [String] ricketyspaceNetGitNginx = [ "# Adapted from https://gist.github.com/konklone/6532544" , "" , "server {" , " listen 80;" , " listen [::]:80;" , " server_name git.ricketyspace.net;" , " return 301 https://$host$request_uri;" , "}" , "" , "server {" , " listen 443 ssl http2;" , " listen [::]:443 ssl http2;" , " server_name git.ricketyspace.net;" , "" , " access_log /var/log/nginx/git-access.log;" , " error_log /var/log/nginx/git-error.log;" , "" , "" , " root /var/www/git.rs/html;" , " error_page 404 /404.html;" , " error_page 403 /403.html;" , " default_type text/plain;" , "" , " location ~ /((style|logo|favicon)\\.(css|png|ico))$ {" , " alias /var/www/git.rs/$1;" , " }" , "" , " rewrite ^(.*)(tree|plain)/(.*)$ $1file/$3.html permanent;" , "" , " # Path to certificate and private key." , " # The .crt may omit the root CA cert, if it's a standard CA that ships with clients." , " ssl_certificate /etc/ssl/certs/git.rs.net.chained.le.pem;" , " ssl_certificate_key /etc/ssl/private/git.rs.net.d.le.key;" , "" , " add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';" , "" , " ssl_prefer_server_ciphers on;" , " ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';" , "" , " ssl_protocols TLSv1.2 TLSv1.1 TLSv1;" , "" , " # as recommended by http://nginx.org/en/docs/http/configuring_https_servers.html" , " ssl_session_cache shared:SSL:10m;" , " ssl_session_timeout 10m;" , " keepalive_timeout 70;" , "" , " # nginx 1.5.9+ ONLY" , " ssl_buffer_size 1400;" , "" , " #" , " # Generated by OpenSSL with the following command:" , " # openssl dhparam -outform pem -out dhparam2048.pem 2048" , " ssl_dhparam /etc/ssl/certs/dhparam4096.pem;" , "}" ] dingySpaceNginx :: [String] dingySpaceNginx = [ "# Adapted from https://gist.github.com/konklone/6532544" , "" , "server {" , " listen 80;" , " listen [::]:80;" , " server_name dingy.space;" , " return 301 https://$host$request_uri;" , "}" , "" , "server {" , " listen 443 ssl http2;" , " listen [::]:443 ssl http2;" , " server_name dingy.space;" , "" , " access_log /var/log/nginx/dingy.space.log;" , " error_log /var/log/nginx/dingy.space.log;" , "" , "" , " root /var/www/dingy.space;" , " error_page 404 /404.html;" , " error_page 403 /403.html;" , " default_type text/plain;" , "" , " # Path to certificate and private key." , " # The .crt may omit the root CA cert, if it's a standard CA that ships with clients." , " ssl_certificate /etc/ssl/certs/ds.chained.le.pem;" , " ssl_certificate_key /etc/ssl/private/ds.d.le.key;" , "" , " add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';" , "" , " ssl_prefer_server_ciphers on;" , " ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';" , "" , " ssl_protocols TLSv1.2 TLSv1.1 TLSv1;" , "" , " # as recommended by http://nginx.org/en/docs/http/configuring_https_servers.html" , " ssl_session_cache shared:SSL:10m;" , " ssl_session_timeout 10m;" , " keepalive_timeout 70;" , "" , " # nginx 1.5.9+ ONLY" , " ssl_buffer_size 1400;" , "" , " #" , " # Generated by OpenSSL with the following command:" , " # openssl dhparam -outform pem -out dhparam2048.pem 2048" , " ssl_dhparam /etc/ssl/certs/dhparam4096.pem;" , "}" ] nfswDingySpaceNginx :: [String] nfswDingySpaceNginx = [ "# Adapted from https://gist.github.com/konklone/6532544" , "" , "server {" , " listen 80;" , " listen [::]:80;" , " server_name dingy.space;" , " return 301 https://$host$request_uri;" , "}" , "" , "server {" , " listen 443 ssl http2;" , " listen [::]:443 ssl http2;" , " server_name nfsw.dingy.space;" , "" , " access_log /var/log/nginx/nfsw.dingy.space.log;" , " error_log /var/log/nginx/nfsw.dingy.space.log;" , "" , "" , " root /var/www/nfsw.dingy.space;" , " error_page 404 /404.html;" , " error_page 403 /403.html;" , " default_type text/plain;" , "" , " # Path to certificate and private key." , " # The .crt may omit the root CA cert, if it's a standard CA that ships with clients." , " ssl_certificate /etc/ssl/certs/nfsw.ds.chained.le.pem;" , " ssl_certificate_key /etc/ssl/private/nfsw.ds.d.le.key;" , "" , " add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';" , "" , " ssl_prefer_server_ciphers on;" , " ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';" , "" , " ssl_protocols TLSv1.2 TLSv1.1 TLSv1;" , "" , " # as recommended by http://nginx.org/en/docs/http/configuring_https_servers.html" , " ssl_session_cache shared:SSL:10m;" , " ssl_session_timeout 10m;" , " keepalive_timeout 70;" , "" , " # nginx 1.5.9+ ONLY" , " ssl_buffer_size 1400;" , "" , " #" , " # Generated by OpenSSL with the following command:" , " # openssl dhparam -outform pem -out dhparam2048.pem 2048" , " ssl_dhparam /etc/ssl/certs/dhparam4096.pem;" , "}" ] --- certs ricketyspaceNetDhparamPem :: Property (HasInfo + UnixLike) ricketyspaceNetDhparamPem = File.hasPrivContent "/etc/ssl/certs/dhparam4096.pem" (Context "ricketyspace.net") ricketyspaceNetCert :: Property (HasInfo + UnixLike) ricketyspaceNetCert = File.hasPrivContent cert (Context "ricketyspace.net") `onChange` File.mode cert 0O0644 where cert = "/etc/ssl/certs/rs.net.chained.le.pem" ricketyspaceNetCertKey :: Property (HasInfo + UnixLike) ricketyspaceNetCertKey = File.hasPrivContent "/etc/ssl/private/rs.net.d.le.key" (Context "ricketyspace.net") ricketyspaceNetGitCert :: Property (HasInfo + UnixLike) ricketyspaceNetGitCert = File.hasPrivContent "/etc/ssl/certs/git.rs.net.chained.le.pem" (Context "git.ricketyspace.net") ricketyspaceNetGitCertKey :: Property (HasInfo + UnixLike) ricketyspaceNetGitCertKey = File.hasPrivContent "/etc/ssl/private/git.rs.net.d.le.key" (Context "git.ricketyspace.net") ricketyspaceNetLyraCert :: Property (HasInfo + UnixLike) ricketyspaceNetLyraCert = File.hasPrivContent cert (Context "lyra.ricketyspace.net") `onChange` File.mode cert 0O0644 where cert = "/etc/ssl/certs/lyra.rs.net.chained.le.pem" ricketyspaceNetLyraCertKey :: Property (HasInfo + UnixLike) ricketyspaceNetLyraCertKey = File.hasPrivContent "/etc/ssl/private/lyra.rs.net.d.le.key" (Context "lyra.ricketyspace.net") dingySpaceCert :: Property (HasInfo + UnixLike) dingySpaceCert = File.hasPrivContent cert (Context "dingy.space") `onChange` File.mode cert 0O0644 where cert = "/etc/ssl/certs/ds.chained.le.pem" dingySpaceCertKey :: Property (HasInfo + UnixLike) dingySpaceCertKey = File.hasPrivContent "/etc/ssl/private/ds.d.le.key" (Context "dingy.space") nfswDingySpaceCert :: Property (HasInfo + UnixLike) nfswDingySpaceCert = File.hasPrivContent cert (Context "nfsw.dingy.space") `onChange` File.mode cert 0O0644 where cert = "/etc/ssl/certs/nfsw.ds.chained.le.pem" nfswDingySpaceCertKey :: Property (HasInfo + UnixLike) nfswDingySpaceCertKey = File.hasPrivContent "/etc/ssl/private/nfsw.ds.d.le.key" (Context "nfsw.dingy.space") --- dkim ricketyspaceNetOpenDkimConf :: [File.Line] ricketyspaceNetOpenDkimConf = [ "KeyTable /etc/opendkim/KeyTable" , "SigningTable /etc/opendkim/SigningTable" , "ExternalIgnoreList /etc/opendkim/TrustedHosts" , "InternalHosts /etc/opendkim/TrustedHosts" , "LogWhy yes" , "Socket inet:12345@localhost" ] ricketyspaceNetOpenDkimKeyTable :: [File.Line] ricketyspaceNetOpenDkimKeyTable = [ "mail._domainkey.ricketyspace.net ricketyspace.net:mail:/etc/dkimkeys/ricketyspace.net/mail.private" , "mail._domainkey.dingy.space dingy.space:mail:/etc/dkimkeys/dingy.space/mail.private" ] ricketyspaceNetOpenDkimSigningTable :: [File.Line] ricketyspaceNetOpenDkimSigningTable = [ "ricketyspace.net mail._domainkey.ricketyspace.net" , "dingy.space mail._domainkey.dingy.space" ] ricketyspaceNetOpenDkimTrustedHosts :: [File.Line] ricketyspaceNetOpenDkimTrustedHosts = [ "127.0.0.1" , "localhost" , "ricketyspace.net" , "dingy.space" ] -- git-daemon rsGitDaemonDefaults :: Property UnixLike rsGitDaemonDefaults = File.hasContent "/etc/default/git-daemon" [ "# Defaults for git-daemon initscript" , "# sourced by /etc/init.d/git-daemon" , "" , "#" , "# This is a POSIX shell fragment" , "#" , "" , "GIT_DAEMON_ENABLE=true" , "GIT_DAEMON_USER=gitdaemon" , "GIT_DAEMON_BASE_PATH=/home/g/c" , "GIT_DAEMON_DIRECTORY=/home/g/c" , "" , "# Additional options that are passed to the Daemon." , "GIT_DAEMON_OPTIONS=\"\"" ] --- postfix rsPostfixHeaderChecks :: Property DebianLike rsPostfixHeaderChecks = Postfix.mappedFile "/etc/postfix/header_checks" (flip File.hasContent [ "/^Received:.*with ESMTPSA/ IGNORE" , "/^X-Originating-IP:/ IGNORE" ]) `describe` "postfix header checks configured" `onChange` Postfix.reloaded rsPostfixRBLOverride :: Property (HasInfo + UnixLike) rsPostfixRBLOverride = File.hasPrivContent rblOFile (Context "ricketyspace.net") `onChange` na where na :: Property UnixLike na = scriptProperty ["postmap " ++ rblOFile] `assume` MadeChange rblOFile = "/etc/postfix/rbl_override" rsPostfixMainCf :: [File.Line] rsPostfixMainCf = [ "smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)" , "biff = no" , "" , "append_dot_mydomain = no" , "compatibility_level = 2" , "" , "readme_directory = /usr/share/doc/postfix" , "html_directory = /usr/share/doc/postfix/html" , "" , "mime_header_checks = regexp:/etc/postfix/header_checks" , "header_checks = regexp:/etc/postfix/header_checks" , "" , "smtpd_tls_cert_file=/etc/ssl/certs/lyra.rs.net.chained.le.pem" , "smtpd_tls_key_file=/etc/ssl/private/lyra.rs.net.d.le.key" , "smtpd_use_tls=yes" , "smtpd_tls_auth_only=yes" , "smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache" , "smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache" , "" , "smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination" , "myhostname = lyra.ricketyspace.net" , "alias_maps = hash:/etc/aliases" , "alias_database = hash:/etc/aliases" , "myorigin = ricketyspace.net" , "mydestination = ricketyspace.net, localhost, /etc/postfix/virtual/domains" , "virtual_maps = hash:/etc/postfix/virtual/addresses" , "relayhost =" , "mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128" , "mailbox_command =" , "mailbox_size_limit = 0" , "recipient_delimiter = +" , "inet_interfaces = all" , "inet_protocols = all" , "relay_domains = ricketyspace.net" , "" , "smtpd_recipient_restrictions = permit_sasl_authenticated," , " reject_invalid_hostname," , " reject_unknown_recipient_domain," , " reject_unauth_destination," , " reject_rbl_client sbl.spamhaus.org," , " check_policy_service unix:private/policy-spf" , " permit" , "" , "smtpd_helo_restrictions = check_helo_access hash:/etc/postfix/rbl_override," , " reject_invalid_helo_hostname," , " reject_non_fqdn_helo_hostname" , "" , "smtpd_client_restrictions = reject_rbl_client dnsbl.sorbs.net" , "" , "home_mailbox = Maildir/" , "" , "# dovecot" , "smtpd_sasl_type = dovecot" , "smtpd_sasl_path = private/auth" , "smtpd_sasl_auth_enable = yes" , "" , "# dkim" , "milter_default_action = accept" , "milter_protocol = 6" , "smtpd_milters = inet:localhost:12345" , "non_smtpd_milters = inet:localhost:12345" , "" , "# spf" , "policy-spf_time_limit = 3600s" , "" , "# map mail username/password to user's unix user/passwd." , "local_recipient_maps = proxy:unix:passwd.byname $alias_maps" ] rsPostfixMasterCf :: [File.Line] rsPostfixMasterCf = [ "# Do not forget to execute `postfix reload` after editing this file." , "#" , "# ==========================================================================" , "# service type private unpriv chroot wakeup maxproc command + args" , "# (yes) (yes) (no) (never) (100)" , "# ==========================================================================" , "smtp inet n - y - - smtpd" , "submission inet n - y - - smtpd" , " -o syslog_name=postfix/submission" , " -o smtpd_tls_security_level=encrypt" , " -o smtpd_sasl_auth_enable=yes" , " -o smtpd_client_restrictions=permit_sasl_authenticated,reject" , " -o milter_macro_daemon_name=ORIGINATING" , "smtps inet n - y - - smtpd -v" , " -o syslog_name=postfix/smtps" , " -o smtpd_tls_wrappermode=yes" , " -o smtpd_sasl_auth_enable=yes" , " -o smtpd_client_restrictions=permit_sasl_authenticated,reject" , " -o milter_macro_daemon_name=ORIGINATING" , "pickup unix n - y 60 1 pickup" , "cleanup unix n - y - 0 cleanup" , "qmgr unix n - n 300 1 qmgr" , "tlsmgr unix - - y 1000? 1 tlsmgr" , "rewrite unix - - y - - trivial-rewrite" , "bounce unix - - y - 0 bounce" , "defer unix - - y - 0 bounce" , "trace unix - - y - 0 bounce" , "verify unix - - y - 1 verify" , "flush unix n - y 1000? 0 flush" , "proxymap unix - - n - - proxymap" , "proxywrite unix - - n - 1 proxymap" , "smtp unix - - y - - smtp" , "relay unix - - y - - smtp" , "showq unix n - y - - showq" , "error unix - - y - - error" , "retry unix - - y - - error" , "discard unix - - y - - discard" , "local unix - n n - - local" , "virtual unix - n n - - virtual" , "lmtp unix - - y - - lmtp" , "anvil unix - - y - 1 anvil" , "scache unix - - y - 1 scache" , "#" , "# ====================================================================" , "# Interfaces to non-Postfix software." , "#" , "maildrop unix - n n - - pipe" , " flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}" , "#" , "# See the Postfix UUCP_README file for configuration details." , "#" , "uucp unix - n n - - pipe" , " flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)" , "#" , "# Other external delivery methods." , "#" , "ifmail unix - n n - - pipe" , " flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)" , "bsmtp unix - n n - - pipe" , " flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient" , "scalemail-backend unix - n n - 2 pipe" , " flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}" , "mailman unix - n n - - pipe" , " flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py" , " ${nexthop} ${user}" , "" , "# For Dovecot." , "dovecot unix - n n - - pipe" , " flags=DRhu user=email:email argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}" , "" , "# SPF snafu (from https://help.ubuntu.com/community/Postfix/SPF)" , "policy-spf unix - n n - - spawn" , " user=nobody argv=/usr/bin/policyd-spf" ] rsPostfixVirtualAddresses :: Property (HasInfo + UnixLike) rsPostfixVirtualAddresses = File.hasPrivContent vaFile (Context "ricketyspace.net") `onChange` na where na :: Property UnixLike na = scriptProperty ["postmap " ++ vaFile] `assume` MadeChange vaFile = "/etc/postfix/virtual/addresses" rsPostfixVirtualDomains :: Property (HasInfo + UnixLike) rsPostfixVirtualDomains = File.hasPrivContent vdFile (Context "ricketyspace.net") where vdFile = "/etc/postfix/virtual/domains" rsDovecotConf :: [File.Line] rsDovecotConf = [ "mail_privileged_group = mail" , "namespace inbox {" , " inbox = yes" , " location =" , " mailbox Drafts {" , " special_use = \\Drafts" , " }" , " mailbox Junk {" , " special_use = \\Junk" , " }" , " mailbox Sent {" , " special_use = \\Sent" , " }" , " mailbox \"Sent Messages\" {" , " special_use = \\Sent" , " }" , " mailbox Trash {" , " special_use = \\Trash" , " }" , " prefix =" , "}" , "passdb {" , " driver = pam" , "}" , "protocols = \" imap\"" , "service auth {" , " unix_listener /var/spool/postfix/private/auth {" , " group = postfix" , " mode = 0666" , " user = postfix" , " }" , "}" , "ssl = required" , "ssl_cert = </etc/ssl/certs/lyra.rs.net.chained.le.pem" , "ssl_key = </etc/ssl/private/lyra.rs.net.d.le.key" , "userdb {" , " driver = passwd" , "}" ] rsMailAliases :: Property (HasInfo + UnixLike) rsMailAliases = File.hasPrivContent "/etc/aliases" (Context "ricketyspace.net") `onChange` na where na :: Property UnixLike na = scriptProperty ["cd /etc", "newaliases"] `assume` MadeChange -- crons stagitGenCron :: Property DebianLike stagitGenCron = Cron.job "stagit-gen" (Cron.Times "* */1 * * *") (User "www-data") "/var/www/git.rs" cmd where cmd = "make" -- common --- tmux conf tmuxConf :: [File.Line] tmuxConf = [ "set -g prefix C-a" , "unbind C-b" , "bind C-a send-prefix" , "set -g status-style bg=white" , "set -g status-right ''" ] --- Docker CE dockerCEInstalled :: Property DebianLike dockerCEInstalled = Apt.installed ["docker-ce"] `requires` Apt.setSourcesListD [ "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" ] "docker-ce" `requires` Apt.trustsKey dockerCEKey dockerCEKey :: Apt.AptKey dockerCEKey = Apt.AptKey "docker-ce" $ unlines [ "-----BEGIN PGP PUBLIC KEY BLOCK-----" , "" , "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" , "YT90qFF93M3v01BbxP+EIY2/9tiIPbrd" , "=0YYh" , "-----END PGP PUBLIC KEY BLOCK-----" ] m31 :: [Host] -- Andromeda. Computers outside s' galaxy. m31 = [ host "ns6.gandi.net" $ props & ipv4 "217.70.177.40" ]