diff options
Diffstat (limited to 'salamina.scm')
-rw-r--r-- | salamina.scm | 805 |
1 files changed, 805 insertions, 0 deletions
diff --git a/salamina.scm b/salamina.scm new file mode 100644 index 0000000..dd5618d --- /dev/null +++ b/salamina.scm @@ -0,0 +1,805 @@ +;; SPDX-License-Identifier: CC0-1.0 + +;; Copyright (C) 2022-2024 W. Kosior <koszko@koszko.org> +;; +;; Available under the terms of Creative Commons Zero v1.0 Universal. + +(use-modules ((srfi srfi-1) #:select (append-map)) + ((srfi srfi-26) #:select (cut)) + + ((ice-9 format) #:select (format)) + ((ice-9 match) #:select (match-lambda)) + + ((gnu bootloader) #:select (bootloader-configuration)) + ((gnu bootloader grub) #:select (grub-bootloader)) + + ((gnu packages) #:select (specifications->packages)) + ((gnu packages admin) #:select (shadow)) + ((gnu packages koszko-services) #:prefix ks:) + ((gnu packages python) #:select (guix-pythonpath-search-path)) + ((gnu packages web) #:select (httpd mod-wsgi)) + ((gnu packages version-control) #:select (git cgit)) + + ((gnu services) #:select + (activation-service-type service simple-service)) + ((gnu services base) #:select + (guix-service-type guix-extension %base-services)) + ((gnu services ssh) #:select + (openssh-service-type openssh-configuration)) + ((gnu services networking) #:select (dhcp-client-service-type)) + ((gnu services overlayfs) #:select + (overlayfs-service-type overlayfs-mount-configuration)) + ((gnu services web) #:prefix web:) + ((gnu services cgit) #:select + (cgit-configuration serialize-cgit-configuration)) + ((gnu services certbot) #:prefix cb:) + ((gnu services dns) #:prefix dns:) + ((gnu services mail) #:prefix mail:) + ((gnu services version-control) #:prefix vc:) + ((gnu services databases) #:select + (postgresql-service-type postgresql-configuration)) + + ((gnu system) #:select (%base-packages operating-system)) + ((gnu system file-systems) #:prefix fs:) + ((gnu system keyboard) #:select (keyboard-layout)) + ((gnu system shadow) #:prefix gss:) + + ((guix build-system python) #:select (default-python)) + ((guix gexp) #:select + (gexp local-file file-append plain-file program-file + mixed-text-file with-imported-modules)) + ((guix modules) #:select (source-module-closure)) + ((guix packages) #:select + (package-transitive-target-inputs package-version)) + ((guix search-paths) #:select (search-path-specification->sexp))) + +(define %services + %base-services) + +(define-syntax-rule (prepend list item) + (define list + (cons item list))) + +(prepend %services + (service dhcp-client-service-type)) + +(prepend %services + (simple-service 'always-forbid-root-login activation-service-type + #~(system "/run/setuid-programs/passwd -l root > /dev/null"))) + +(prepend %services + (simple-service 'guix-authorize-key guix-service-type + (guix-extension + (authorized-keys (list (local-file "guix-signing-key.pub")))))) + +(prepend %services + (service web:httpd-service-type + (web:httpd-configuration + (config + (web:httpd-config-file + (server-name "koszko.org") + (listen '("80" "443")) + (error-log "/var/log/httpd/error.log") + (modules (append + (map (lambda (name) + (let ((filename (format #f "/modules/mod_~a.so" name))) + (web:httpd-module + (name (string-append name "_module")) + (file (file-append httpd filename))))) + (list "cgid" + "logio" + "rewrite" + "ssl" + "proxy" + "proxy_http" + "headers")) + (list (web:httpd-module + (name "wsgi_module") + (file (file-append mod-wsgi "/modules/mod_wsgi.so")))) + web:%default-httpd-modules)) + (extra-config + (list "\ + LogFormat \"%>s %u %t \\\"%r\\\" %I in %O out \ +\\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\"\" combined + CustomLog /var/log/httpd/access.log combined + ScriptSock /var/run/cgid.sock + "))))))) + +(prepend %services + (simple-service 'acme-challenge-http-virtualhost web:httpd-service-type + (map (match-lambda + ((main-domain . other-domains) + (web:httpd-virtualhost + "*:80" + `("\ + ServerName " ,main-domain " + " ,(format #f "~{ServerAlias ~a~^~%~}" other-domains) " + ServerAdmin webmaster@koszko.org + <If \"%{HTTP_HOST} != '" ,main-domain "'\"> + Redirect permanent / http://" ,main-domain "/ + </If> + #<ElseIf \"true && (%{REQUEST_URI} !~ \ + # m#^/[.]well-known/acme-challenge/.*#)\"> + # Redirect permanent / https://" ,main-domain "/ + #</ElseIf> + DocumentRoot /var/empty + Alias /.well-known/acme-challenge \ + /var/certbot-validation/.well-known/acme-challenge + ")))) + '(("koszko.org" "www.koszko.org" + "koszkonutek-tmp.pl.eu.org" "www.koszkonutek-tmp.pl.eu.org") + ("git.koszko.org" "www.git.koszko.org" + "git.koszkonutek-tmp.pl.eu.org" "www.git.koszkonutek-tmp.pl.eu.org" + "git.happyhacking.pl" "www.git.happyhacking.pl") + ("haketilo.koszko.org" "www.haketilo.koszko.org") + ("hydrilla.koszko.org") + ("hydrillabugs.koszko.org" "www.hydrillabugs.koszko.org" + "hachettebugs.koszko.org" "www.hachettebugs.koszko.org") + ("imap.koszko.org") + ("pray.koszko.org" "www.pray.koszko.org") + ("sheets.koszko.org" "www.sheets.koszko.org") + ("smtp.koszko.org"))))) + +(define %cgitrc + (serialize-cgit-configuration + (cgit-configuration + (about-filter (file-append cgit "/lib/cgit/filters/about-formatting.sh")) + (cache-root "/var/cache/cgit") + (cache-size 1000) + ;; Snapshots are likely to get pretty big and there seems to be no simple + ;; way to limit cache size by bytes rather than a number of entries. Let's + ;; disable snapshot cache entirely to avoid running out of disk space. + (cache-snapshot-ttl 0) + (css "/cgit-static/cgit.css") + (enable-index-links? #t) + (enable-index-owner? #f) + (favicon "/cgit-static/favicon.ico") + (footer (plain-file "cgit-footer" + "\ + <div class=footer>generated by + <a href=\"https://git.zx2c4.com/cgit/about/\"> + cgit + </a> + </div> + ")) + (logo "https://git.koszko.org/cgit-static/cgit.png") + (max-blob-size 100) + ;; Owners are not used in this setup but cgit nevertheless tries to deduce + ;; them from the filesystem&passwd and presents "Gitolite user" as the owner + ;; in the UI. This hack hides that string from visitors. + (owner-filter (program-file "dummy-format-owner" #~(noop))) + (project-list "/var/lib/gitolite/projects.list") + (remove-suffix? #t) + (repository-directory "/var/lib/gitolite/repositories") + (root-desc "Repositories of Wojtek") + (snapshots '("tar.gz" "zip")) + (extra-options (append + ;; Setting `js` option to an empty list removes JS from the + ;; UI. + '("js=") + ;; TODO: improve Guix' cgit-configuration to allow passing + ;; multiple CSS files. + '("css=/cgit-static/better-cgit-markdown-heading-color.css") + (append-map + (lambda (file-name) + (map (cut string-append "readme=:" file-name <>) + '(".md" ".mkd" ".rst" ".html" ".htm" ".txt" ""))) + '("readme" "README" "install" "INSTALL"))))))) + +(define %better-cgit-markdown-heading-color.css + (mixed-text-file "better-cgit-markdown-heading-color.css" + (format #f "~{.markdown-body h~a a~^,~%~} " (iota 6 1)) + "{ color: #555 !important; }")) + +(prepend %services + (simple-service 'cgit-http-virtualhost web:httpd-service-type + (list (web:httpd-virtualhost + "*:443" + `("\ + ServerName git.koszko.org + ServerAlias www.git.koszko.org + ServerAlias git.koszkonutek-tmp.pl.eu.org + ServerAlias www.git.koszkonutek-tmp.pl.eu.org + ServerAlias git.happyhacking.pl + ServerAlias www.git.happyhacking.pl + ServerAdmin webmaster@koszko.org + + <If \"%{HTTP_HOST} != 'git.koszko.org'\"> + Redirect permanent / https://git.koszko.org/ + </If> + + <Directory " ,(file-append git "/libexec/git-core") "> + Require all granted + SetEnv GIT_PROJECT_ROOT /var/lib/gitolite/repositories + </Directory> + ScriptAliasMatch \ + ^/(.*/(HEAD|info/refs|objects/info/[^/]+|git-upload-pack))$ \ + " ,(file-append git "/libexec/git-core/git-http-backend/$1") " + + Alias /cgit-static/better-cgit-markdown-heading-color.css \ + " ,%better-cgit-markdown-heading-color.css " + Alias /cgit-static " ,(file-append cgit "/share/cgit") " + + SetEnv CGIT_CONFIG " ,(mixed-text-file "cgitrc" %cgitrc) " + ScriptAlias / " ,(file-append cgit "/lib/cgit/cgit.cgi/") " + <Directory " ,(file-append cgit "/lib/cgit/") "> + Options +ExecCGI + </Directory> + + SSLEngine on + SSLCertificateFile /etc/certs/git.koszko.org/fullchain.pem + SSLCertificateKeyFile /etc/certs/git.koszko.org/privkey.pem + "))))) + +(prepend %services + (simple-service 'prepare-cgit-cache-dir activation-service-type + #~(begin + (mkdir-p "/var/cache/cgit") + (chown "/var/cache/cgit" -1 (group:gid (getgr "httpd"))) + (chmod "/var/cache/cgit" #o770)))) + +(prepend %services + (simple-service 'demo-01-http-virtualhost web:httpd-service-type + (list (web:httpd-virtualhost + "*:443" + `("\ + ServerName demo-01.happyhacking.pl + ServerAlias www.demo-01.happyhacking.pl + ServerAdmin webmaster@happyhacking.pl + + <If \"%{HTTP_HOST} != 'demo-01.happyhacking.pl'\"> + Redirect permanent / https://demo-01.happyhacking.pl/ + </If> + + ProxyPass / http://127.0.0.1:5050/ + ProxyPassReverse / http://127.0.0.1:5050/ + + Header add Content-Security-Policy \"img-src 'self' data:; connect-src 'self'; default-src ws: 'self' data: blob: 'unsafe-inline' 'unsafe-eval';\" + + SSLEngine on + SSLCertificateFile \ + /etc/certs/demo-01.happyhacking.pl/fullchain.pem + SSLCertificateKeyFile \ + /etc/certs/demo-01.happyhacking.pl/privkey.pem + "))))) + +(prepend %services + (simple-service 'httpd-virtualhost-koszko web:httpd-service-type + (list (let ((wsgi (file-append ks:koszko-org-website + "/share/koszko-org-website/wsgi.py"))) + (web:httpd-virtualhost + "*:443" + `("\ + ServerName koszko.org + ServerAlias www.koszko.org + ServerAlias koszkonutek-tmp.pl.eu.org + ServerAlias www.koszkonutek-tmp.pl.eu.org + ServerAdmin koszko@koszko.org + + <If \"%{HTTP_HOST} != 'koszko.org'\"> + Redirect permanent / https://koszko.org/ + </If> + + DocumentRoot /srv/http/koszko.org + Alias /sideload /srv/http/koszko.org + <Files " ,wsgi "> + Require all granted + </Files> + WSGIScriptAlias / " ,wsgi " + + SSLEngine on + SSLCertificateFile /etc/certs/koszko.org/fullchain.pem + SSLCertificateKeyFile /etc/certs/koszko.org/privkey.pem + ")))))) + +(prepend %services + (simple-service 'httpd-virtualhost-haketilo web:httpd-service-type + (list (let ((wsgi (file-append ks:hydrilla-website + "/share/hydrilla-website/wsgi.py"))) + (web:httpd-virtualhost + "*:443" + `("\ + ServerName haketilo.koszko.org + ServerAlias www.haketilo.koszko.org + ServerAdmin koszko@koszko.org + + <If \"%{HTTP_HOST} != 'haketilo.koszko.org'\"> + Redirect permanent / https://haketilo.koszko.org/ + </If> + + <Files " ,wsgi "> + Require all granted + </Files> + WSGIScriptAlias / " ,wsgi " + + SSLEngine on + SSLCertificateFile /etc/certs/haketilo.koszko.org/fullchain.pem + SSLCertificateKeyFile /etc/certs/haketilo.koszko.org/privkey.pem + ")))))) + +(define %python-path-spec-sexp + (search-path-specification->sexp + (guix-pythonpath-search-path (package-version (default-python))))) + +(define %hydrilla-pythonpath-inputs + (cons ks:hydrilla-without-haketilo + (map cadr (package-transitive-target-inputs + ks:hydrilla-without-haketilo)))) + +(define %hydrilla-pythonpath-gexp + (with-imported-modules (source-module-closure '((guix search-paths))) + #~(begin + (use-modules ((guix search-paths) #:prefix sp:)) + + (let ((evaluated-list (sp:evaluate-search-paths + (list (sp:sexp->search-path-specification + '#$%python-path-spec-sexp)) + '#$%hydrilla-pythonpath-inputs))) + (cdar evaluated-list))))) + +(prepend %services + (simple-service 'httpd-virtualhost-hydrilla web:httpd-service-type + (list (web:httpd-virtualhost + "*:443" + `("\ + ServerName hydrilla.koszko.org + ServerAdmin webmaster@koszko.org + + <If \"%{HTTP_HOST} != 'hydrilla.koszko.org'\"> + Redirect permanent / https://hydrilla.koszko.org/ + </If> + + Alias /downloads /srv/http/hydrilla.koszko.org/downloads + + Alias /schemas \ + " ,(file-append ks:hydrilla-json-schemas-all + "/share/hydrilla-json-schemas") " + + DocumentRoot /var/lib/hydrilla/malcontent_dirs + + <Location ~ ^/api_v[^/]+/(resource|mapping)/> + ForceType application/json + </Location> + + SetEnvIf Request_URI ^/(api_v[0-9]+)/ \ + MALCONENT_DIR=/var/lib/hydrilla/malcontent_dirs/$1 + + SetEnvIf Request_URI ^/api_v[0-9]+/ \ + HYDRILLA_GUIX_PYTHONPATH=" ,%hydrilla-pythonpath-gexp " + + WSGIScriptAliasMatch \ + ^/api_v[^/]+/((resource|mapping)/[^/]+[.]json|query|list_all)$ \ + " ,(local-file "hydrilla-wsgi.py") "/$1 + + SSLEngine on + SSLCertificateFile \ + /etc/certs/hydrilla.koszko.org/fullchain.pem + SSLCertificateKeyFile \ + /etc/certs/hydrilla.koszko.org/privkey.pem + "))))) + +(prepend %services + (simple-service 'httpd-virtualhost-hydrillabugs web:httpd-service-type + (list (web:httpd-virtualhost + "*:443" + `("\ + ServerName hydrillabugs.koszko.org + ServerAlias www.hydrillabugs.koszko.org + ServerAlias hachettebugs.koszko.org + ServerAlias www.hachettebugs.koszko.org + ServerAdmin webmaster@koszko.org + + <If \"%{HTTP_HOST} != 'hydrillabugs.koszko.org'\"> + Redirect permanent / https://hydrillabugs.koszko.org/ + </If> + + DocumentRoot /srv/http/hydrillabugs.koszko.org + + RewriteEngine On + + RewriteCond %{REQUEST_METHOD} !GET + RewriteRule ^(.*)$ /hydrillabugs-archived.html [L,R=301,QSD] + + Alias /hydrillabugs-archived.html \ + " ,(local-file "hydrillabugs-archived.html") " + + RewriteRule /uri-map.txt /dummy [L,F] + + # Serve wget-archived website. + RewriteMap add-ext \ + txt:/srv/http/hydrillabugs.koszko.org/uri-map.txt + + <Location /javascripts> + ForceType application/javascript + </Location> + + # Make `hachette' project display under the name `haketilo'. + RewriteRule ^/projects/haketilo(.*)$ /projects/hachette$1 + + RewriteCond %{QUERY_STRING} !^$ + RewriteCond ${add-ext:$1?%{QUERY_STRING}|NONE} !NONE + RewriteRule ^(.*)$ ${add-ext:$1?%{QUERY_STRING}} [L,R=301] + RewriteCond %{QUERY_STRING} !^$ + RewriteRule ^(.*)$ $1?%{QUERY_STRING}? [L,QSL] + RewriteCond %{QUERY_STRING} ^$ + RewriteCond ${add-ext:$1|NONE} !NONE + RewriteRule ^(.*)$ ${add-ext:$1} [L,R=301] + + SSLEngine on + SSLCertificateFile \ + /etc/certs/hydrillabugs.koszko.org/fullchain.pem + SSLCertificateKeyFile \ + /etc/certs/hydrillabugs.koszko.org/privkey.pem + "))))) + +(prepend %services + (simple-service 'httpd-virtualhost-sheets web:httpd-service-type + (map (lambda (what) + (define website-files + (file-append ks:sheets-websites + (format #f "/share/~a-website" what))) + + (web:httpd-virtualhost + "*:443" + `("\ + ServerName " ,what ".koszko.org + ServerAlias www." ,what ".koszko.org + ServerAdmin koszko@koszko.org + + <If \"%{HTTP_HOST} != '" ,what ".koszko.org'\"> + Redirect permanent / https://" ,what ".koszko.org/ + </If> + + DocumentRoot " ,website-files " + + SSLEngine on + SSLCertificateFile /etc/certs/" ,what ".koszko.org/fullchain.pem + SSLCertificateKeyFile /etc/certs/" ,what ".koszko.org/privkey.pem + "))) + '("pray" "sheets")))) + +(define %certbot-deploy-hook + (program-file "httpd-deploy-hook" + #~(for-each (lambda (pidfile) + (false-if-exception + (kill (call-with-input-file pidfile read) SIGHUP))) + '("/var/run/httpd" + "/var/spool/exim/exim-daemon.pid" + "/var/run/dovecot/master.pid")))) + +(prepend %services + (service cb:certbot-sans-nginx-service-type + (cb:certbot-configuration + (webroot "/var/certbot-validation") + (certificates + (map (match-lambda + ((domains . key-read-group) + (cb:certificate-configuration + (name (car domains)) + (domains domains) + (deploy-hook %certbot-deploy-hook) + (key-read-group key-read-group)))) + '((("koszko.org" "www.koszko.org" + "koszkonutek-tmp.pl.eu.org" "www.koszkonutek-tmp.pl.eu.org") + . #f) + (("git.koszko.org" "www.git.koszko.org" + "git.koszkonutek-tmp.pl.eu.org" + "www.git.koszkonutek-tmp.pl.eu.org" + "git.happyhacking.pl" "www.git.happyhacking.pl") . #f) + (("haketilo.koszko.org" "www.haketilo.koszko.org") . #f) + (("hydrilla.koszko.org") . #f) + (("hydrillabugs.koszko.org" "www.hydrillabugs.koszko.org" + "hachettebugs.koszko.org" "www.hachettebugs.koszko.org") . #f) + (("imap.koszko.org") . #f) + (("pray.koszko.org" "www.pray.koszko.org") . #f) + (("sheets.koszko.org" "www.sheets.koszko.org") . #f) + (("smtp.koszko.org") . "smtp-certificates")))) + (email "koszko@koszko.org") + (rsa-key-size 4096) + (service-reload '()) + (service-requirement '(httpd))))) + +(prepend %services + (simple-service 'prepare-certbot-tokens-dir activation-service-type + #~(mkdir-p "/var/certbot-validation"))) + +(define (make-koszko-zone-entries domain) + (dns:define-zone-entries entries + ;; nameservers + ("@" "" "IN" "NS" (format #f "ns2.~a." domain)) + ("@" "" "IN" "NS" "ns0.1984.is.") + ("@" "" "IN" "NS" "ns1.1984.is.") + ("@" "" "IN" "NS" "ns2.1984.is.") + ("@" "" "IN" "NS" "ns1.1984hosting.com.") + ("@" "" "IN" "NS" "ns2.1984hosting.com.") + + ;; domain->IP assignments + ("@" "" "IN" "A" "188.68.237.248") + + ("antioch" "" "IN" "A" "188.68.236.76") + ("*.antioch" "" "IN" "CNAME" "antioch") + ("salamina" "" "IN" "A" "188.68.237.248") + ("*.salamina" "" "IN" "CNAME" "salamina") + + ("ctftilde" "" "IN" "A" "127.0.0.1") + ("ctftilde" "" "IN" "AAAA" "::1") + ("*.ctftilde" "" "IN" "CNAME" "ctftilde") + + ("git" "" "IN" "CNAME" "salamina") + ("www.git" "" "IN" "CNAME" "git") + ("hachettebugs" "" "IN" "CNAME" "hydrillabugs") + ("www.hachettebugs" "" "IN" "CNAME" "hachettebugs") + ("haketilo" "" "IN" "CNAME" "salamina") + ("www.haketilo" "" "IN" "CNAME" "haketilo") + ("hydrilla" "" "IN" "CNAME" "salamina") + ("hydrillabugs" "" "IN" "CNAME" "salamina") + ("www.hydrillabugs" "" "IN" "CNAME" "hydrillabugs") + ("imap" "" "IN" "CNAME" "salamina") + ("ns1" "" "IN" "CNAME" "antioch") + ("ns2" "" "IN" "CNAME" "salamina") + ("pray" "" "IN" "CNAME" "salamina") + ("www.pray" "" "IN" "CNAME" "pray") + ("sheets" "" "IN" "CNAME" "salamina") + ("www.sheets" "" "IN" "CNAME" "sheets") + ("smtp" "" "IN" "CNAME" "salamina") + + ;; mail + ("@" "" "IN" "MX 10" "smtp.koszko.org.") + ;; dmarc + ("@" "" "IN" "TXT" "\"v=spf1 ip4:188.68.236.76 ip4:188.68.237.248 -all\"") + ("_dmarc" "" "IN" "TXT" (format #f "\"~{~{~a=~a~}~^;~}\"" + '(("v" "DMARC1") + ("p" "reject") + ("rua" "mailto:dmarc@koszko.org") + ("ruf" "mailto:dmarc@koszko.org") + ("rf" "afrf") + ("pct" "100")))) + ("mail-salamina._domainkey" "" "IN" "TXT" "( + \"k=rsa;t=s;p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsC9HfcId\" + \"QGcBzYtBzv/VF7vPrRAASwfeAJ3pr0tddpYtFMGGm8kWPAKykX2LvP4epQPdzGL9\" + \"W9qLJk3R+iJSlUYLgP1s4Tr5qiUm/PEHPnjzwC8kqtJ/CrQs7WLfiuE3SElWI3iQ\" + \"FMRCD1Kk07axSOCgLbshthEAxZQqScYiZT7Irl4SHm9SpTUJkqh5xcCTqsW1yuG/\" + \"YWbfERH4PFp2pA85ZZvVEHqd+e8LMLh9EKMYRbhp9AVKMaESIegkO0RZv0KGp4aU\" + \"vzquG1FYQ9VOJ6KiviZANuEL4cpNrqmFb4Wbuwc6w7drWaHjFT/j1mS/eB0DN3el\" + \"nPQnWMTJZPhqnFZKzG37P5VkIDjbcotevsBGV28gx3VJNf1ye1x/P9f4fJw2s7EY\" + \"izNZx9/xfmAiOpP3KhrpE+cccBWnMHYyp0X7ClgBIQTDiLOBX3KhH+GOuADMcum1\" + \"4y8SHw2xSYGGk46YI0fBf8kaJsAA9wBQvuBFSj1MjxjdWt0GF0OLnGB1RsPZx+nU\" + \"Q+EZz0PDuv16ofN7MaOfY+kD6XoBCDjj4FDqLOgBgoLS7LfLyYTElbuItj12Yqph\" + \"ZPY4I+Lmn9nzl3tEnUqtRNu5LPhIR9mj/4BLp2UPgkVnqTAcA+qxoJghm8hh9AS9\" + \"2pelav0CarwwvUo09rcvujksuwy8TulK8ckCAwEAAQ==\" + )") + + ((string-append domain "._report._dmarc") "" "IN" "TXT" "\"v=DMARC1\"")) + + entries) + +(dns:define-zone-entries %happyhacking.pl-zone-entries + ;; nameservers + ("@" "" "IN" "NS" "ns2.happyhacking.pl.") + ("@" "" "IN" "NS" "ns0.1984.is.") + ("@" "" "IN" "NS" "ns1.1984.is.") + ("@" "" "IN" "NS" "ns2.1984.is.") + ("@" "" "IN" "NS" "ns1.1984hosting.com.") + ("@" "" "IN" "NS" "ns2.1984hosting.com.") + ;; domain->IP assignments + ("ns1" "" "IN" "A" "188.68.236.76") + ("ns2" "" "IN" "A" "188.68.237.248") + ("@" "" "IN" "CNAME" "salamina.koszko.org") + ("www" "" "IN" "CNAME" "@") + ("git" "" "IN" "CNAME" "@") + ("www.git" "" "IN" "CNAME" "git") + ;; mail + ("@" "" "IN" "MX 10" "smtp.koszko.org.") + ("@" "" "IN" "TXT" "\"v=spf1 ip4:188.68.236.76 ip4:188.68.237.248 -all\"") + ("_dmarc" "" "IN" "TXT" (format #f "\"~{~{~a=~a~}~^;~}\"" + '(("v" "DMARC1") + ("p" "reject") + ("rua" "mailto:dmarc@happyhacking.pl") + ("ruf" "mailto:dmarc@happyhacking.pl") + ("rf" "afrf") + ("pct" "100")))) + ("happyhacking.pl._report._dmarc" "" "IN" "TXT" "\"v=DMARC1\"") + ("mail-salamina._domainkey" "" "IN" "TXT" "( + \"k=rsa;t=s;p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsC9HfcId\" + \"QGcBzYtBzv/VF7vPrRAASwfeAJ3pr0tddpYtFMGGm8kWPAKykX2LvP4epQPdzGL9\" + \"W9qLJk3R+iJSlUYLgP1s4Tr5qiUm/PEHPnjzwC8kqtJ/CrQs7WLfiuE3SElWI3iQ\" + \"FMRCD1Kk07axSOCgLbshthEAxZQqScYiZT7Irl4SHm9SpTUJkqh5xcCTqsW1yuG/\" + \"YWbfERH4PFp2pA85ZZvVEHqd+e8LMLh9EKMYRbhp9AVKMaESIegkO0RZv0KGp4aU\" + \"vzquG1FYQ9VOJ6KiviZANuEL4cpNrqmFb4Wbuwc6w7drWaHjFT/j1mS/eB0DN3el\" + \"nPQnWMTJZPhqnFZKzG37P5VkIDjbcotevsBGV28gx3VJNf1ye1x/P9f4fJw2s7EY\" + \"izNZx9/xfmAiOpP3KhrpE+cccBWnMHYyp0X7ClgBIQTDiLOBX3KhH+GOuADMcum1\" + \"4y8SHw2xSYGGk46YI0fBf8kaJsAA9wBQvuBFSj1MjxjdWt0GF0OLnGB1RsPZx+nU\" + \"Q+EZz0PDuv16ofN7MaOfY+kD6XoBCDjj4FDqLOgBgoLS7LfLyYTElbuItj12Yqph\" + \"ZPY4I+Lmn9nzl3tEnUqtRNu5LPhIR9mj/4BLp2UPgkVnqTAcA+qxoJghm8hh9AS9\" + \"2pelav0CarwwvUo09rcvujksuwy8TulK8ckCAwEAAQ==\" + )")) + +(prepend %services + (service dns:knot-service-type + (dns:knot-configuration + (acls (list (dns:knot-acl-configuration + (id "allow-axfr-from-1984") + (address '("93.95.224.6")) + (action '(transfer))))) + + (remotes (list (dns:knot-remote-configuration + (id "1984-axfr-remote") + (address '("93.95.224.6"))))) + + (zones (cons* (dns:knot-zone-configuration + (domain "happyhacking.pl") + (zone (dns:zone-file + (origin "happyhacking.pl") + (entries %happyhacking.pl-zone-entries) + (ns "ns2") + (mail "hostmaster") + (serial 2024050300))) + (acl '("allow-axfr-from-1984")) + (semantic-checks? #t) + (notify '("1984-axfr-remote"))) + + (map (lambda (domain) + (dns:knot-zone-configuration + (domain domain) + (zone (dns:zone-file + (origin domain) + (entries (make-koszko-zone-entries domain)) + (ns "ns2") + (mail "koszko") + (serial 2024050301))) + (acl '("allow-axfr-from-1984")) + (semantic-checks? #t) + (notify '("1984-axfr-remote")))) + '("koszko.org" "koszkonutek-tmp.pl.eu.org"))))))) + +(prepend %services + (service mail:mail-aliases-service-type + '(("root" "admin")))) + +(prepend %services + (service mail:exim-service-type + (mail:exim-configuration + (config-file (local-file "./exim.conf")) + (setuid-user 0)))) + +(prepend %services + (simple-service 'make-maildirs-directory activation-service-type + #~(begin + (mkdir-p "/var/vmail") + (let ((initial-umask (umask))) + (umask #o007) + (mkdir-p "/var/vmail/maildirs") + (chown "/var/vmail/maildirs" -1 (group:gid (getgr "vmail"))) + (umask initial-umask))))) + +(prepend %services + (service mail:dovecot-service-type + (mail:dovecot-configuration + (services (list (mail:service-configuration + (kind "imap-login") + (listeners (list (mail:inet-listener-configuration + (protocol "imaps") + (port 993) + (ssl? #t)))) + ;; '1' is more secure than '0' because each + ;; connection is handled in a separate process. + (service-count 1)) + (mail:service-configuration + (kind "imap")) + (mail:service-configuration + (kind "auth") + (listeners (list (mail:unix-listener-configuration + (path "auth-userdb")))) + ;; Dovecot requires process-limit to be 1 here. + (service-count 0) + (process-limit 1)))) + (ssl-cert "</etc/certs/imap.koszko.org/fullchain.pem") + (ssl-key "</etc/certs/imap.koszko.org/privkey.pem") + (auth-mechanisms '("plain" "login")) + (passdbs (list (mail:passdb-configuration + (driver "passwd-file") + (args '("scheme=SHA256-CRYPT" + "username_format=%u" + "/var/vmail/passwd"))))) + (userdbs (list (mail:userdb-configuration + (driver "static") + (args '("home=/var/vmail/maildirs/%n"))))) + (mail-uid "vmail") + (mail-gid "vmail") + (mail-location "maildir:/var/vmail/maildirs/%n")))) + +(prepend %services + (service openssh-service-type + (openssh-configuration + (permit-root-login 'prohibit-password) + (authorized-keys `(("root" ,(local-file "koszko.pub")))) + (port-number 10022)))) + +(prepend %services + (service vc:gitolite-service-type + (vc:gitolite-configuration + (admin-pubkey (local-file "koszko.pub")) + (rc-file (vc:gitolite-rc-file + (umask #o027) + (git-config-keys ".*") + (enable '("help" + "desc" + "info" + "perms" + "writable" + "ssh-authkeys" + "git-config" + "daemon" + "gitweb" + "cgit"))))))) + +(prepend %services + (service postgresql-service-type + (postgresql-configuration (port 15432)))) + +(operating-system + (host-name "salamina") + (timezone "Europe/Warsaw") + (locale "en_US.utf8") + + (keyboard-layout (keyboard-layout "pl")) + + (bootloader (bootloader-configuration + (bootloader grub-bootloader) + (targets '("/dev/vda")))) + + (users (cons* (gss:user-account + (name "vmail") + (group "vmail") + (system? #t) + (comment "Email access user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin"))) + (gss:user-account + (name "minetest") + (group "minetest") + (system? #t) + (comment "Minetest server") + (home-directory "/var/minetest") + (shell (file-append shadow "/sbin/nologin"))) + gss:%base-user-accounts)) + + (groups (cons* (gss:user-group + (name "vmail") + (system? #t)) + (gss:user-group + (name "minetest") + (system? #t)) + (gss:user-group + (name "smtp-certificates") + (system? #t)) + gss:%base-groups)) + + (extra-groups (list (gss:user-extra-groups + (user "exim") + (groups '("smtp-certificates"))) + (gss:user-extra-groups + (user "httpd") + (groups '("git"))))) + + (file-systems (cons* (fs:file-system + (device (fs:file-system-label "salamina-root")) + (mount-point "/") + (type "ext4")) + fs:%base-file-systems)) + + (packages (append (specifications->packages + '("nss-certs" + "file" + "bind:utils" + "net-tools" + "man-pages-posix" + "emacs" + "minetest")) + %base-packages)) + + (services %services)) + +;;; Local Variables: +;;; eval: (put 'prepend 'scheme-indent-function 1) +;;; End: |