(define-module (tw system) #:use-module (ice-9 format) #:use-module (ice-9 regex) #:use-module (ice-9 string-fun) #:use-module ((srfi srfi-1) #:select (append-map every)) #:use-module ((srfi srfi-26) #:select (cut)) #:use-module (gnu) #:use-module (gnu services) #:use-module (gnu system) #:use-module (gnu system keyboard) #:use-module (guix gexp)) (use-package-modules admin avahi certs curl disk file-systems linux lsof man moreutils python rsync search shells version-control vpn) (use-service-modules configuration mcron monitoring networking ssh vpn) (define-public %base-system-packages (cons* acpi btrfs-progs cpupower curl efibootmgr exfat-utils git glibc-locales hddtemp htop lshw lsof man-db man-pages man-pages-posix mlocate moreutils nss-certs nss-mdns python rsync strace wireguard-tools %base-packages)) (define-public %british-keyboard (keyboard-layout "gb" #:options '("caps:swapescape" "parens:swap_brackets" "terminate:ctrl_alt_bksp" "compose:rctrl" "keypad:oss" "kpdl:kposs"))) ;; This is used for the servers, and also by (tw home) to generate the ;; appropriate ~/.ssh/config. (define-public %ssh-ports '(("lud.twilken.net" . 22022) ("vin.twilken.net" . 22022) ("pi3.twilken.net" . 51022))) (define-public (server-base-services host-name) (cons* ;; SSH login, allowing access only for me. To give more public keys ;; access, extend `openssh-service-type'. (service openssh-service-type (openssh-configuration (port-number (assoc-ref %ssh-ports host-name)) (password-authentication? #f) (accepted-environment '("LANG" "LC_*")) (authorized-keys `(("timo" ,(local-file "system/files/timo.pub") ,(local-file "system/files/timo-phone-gpg.pub")))))) ;; Prometheus node exporter (service prometheus-node-exporter-service-type (prometheus-node-exporter-configuration (web-listen-address (string-replace-substring (car ; get the IPv4 address (wireguard-peer-allowed-ips (assoc-ref %wireguard-peers host-name))) "/32" ":9100")))) (simple-service 'disk-maintenance mcron-service-type (list #~(job "0 2 * * *" "guix gc -d 2w") #~(job "0 4 * * *" ; after guix gc (string-append #$(file-append util-linux "/sbin/fstrim") " --fstab --verbose")))) ;; Network setup (service dhcp-client-service-type) (service ntp-service-type) (service tw-wireguard-service-type (tw-wireguard-configuration (this-host host-name))) ;; Delete the annoying message on SSH login. Beware when setting up a new ;; host, as `allow-empty-passwords' will block login and sudo execution for ;; all Guix-declared users (as these have no initial password). (modify-services %base-services (login-service-type config => (login-configuration (inherit config) (motd (plain-file "no-motd" "")) (allow-empty-passwords? #f)))))) (define-public %server-base-user-accounts (cons* (user-account (name "timo") (comment "Timo Wilken") (group "users") (home-directory "/home/timo") (supplementary-groups '("wheel" "netdev" "audio" "video")) (shell (file-append zsh "/bin/zsh"))) %base-user-accounts)) (define-public %wireguard-peers `(("lap.twilken.net" . ,(wireguard-peer (name "lap.wg") (public-key "lap/DvCb8xXLUCqcaPEx8kCRcoeV4ScTMVZW5hvvNzA=") (preshared-key "/etc/wireguard/lap.psk") (allowed-ips '("10.0.0.1/32" "fc00::1/128")))) ("lud.twilken.net" . ,(wireguard-peer (name "lud.wg") (endpoint "lud.twilken.net:58921") (public-key "lud/9sbXVdOYXxOkRgAB+b/17QxbwllfJY/pbA3/MkE=") (preshared-key "/etc/wireguard/lud.psk") (allowed-ips '("10.0.0.2/32" "fc00::2/128")))) ("vin.twilken.net" . ,(wireguard-peer (name "vin.wg") (endpoint "vin.twilken.net:58921") (public-key "vin/Im+sOszZFE01UF1+QlyxLP1PsPXJgTz4KmgvL3Y=") (preshared-key "/etc/wireguard/vin.psk") (allowed-ips '("10.0.0.3/32" "fc00::3/128")))) ("fp4.twilken.net" . ,(wireguard-peer (name "fp4.wg") (public-key "fp4/aLAVBADTy+UGmNh011w1CFOOwq70Df6EWlZRkAs=") (preshared-key "/etc/wireguard/fp4.psk") (allowed-ips '("10.0.0.4/32" "fc00::4/128")))) ("pi3.twilken.net" . ,(wireguard-peer (name "pi3.wg") (endpoint "pi3.twilken.net:58922") (public-key "pi3/ThUH4qDTuyvNQIiiyy2dbziF/xLRTwO0+vcUoVY=") (preshared-key "/etc/wireguard/pi3.psk") (allowed-ips '("10.0.0.5/32" "fc00::5/128")))))) (define (wireguard-peers-list? object) (and (list? object) (every (compose string? car) object) (every (compose wireguard-peer? cdr) object))) (export tw-wireguard-configuration) (define-configuration/no-serialization tw-wireguard-configuration (this-host (string) "The host name of the machine being configured.") (peers (wireguard-peers-list %wireguard-peers) "An alist of WireGuard peers to install.")) (define (tw-wireguard-service config) "Create a full WireGuard config from the personal network CONFIG." (let ((own-peer (assoc-ref (tw-wireguard-configuration-peers config) (tw-wireguard-configuration-this-host config)))) (wireguard-configuration (addresses (map (lambda (cidr) (let ((ipv4 (string-match "/32$" cidr)) (ipv6 (string-match "/128$" cidr))) (cond (ipv4 (regexp-substitute #f ipv4 'pre "/24")) (ipv6 (regexp-substitute #f ipv6 'pre "/64")) (#t cidr)))) (wireguard-peer-allowed-ips own-peer))) (port (let ((endpoint (wireguard-peer-endpoint own-peer))) (if endpoint (string->number (cadr (string-split endpoint #\:))) 58921))) (private-key "/etc/wireguard/private.key") (peers (delq own-peer (map cdr (tw-wireguard-configuration-peers config))))))) (define (peer->ips peer) "Extract IP addresses assigned to the given `wireguard-peer' PEER." (map (compose car (cut string-split <> #\/)) (wireguard-peer-allowed-ips peer))) (define (tw-wireguard-hosts config) "Generate a hosts file entries from the personal WireGuard network CONFIG." (append-map (lambda (peer) (map (cut host <> (wireguard-peer-name peer)) (peer->ips peer))) (map cdr (tw-wireguard-configuration-peers config)))) (define-public tw-wireguard-service-type (service-type (name 'tw-wireguard) (description "Set up my personal WireGuard network.") (extensions (cons* (service-extension hosts-service-type tw-wireguard-hosts) ;; FIXME: `wireguard-service-type' cannot be extended, so copy its ;; service-extensions directly. (map (lambda (ext) (service-extension (service-extension-target ext) (compose (service-extension-compute ext) tw-wireguard-service))) (service-type-extensions wireguard-service-type))))))