;;; SPDX-License-Identifier: GPL-3.0-or-later ;;; SPDX-FileCopyrightText: 2024-2026 Marek Paśnikowski (define-module (deployment systems aisaka) #:use-module (guix gexp) #:use-module ((deployment keys) #:prefix deployment:keys:) #:use-module ((gnu bootloader) #:prefix gnu:bootloader:) #:use-module ((gnu bootloader grub) #:prefix gnu:bootloader:grub:) #:use-module ((gnu packages) #:prefix gnu:packages:) #:use-module ((gnu packages linux) #:prefix gnu:packages:linux:) #:use-module ((gnu packages tls) #:prefix gnu:packages:tls:) #:use-module ((gnu packages version-control) #:prefix gnu:packages:version-control:) #:use-module ((gnu services) #:prefix gnu:services:) #:use-module ((gnu services base) #:prefix gnu:services:base:) #:use-module ((gnu services certbot) #:prefix gnu:services:certbot:) #:use-module ((gnu services cgit) #:prefix gnu:services:cgit:) #:use-module ((gnu services dns) #:prefix gnu:services:dns:) #:use-module ((gnu services mail) #:prefix gnu:services:mail:) #:use-module ((gnu services networking) #:prefix gnu:services:networking:) #:use-module ((gnu services shepherd) #:prefix gnu:services:shepherd:) #:use-module ((gnu services ssh) #:prefix gnu:services:ssh:) #:use-module ((gnu services version-control) #:prefix gnu:services:version-control:) #:use-module ((gnu services web) #:prefix gnu:services:web:) #:use-module ((gnu system) #:prefix gnu:system:) #:use-module ((gnu system accounts) #:prefix gnu:system:accounts:) #:use-module ((gnu system file-systems) #:prefix gnu:system:file-systems:) #:use-module ((gnu system keyboard) #:prefix gnu:system:keyboard:) #:use-module ((gnu system shadow) #:prefix gnu:system:shadow:) #:use-module ((nongnu packages linux) #:prefix nongnu:packages:linux:) #:use-module ((nongnu system linux-initrd) #:prefix nongnu:system:linux-initrd:) #:use-module ((sovereign devices) #:prefix sovereign:devices:) #:use-module ((sovereign devices amd64) #:prefix sovereign:devices:amd64:) #:use-module ((sovereign packages jekyll) #:prefix sovereign:packages:jekyll:) #:use-module ((sovereign systems) #:prefix sovereign:systems:) #:use-module ((users id1000) #:prefix users:id1000:) #:use-module ((users vmail) #:prefix users:vmail:)) (define system-name "aisaka") (define ip-multimedia "81.190.248.246") (define ip-otvarta "95.171.119.109") (define spf-value (string-append "\"v=spf1 ip4:" ip-otvarta " -all\"")) (define ttl "3600") (gnu:services:dns:define-zone-entries marekpasnikowski.pl-entries ("@" ttl "IN" "A" ip-multimedia) ("ns" ttl "IN" "A" ip-multimedia) ("@" ttl "IN" "NS" "ns.marekpasnikowski.pl.") ("ns1" ttl "IN" "A" ip-multimedia) ("@" ttl "IN" "NS" "ns1.marekpasnikowski.pl.") ("mx" ttl "IN" "A" ip-otvarta) ("@" ttl "IN" "MX" "10 mx1.forwardemail.net.") ("@" ttl "IN" "MX" "10 mx2.forwardemail.net.") ;("@" ttl "IN" "MX" "20 mx.marekpasnikowski.pl.") ("@" ttl "IN" "TXT" "\"forward-email-port=49152\"") ("@" ttl "IN" "TXT" "\"forward-email=marekpasnikowski.pl\"") ("@" ttl "IN" "TXT" spf-value) ("_caldavs._tcp" ttl "IN" "SRV" "10 0 443 radicale.marekpasnikowski.pl") ("_carddavs._tcp" ttl "IN" "SRV" "10 0 443 radicale.marekpasnikowski.pl") ("_dmarc" ttl "IN" "TXT" "\"v=DMARC1; p=reject; sp=reject; pct=100; aspf=s; adkim=s; fo=1; rua=mailto:abuse@marekpasnikowski.pl; ruf=mailto:abuse@marekpasnikowski.pl\"") ("dkim._domainkey" ttl "IN" "TXT" "\"v=DKIM1; d=marekpasnikowski.pl; t=s; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo/b/WV5EUxqAhBgJ4v5K3sP8QI+IwziRJ/F9SDO3p3QOMjZd9AGVt2/AztZ4EmcOJnTlbQnLE/DKCOq4HAdxSZjIqj5AXyMddvWiO78+ugdame/flV0tjdDGNflx65Twap3qgJ9jzhvJfZ1BDuh2WC06fn2pyFl1TCETEGp6ZDkI41FW5GH8l9Jk7hhCmr+Mau0EpE7V42lBdireItOA1e7jQcub50584QATme4rYxA7WR4AeIsknOkUo4q8vkVrssoP11nSg/sNM9RGn1QDfVMJRX0twtgGnJ8N5QE4Ia9DvXL4Y0PNMC0/frp13pB6m1VQP/Z4jfDy+TQzEdSRaQIDAQAB\"") ("git" ttl "IN" "A" ip-multimedia) ("radicale" ttl "IN" "A" ip-multimedia) ("schron" ttl "IN" "A" ip-multimedia) ("sejf" ttl "IN" "A" ip-multimedia) ("test" ttl "IN" "A" ip-multimedia) ("www" ttl "IN" "A" ip-multimedia)) (define marekpasnikowski.pl-zone (gnu:services:dns:zone-file (entries marekpasnikowski.pl-entries) (origin "marekpasnikowski.pl") (ns "ns.marekpasnikowski.pl.") (mail "marek.marekpasnikowski.pl.") (serial 2026010903))) (define master-zone (gnu:services:dns:knot-zone-configuration (domain "marekpasnikowski.pl") (zone marekpasnikowski.pl-zone))) (define knot-configuration (gnu:services:dns:knot-configuration (listen-v4 "192.168.10.2") (zones (list master-zone)))) (define knot (gnu:services:service gnu:services:dns:knot-service-type knot-configuration)) (define radicale-keys "/secrets/radicale/keys") (define dovecot-keys "/secrets/dovecot") (define nginx-account (gnu:system:accounts:user-account (name "nginx") (group "nginx") (supplementary-groups '("git")) (system? #t) (comment "nginx server user") (home-directory "/var/empty") (shell (file-append (gnu:packages:specification->package "shadow") "/sbin/nologin")))) (define nginx-group (gnu:system:accounts:user-group (name "nginx") (system? #t))) (define nginx-accounts (let ((accounts- (list nginx-group nginx-account))) (const accounts-))) (define nginx-extension-of-account (gnu:services:service-extension gnu:system:shadow:account-service-type nginx-accounts)) (define (extend-account extension) (let* ((extension-target- (gnu:services:service-extension-target extension)) (account-service-type?- (eq? extension-target- gnu:system:shadow:account-service-type))) (if account-service-type?- nginx-extension-of-account extension))) (define nginx-service-type* (let ((nginx-extensions- (gnu:services:service-type-extensions gnu:services:web:nginx-service-type))) (gnu:services:service-type (inherit gnu:services:web:nginx-service-type) (extensions (map extend-account nginx-extensions-))))) (define cgit-repository-configuration (gnu:services:cgit:repository-cgit-configuration (hide? #t) (path "/srv/git/marek/packages"))) (define git-http-configuration (gnu:services:version-control:git-http-configuration (git-root "/var/lib/gitolite/repositories") (uri-path "/git"))) (define nginx-extension-of-cgit (gnu:services:service-extension nginx-service-type* gnu:services:cgit:cgit-configuration-nginx-config)) (define (extend-cgit extension) (let* ((extension-target- (gnu:services:service-extension-target extension)) (nginx-service-type?- (eq? extension-target- gnu:services:web:nginx-service-type))) (if nginx-service-type?- nginx-extension-of-cgit extension))) (define cgit-type (let ((cgit-extensions- (gnu:services:service-type-extensions gnu:services:cgit:cgit-service-type))) (gnu:services:service-type (inherit gnu:services:cgit:cgit-service-type) (extensions (map extend-cgit cgit-extensions-))))) (define nginx-location-cgit (gnu:services:web:nginx-location-configuration (body (list "fastcgi_param HTTP_HOST $server_name ;" "fastcgi_param PATH_INFO $uri ;" "fastcgi_param QUERY_STRING $args ;" "fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi ;" "fastcgi_pass 127.0.0.1:9000 ;")) (uri "@cgit"))) (define nginx-location-proxy (gnu:services:web:nginx-location-configuration (body (list "proxy_pass http://localhost:5232/ ;" "proxy_set_header X-Script-Name \"\" ;" "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;" "proxy_set_header Host $http_host ;" "proxy_pass_header Authorization ;")) (uri "/"))) (define nginx-location-proxy-auth (gnu:services:web:nginx-location-configuration (body (list "proxy_set_header Host $host;" "proxy_set_header X-Real-IP $remote_addr;" "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;" "proxy_set_header X-Forwarded-Proto $scheme;" "if ($ssl_client_verify != SUCCESS) {return 403;}")) (uri "/"))) (define nginx-location-well-known (gnu:services:web:nginx-location-configuration (body (list "root /srv/www/marek/marekpasnikowski.pl ;")) (uri "/.well-known"))) (define nginx-server-cgit (let ((git-http- (gnu:services:version-control:git-http-nginx-location-configuration git-http-configuration))) (gnu:services:web:nginx-server-configuration (locations (list git-http- nginx-location-cgit nginx-location-well-known)) (listen (list "192.168.10.2:443 ssl")) (root gnu:packages:version-control:cgit) (server-name (list "git.marekpasnikowski.pl")) (ssl-certificate "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem") (ssl-certificate-key "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem") (try-files (list "$uri" "@cgit"))))) (define nginx-server-portal (gnu:services:web:nginx-server-configuration (locations (list nginx-location-well-known)) (listen (list "192.168.10.2:443 ssl")) (root "/home/marek/Publiczne/www") (server-name (list "marekpasnikowski.pl")) (ssl-certificate "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem") (ssl-certificate-key "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem"))) (define nginx-server-radicale (gnu:services:web:nginx-server-configuration (locations (list nginx-location-proxy nginx-location-well-known)) (listen (list "192.168.10.2:443 ssl")) (server-name (list "radicale.marekpasnikowski.pl")))) (define nginx-server-schron (gnu:services:web:nginx-server-configuration (locations (list nginx-location-proxy-auth)) (listen (list "192.168.10.2:443 ssl")) (root "/home/marek/Publiczne/schron") (server-name (list "schron.marekpasnikowski.pl")) (ssl-certificate "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem") (ssl-certificate-key "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem") (raw-content (list "ssl_client_certificate /secrets/ca/intermediate/certs/ca-chain.cert.pem;" "ssl_verify_client on;")))) (define nginx-server-sejf (gnu:services:web:nginx-server-configuration (locations (list nginx-location-proxy-auth)) (listen (list "192.168.10.2:443 ssl")) (root "/home/marek/Publiczne/sejf") (server-name (list "sejf.marekpasnikowski.pl")) (ssl-certificate "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem") (ssl-certificate-key "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem") (raw-content (list "ssl_client_certificate /secrets/ca/intermediate/certs/ca-chain.cert.pem;" "ssl_verify_client on;")))) (define nginx-server-test (gnu:services:web:nginx-server-configuration (locations (list nginx-location-proxy-auth)) (listen (list "192.168.10.2:443 ssl")) (root "/home/marek/Publiczne/schron") (server-name (list "test.marekpasnikowski.pl")) (ssl-certificate "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem") (ssl-certificate-key "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem") (raw-content (list "ssl_client_certificate /secrets/ca/intermediate/certs/ca-chain.cert.pem;" "ssl_verify_client on;")))) (define nginx-server-www (gnu:services:web:nginx-server-configuration (listen (list "192.168.10.2:443 ssl")) (root "/home/marek/Publiczne/www") (server-name (list "www.marekpasnikowski.pl")))) (define cgit-configuration (gnu:services:cgit:cgit-configuration (nginx (list nginx-server-cgit)) (repositories (list cgit-repository-configuration)) (project-list (list "deployment.git" "nonguix.git" "sovereign.git")) (repository-directory "/var/lib/gitolite/repositories"))) (define nginx-configuration* (gnu:services:web:nginx-configuration (shepherd-requirement (list 'networking)) (server-blocks (list nginx-server-portal nginx-server-www nginx-server-test nginx-server-schron nginx-server-sejf nginx-server-radicale)))) (define nginx-deploy-hook-file #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) (kill pid SIGHUP))) (define nginx-extension-of-certbot (gnu:services:service-extension nginx-service-type* (@@ (gnu services certbot) certbot-nginx-server-configurations))) (define (extend-certbot extension) (let* ((extension-target- (gnu:services:service-extension-target extension)) (nginx-service-type?- (eq? extension-target- gnu:services:web:nginx-service-type))) (if nginx-service-type?- nginx-extension-of-certbot extension))) (define certbot-type (let ((certbot-extensions- (gnu:services:service-type-extensions gnu:services:certbot:certbot-service-type))) (gnu:services:service-type (inherit gnu:services:certbot:certbot-service-type) (extensions (map extend-certbot certbot-extensions-))))) (define certificate-configuration (gnu:services:certbot:certificate-configuration (deploy-hook (program-file "nginx-deploy-hook" nginx-deploy-hook-file)) (domains (list "marekpasnikowski.pl" "git.marekpasnikowski.pl" "radicale.marekpasnikowski.pl" "schron.marekpasnikowski.pl" "sejf.marekpasnikowski.pl" "test.marekpasnikowski.pl" "www.marekpasnikowski.pl")))) (define certbot-configuration (gnu:services:certbot:certbot-configuration (certificates (list certificate-configuration)) (email "marek@marekpasnikowski.pl") (webroot "/srv/www/marek/marekpasnikowski.pl"))) (define certbot (gnu:services:service certbot-type certbot-configuration)) (define cgit (gnu:services:service cgit-type cgit-configuration)) (define etc (let* ((mailname-file- (plain-file "mailname" "marekpasnikowski.pl\n")) (mailname-link- (list "mailname" mailname-file-)) (etc-links- (list mailname-link-))) (gnu:services:simple-service 'etc-files gnu:services:etc-service-type etc-links-))) (define fcgiwrap-configuration (gnu:services:web:fcgiwrap-configuration (user "git") (group "git"))) (define fcgiwrap (gnu:services:service gnu:services:web:fcgiwrap-service-type fcgiwrap-configuration)) (define file-system-efi (gnu:system:file-systems:file-system (device (gnu:system:file-systems:file-system-label "AISAKA")) (mount-point "/boot") (type "vfat") (flags (list)) (options #f) (mount? #t) (mount-may-fail? #t) (needed-for-boot? #f) (check? #t) (skip-check-if-clean? #f) (repair 'preen) (create-mount-point? #f) (dependencies (list)) (shepherd-requirements (list)) (location (current-source-location)))) (define file-system-root (gnu:system:file-systems:file-system (device (gnu:system:file-systems:file-system-label "aisaka-root")) (mount-point "/") (type "ext4") (flags (list)) (options #f) (mount? #t) (mount-may-fail? #f) (needed-for-boot? #t) (check? #t) (skip-check-if-clean? #f) (repair 'preen) (create-mount-point? #f) (dependencies (list)) (shepherd-requirements (list)) (location (current-source-location)))) (define gitolite-rc-file (gnu:services:version-control:gitolite-rc-file (umask #o0027))) (define gitolite-configuration (gnu:services:version-control:gitolite-configuration (rc-file gitolite-rc-file) (admin-pubkey #f))) (define gitolite (gnu:services:service gnu:services:version-control:gitolite-service-type gitolite-configuration)) (define system-keyboard-layout (gnu:system:keyboard:keyboard-layout "pl")) (define nginx (gnu:services:service nginx-service-type* nginx-configuration*)) (define rakan-machine #~(build-machine (name "rakan") (systems (list "x86_64-linux" "i686-linux")) (user "marek") (host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFxlIhNlkWCNA+l/RiOJztB+VWhuJtDTUvSwwlE3MpgJ root@rakan") (private-key "/home/marek/.ssh/id_ed25519"))) (define guix-offload-rakan (gnu:services:base:guix-extension (authorized-keys (list deployment:keys:akashi-guix deployment:keys:rakan-guix)) (build-machines (list rakan-machine)))) (define offload-rakan (gnu:services:simple-service 'offload-rakan gnu:services:base:guix-service-type guix-offload-rakan)) (define openssh (gnu:services:service gnu:services:ssh:openssh-service-type)) (define radicale-auth-configuration (gnu:services:mail:radicale-auth-configuration (type 'htpasswd) (htpasswd-filename radicale-keys) (htpasswd-encryption 'plain))) (define radicale-storage-configuration (gnu:services:mail:radicale-storage-configuration (filesystem-folder "/data/radicale/collections"))) (define radicale-configuration (gnu:services:mail:radicale-configuration (auth radicale-auth-configuration) (storage radicale-storage-configuration))) (define radicale (gnu:services:service gnu:services:mail:radicale-service-type radicale-configuration)) (define enp1s0-address-4 (gnu:services:base:network-address (device "enp1s0") (value "192.168.10.2/24") (ipv6? #f))) (define enp2s0-address-4 (gnu:services:base:network-address (device "enp2s0") (value "192.168.1.2/24") (ipv6? #f))) (define enp1s0-route-4-default (gnu:services:base:network-route (destination "default") (source #f) (device #f) (ipv6? #f) (gateway "192.168.10.1"))) (define network-hardware (gnu:services:base:static-networking (addresses (list enp1s0-address-4 enp2s0-address-4)) (links (list)) (routes (list enp1s0-route-4-default)) (name-servers (list "192.168.10.1" "192.168.1.1")) (provision (list 'network-hardware)) (requirement (list)))) (define static-networking-configuration (list network-hardware)) (define static-networking (gnu:services:service gnu:services:networking:static-networking-service-type static-networking-configuration)) (define ip-command (file-append gnu:packages:linux:iproute "/sbin/ip")) (define network-enp2s0-route-default (let ((route-default- #~(list #$ip-command "route" "add" "default" "via" "192.168.1.1" "table" "1"))) (gnu:services:shepherd:shepherd-service (provision (list 'network-enp2s0-route-default)) (requirement (list 'network-enp2s0-table)) (one-shot? #t) (respawn? #f) (start #~(make-forkexec-constructor #$route-default-)) (stop #~(const #f)) (actions (list)) (auto-start? #t) (documentation "Sets up a default route for traffic from enp2s0.") (modules gnu:services:shepherd:%default-modules)))) (define network-enp2s0-table (let ((table- #~(list #$ip-command "rule" "add" "from" "192.168.1.2" "table" "1" "prio" "1"))) (gnu:services:shepherd:shepherd-service (provision (list 'network-enp2s0-table)) (requirement (list 'network-hardware)) (one-shot? #t) (respawn? #f) (start #~(make-forkexec-constructor #$table-)) (stop #~(const #f)) (actions (list)) (auto-start? #t) (documentation "Defines a table of rules number 1 for routes through enp2s0.") (modules gnu:services:shepherd:%default-modules)))) (define networking (gnu:services:shepherd:shepherd-service (provision (list 'networking)) (requirement (list 'network-enp2s0-table 'network-enp2s0-route-default)) (one-shot? #t) (respawn? #f) (start #~(const #t)) (stop #~(const #f)) (actions (list)) (auto-start? #t) (documentation "Defines a graph root of one-shot services to invoke various ip commands.") (modules gnu:services:shepherd:%default-modules))) (define iproute2-networking (let ((extensions- (list network-enp2s0-table network-enp2s0-route-default networking))) (gnu:services:simple-service 'networking gnu:services:shepherd:shepherd-root-service-type extensions-))) (define swap-device-izumi-1-label (gnu:system:file-systems:file-system-label "izumi-swap-f")) (define %sovereign-services* (gnu:services:modify-services sovereign:systems:%sovereign-services (gnu:services:delete gnu:services:networking:network-manager-service-type))) (define system-bootloader (gnu:bootloader:bootloader-configuration (bootloader gnu:bootloader:grub:grub-efi-bootloader) (targets (list "/boot")) (keyboard-layout sovereign:devices:pl-keyboard-layout))) (define vmail-group (gnu:system:accounts:user-group (name "vmail") (system? #t))) (define-public system (let* ((home-environments- (list users:id1000:name/home-environment)) (home-service- (sovereign:systems:guix-home-service home-environments-))) (gnu:system:operating-system (bootloader system-bootloader) (label (sovereign:systems:operating-system-label* system-name gnu:system:this-operating-system)) (kernel nongnu:packages:linux:linux) (keyboard-layout system-keyboard-layout) (initrd nongnu:system:linux-initrd:microcode-initrd) (firmware (list nongnu:packages:linux:linux-firmware)) (host-name system-name) (file-systems (cons* file-system-root file-system-efi gnu:system:file-systems:%base-file-systems)) (users (cons* users:id1000:uid1000-account users:vmail:vmail-account gnu:system:shadow:%base-user-accounts)) (groups (cons* vmail-group gnu:system:shadow:%base-groups)) (packages (cons* sovereign:packages:jekyll:custom-jekyll gnu:packages:tls:openssl gnu:system:%base-packages)) (timezone "Europe/Warsaw") (locale sovereign:systems:pl-locale) (locale-definitions sovereign:systems:%sovereign-locale-definitions) (services (cons* users:id1000:dkim-service users:id1000:dovecot-service users:id1000:smtp-service knot certbot cgit etc fcgiwrap gitolite home-service- nginx offload-rakan openssh radicale static-networking iproute2-networking %sovereign-services*)) (sudoers-file sovereign:systems:%sovereign-sudoers-specification)))) (define-public operating-system* system)