414 lines
18 KiB
Scheme
414 lines
18 KiB
Scheme
;; OS configuration for "berlin", the frontend of the compile farm
|
||
;; hosted at the MDC.
|
||
;; Copyright © 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
|
||
;; Copyright © 2017, 2018, 2019, 2020, 2021 Ricardo Wurmus <rekado@elephly.net>
|
||
;; Copyright © 2019, 2021 Julien Lepiller <julien@lepiller.eu>
|
||
;; Copyright © 2020, 2021 Florian Pelz <pelzflorian@pelzflorian.de>
|
||
;; Copyright © 2020, 2021 Mathieu Othacehe <othacehe@gnu.org>
|
||
;; Copyright © 2021 Tobias Geerinckx-Rice <me@tobias.gr>
|
||
;; Released under the GNU GPLv3 or any later version.
|
||
|
||
(use-modules (gnu) (guix) (sysadmin services) (sysadmin people) (sysadmin dns)
|
||
(sysadmin web)
|
||
(guix git-download)
|
||
((guix utils) #:select (current-source-directory))
|
||
((guix build utils) #:select (find-files))
|
||
(srfi srfi-1)
|
||
(ice-9 match))
|
||
(use-service-modules avahi base databases dns monitoring networking admin
|
||
shepherd ssh vpn)
|
||
(use-package-modules admin base certs databases emacs linux mail monitoring
|
||
ssh tls tor vim package-management
|
||
version-control
|
||
web wget ci rsync
|
||
guile-xyz)
|
||
|
||
(define %sysadmins
|
||
;; The sysadmins.
|
||
(list (sysadmin (name "ludo")
|
||
(full-name "Ludovic Courtès")
|
||
(ssh-public-key (local-file "keys/ssh/ludo.pub")))
|
||
(sysadmin (name "rekado")
|
||
(full-name "Ricardo Wurmus")
|
||
(ssh-public-key (local-file "keys/ssh/rekado.pub")))
|
||
(sysadmin (name "andreas")
|
||
(full-name "Andreas Enge")
|
||
(ssh-public-key (local-file "keys/ssh/andreas.pub")))
|
||
(sysadmin (name "mbakke")
|
||
(full-name "Marius Bakke")
|
||
(ssh-public-key (local-file "keys/ssh/mbakke.pub")))
|
||
(sysadmin (name "g_bor")
|
||
(full-name "Gábor Boskovits")
|
||
(ssh-public-key (local-file "keys/ssh/g_bor.pub")))
|
||
(sysadmin (name "nckx")
|
||
(full-name "Tobias Geerinckx-Rice")
|
||
(ssh-public-key (local-file "keys/ssh/nckx.pub")))
|
||
(sysadmin (name "mathieu")
|
||
(full-name "Mathieu Othacehe")
|
||
(ssh-public-key (local-file "keys/ssh/mathieu.pub")))
|
||
(sysadmin (name "pimi")
|
||
(full-name "Mădălin Patrascu")
|
||
(ssh-public-key (local-file "keys/ssh/pimi.pub")))
|
||
(sysadmin (name "janneke")
|
||
(full-name "Jan (janneke) Nieuwenhuizen")
|
||
(ssh-public-key (local-file "keys/ssh/janneke.pub")))
|
||
(sysadmin (name "cbaines")
|
||
(full-name "Christopher Baines")
|
||
(ssh-public-key (local-file "keys/ssh/cbaines.pub")))
|
||
(sysadmin (name "lfam")
|
||
(full-name "Leo Famulari")
|
||
(ssh-public-key (local-file "keys/ssh/lfam.pub")))
|
||
(sysadmin (name "maxim")
|
||
(full-name "Maxim Cournoyer")
|
||
(ssh-public-key (local-file "keys/ssh/maxim.pub")))))
|
||
|
||
(include "nginx/berlin.scm")
|
||
|
||
|
||
;;;
|
||
;;; Operating system.
|
||
;;;
|
||
|
||
(define %motd
|
||
;; Message of the day!
|
||
(plain-file "motd"
|
||
"\
|
||
░░░ ░░░
|
||
░░▒▒░░░░░░░░░ ░░░░░░░░░▒▒░░
|
||
░░▒▒▒▒▒░░░░░░░ ░░░░░░░▒▒▒▒▒░
|
||
░▒▒▒░░▒▒▒▒▒ ░░░░░░░▒▒░
|
||
░▒▒▒▒░ ░░░░░░
|
||
▒▒▒▒▒ ░░░░░░
|
||
▒▒▒▒▒ ░░░░░
|
||
░▒▒▒▒▒ ░░░░░ Welcome to berlin!
|
||
▒▒▒▒▒ ░░░░░
|
||
▒▒▒▒▒ ░░░░░
|
||
░▒▒▒▒▒░░░░░
|
||
▒▒▒▒▒▒░░░
|
||
▒▒▒▒▒▒░
|
||
|
||
Best practices:
|
||
|
||
1. Store everything in guix-maintenance.git.
|
||
2. Use the Git checkouts of Guix and guix-maintenance in ~root.
|
||
3. Notify guix-sysadmin@gnu.org when reconfiguring.
|
||
4. Notify guix-sysadmin@gnu.org when something goes wrong.
|
||
|
||
5. Notify ricardo.wurmus@mdc-berlin.de or rekado@elephly.net when the
|
||
machine doesn't respond. Only Ricardo has access to the serial console
|
||
to reset the machine.
|
||
|
||
Happy hacking!\n"))
|
||
|
||
|
||
(define %copy-kernel-and-initrd
|
||
;; The storage device where the root file system is is invisible to GRUB.
|
||
;; Thus, copy the kernel and initrd to /store, where GRUB will be able to
|
||
;; find them.
|
||
(with-imported-modules '((guix build utils))
|
||
#~(begin
|
||
(use-modules (guix build utils))
|
||
|
||
(for-each (lambda (file)
|
||
(let ((target (string-append "/store/" (basename file))))
|
||
(unless (file-exists? target)
|
||
(format #t "copying '~a' to /store...~%" file)
|
||
(copy-recursively file target
|
||
#:log (%make-void-port "w")))))
|
||
|
||
;; /run/current-system/kernel is a profile. The trick
|
||
;; below allows us to get at its actual directory name,
|
||
;; which is what 'grub.cfg' refers to.
|
||
(list (dirname
|
||
(canonicalize-path "/run/current-system/kernel/bzImage"))
|
||
(dirname (canonicalize-path "/run/current-system/initrd")))))))
|
||
|
||
|
||
(define %build-node-key-directory
|
||
;; Directory containing the signing keys of build nodes.
|
||
(string-append (current-source-directory) "/keys/guix/berlin"))
|
||
|
||
(define %build-node-keys
|
||
;; Signing keys of the build nodes.
|
||
(map (lambda (file)
|
||
(local-file file (string-map (match-lambda
|
||
(#\: #\-)
|
||
(chr chr))
|
||
(basename file))))
|
||
(find-files %build-node-key-directory "\\.pub$")))
|
||
|
||
|
||
(operating-system
|
||
(host-name "berlin.guix.gnu.org")
|
||
(timezone "Europe/Berlin")
|
||
(locale "en_US.utf8")
|
||
|
||
(name-service-switch %mdns-host-lookup-nss)
|
||
;; Allow access through the serial console at 141.80.167.201; the
|
||
;; management interface can only be accessed through selected
|
||
;; servers within the MDC campus network.
|
||
(kernel-arguments '("console=tty0"
|
||
"console=ttyS0,115200"))
|
||
|
||
;; The Dell server need these kernel modules for the
|
||
;; RAID controller.
|
||
(initrd-modules (append (list "megaraid_sas" "scsi_transport_sas"
|
||
"mpt3sas" "libsas")
|
||
%base-initrd-modules))
|
||
|
||
;; Show the GRUB menu on the serial interface.
|
||
(bootloader (bootloader-configuration
|
||
(bootloader grub-bootloader)
|
||
(targets '("/dev/sda"))
|
||
(terminal-inputs '(serial))
|
||
(terminal-outputs '(serial))))
|
||
|
||
(file-systems (cons*
|
||
;; The root file system resides on just a single
|
||
;; disk, no RAID :-/
|
||
(file-system
|
||
(device (file-system-label "my-root"))
|
||
(mount-point "/")
|
||
(type "ext4"))
|
||
;; This is a large external storage array
|
||
;; connected via 2 HBA cards. We only mount it
|
||
;; through one of the HBA cards. We would need
|
||
;; to use multipathd otherwise.
|
||
(file-system
|
||
(device (uuid "a6455b66-59d2-40bd-bddb-0c572bb62a2f"))
|
||
(mount-point "/gnu")
|
||
(type "ext4"))
|
||
;; Bind mount cache to large external storage.
|
||
(file-system
|
||
(device "/gnu/cache")
|
||
(mount-point "/var/cache")
|
||
(flags '(bind-mount))
|
||
(type "none"))
|
||
;; Access root file system without bind mounts.
|
||
(file-system
|
||
(device "/")
|
||
(mount-point "/mnt/root-fs")
|
||
(flags '(bind-mount))
|
||
(type "none"))
|
||
%base-file-systems))
|
||
|
||
;; Local admin account for MDC maintenance.
|
||
(users (cons (user-account
|
||
(name "bi-admin")
|
||
(comment "Local admin")
|
||
(group "users")
|
||
(supplementary-groups '("wheel"))
|
||
(home-directory "/home/bi-admin"))
|
||
%base-user-accounts))
|
||
|
||
(packages (cons* certbot emacs wget iptables
|
||
jnettop openssh rsync
|
||
;; This is needed to set GIT_SSL_CAINFO allowing
|
||
;; Cuirass to fetch sources via HTTPS.
|
||
nss-certs
|
||
;; This is for git-receive-pack et al
|
||
git-minimal
|
||
;; This is for the mumi mailer
|
||
msmtp
|
||
;; This is for bypassing the firewall...
|
||
torsocks
|
||
%base-packages))
|
||
|
||
(services (cons*
|
||
(simple-service 'copy-kernel+initrd-to-/store
|
||
activation-service-type
|
||
%copy-kernel-and-initrd)
|
||
|
||
;; Connection to the DMZ for public access
|
||
;; This is a 10G port.
|
||
(static-networking-service "eno2"
|
||
"141.80.181.40"
|
||
#:netmask "255.255.255.0"
|
||
#:gateway "141.80.181.1")
|
||
;; Connection to build nodes
|
||
(static-networking-service "eno1"
|
||
"141.80.167.131"
|
||
#:netmask "255.255.255.192")
|
||
|
||
;; Allow login over serial console.
|
||
(agetty-service (agetty-configuration
|
||
(tty "ttyS0")
|
||
(baud-rate "115200")))
|
||
|
||
;; Discover substitute servers.
|
||
(service avahi-service-type
|
||
(avahi-configuration (debug? #t)))
|
||
|
||
;; Periodically populate the Disarchive database. Store it
|
||
;; under /gnu, which is the big drive; talk directly to the
|
||
;; local Cuirass instance.
|
||
(service disarchive-service-type
|
||
(disarchive-configuration
|
||
(directory "/gnu/disarchive")
|
||
(cuirass-url "http://localhost:8081")))
|
||
|
||
;; DNS
|
||
(service knot-service-type
|
||
(knot-configuration
|
||
(zones (list (knot-zone-configuration
|
||
(domain "guix.gnu.org")
|
||
(master '("bayfront-master"))
|
||
(acl '("notify-allow")))))
|
||
(acls (list (knot-acl-configuration
|
||
(id "notify-allow")
|
||
(address (list bayfront-ip4))
|
||
(action '(notify)))))
|
||
(remotes (list (knot-remote-configuration
|
||
(id "bayfront-master")
|
||
(address (list bayfront-ip4)))))))
|
||
|
||
;; Monitoring
|
||
(service prometheus-node-exporter-service-type)
|
||
|
||
(service zabbix-agent-service-type)
|
||
(service zabbix-server-service-type
|
||
(zabbix-server-configuration
|
||
(include-files '("/root/zabbix-pass"))
|
||
(extra-options "AlertScriptsPath=/root/zabbix-alert-scripts\n")))
|
||
(service zabbix-front-end-service-type
|
||
(zabbix-front-end-configuration
|
||
(nginx (list %zabbix-nginx-server
|
||
%zabbix-nginx-local-server))
|
||
(db-secret-file "/root/zabbix-front-end-secrets")))
|
||
|
||
;; For the Zabbix database. It was created by manually
|
||
;; following the instructions here:
|
||
;; https://www.zabbix.com/documentation/3.0/manual/appendix/install/db_scripts
|
||
(service postgresql-service-type
|
||
(postgresql-configuration
|
||
(postgresql postgresql-13)))
|
||
(service postgresql-role-service-type)
|
||
|
||
(service ntp-service-type)
|
||
|
||
;; Make SSH and HTTP/HTTPS available over Tor.
|
||
(tor-hidden-service "http"
|
||
'((22 "127.0.0.1:22")
|
||
(80 "127.0.0.1:80")
|
||
(443 "127.0.0.1:443")))
|
||
(service tor-service-type)
|
||
|
||
(service nginx-service-type %nginx-configuration)
|
||
|
||
;; Runnning guix.gnu.org.
|
||
(service static-web-site-service-type
|
||
(static-web-site-configuration
|
||
(git-url
|
||
"https://git.savannah.gnu.org/git/guix/guix-artwork.git")
|
||
(directory "/srv/guix.gnu.org")
|
||
(build-file "website/.guix.scm")))
|
||
|
||
;; Manual for the latest stable release.
|
||
(service static-web-site-service-type
|
||
(static-web-site-configuration
|
||
(git-url "https://git.savannah.gnu.org/git/guix.git")
|
||
(git-ref '(branch . "version-1.3.0"))
|
||
(period (* 24 3600)) ;check once per day
|
||
(directory "/srv/guix-manual")
|
||
(build-file "doc/build.scm")
|
||
(environment-variables
|
||
'(("GUIX_MANUAL_VERSION" . "1.3.0")
|
||
("GUIX_WEB_SITE_URL" . "/")))))
|
||
|
||
;; Manual for 'master'.
|
||
(service static-web-site-service-type
|
||
(static-web-site-configuration
|
||
(git-url "https://git.savannah.gnu.org/git/guix.git")
|
||
(directory "/srv/guix-manual-devel")
|
||
|
||
;; XXX: Use a different cache directory to work around
|
||
;; the fact that (guix git) would use a same-named
|
||
;; checkout directory for 'master' and for the branch
|
||
;; above. Since both mcron jobs run at the same time,
|
||
;; they would end up using one branch or the other, in
|
||
;; a non-deterministic way.
|
||
(cache-directory "guix-master-manual")
|
||
|
||
(build-file "doc/build.scm")
|
||
(environment-variables
|
||
'(("GUIX_WEB_SITE_URL" . "/")))))
|
||
|
||
;; Cookbook for 'master'.
|
||
(service static-web-site-service-type
|
||
(static-web-site-configuration
|
||
(git-url "https://git.savannah.gnu.org/git/guix.git")
|
||
(directory "/srv/guix-cookbook")
|
||
|
||
;; XXX: Use a different cache directory (see above).
|
||
(cache-directory "guix-cookbook-master")
|
||
|
||
(build-file "doc/build.scm")
|
||
(environment-variables
|
||
'(("GUIX_MANUAL" . "guix-cookbook")
|
||
("GUIX_WEB_SITE_URL" . "/")))))
|
||
|
||
;; The bootstrappable.org web site.
|
||
(service static-web-site-service-type
|
||
(static-web-site-configuration
|
||
(git-url
|
||
"https://git.savannah.gnu.org/git/guix/bootstrappable.git")
|
||
(period (* 24 3600)) ;check once per day
|
||
(directory "/srv/bootstrappable.org")))
|
||
|
||
;; GWL web site.
|
||
(service gwl-web-service-type)
|
||
(service mumi-service-type
|
||
(mumi-configuration
|
||
;; XXX Please do not re-enable the mailer lightly. We've
|
||
;; lost months worth of contributions (hopefully not
|
||
;; contributors...) because all replies submitted through
|
||
;; it are lost, e.g. <http://issues.guix.gnu.org/22366#4>
|
||
(mailer? #f)
|
||
(sender "issues.guix.gnu.org@elephly.net")
|
||
(smtp "sendmail:///var/mumi/mumi-mailer")))
|
||
;; For the Mumi mailer queue
|
||
(service redis-service-type)
|
||
|
||
;; Stop Cuirass when disk space is low.
|
||
(service disk-space-watchdog-service-type
|
||
(list (* 500 GiB) (* 50 GiB)))
|
||
|
||
;; VPN connection to the remote build nodes.
|
||
(service wireguard-service-type
|
||
(wireguard-configuration
|
||
(addresses (list "10.0.0.1/32"))
|
||
(peers
|
||
(list
|
||
(wireguard-peer
|
||
(name "overdrive1")
|
||
(public-key "m2qys8ATAKUTT8YNUM3OmnJnw1lYm5GHpUA42/l1Qz8=")
|
||
(allowed-ips '("10.0.0.3/32")))
|
||
(wireguard-peer
|
||
(name "dover")
|
||
(public-key "b3D6Nv5X4npfko99HELdewtKL8LzbbeUAIFjpwU7HhA=")
|
||
(allowed-ips '("10.0.0.4/32")))
|
||
(wireguard-peer
|
||
(name "guix-x15")
|
||
(public-key "pM7dAWXJ35isIDJA3OpbR2YG1Pk3MI9VTlP5ELAeQkM=")
|
||
(allowed-ips '("10.0.0.5/32")))
|
||
(wireguard-peer
|
||
(name "guix-x15b")
|
||
(public-key "cwRqmMc8IPAHxFCGIt1WcnJnoWJcefcTXte2vMNi6Wo=")
|
||
(allowed-ips '("10.0.0.6/32")))
|
||
(wireguard-peer
|
||
(name "guixp9")
|
||
(public-key "4jflGVC+6ee1jsXR/6GgBKjxzw4T4WIwYiMhj/lYQTE=")
|
||
(allowed-ips '("10.0.0.7/32")))))))
|
||
|
||
(frontend-services %sysadmins
|
||
;; Make sure we get enough build users.
|
||
#:authorized-keys %build-node-keys
|
||
#:build-accounts-to-max-jobs-ratio 5
|
||
#:gc-threshold (* 10 TiB)
|
||
#:systems '("x86_64-linux" "i686-linux"
|
||
"aarch64-linux"
|
||
"powerpc64le-linux")
|
||
#:motd %motd
|
||
#:publish-workers 8
|
||
#:max-jobs 20))))
|