;; ======================================================================= ;; Guix System configuration for my local server-in-a-closet, `chinstrap`. ;; ======================================================================= ;; ;; TODO: I'd like to split this into separate files. I would also like to ;; rewrite this as a 'literate' configuration at some point in the future. (define-module (bluechateau systems chinstrap) #:use-module (gnu) #:use-module (gnu packages databases) #:use-module (gnu packages emacs) #:use-module (gnu packages guile-xyz) #:use-module (gnu packages ssh) #:use-module (gnu packages version-control) #:use-module (gnu packages web) #:use-module (gnu services admin) #:use-module (gnu services certbot) #:use-module (gnu services cgit) #:use-module (gnu services containers) #:use-module (gnu services dbus) #:use-module (gnu services databases) #:use-module (gnu services desktop) #:use-module (gnu services docker) #:use-module (gnu services dns) #:use-module (gnu services messaging) #:use-module (gnu services networking) #:use-module (gnu services ssh) #:use-module (gnu services virtualization) #:use-module (gnu services web) #:use-module (gnu system) #:use-module (guix gexp) #:use-module (nongnu packages linux) #:use-module (nongnu system linux-initrd) #:use-module (bluechateau services version-control)) (define ssl-domains '("bluechateau.org" "www.bluechateau.org" ;; CGit "git.bluechateau.org" ;; SearXNG "search.bluechateau.org" ;; lemmy.sdf.org "Funhole" wiki mirror "fwiki.bluechateau.org" ;; PlanarAlly "vtt.bluechateau.org" ;; CryptPad "pad.bluechateau.org" "padsandbox.bluechateau.org" ;; XMPP via Prosody "xmpp.bluechateau.org" )) (define nginx-accounts (list (user-group (name "nginx") (system? #t)) (user-account (name "nginx") (group "nginx") (supplementary-groups '("git")) (system? #t) (comment "nginx server user") (home-directory "/var/empty") (shell (file-append (specification->package "shadow") "/sbin/nologin"))))) (define (nginx-signal name signal) (program-file name #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) (kill pid #$signal)))) ;; Override the default nginx service account configuration so ;; the nginx user is a member of the 'git' group. (required for ;; cgit) (define nginx-service-type* (service-type (inherit nginx-service-type) (extensions (map (lambda (extension) (if (eq? (service-extension-target extension) account-service-type) (service-extension account-service-type (const nginx-accounts)) extension)) (service-type-extensions nginx-service-type))))) (define blog-nginx-server-configuration (nginx-server-configuration (listen '("443 ssl")) (server-name '("bluechateau.org")) (root "/srv/blog/site/") (ssl-certificate "/etc/certs/bluechateau/fullchain.pem") (ssl-certificate-key "/etc/certs/bluechateau/privkey.pem"))) (define git-fcgiwrap-service (service fcgiwrap-service-type (fcgiwrap-configuration ;; Use 'git' user to read from the Git repositories. (user "git") (socket "tcp:127.0.0.1:9000")))) ;; XMPP via Prosody (define prosody-service (service prosody-service-type (prosody-configuration (plugin-paths '("/srv/lib/prosody-modules-enabled")) (modules-enabled (cons* "groups" "mam" "smacks" "user_account_management" "http_file_share" "cloud_notify" "cloud_notify_encrypted" "cloud_notify_extensions" %default-modules-enabled)) (virtualhosts (list (virtualhost-configuration (domain "xmpp.bluechateau.org")))) ;;(certificates "/etc/certs/bluechateau") ))) ;; Gitolite (git repository hosting) (define gitolite-service (service gitolite-service-type (gitolite-configuration (admin-pubkey (local-file "../../keys/azalea.pub")) (home-directory "/srv/git") (rc-file (gitolite-rc-file ;; Grant read access to 'git' group so ;; cgit will work. (umask #o0027) ;; In order to hide repositories in cgit, ;; this value must be set. (git-config-keys ".*") (extra-content "WRITER_CAN_UPDATE_DESC => 1")))))) ;; CGit (git repository browser) (define cgit-service (let ((cgit (specification->package "cgit"))) (service (service-type (inherit cgit-service-type) (extensions ;; Replace original nginx-service with ;; the modified one. (map (lambda (extension) (if (eq? (service-extension-target extension) nginx-service-type) (service-extension nginx-service-type* cgit-configuration-nginx-config) extension)) (service-type-extensions cgit-service-type)))) (cgit-configuration (repository-directory "/srv/git/repositories") (root-desc "Move slow and build things.") (enable-git-config? #t) (enable-http-clone? #f) (enable-index-links? #t) (enable-index-owner? #f) (enable-commit-graph? #t) (enable-log-filecount? #t) (enable-log-linecount? #t) (remove-suffix? #t) (clone-url '("https://git.bluechateau.org/$CGIT_REPO_URL.git")) ;; Source code syntax highlighting wrapper script. (source-filter (program-file "cgit-syntax-highlight" #~(apply execl (string-append #$cgit "/lib/cgit/filters/syntax-highlighting.py") (command-line)))) (nginx (list (nginx-server-configuration (listen '("443 ssl")) (server-name '("git.bluechateau.org")) (root cgit) (ssl-certificate "/etc/certs/bluechateau/fullchain.pem") (ssl-certificate-key "/etc/certs/bluechateau/privkey.pem") (locations (list (nginx-location-configuration (uri "~ (/.*\\.git/.*)") (body `("fastcgi_pass 127.0.0.1:9000;" ("fastcgi_param SCRIPT_FILENAME " ,git "/libexec/git-core/git-http-backend;") "fastcgi_param QUERY_STRING $query_string;" "fastcgi_param REQUEST_METHOD $request_method;" "fastcgi_param CONTENT_TYPE $content_type;" "fastcgi_param CONTENT_LENGTH $content_length;" "fastcgi_param GIT_PROJECT_ROOT /srv/git/repositories;" "fastcgi_param PATH_INFO $1;"))) (git-http-nginx-location-configuration (git-http-configuration (uri-path "/") (git-root "/srv/git/repositories") (export-all? #t))) (nginx-location-configuration (uri "~ (/.*)\\.git") (body '("return 301 $1;"))) (nginx-location-configuration (uri "/") (body '("try_files $uri @cgit;"))) (nginx-location-configuration (uri "@cgit") (body '("fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi;" "fastcgi_param PATH_INFO $uri;" "fastcgi_param QUERY_STRING $args;" "fastcgi_param HTTP_HOST $server_name;" "fastcgi_pass 127.0.0.1:9000;")))))))))))) (define searxng-oci-container-configuration (oci-container-configuration (image "docker.io/searxng/searxng") (ports '(("8888" . "8080"))) (volumes '("searx-config:/etc/searxng/" "searx-data:/var/cache/searxng/")))) (define searxng-nginx-server-configuration (nginx-server-configuration (listen '("443 ssl")) (server-name '("search.bluechateau.org")) (ssl-certificate "/etc/certs/bluechateau/fullchain.pem") (ssl-certificate-key "/etc/certs/bluechateau/privkey.pem") (locations (list (nginx-location-configuration (uri "/") (body '("proxy_pass http://localhost:8888;" "proxy_set_header X-Real-IP $remote_addr;" "proxy_set_header Host $host;" "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;"))))))) (define cryptpad-config (plain-file "config.js" "module.exports = { httpUnsafeOrigin: 'https://pad.bluechateau.org', httpSafeOrigin: 'https://padsandbox.bluechateau.org', httpAddress: '0.0.0.0', httpPort: 3000, websocketPort: 3003, adminKeys: [], filePath: './datastore/', archivePath: './data/archive', pinPath: './data/pins', taskPath: './data/tasks', blockPath: './block', blobPath: './blob', blobStagingPath: './data/blobstage', decreePath: './data/decrees', logPath: './data/logs', logToStdout: false, logLevel: 'info', logFeedback: false, verbose: false, installMethod: 'docker', };")) (define cryptpad-oci-container-configuration (oci-container-configuration (image "cryptpad/cryptpad") (ports '(("3000" . "3000") ("3003" . "3003"))) (volumes `("cryptpad-blob:/cryptpad/blob" "cryptpad-block:/cryptpad/block" "cryptpad-customize:/cryptpad/customize" "cryptpad-data:/cryptpad/data" "cryptpad-datastore:/cryptpad/datastore" "cryptpad-onlyoffice-dist:/cryptpad/www/common/onlyoffice/dist" "cryptpad-onlyoffice-conf:/cryptpad/onlyoffice-conf" (,cryptpad-config . "/cryptpad/config/config.js"))) (environment '("CPAD_MAIN_DOMAIN=https://pad.bluechateau.org" "CPAD_SANDBOX_DOMAIN=https://padsandbox.bluechateau.org" "CPAD_CONF=/cryptpad/config/config.js")) (extra-arguments '("-h cryptpad")))) (define cryptpad-nginx-server-configuration (nginx-server-configuration (listen '("443 ssl")) (server-name '("pad.bluechateau.org" "padsandbox.bluechateau.org")) (ssl-certificate "/etc/certs/bluechateau/fullchain.pem") (ssl-certificate-key "/etc/certs/bluechateau/privkey.pem") (raw-content '("ssl_dhparam /srv/cryptpad/dhparam.pem;" "ssl_session_timeout 1d;" "ssl_session_cache shared:MozSSL:10m;" "ssl_session_tickets off;" "ssl_protocols TLSv1.2 TLSv1.3;" "ssl_ciphers 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;" "ssl_prefer_server_ciphers off;" "add_header Strict-Transport-Security \"max-age=63072000; includeSubDomains\" always;")) (locations (list (nginx-location-configuration (uri "/") (body '("proxy_pass http://localhost:3000;" "proxy_set_header X-Real-IP $remote_addr;" "proxy_set_header Host $host;" "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;" "client_max_body_size 150m;" "proxy_http_version 1.1;" "proxy_set_header Upgrade $http_upgrade;" "proxy_set_header Connection upgrade;"))) (nginx-location-configuration (uri "^~ /cryptpad_websocket") (body '("proxy_pass http://localhost:3003;" "proxy_set_header X-Real-IP $remote_addr;" "proxy_set_header Host $host;" "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;" "proxy_http_version 1.1;" "proxy_set_header Upgrade $http_upgrade;" "proxy_set_header Connection upgrade;"))))))) (define planarally-config (plain-file "config.toml" "[general] save_file = \"data/planar.sqlite\" admin_user = \"azalea\" allow_signups = true enable_export = true max_log_size_in_bytes = 200000 max_log_backups = 5 [assets] max_single_asset_size_in_bytes = 0 max_total_asset_size_in_bytes = 0 [webserver] max_upload_size_in_bytes = 10485760 [webserver.connection] type = \"hostport\" host = \"0.0.0.0\" port = 8000")) (define planarally-oci-container-configuration (oci-container-configuration (image "kruptein/planarally") (ports '(("8000" . "8000"))) (volumes `("pa-data:/planarally/data" "pa-assets:/planarally/static/assets" "pa-mods:/planarally/static/mods" (,planarally-config . "/planarally/data/config.toml"))))) (define planarally-nginx-server-configuration (nginx-server-configuration (listen '("443 ssl")) (server-name '("vtt.bluechateau.org")) (ssl-certificate "/etc/certs/bluechateau/fullchain.pem") (ssl-certificate-key "/etc/certs/bluechateau/privkey.pem") (locations (list (nginx-location-configuration (uri "/") (body '("proxy_set_header Host $http_host;" "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;" "proxy_redirect off;" "proxy_buffering off;" "proxy_set_header X-Real-IP $remote_addr;" "proxy_pass http://localhost:8000;"))) (nginx-location-configuration (uri "/socket.io/") (body '("proxy_http_version 1.1;" "proxy_set_header Upgrade $http_upgrade;" "proxy_set_header Connection \"Upgrade\";" "proxy_set_header Host $host;" "proxy_pass http://localhost:8000/socket.io/;"))))))) (define funhole-nginx-server-configuration (nginx-server-configuration (listen '("443 ssl")) (server-name '("fwiki.bluechateau.org")) (root "/srv/fwiki/") (ssl-certificate "/etc/certs/bluechateau/fullchain.pem") (ssl-certificate-key "/etc/certs/bluechateau/privkey.pem") (locations (list (nginx-location-configuration (uri "/") (body `(("default_type text/html;") "try_files $uri $uri/ =404;"))))))) (define chinstrap (operating-system (kernel linux) (firmware (list linux-firmware)) (initrd microcode-initrd) (locale "en_US.utf8") (timezone "America/Los_Angeles") (keyboard-layout (keyboard-layout "us")) (host-name "chinstrap") (users (cons* (user-account (name "moshimoshi") (comment "Captain 'Moshi-Moshi' Momo") (group "users") (home-directory "/home/moshimoshi") (supplementary-groups '("docker" "git" "netdev" "wheel"))) %base-user-accounts)) (bootloader (bootloader-configuration (bootloader grub-efi-bootloader) (targets (list "/boot/efi")) (keyboard-layout keyboard-layout))) (file-systems (cons* (file-system (mount-point "/boot/efi") (device (uuid "BBEC-EE14" 'fat32)) (type "vfat")) (file-system (mount-point "/") (device (uuid "74a221a4-2d9d-4250-b0de-cb5a6a5962ae" 'ext4)) (type "ext4")) %base-file-systems)) (swap-devices (list (swap-space (target (uuid "a46ba488-1ad1-4c5e-a4f6-e177d4c498aa"))))) (packages (append (map specification->package '("emacs" "git" "mercurial" "prosody")) %base-packages)) (services (append (list ;; Basic system services (service dhcpcd-service-type) (service dbus-root-service-type) (service dnsmasq-service-type (dnsmasq-configuration (no-resolv? #t) (cache-size 1000) (servers '("95.215.19.53")) ;; Use Njalla public DNS upstream (addresses '("/bluechateau.org/192.168.254.159")) )) (service elogind-service-type) ;; OpenSSH (service openssh-service-type (openssh-configuration (openssh openssh-sans-x) (port-number 22))) ;; Docker containers & virtual machines (service containerd-service-type) (service docker-service-type) (service libvirt-service-type (libvirt-configuration (unix-sock-group "libvirt") (tls-port "16555"))) (simple-service 'oci-service oci-service-type (oci-extension (networks (list (oci-network-configuration (name "host")))) (containers (list ;; SearXNG searxng-oci-container-configuration ;; CryptPad cryptpad-oci-container-configuration ;; PlanarAlly planarally-oci-container-configuration )))) ;; Certbot (TLS certificates) ;; Certbot extends nginx with configuration to ;; redirect all HTTP requests to HTTPS. (service (service-type (inherit certbot-service-type) (extensions ;; Replace original nginx-service with ;; the modified one. (map (lambda (extension) (if (eq? (service-extension-target extension) nginx-service-type) (service-extension nginx-service-type* (@@ (gnu services certbot) certbot-nginx-server-configurations)) extension)) (service-type-extensions certbot-service-type)))) (certbot-configuration (email "mononoke@anche.no") (webroot "/var/www/certbot") (certificates (list (certificate-configuration (name "bluechateau") (domains ssl-domains) ;; Send SIGHUP signal to nginx to trigger a ;; configuration reload, thus loading the ;; updated certificates. (deploy-hook (nginx-signal "nginx-deploy-hook" SIGHUP))))))) ;; NGINX (web hosting) ;; Be sure to use the custom service defined at the ;; top of this file! (service nginx-service-type* (nginx-configuration (server-blocks (list ;; Static content blog-nginx-server-configuration ;; SearXNG searxng-nginx-server-configuration ;; Funhole wiki mirror funhole-nginx-server-configuration ;; CryptPad cryptpad-nginx-server-configuration ;; PlanarAlly VTT planarally-nginx-server-configuration )))) prosody-service git-fcgiwrap-service gitolite-service cgit-service) %base-services)))) chinstrap