;;; SPDX-License-Identifier: GPL-3.0-or-later ;;; SPDX-FileCopyrightText: 2024-2026 Marek Paśnikowski (define-module (deployment services web) #:export (aisaka-certbot-service aisaka-nginx-service nginx-location-well-known nginx-service-type*) #:use-module (gnu services) #:use-module (gnu services web) #:use-module (guix gexp) #:use-module ((gnu packages matrix) #:prefix gnu:packages:matrix:) #:use-module ((gnu services certbot) #:prefix gnu:services:certbot:) #:use-module ((gnu system shadow) #:prefix gnu:system:shadow:) #:use-module ((sovereign system accounts) #:prefix sovereign:system:accounts:)) (define nginx-accounts (let ((accounts- (list sovereign:system:accounts:nginx-group sovereign:system:accounts:nginx-account))) (const accounts-))) (define nginx-extension-of-account (service-extension gnu:system:shadow:account-service-type nginx-accounts)) (define (extend-account extension) (let* ((extension-target- (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- (service-type-extensions nginx-service-type))) (service-type (inherit nginx-service-type) (extensions (map extend-account nginx-extensions-))))) (define nginx-location-proxy-guix (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-matrix (nginx-location-configuration (body (list "proxy_pass http://localhost:8008 ;" "proxy_set_header X-Forwarded-For $remote_addr ;" "proxy_set_header X-Forwarded-Proto $scheme ;" "proxy_set_header Host $host:$server_port ;" "client_max_body_size 1024M ;")) (uri "~ ^(/_matrix|/_synapse/client)"))) (define nginx-location-proxy-radicale (nginx-location-configuration (body (list "proxy_pass http://localhost:8080/ ;" "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 (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 (nginx-location-configuration (body (list "root /srv/www/marek/marekpasnikowski.pl ;")) (uri "/.well-known"))) (define nginx-location-well-known-matrix-client (nginx-location-configuration (body (list "return 200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.marekpasnikowski.pl\"}}' ;" "default_type application/json ;" "add_header Access-Control-Allow-Origin * ;")) (uri "/.well-known/matrix/client"))) (define nginx-server-guix (nginx-server-configuration (locations (list nginx-location-proxy-guix)) (listen (list "192.168.10.2:443 ssl")) (server-name (list "guix.marekpasnikowski.pl")) (ssl-certificate "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem") (ssl-certificate-key "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem"))) (define nginx-server-matrix (nginx-server-configuration (locations (list nginx-location-proxy-matrix)) (listen (list "192.168.10.2:443 ssl" "192.168.10.2:8448 ssl default_server")) (root (file-append gnu:packages:matrix:synapse "/lib/python3.11/site-packages/synapse/static")) (server-name (list "matrix.marekpasnikowski.pl")) (ssl-certificate "/etc/letsencrypt/live/marekpasnikowski.pl/fullchain.pem") (ssl-certificate-key "/etc/letsencrypt/live/marekpasnikowski.pl/privkey.pem") (raw-content (list "proxy_http_version 1.1 ;")))) (define nginx-server-portal (nginx-server-configuration (locations (list nginx-location-well-known nginx-location-well-known-matrix-client)) (listen (list "192.168.10.2:443 ssl")) (root "/home/marek/Publiczne/www") (server-name (list 'default "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 (nginx-server-configuration (locations (list nginx-location-proxy-radicale nginx-location-well-known)) (listen (list "192.168.10.2:443 ssl")) (server-name (list "radicale.marekpasnikowski.pl")))) (define nginx-server-schron (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 (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 (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 (nginx-server-configuration (listen (list "192.168.10.2:443 ssl")) (root "/home/marek/Publiczne/www") (server-name (list "www.marekpasnikowski.pl")))) (define nginx-configuration* (nginx-configuration (shepherd-requirement (list 'networking)) (server-blocks (list nginx-server-portal nginx-server-www nginx-server-guix nginx-server-matrix nginx-server-test nginx-server-schron nginx-server-sejf nginx-server-radicale)))) (define aisaka-nginx-service (service nginx-service-type* nginx-configuration*)) (define nginx-extension-of-certbot (service-extension nginx-service-type* (@@ (gnu services certbot) certbot-nginx-server-configurations))) (define (extend-certbot extension) (let* ((extension-target- (service-extension-target extension)) (nginx-service-type?- (eq? extension-target- nginx-service-type))) (if nginx-service-type?- nginx-extension-of-certbot extension))) (define certbot-type (let ((certbot-extensions- (service-type-extensions gnu:services:certbot:certbot-service-type))) (service-type (inherit gnu:services:certbot:certbot-service-type) (extensions (map extend-certbot certbot-extensions-))))) (define nginx-deploy-hook-file #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) (kill pid SIGHUP))) (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" "guix.marekpasnikowski.pl" "matrix.marekpasnikowski.pl" "mx.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 aisaka-certbot-service (service certbot-type certbot-configuration)) ;;; EOF