From 4632280e2dcadfcb2491193de3583bcb6c747e58 Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Sun, 18 Aug 2024 17:39:33 -0300 Subject: git mv src/infrastructure/guix/ src/ --- src/guix/channels.scm | 12 + src/guix/packages.scm | 72 +++++ src/guix/system.scm | 504 +++++++++++++++++++++++++++++++++++ src/infrastructure/guix/channels.scm | 12 - src/infrastructure/guix/packages.scm | 72 ----- src/infrastructure/guix/system.scm | 504 ----------------------------------- 6 files changed, 588 insertions(+), 588 deletions(-) create mode 100644 src/guix/channels.scm create mode 100644 src/guix/packages.scm create mode 100644 src/guix/system.scm delete mode 100644 src/infrastructure/guix/channels.scm delete mode 100644 src/infrastructure/guix/packages.scm delete mode 100644 src/infrastructure/guix/system.scm (limited to 'src') diff --git a/src/guix/channels.scm b/src/guix/channels.scm new file mode 100644 index 0000000..697eb4f --- /dev/null +++ b/src/guix/channels.scm @@ -0,0 +1,12 @@ +(append + (list + (channel + (name 'EuAndreh) + (url "git://euandre.org/packages") + (branch "main") + (introduction + (make-channel-introduction + "d749e053e6db365069cb9b2ef47a78b06f9e7361" + (openpgp-fingerprint + "5BDA E9B8 B2F6 C6BC BB0D 6CE5 81F9 0EC3 CD35 6060"))))) + %default-channels) diff --git a/src/guix/packages.scm b/src/guix/packages.scm new file mode 100644 index 0000000..7fe4e93 --- /dev/null +++ b/src/guix/packages.scm @@ -0,0 +1,72 @@ +(define-module (packages) + #:use-module ((ice-9 popen) #:prefix popen:) + #:use-module ((ice-9 rdelim) #:prefix rdelim:) + #:use-module ((org euandre queue) #:prefix queue:) + #:use-module ((org euandre packages) #:prefix org-euandre:) + #:use-module ((xyz euandreh heredoc) #:prefix heredoc:) + #:use-module (gnu) + #:use-module (guix build utils) + #:use-module (guix build-system gnu) + #:use-module (guix packages)) +(use-package-modules + check + finance + groff + haskell-apps + haskell-xyz + imagemagick + python + python-web + python-xyz + version-control) +(heredoc:enable-syntax) + + +(define working-dir + (if (directory-exists? "/opt/deploy/current") + "/opt/deploy/current" + (canonicalize-path "."))) + +(define version-cmd #"- + if grep -q deployer /etc/passwd && [ -e /opt/deploy/current ]; then + sudo -u deployer git -C /opt/deploy/current rev-parse HEAD + else + git rev-parse HEAD + fi + "#) + +(define repo-version + (let* ((port (popen:open-input-pipe version-cmd)) + (v (rdelim:read-line port))) + (popen:close-pipe port) + v)) + +(define-public server + (package + (name "server") + (version repo-version) + (source + (local-file working-dir #:recursive? #t)) + (build-system gnu-build-system) + (arguments + (list + #:make-flags #~(list (string-append "PREFIX=" %output)) + #:phases + #~(modify-phases %standard-phases + (delete 'configure) + (add-after 'install 'installcheck + (lambda* (#:key make-flags #:allow-other-keys) + (define dash-j (format #f "-j~a" (parallel-job-count))) + (apply invoke "make" dash-j "installcheck" make-flags)))))) + (native-inputs + (list + git-minimal + pandoc + shellcheck)) + (home-page #f) + (synopsis #f) + (description #f) + (license #f))) + +(list + server) diff --git a/src/guix/system.scm b/src/guix/system.scm new file mode 100644 index 0000000..1690f31 --- /dev/null +++ b/src/guix/system.scm @@ -0,0 +1,504 @@ +(use-modules + ((ice-9 textual-ports) #:prefix textual-ports:) + ((srfi srfi-1) #:prefix s1:) + ((xyz euandreh heredoc) #:prefix heredoc:) + ((org euandre queue) #:prefix queue:) + (gnu) + (guix build-system trivial) + (guix build utils) + (guix packages)) +(use-package-modules + admin + ssh + version-control) +(use-service-modules + admin + certbot + cgit + dns + mail + mcron + networking + security + ssh + version-control + vpn + web) +(heredoc:enable-syntax) + + +(define ipv4 "216.238.68.100") +(define ipv6 "2001:19f0:b400:1f0c:5400:04ff:fe35:8c89") +(define tld "euandre.org") + +(define users + '(("andreh" "EuAndreh" ("wheel" "become-deployer" "become-secrets-keeper")))) + + +(define working-dir + (if (directory-exists? "/opt/deploy/current") + "/opt/deploy/current" + (canonicalize-path "."))) + +(add-to-load-path + (string-append working-dir "/src/infrastructure/guix")) +(use-modules + ((packages) #:prefix packages:)) + + +(define (str . rest) + (apply string-append rest)) + +(define (fmt . rest) + (apply format #f rest)) + +(define (path s) + (str working-dir "/" s)) + +(define (slurp s) + (call-with-input-file + s + textual-ports:get-string-all)) + +(define (file s) + (slurp (path s))) + +(define (script name content) + (package + (name name) + (version "latest") + (source #f) + (build-system trivial-build-system) + (arguments + (list + #:modules '((guix build utils)) + #:builder + #~(begin + (use-modules (guix build utils)) + (let* ((bin (string-append %output "/bin")) + (prog (string-append bin "/" #$name))) + (mkdir-p bin) + (call-with-output-file prog + (lambda (port) + (display #$content port))) + (chmod prog #o755))))) + (home-page #f) + (synopsis #f) + (description #f) + (license #f))) + +(define user-accounts + (map (lambda (user) + (let ((name (s1:first user)) + (comment (s1:second user)) + (groups (s1:third user))) + (user-account + (name name) + (comment comment) + (group "users") + (supplementary-groups groups)))) + users)) + +(define (ssh-file-for user) + (let ((name (s1:first user))) + (path (fmt "src/infrastructure/keys/SSH/~a.pub.txt" name)))) + +(define authorized-keys + (let ((users-with-keys + (map (lambda (user) + `(,@user ,(slurp (ssh-file-for user)))) + (filter (lambda (user) + (file-exists? (ssh-file-for user))) + users)))) + (append + (map (lambda (user) + (let ((name (s1:first user)) + (key (s1:fourth user))) + `(,name ,(plain-file (str name "-id_rsa.pub") + key)))) + users-with-keys) + `(("git" ,@(map (lambda (user) + (let ((name (s1:first user)) + (key (s1:fourth user))) + (plain-file (str name "-git-id_rsa.pub") + key))) + users-with-keys)))))) + + +(define ns (fmt "ns1.~a." tld)) +(define mail (fmt "hostmaster.~a." tld)) +(define dkim-selector "dkimproxyout") +(define dkim-public-key-path "/var/lib/dkimproxyout/public.key") + +(define dkim-name (str dkim-selector "._domainkey")) +(define dkim-public-key + (if (file-exists? dkim-public-key-path) + (string-join (reverse + (cdr + (reverse + (cdr + (string-split (slurp dkim-public-key-path) + #\newline))))) + "") + "stub-public-key-for-building")) + +(define ipv4-reverse-domain + (str + (string-join (reverse + (string-split ipv4 + #\.)) + ".") + ".in-addr.arpa")) + +(define ipv6-reverse-domain + (str + (string-join (reverse + (map (lambda (s) (fmt "~a" s)) + (string->list + (string-delete #\: ipv6)))) + ".") + ".ip6.arpa")) + +(define-zone-entries tld-zone + ("@" "" "IN" "NS" (fmt "ns1.~a." tld)) + ("@" "" "IN" "NS" (fmt "ns2.~a." tld)) + ("ns1" "" "IN" "A" ipv4) + ("ns1" "" "IN" "AAAA" ipv6) + ("ns2" "" "IN" "A" ipv4) + ("ns2" "" "IN" "AAAA" ipv6) + + ("@" "" "IN" "A" ipv4) + ("@" "" "IN" "AAAA" ipv6) + + ("@" "" "IN" "CAA" "0 issue \"letsencrypt.org\"") + ("@" "" "IN" "CAA" "0 issuewild \";\"") + ("@" "" "IN" "CAA" "0 iodef \"mailto:eu@euandre.org\"") + + ("mta-sts" "" "IN" "A" ipv4) + ("mta-sts" "" "IN" "AAAA" ipv6) + ("_mta-sts" "" "IN" "TXT" "\"v=STSv1; id=20230314\"") + ("@" "" "IN" "MX" (fmt "10 ~a." tld)) + ("_dmarc" "" "IN" "TXT" "\"v=DMARC1; p=quarantine\"") + ("@" "" "IN" "TXT" (fmt "\"v=spf1 a:~a -all\"" tld)) + (dkim-name "" "IN" "TXT" (fmt "\"v=DKIM1; k=rsa; t=s; p=~a\"" dkim-public-key))) + +(define-zone-entries ipv4-reverse-domain-zone + ("@" "" "IN" "PTR" (str tld ".")) + ("@" "" "IN" "NS" (fmt "ns1.~a." tld)) + ("@" "" "IN" "NS" (fmt "ns2.~a." tld))) + +(define-zone-entries ipv6-reverse-domain-zone + ("@" "" "IN" "PTR" (str tld ".")) + ("@" "" "IN" "NS" (fmt "ns1.~a." tld)) + ("@" "" "IN" "NS" (fmt "ns2.~a." tld))) + +(define zones + (list + (knot-zone-configuration + (domain tld) + (semantic-checks? #t) + (zone + (zone-file + (origin tld) + (ns ns) + (mail mail) + (entries tld-zone)))) + (knot-zone-configuration + (domain ipv4-reverse-domain) + (semantic-checks? #t) + (zone + (zone-file + (origin ipv4-reverse-domain) + (ns ns) + (mail mail) + (entries ipv4-reverse-domain-zone)))) + (knot-zone-configuration + (domain ipv6-reverse-domain) + (semantic-checks? #t) + (zone + (zone-file + (origin ipv6-reverse-domain) + (ns ns) + (mail mail) + (entries ipv6-reverse-domain-zone)))))) + + +(operating-system + (locale "fr_FR.UTF-8") + (timezone "America/Sao_Paulo") + (host-name tld) + (skeletons + `((".profile" + ,(plain-file "user-profile" + (file "src/infrastructure/config/profile.sh"))))) + (users + (append + (list + (user-account + (name "git") + (group "git") + (system? #t) + (comment "External SSH Git user") + (home-directory "/srv/git") + (create-home-directory? #f) + (shell + (file-append git "/bin/git-shell"))) + (user-account + (name "deployer") + (group "deployer") + (system? #t) + (comment "The account used to run deployment commands") + (home-directory "/var/empty") + (create-home-directory? #f) + (shell + (file-append shadow "/sbin/nologin"))) + (user-account + (name "secrets-keeper") + (group "secrets-keeper") + (system? #t) + (comment "The account used to manage production secrets") + (home-directory "/var/empty") + (create-home-directory? #f) + (shell + (file-append shadow "/sbin/nologin")))) + user-accounts + %base-user-accounts)) + (groups + (append + (list + (user-group + (name "git") + (system? #t)) + (user-group + (name "deployer") + (system? #t)) + (user-group + (name "become-deployer") + (system? #t)) + (user-group + (name "secrets-keeper") + (system? #t)) + (user-group + (name "become-secrets-keeper") + (system? #t))) + %base-groups)) + (sudoers-file + (plain-file "sudoers" #"- + root ALL=(ALL) ALL + %wheel ALL= ALL + %become-deployer ALL=(deployer) NOPASSWD: ALL + %become-secrets-keeper ALL=(secrets-keeper) NOPASSWD: /run/current-system/profile/bin/rsync, /run/current-system/profile/bin/setfacl, /run/current-system/profile/bin/rm + git ALL= NOPASSWD: /run/current-system/profile/bin/reconfigure, /run/current-system/profile/bin/cicd + git ALL=(deployer) NOPASSWD: /run/current-system/profile/bin/rsync, /run/current-system/profile/bin/mkdir + "#)) + (packages + (append + (map (compose list specification->package+output symbol->string) + '(parted + acl + bind:utils + tcpdump + knot:tools + file + git + guile-heredoc + entr + lsof + jq + moreutils + mailutils-sendmail + curl + make + gnupg + borg + rsync + sqlite + strace + rlwrap + trash-cli + tree)) + (list + packages:server + (script "gc" (file "src/infrastructure/scripts/gc.sh")) + (script "cicd" (file "src/infrastructure/scripts/cicd.sh")) + (script "check" (file "src/infrastructure/scripts/check.sh")) + (script "backup" (file "src/infrastructure/scripts/backup.sh")) + (script "deploy" (file "src/infrastructure/scripts/deploy.sh")) + (script "report" (file "src/infrastructure/scripts/report.sh")) + (script "cronjob" (file "src/infrastructure/scripts/cronjob.sh")) + (script "reconfigure" (file "src/infrastructure/scripts/reconfigure.sh"))) + %base-packages)) + (services + (append + (list + (service ntp-service-type) + (service dhcp-client-service-type) + (service knot-service-type + (knot-configuration + (zones zones))) + (service openssh-service-type + (openssh-configuration + (openssh openssh-sans-x) + (password-authentication? #f) + (authorized-keys authorized-keys) + (extra-content #"- + ClientAliveInterval 30 + ClientAliveCountMax 20 + MaxSessions 20 + SetEnv GIT_CONFIG_GLOBAL=/etc/gitconfig + "#))) + (simple-service 'extra-rottlog-rotations rottlog-service-type + (list + (log-rotation + (frequency 'weekly) + (files '("/var/log/cronjobs.log")) + (options '("rotate 52"))))) + (service fail2ban-service-type) + (service mcron-service-type + (mcron-configuration + (jobs + (list + #~(job "0 0 * * *" "cronjob check") + #~(job "0 1 * * *" "cronjob env BORG_REPO=/mnt/backup/borg backup -q cron") + #~(job "0 2 * * *" "cronjob backup -q cron") + #~(job "0 3 * * 0" "cronjob gc") + #~(job "0 4 * * *" "cronjob reconfigure -U"))))) + (service certbot-service-type + (certbot-configuration + (email (str "root@" tld)) + (certificates + (list + (certificate-configuration + (domains (list tld)) + (deploy-hook + (program-file + "nginx-deploy-hook" + #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) + (kill pid SIGHUP))))))))) + (service nginx-service-type + (nginx-configuration + (server-blocks + (list + (nginx-server-configuration + (server-name (list tld)) + (listen '("[::]:443 ssl http2" "443 ssl http2")) + (root "/srv/www") + (ssl-certificate (fmt "/etc/letsencrypt/live/~a/fullchain.pem" tld)) + (ssl-certificate-key (fmt "/etc/letsencrypt/live/~a/privkey.pem" tld)) + (locations + (list + (nginx-location-configuration + (uri "/r/velhinho/") + (body + '(#"- + rewrite /r/velhinho(.*) $1 break; + proxy_pass http://velhinho:4219; + "#))) + (nginx-location-configuration + (uri "/git/static/") + (body + (list + (list "alias " cgit "/share/cgit/;")))) + (nginx-location-configuration + (uri "/git/") + (body + (list + (list "fastcgi_param SCRIPT_FILENAME " cgit "/lib/cgit/cgit.cgi;") + #"- + fastcgi_param PATH_INFO $uri; + fastcgi_param QUERY_STRING $args; + fastcgi_param HTTP_HOST $server_name; + fastcgi_pass localhost:9000; + rewrite /git(.*) $1 break; + "#))))) + (raw-content + '(#"- + ssl_protocols TLSv1.3; + ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH; + ssl_prefer_server_ciphers on; + gzip off; # Disable compression altogether due to BREACH + charset utf-8; + autoindex on; + add_header Strict-Transport-Security 'max-age=31536000; includeSubdomains' always; + "#))))))) + (service cgit-service-type queue:cgit-pre-configuration) + (simple-service 'extra-etc-file etc-service-type + `(("rc" ,(plain-file "rc.sh" (file "src/infrastructure/config/rc.sh"))) + ("known_hosts" ,(plain-file "known_hosts" (file "src/infrastructure/config/known_hosts.txt"))) + ("id_rsa.pub" ,(plain-file "id_rsa.pub" (file (fmt "src/infrastructure/keys/SSH/root@~a.id_rsa.pub.stripped" tld)))) + ("ssh.conf" ,(plain-file "ssh.conf" (file "src/infrastructure/config/ssh.conf"))) + ("init.scm" ,(plain-file "init.scm" (file "src/infrastructure/config/init.scm"))) + ("conf.env" ,(plain-file "conf.env" (file "src/infrastructure/config/conf.env"))) + ("gitconfig" ,(plain-file "gitconfig" (file "src/infrastructure/config/gitconfig"))))) + (service git-daemon-service-type + (git-daemon-configuration + (export-all? #t))) + (simple-service 'add-wireguard-aliases hosts-service-type + (list + (host "10.0.0.0" "toph") + (host "10.0.0.1" "velhinho") + (host "10.0.0.2" "azula"))) + (service wireguard-service-type + (wireguard-configuration + (addresses '("10.0.0.0/32")) + (peers + (list + (wireguard-peer + (name "velhinho") + (public-key "Mhv8KxB/QXQpNKNtqD57PoFv43TXJ1lg52PJd6TmtwI=") + (allowed-ips '("10.0.0.1/32")) + (keep-alive 25)) + (wireguard-peer + (name "azula") + (public-key "8IxSFlJoFuTzLtIkoKZH4CkUbIxd6++E0lBOin/7rT8=") + (allowed-ips '("10.0.0.2/32")) + (keep-alive 25)))))) + (service queue:shadow-group-service-type) + (service queue:dkimproxyout-service-type) + (service queue:cyrus-sasl-service-type) + (service queue:dovecot-service-type) + (service queue:internet-postfix-service-type + (queue:postfix-configuration + (enable-submission? #t) + (main.cf-extra #"- + message_size_limit = 102400000 + mailbox_size_limit = 5120000000 + "#))) + (service mail-aliases-service-type + '(("root" "andreh") + ("eu" "andreh") + ("mailing-list" "andreh")))) + (modify-services %base-services + (rottlog-service-type config => + (rottlog-configuration + (inherit config) + (rc-file (file-append queue:rottlog-mailutils-sendmail "/etc/rc"))))))) + (bootloader + (bootloader-configuration + (bootloader grub-bootloader) + (targets '("/dev/vda")))) + (swap-devices + (list + (swap-space + (target + (uuid "94b47d91-3542-438a-84a9-859fe347ce09"))))) + (file-systems + (append + (list + (file-system + (mount-point "/") + (device + (uuid "4c36d5ad-f996-413e-a55c-c05b7e1876f2" 'btrfs)) + (type "btrfs")) + (file-system + (mount-point "/mnt/production") + (needed-for-boot? #t) + (device + (uuid "b1a7e4a1-a8ea-48a4-ab8b-884a1b6a9c11" 'btrfs)) + (type "btrfs")) + (file-system + (mount-point "/mnt/backup") + (device + (uuid "6632849d-f180-4740-86e6-a519d43ab75a" 'btrfs)) + (type "btrfs"))) + %base-file-systems))) diff --git a/src/infrastructure/guix/channels.scm b/src/infrastructure/guix/channels.scm deleted file mode 100644 index 697eb4f..0000000 --- a/src/infrastructure/guix/channels.scm +++ /dev/null @@ -1,12 +0,0 @@ -(append - (list - (channel - (name 'EuAndreh) - (url "git://euandre.org/packages") - (branch "main") - (introduction - (make-channel-introduction - "d749e053e6db365069cb9b2ef47a78b06f9e7361" - (openpgp-fingerprint - "5BDA E9B8 B2F6 C6BC BB0D 6CE5 81F9 0EC3 CD35 6060"))))) - %default-channels) diff --git a/src/infrastructure/guix/packages.scm b/src/infrastructure/guix/packages.scm deleted file mode 100644 index 7fe4e93..0000000 --- a/src/infrastructure/guix/packages.scm +++ /dev/null @@ -1,72 +0,0 @@ -(define-module (packages) - #:use-module ((ice-9 popen) #:prefix popen:) - #:use-module ((ice-9 rdelim) #:prefix rdelim:) - #:use-module ((org euandre queue) #:prefix queue:) - #:use-module ((org euandre packages) #:prefix org-euandre:) - #:use-module ((xyz euandreh heredoc) #:prefix heredoc:) - #:use-module (gnu) - #:use-module (guix build utils) - #:use-module (guix build-system gnu) - #:use-module (guix packages)) -(use-package-modules - check - finance - groff - haskell-apps - haskell-xyz - imagemagick - python - python-web - python-xyz - version-control) -(heredoc:enable-syntax) - - -(define working-dir - (if (directory-exists? "/opt/deploy/current") - "/opt/deploy/current" - (canonicalize-path "."))) - -(define version-cmd #"- - if grep -q deployer /etc/passwd && [ -e /opt/deploy/current ]; then - sudo -u deployer git -C /opt/deploy/current rev-parse HEAD - else - git rev-parse HEAD - fi - "#) - -(define repo-version - (let* ((port (popen:open-input-pipe version-cmd)) - (v (rdelim:read-line port))) - (popen:close-pipe port) - v)) - -(define-public server - (package - (name "server") - (version repo-version) - (source - (local-file working-dir #:recursive? #t)) - (build-system gnu-build-system) - (arguments - (list - #:make-flags #~(list (string-append "PREFIX=" %output)) - #:phases - #~(modify-phases %standard-phases - (delete 'configure) - (add-after 'install 'installcheck - (lambda* (#:key make-flags #:allow-other-keys) - (define dash-j (format #f "-j~a" (parallel-job-count))) - (apply invoke "make" dash-j "installcheck" make-flags)))))) - (native-inputs - (list - git-minimal - pandoc - shellcheck)) - (home-page #f) - (synopsis #f) - (description #f) - (license #f))) - -(list - server) diff --git a/src/infrastructure/guix/system.scm b/src/infrastructure/guix/system.scm deleted file mode 100644 index 1690f31..0000000 --- a/src/infrastructure/guix/system.scm +++ /dev/null @@ -1,504 +0,0 @@ -(use-modules - ((ice-9 textual-ports) #:prefix textual-ports:) - ((srfi srfi-1) #:prefix s1:) - ((xyz euandreh heredoc) #:prefix heredoc:) - ((org euandre queue) #:prefix queue:) - (gnu) - (guix build-system trivial) - (guix build utils) - (guix packages)) -(use-package-modules - admin - ssh - version-control) -(use-service-modules - admin - certbot - cgit - dns - mail - mcron - networking - security - ssh - version-control - vpn - web) -(heredoc:enable-syntax) - - -(define ipv4 "216.238.68.100") -(define ipv6 "2001:19f0:b400:1f0c:5400:04ff:fe35:8c89") -(define tld "euandre.org") - -(define users - '(("andreh" "EuAndreh" ("wheel" "become-deployer" "become-secrets-keeper")))) - - -(define working-dir - (if (directory-exists? "/opt/deploy/current") - "/opt/deploy/current" - (canonicalize-path "."))) - -(add-to-load-path - (string-append working-dir "/src/infrastructure/guix")) -(use-modules - ((packages) #:prefix packages:)) - - -(define (str . rest) - (apply string-append rest)) - -(define (fmt . rest) - (apply format #f rest)) - -(define (path s) - (str working-dir "/" s)) - -(define (slurp s) - (call-with-input-file - s - textual-ports:get-string-all)) - -(define (file s) - (slurp (path s))) - -(define (script name content) - (package - (name name) - (version "latest") - (source #f) - (build-system trivial-build-system) - (arguments - (list - #:modules '((guix build utils)) - #:builder - #~(begin - (use-modules (guix build utils)) - (let* ((bin (string-append %output "/bin")) - (prog (string-append bin "/" #$name))) - (mkdir-p bin) - (call-with-output-file prog - (lambda (port) - (display #$content port))) - (chmod prog #o755))))) - (home-page #f) - (synopsis #f) - (description #f) - (license #f))) - -(define user-accounts - (map (lambda (user) - (let ((name (s1:first user)) - (comment (s1:second user)) - (groups (s1:third user))) - (user-account - (name name) - (comment comment) - (group "users") - (supplementary-groups groups)))) - users)) - -(define (ssh-file-for user) - (let ((name (s1:first user))) - (path (fmt "src/infrastructure/keys/SSH/~a.pub.txt" name)))) - -(define authorized-keys - (let ((users-with-keys - (map (lambda (user) - `(,@user ,(slurp (ssh-file-for user)))) - (filter (lambda (user) - (file-exists? (ssh-file-for user))) - users)))) - (append - (map (lambda (user) - (let ((name (s1:first user)) - (key (s1:fourth user))) - `(,name ,(plain-file (str name "-id_rsa.pub") - key)))) - users-with-keys) - `(("git" ,@(map (lambda (user) - (let ((name (s1:first user)) - (key (s1:fourth user))) - (plain-file (str name "-git-id_rsa.pub") - key))) - users-with-keys)))))) - - -(define ns (fmt "ns1.~a." tld)) -(define mail (fmt "hostmaster.~a." tld)) -(define dkim-selector "dkimproxyout") -(define dkim-public-key-path "/var/lib/dkimproxyout/public.key") - -(define dkim-name (str dkim-selector "._domainkey")) -(define dkim-public-key - (if (file-exists? dkim-public-key-path) - (string-join (reverse - (cdr - (reverse - (cdr - (string-split (slurp dkim-public-key-path) - #\newline))))) - "") - "stub-public-key-for-building")) - -(define ipv4-reverse-domain - (str - (string-join (reverse - (string-split ipv4 - #\.)) - ".") - ".in-addr.arpa")) - -(define ipv6-reverse-domain - (str - (string-join (reverse - (map (lambda (s) (fmt "~a" s)) - (string->list - (string-delete #\: ipv6)))) - ".") - ".ip6.arpa")) - -(define-zone-entries tld-zone - ("@" "" "IN" "NS" (fmt "ns1.~a." tld)) - ("@" "" "IN" "NS" (fmt "ns2.~a." tld)) - ("ns1" "" "IN" "A" ipv4) - ("ns1" "" "IN" "AAAA" ipv6) - ("ns2" "" "IN" "A" ipv4) - ("ns2" "" "IN" "AAAA" ipv6) - - ("@" "" "IN" "A" ipv4) - ("@" "" "IN" "AAAA" ipv6) - - ("@" "" "IN" "CAA" "0 issue \"letsencrypt.org\"") - ("@" "" "IN" "CAA" "0 issuewild \";\"") - ("@" "" "IN" "CAA" "0 iodef \"mailto:eu@euandre.org\"") - - ("mta-sts" "" "IN" "A" ipv4) - ("mta-sts" "" "IN" "AAAA" ipv6) - ("_mta-sts" "" "IN" "TXT" "\"v=STSv1; id=20230314\"") - ("@" "" "IN" "MX" (fmt "10 ~a." tld)) - ("_dmarc" "" "IN" "TXT" "\"v=DMARC1; p=quarantine\"") - ("@" "" "IN" "TXT" (fmt "\"v=spf1 a:~a -all\"" tld)) - (dkim-name "" "IN" "TXT" (fmt "\"v=DKIM1; k=rsa; t=s; p=~a\"" dkim-public-key))) - -(define-zone-entries ipv4-reverse-domain-zone - ("@" "" "IN" "PTR" (str tld ".")) - ("@" "" "IN" "NS" (fmt "ns1.~a." tld)) - ("@" "" "IN" "NS" (fmt "ns2.~a." tld))) - -(define-zone-entries ipv6-reverse-domain-zone - ("@" "" "IN" "PTR" (str tld ".")) - ("@" "" "IN" "NS" (fmt "ns1.~a." tld)) - ("@" "" "IN" "NS" (fmt "ns2.~a." tld))) - -(define zones - (list - (knot-zone-configuration - (domain tld) - (semantic-checks? #t) - (zone - (zone-file - (origin tld) - (ns ns) - (mail mail) - (entries tld-zone)))) - (knot-zone-configuration - (domain ipv4-reverse-domain) - (semantic-checks? #t) - (zone - (zone-file - (origin ipv4-reverse-domain) - (ns ns) - (mail mail) - (entries ipv4-reverse-domain-zone)))) - (knot-zone-configuration - (domain ipv6-reverse-domain) - (semantic-checks? #t) - (zone - (zone-file - (origin ipv6-reverse-domain) - (ns ns) - (mail mail) - (entries ipv6-reverse-domain-zone)))))) - - -(operating-system - (locale "fr_FR.UTF-8") - (timezone "America/Sao_Paulo") - (host-name tld) - (skeletons - `((".profile" - ,(plain-file "user-profile" - (file "src/infrastructure/config/profile.sh"))))) - (users - (append - (list - (user-account - (name "git") - (group "git") - (system? #t) - (comment "External SSH Git user") - (home-directory "/srv/git") - (create-home-directory? #f) - (shell - (file-append git "/bin/git-shell"))) - (user-account - (name "deployer") - (group "deployer") - (system? #t) - (comment "The account used to run deployment commands") - (home-directory "/var/empty") - (create-home-directory? #f) - (shell - (file-append shadow "/sbin/nologin"))) - (user-account - (name "secrets-keeper") - (group "secrets-keeper") - (system? #t) - (comment "The account used to manage production secrets") - (home-directory "/var/empty") - (create-home-directory? #f) - (shell - (file-append shadow "/sbin/nologin")))) - user-accounts - %base-user-accounts)) - (groups - (append - (list - (user-group - (name "git") - (system? #t)) - (user-group - (name "deployer") - (system? #t)) - (user-group - (name "become-deployer") - (system? #t)) - (user-group - (name "secrets-keeper") - (system? #t)) - (user-group - (name "become-secrets-keeper") - (system? #t))) - %base-groups)) - (sudoers-file - (plain-file "sudoers" #"- - root ALL=(ALL) ALL - %wheel ALL= ALL - %become-deployer ALL=(deployer) NOPASSWD: ALL - %become-secrets-keeper ALL=(secrets-keeper) NOPASSWD: /run/current-system/profile/bin/rsync, /run/current-system/profile/bin/setfacl, /run/current-system/profile/bin/rm - git ALL= NOPASSWD: /run/current-system/profile/bin/reconfigure, /run/current-system/profile/bin/cicd - git ALL=(deployer) NOPASSWD: /run/current-system/profile/bin/rsync, /run/current-system/profile/bin/mkdir - "#)) - (packages - (append - (map (compose list specification->package+output symbol->string) - '(parted - acl - bind:utils - tcpdump - knot:tools - file - git - guile-heredoc - entr - lsof - jq - moreutils - mailutils-sendmail - curl - make - gnupg - borg - rsync - sqlite - strace - rlwrap - trash-cli - tree)) - (list - packages:server - (script "gc" (file "src/infrastructure/scripts/gc.sh")) - (script "cicd" (file "src/infrastructure/scripts/cicd.sh")) - (script "check" (file "src/infrastructure/scripts/check.sh")) - (script "backup" (file "src/infrastructure/scripts/backup.sh")) - (script "deploy" (file "src/infrastructure/scripts/deploy.sh")) - (script "report" (file "src/infrastructure/scripts/report.sh")) - (script "cronjob" (file "src/infrastructure/scripts/cronjob.sh")) - (script "reconfigure" (file "src/infrastructure/scripts/reconfigure.sh"))) - %base-packages)) - (services - (append - (list - (service ntp-service-type) - (service dhcp-client-service-type) - (service knot-service-type - (knot-configuration - (zones zones))) - (service openssh-service-type - (openssh-configuration - (openssh openssh-sans-x) - (password-authentication? #f) - (authorized-keys authorized-keys) - (extra-content #"- - ClientAliveInterval 30 - ClientAliveCountMax 20 - MaxSessions 20 - SetEnv GIT_CONFIG_GLOBAL=/etc/gitconfig - "#))) - (simple-service 'extra-rottlog-rotations rottlog-service-type - (list - (log-rotation - (frequency 'weekly) - (files '("/var/log/cronjobs.log")) - (options '("rotate 52"))))) - (service fail2ban-service-type) - (service mcron-service-type - (mcron-configuration - (jobs - (list - #~(job "0 0 * * *" "cronjob check") - #~(job "0 1 * * *" "cronjob env BORG_REPO=/mnt/backup/borg backup -q cron") - #~(job "0 2 * * *" "cronjob backup -q cron") - #~(job "0 3 * * 0" "cronjob gc") - #~(job "0 4 * * *" "cronjob reconfigure -U"))))) - (service certbot-service-type - (certbot-configuration - (email (str "root@" tld)) - (certificates - (list - (certificate-configuration - (domains (list tld)) - (deploy-hook - (program-file - "nginx-deploy-hook" - #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) - (kill pid SIGHUP))))))))) - (service nginx-service-type - (nginx-configuration - (server-blocks - (list - (nginx-server-configuration - (server-name (list tld)) - (listen '("[::]:443 ssl http2" "443 ssl http2")) - (root "/srv/www") - (ssl-certificate (fmt "/etc/letsencrypt/live/~a/fullchain.pem" tld)) - (ssl-certificate-key (fmt "/etc/letsencrypt/live/~a/privkey.pem" tld)) - (locations - (list - (nginx-location-configuration - (uri "/r/velhinho/") - (body - '(#"- - rewrite /r/velhinho(.*) $1 break; - proxy_pass http://velhinho:4219; - "#))) - (nginx-location-configuration - (uri "/git/static/") - (body - (list - (list "alias " cgit "/share/cgit/;")))) - (nginx-location-configuration - (uri "/git/") - (body - (list - (list "fastcgi_param SCRIPT_FILENAME " cgit "/lib/cgit/cgit.cgi;") - #"- - fastcgi_param PATH_INFO $uri; - fastcgi_param QUERY_STRING $args; - fastcgi_param HTTP_HOST $server_name; - fastcgi_pass localhost:9000; - rewrite /git(.*) $1 break; - "#))))) - (raw-content - '(#"- - ssl_protocols TLSv1.3; - ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH; - ssl_prefer_server_ciphers on; - gzip off; # Disable compression altogether due to BREACH - charset utf-8; - autoindex on; - add_header Strict-Transport-Security 'max-age=31536000; includeSubdomains' always; - "#))))))) - (service cgit-service-type queue:cgit-pre-configuration) - (simple-service 'extra-etc-file etc-service-type - `(("rc" ,(plain-file "rc.sh" (file "src/infrastructure/config/rc.sh"))) - ("known_hosts" ,(plain-file "known_hosts" (file "src/infrastructure/config/known_hosts.txt"))) - ("id_rsa.pub" ,(plain-file "id_rsa.pub" (file (fmt "src/infrastructure/keys/SSH/root@~a.id_rsa.pub.stripped" tld)))) - ("ssh.conf" ,(plain-file "ssh.conf" (file "src/infrastructure/config/ssh.conf"))) - ("init.scm" ,(plain-file "init.scm" (file "src/infrastructure/config/init.scm"))) - ("conf.env" ,(plain-file "conf.env" (file "src/infrastructure/config/conf.env"))) - ("gitconfig" ,(plain-file "gitconfig" (file "src/infrastructure/config/gitconfig"))))) - (service git-daemon-service-type - (git-daemon-configuration - (export-all? #t))) - (simple-service 'add-wireguard-aliases hosts-service-type - (list - (host "10.0.0.0" "toph") - (host "10.0.0.1" "velhinho") - (host "10.0.0.2" "azula"))) - (service wireguard-service-type - (wireguard-configuration - (addresses '("10.0.0.0/32")) - (peers - (list - (wireguard-peer - (name "velhinho") - (public-key "Mhv8KxB/QXQpNKNtqD57PoFv43TXJ1lg52PJd6TmtwI=") - (allowed-ips '("10.0.0.1/32")) - (keep-alive 25)) - (wireguard-peer - (name "azula") - (public-key "8IxSFlJoFuTzLtIkoKZH4CkUbIxd6++E0lBOin/7rT8=") - (allowed-ips '("10.0.0.2/32")) - (keep-alive 25)))))) - (service queue:shadow-group-service-type) - (service queue:dkimproxyout-service-type) - (service queue:cyrus-sasl-service-type) - (service queue:dovecot-service-type) - (service queue:internet-postfix-service-type - (queue:postfix-configuration - (enable-submission? #t) - (main.cf-extra #"- - message_size_limit = 102400000 - mailbox_size_limit = 5120000000 - "#))) - (service mail-aliases-service-type - '(("root" "andreh") - ("eu" "andreh") - ("mailing-list" "andreh")))) - (modify-services %base-services - (rottlog-service-type config => - (rottlog-configuration - (inherit config) - (rc-file (file-append queue:rottlog-mailutils-sendmail "/etc/rc"))))))) - (bootloader - (bootloader-configuration - (bootloader grub-bootloader) - (targets '("/dev/vda")))) - (swap-devices - (list - (swap-space - (target - (uuid "94b47d91-3542-438a-84a9-859fe347ce09"))))) - (file-systems - (append - (list - (file-system - (mount-point "/") - (device - (uuid "4c36d5ad-f996-413e-a55c-c05b7e1876f2" 'btrfs)) - (type "btrfs")) - (file-system - (mount-point "/mnt/production") - (needed-for-boot? #t) - (device - (uuid "b1a7e4a1-a8ea-48a4-ab8b-884a1b6a9c11" 'btrfs)) - (type "btrfs")) - (file-system - (mount-point "/mnt/backup") - (device - (uuid "6632849d-f180-4740-86e6-a519d43ab75a" 'btrfs)) - (type "btrfs"))) - %base-file-systems))) -- cgit v1.2.3