(define-module (tw system lud) #:use-module (gnu) #:use-module (gnu bootloader grub) #:use-module (gnu system locale) #:use-module (gnu system nss) #:use-module (guix gexp) #:use-module (tw packages php) #:use-module (tw system common)) (use-package-modules admin bash certs databases linux man php rsync shells version-control video) (use-service-modules certbot databases file-sharing mcron monitoring networking pm ssh syncthing vpn web) (define efi-system-partition ; /dev/sda1 (uuid "51F3-FB71" 'fat32)) (define guixsd-root-partition ; /dev/sda2 (uuid "c63af3e6-3c2b-43d2-b1e6-944f09a10e0f" 'btrfs)) (define backups-partition ; /dev/sdb1 (uuid "c6ac4033-cce6-4365-abcc-483b79c4ca36" 'btrfs)) (define data-partition ; /dev/sdc1 (uuid "4715ae0e-5cef-48f2-a59e-025321153888" 'btrfs)) (define httpd-cert-deploy-hook (program-file "httpd-cert-deploy-hook" #~(kill (call-with-input-file "/var/run/httpd" read) SIGHUP))) (define nextcloud-php.ini (computed-file "nextcloud-php.ini" #~(begin (use-modules (ice-9 popen) (ice-9 rdelim)) (let* ((php-config #$(file-append php "/bin/php-config")) (pipe (open-pipe* OPEN_READ php-config "--extension-dir")) (php-extdir (read-line pipe))) (unless (zero? (status:exit-val (close-pipe pipe))) (error "Failed to get PHP extension dir")) (with-output-to-file #$output ;; Guix's PHP comes with the following extensions built-in, ;; so no extension= line necessary: ;; pdo_mysql, bcmath, bz2, exif, gd, iconv, intl (lambda () (display (string-append "\ memory_limit=512M extension_dir=/run/current-system/profile/lib/php/extensions/" (basename php-extdir) " ; Caching extensions for Nextcloud extension=apcu apc.enable_cli=1 zend_extension=opcache ; https://www.php.net/manual/en/opcache.configuration.php opcache.enable=1 opcache.interned_strings_buffer=32 opcache.max_accelerated_files=10000 opcache.memory_consumption=128 opcache.save_comments=1 ; It will take up to revalidate_freq seconds for changes to config.php to be applied. opcache.revalidate_freq=120 ")))))))) (define httpd-intermediate-ssl-config "\ # SSL configuration. # https://ssl-config.mozilla.org/#server=apache&version=2.4.53&config=intermediate&openssl=1.1.1n&ocsp=false&guideline=5.6 SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 SSLHonorCipherOrder Off SSLSessionTickets Off SSLUseStapling On SSLStaplingCache \"shmcb:logs/ssl_stapling(32768)\" SSLSessionCache \"shmcb:logs/ssl_scache(65535)\" # 20 minutes -- default is 5 minutes, which is not long, and the cache # size is limited anyway above. SSLSessionCacheTimeout 1200 ") (define nextcloud-services (list (simple-service 'nextcloud-https-server httpd-service-type ;; The certbot service redirects everything on port 80 to ;; port 443 by default, modulo its own /.well-known paths. (list (httpd-virtualhost "*:443" (list "\ # For Nextcloud. ServerName cloud.wilkenfamily.de DocumentRoot /var/www/nextcloud SSLEngine on SSLCertificateFile \"/etc/letsencrypt/live/cloud.wilkenfamily.de/fullchain.pem\" SSLCertificateKeyFile \"/etc/letsencrypt/live/cloud.wilkenfamily.de/privkey.pem\" Header always set Strict-Transport-Security \"max-age=15552000\" # Don't check for .htaccess files above DocumentRoot. AllowOverride None Options +FollowSymlinks AllowOverride All Dav off SetEnv HOME /var/www/nextcloud SetEnv HTTP_HOME /var/www/nextcloud # Redirect to local php-fpm if mod_php is not available # Enable http authorization headers SetEnvIfNoCase ^Authorization$ \"(.+)\" HTTP_AUTHORIZATION=$1 SetHandler \"proxy:unix:/var/run/php-fpm.sock|fcgi://localhost/\" # Deny access to raw PHP sources and files without filename (e.g. '.php') Require all denied ")))) (service php-fpm-service-type (php-fpm-configuration (user "httpd") (group "httpd") (socket "/var/run/php-fpm.sock") (socket-user "httpd") (socket-group "httpd") (php-ini-file nextcloud-php.ini))) (simple-service 'nextcloud-certificates certbot-service-type (list (certificate-configuration (domains '("cloud.wilkenfamily.de")) (deploy-hook httpd-cert-deploy-hook)))) ;; Nextcloud cron (simple-service 'nextcloud-cron mcron-service-type (list #~(job "*/5 * * * *" (lambda () (chdir "/var/www/nextcloud") ;; `setgid' first while we're still root (setgid (group:gid (getgr "httpd"))) (setuid (passwd:uid (getpw "httpd"))) (execl #$(file-append php "/bin/php") "php" "-c" #$nextcloud-php.ini "cron.php")) (string-append #$(file-append php "/bin/php") " -c " #$nextcloud-php.ini " /var/www/nextcloud/cron.php")) ;; Nextcloud backups ;; Requires: sudo, php, btrfs, mysqldump, rsync (let ((backup-script (local-file "files/nextcloud-backup" #:recursive? #t))) #~(job "0 6 * * *" (lambda () ;; Pass through the php.ini file that allows us ;; to use Nextcloud's occ script. ;; Alternatively, set NEXTCLOUD_PHP_CONFIG. (execl #$backup-script "nextcloud-backup" #$nextcloud-php.ini)) (string-append #$backup-script " " #$nextcloud-php.ini))))))) (define matrix-services (list (simple-service 'synapse-certificates certbot-service-type (list (certificate-configuration (domains '("matrix.twilken.net")) (deploy-hook httpd-cert-deploy-hook)))) (simple-service 'synapse-https-proxy httpd-service-type ;; Synapse can't access certbot certs, but Apache/httpd ;; can, so proxy HTTPS access through. It's good to have ;; Synapse available on port 443 anyway. (list (httpd-virtualhost "*:443" (list "\ # Redirect to Synapse, to avoid having to specify its port number in Matrix clients. ServerName matrix.twilken.net SSLEngine on SSLCertificateFile \"/etc/letsencrypt/live/matrix.twilken.net/fullchain.pem\" SSLCertificateKeyFile \"/etc/letsencrypt/live/matrix.twilken.net/privkey.pem\" ProxyPass \"/\" \"https://127.0.0.1:48448/\" ")))) ;; TODO: Postgres for Synapse ;; (service postgresql-service-type ;; (postgresql-configuration ;; (postgresql postgresql-15) ;; (data-directory "/var/lib/postgresql/data"))) ;; (service postgresql-role-service-type ;; (postgresql-role-configuration ;; (roles (list (postgresql-role ;; (name "synapse") ; TODO ;; (create-database? #t)))))) ;; TODO: Matrix/Synapse ;; TODO: Matrix bridges )) (operating-system (host-name "lud.twilken.net") (timezone "Europe/Berlin") (locale "en_GB.utf8") (locale-definitions (list (locale-definition (name "en_GB.utf8") (source "en_GB")) (locale-definition (name "de_DE.utf8") (source "de_DE")) (locale-definition (name "fr_FR.utf8") (source "fr_FR")) (locale-definition (name "pt_BR.utf8") (source "pt_BR")) (locale-definition (name "en_US.utf8") (source "en_US")))) (hosts-file %wireguard-etc-hosts) ;; Allow resolution of '.local' host names with mDNS. (name-service-switch %mdns-host-lookup-nss) ;; Choose UK English console keyboard layout. (keyboard-layout %british-keyboard) ;; Packages installed system-wide. Users can also install packages ;; under their own account: use 'guix search KEYWORD' to search ;; for packages and 'guix install PACKAGE' to install a package. (packages (append (list ;; For nightly yt-dlp. ffmpeg ;; For Nextcloud backup script. btrfs-progs mariadb rsync ;; For Nextcloud. PHP modules must be installed in system ;; profile, as that's referred to in Nextcloud's php.ini. php php-apcu) %common-system-packages %base-packages)) ;; Below is the list of system services. To search for available ;; services, run 'guix system search KEYWORD' in a terminal. (services (append (list (service openssh-service-type (openssh-configuration (port-number 22022) (password-authentication? #f) (accepted-environment '("LANG" "LC_*")) (authorized-keys `(("timo" ,(local-file "files/timo.pub")) ("ira" ; for Duplicity backups ,(local-file "files/kitchen-pc.pub") ,(local-file "files/wilken-laptop.pub")))))) (service tor-service-type) (service dhcp-client-service-type) (service ntp-service-type) (service thermald-service-type (thermald-configuration (adaptive? #t))) (simple-service 'cronjobs mcron-service-type (list #~(job "0 21 * * *" "guix gc -d 2w -F 25G") #~(job "0 22 * * *" ; after guix gc (string-append #$(file-append util-linux "/sbin/fstrim") " --fstab --verbose")))) ;; Transmission (torrents) (service transmission-daemon-service-type (transmission-daemon-configuration (download-dir "/var/data/bt") (incomplete-dir "/var/data/bt/incomplete") (incomplete-dir-enabled? #t) (speed-limit-up-enabled? #t) (speed-limit-up 512) ; KiB/s (encryption 'require-encrypted-connections) ;; Don't try to configure port forwarding automatically. (port-forwarding-enabled? #f) ;; Make RPC interface only accessible via WireGuard. (rpc-bind-address "10.0.0.2") (rpc-whitelist-enabled? #t) (rpc-whitelist '("127.0.0.1" "::1" "10.0.0.*" "fc00::*")) (rpc-host-whitelist-enabled? #t) (rpc-host-whitelist '("lud.wg")))) ;; TODO: Streama ;; Syncthing (service syncthing-service-type (syncthing-configuration (user "syncthing") (group "syncthing"))) ;; certbot for Synapse + Apache/Nextcloud ;; This also installs a nginx server on port 80, redirecting to port 443. (service certbot-service-type (certbot-configuration (email "letsencrypt@twilken.net"))) (service httpd-service-type (httpd-configuration (config (httpd-config-file (listen '("443")) ; leave port 80 free for certbot/nginx (modules (cons* (httpd-module (name "ssl_module") (file "modules/mod_ssl.so")) (httpd-module (name "proxy_module") (file "modules/mod_proxy.so")) (httpd-module (name "rewrite_module") (file "modules/mod_rewrite.so")) (httpd-module (name "alias_module") (file "modules/mod_alias.so")) (httpd-module (name "socache_shmcb_module") ; for SSLStaplingCache (file "modules/mod_socache_shmcb.so")) (httpd-module (name "proxy_fcgi_module") ; for PHP/FastCGI (file "modules/mod_proxy_fcgi.so")) %default-httpd-modules)) ;; Preserve default value for `extra-config'. (extra-config (list "TypesConfig etc/httpd/mime.types\n" "ServerAdmin webmaster@twilken.net\n" httpd-intermediate-ssl-config)))))) ;; For Nextcloud (and Streama) (service mysql-service-type (mysql-configuration (extra-content "\ [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_general_ci # https://wiki.archlinux.org/title/Nextcloud skip_networking transaction_isolation = READ-COMMITTED # https://docs.nextcloud.com/server/stable/admin_manual/installation/server_tuning.html#using-mariadb-mysql-instead-of-sqlite innodb_buffer_pool_size = 1G innodb_io_capacity = 4000 "))) ;; Prometheus node exporter (service prometheus-node-exporter-service-type (prometheus-node-exporter-configuration (web-listen-address "10.0.0.2:9100"))) ;; TODO: JSON exporter (Nextcloud) ;; TODO: Syncthing exporter ;; TODO: Transmission exporter ;; TODO: git-daemon-service-type / cgit-service-type? (wireguard-service 'lud)) nextcloud-services matrix-services (modify-services %base-services (login-service-type config => (login-configuration (inherit config) (motd (plain-file "no-motd" "")) (allow-empty-passwords? #f)))))) ;; The list of user accounts ('root' is implicit). (users (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"))) (user-account ; TODO: merge with "timo"? (name "timo-phone") (comment "Backups of Timo's phone") (group "users") (home-directory "/var/backups/timo-phone") (shell (file-append bash-minimal "/bin/sh"))) (user-account (name "robin") (comment "Robin Wilken") (group "users") (home-directory "/home/robin")) (user-account (name "ira") (comment "Ira Wilken") (group "users") (home-directory "/home/ira")) (user-account (system? #t) (name "syncthing") (comment "Syncthing service") (group "syncthing") (home-directory "/var/data/syncthing")) %base-user-accounts)) (groups (cons* (user-group ; This is NOT implict from the "syncthing" user. (system? #t) (name "syncthing")) %base-groups)) ;; Use the UEFI variant of GRUB with the EFI System Partition mounted ;; on /boot/efi. (bootloader (bootloader-configuration (bootloader grub-efi-bootloader) (targets '("/boot/efi")) (keyboard-layout keyboard-layout))) ;; The list of file systems that get "mounted". The unique ;; file system identifiers there ("UUIDs") can be obtained ;; by running 'blkid' in a terminal. (file-systems (cons* (file-system (mount-point "/") (device guixsd-root-partition) (flags '(no-atime)) (options (alist->file-system-options '("ssd" ("compress" . "zstd")))) (type "btrfs")) (file-system (mount-point "/boot/efi") (device efi-system-partition) (flags '(no-atime)) (type "vfat")) (file-system (mount-point "/var/backups") (create-mount-point? #t) (device backups-partition) (flags '(no-atime)) (type "btrfs")) (file-system (mount-point "/var/data") (create-mount-point? #t) (device data-partition) (flags '(no-atime)) (type "btrfs")) %base-file-systems)))