summaryrefslogtreecommitdiff
path: root/bluechateau/systems
diff options
context:
space:
mode:
authorAzalea Redmyer <azalea@grrlz.net>2026-02-05 20:33:37 -0800
committerAzalea Redmyer <azalea@grrlz.net>2026-02-05 20:33:37 -0800
commit355f1bd0fabf2667fa8ce05b083af67b491f5176 (patch)
tree50a07e58080097a742d686e86b7a414febdfd1f4 /bluechateau/systems
parentce9701aca45b19ea95176d72871fe37383edc4b5 (diff)
Add 'chinstrap' server configuration & supporting files
Diffstat (limited to 'bluechateau/systems')
-rw-r--r--bluechateau/systems/chinstrap.scm501
1 files changed, 501 insertions, 0 deletions
diff --git a/bluechateau/systems/chinstrap.scm b/bluechateau/systems/chinstrap.scm
new file mode 100644
index 0000000..bc6ba82
--- /dev/null
+++ b/bluechateau/systems/chinstrap.scm
@@ -0,0 +1,501 @@
+;; =======================================================================
+;; 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 networking)
+ #:use-module (gnu services ssh)
+ ;;#:use-module (gnu services version-control)
+ #: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"
+ "git.bluechateau.org"
+ "search.bluechateau.org"
+ "fwiki.bluechateau.org"
+ "vtt.bluechateau.org"
+ "docs.bluechateau.org"
+ "sbdocs.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")))))
+
+;; 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"))))
+
+;; 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://docs.bluechateau.org',
+ httpSafeOrigin: 'https://sbdocs.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://docs.bluechateau.org"
+ "CPAD_SANDBOX_DOMAIN=https://sbdocs.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 '("docs.bluechateau.org"
+ "sbdocs.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"))
+ %base-packages))
+
+ (services
+ (append
+ (list
+ ;; Basic system services
+ (service dhcpcd-service-type)
+ (service dbus-root-service-type)
+ (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
+ (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")
+ (certificates
+ (list
+ (certificate-configuration
+ (name "bluechateau")
+ (domains ssl-domains))))))
+
+ ;; 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))))
+
+ git-fcgiwrap-service
+ gitolite-service
+ cgit-service)
+ %base-services))))
+
+chinstrap