aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCollin J. Doering2024-05-31 09:08:19 -0400
committerCollin J. Doering2024-05-31 09:19:17 -0400
commitb4dda63855d5b1fb5dd18e78dfe0ca1b59ddbb15 (patch)
tree0cba21247b0fa701fb7da8c42dc6c6d992c09fa1
parent10c47f382699f41048ca790933977121c0134e54 (diff)
downloadguix-north-america-b4dda63855d5b1fb5dd18e78dfe0ca1b59ddbb15.tar.gz
balg02: Initial implementation of Guix build farm
* .guix/guix-na/config/balg02.scm (%automation-user): Removed variable (only used in one place). (%cuirass-specs): New variable. (Initial) Cuirass specifications that are run by the guix-na build farm. (publish-robots.txt): New variable. Used in nginx configuration. (publish-locations): New function. Defines nginx publish locations (used for http and https servers). (balg02-locations): New function. Defines nginx publish locations used for guix-na. (%publish-url): New variable. String representing local publish URL. (%tls-settings): New variable. Captures nginx tls settings used in nginx configuration. (le): New function. Generates lets encrypt path given a host and optionally a private key. (languages-to-accept): New variable. Languages for i8ln. (accept-languages): New function. (%balg02-servers): New variable. balg02 nginx servers. (%extra-content): New variable. Extra nginx configuration content. (%nginx-configuration): New variable. Capture nginx configuration given all previous helper functions and variables. (%nginx-cache-activation): New variable. Service the ensures /var/cache/nginx exists on the first run. (%nginx-deploy-hook): New variable. Hook used upon cerbot certificate updates. (balg02 (packages)): Add btrfs-progs. (balg02): Remove root ssh key (not necessary as ssh root login is disabled). (balg02 (services)): Add cuirass, certbot, nginx, and guix-publish services.
-rw-r--r--.guix/guix-na/config/balg02.scm419
1 files changed, 413 insertions, 6 deletions
diff --git a/.guix/guix-na/config/balg02.scm b/.guix/guix-na/config/balg02.scm
index ab17951..fb211ea 100644
--- a/.guix/guix-na/config/balg02.scm
+++ b/.guix/guix-na/config/balg02.scm
@@ -22,14 +22,400 @@
#:use-module (gnu system)
#:use-module (gnu packages bash)
#:use-module (gnu packages shells)
+ #:use-module (gnu packages web)
#:use-module (gnu services base)
#:use-module (gnu services cuirass)
+ #:use-module (gnu services certbot)
#:use-module (gnu services networking)
#:use-module (gnu services ssh)
#:use-module (gnu services web)
#:export (balg02 %system))
-(define %automation-user "auto")
+(define %cuirass-specs
+ #~(list (specification
+ (name "guix")
+ (priority 0)
+ (build '(channels guix))
+ (channels %default-channels))))
+
+;; Taken from: https://git.savannah.gnu.org/cgit/guix/maintenance.git/tree/hydra/nginx/berlin.scm
+(define publish-robots.txt
+ ;; Try to prevent good-faith crawlers from downloading substitutes. Allow
+ ;; indexing the root—which is expected to be static or cheap—to remain visible
+ ;; in search engine results for, e.g., ‘Guix CI’.
+ "\
+User-agent: *\r
+Disallow: /\r
+Allow: /$\r
+\r
+")
+
+(define (publish-locations url)
+ "Return the nginx location blocks for 'guix publish' running on URL."
+ (list (nginx-location-configuration
+ (uri "/nix-cache-info")
+ (body
+ (list
+ (string-append
+ "proxy_pass " url "/nix-cache-info;")
+ ;; Cache this file since that's always the first thing we ask
+ ;; for.
+ "proxy_cache static;"
+ "proxy_cache_valid 200 100d;" ; cache hits for a looong time.
+ "proxy_cache_valid any 5m;" ; cache misses/others for 5 min.
+ "proxy_ignore_client_abort on;"
+
+ ;; We need to hide and ignore the Set-Cookie header to enable
+ ;; caching.
+ "proxy_hide_header Set-Cookie;"
+ "proxy_ignore_headers Set-Cookie;")))
+
+ (nginx-location-configuration
+ (uri "/nar/")
+ (body
+ (list
+ (string-append "proxy_pass " url ";")
+ "client_body_buffer_size 256k;"
+
+ ;; Be more tolerant of delays when fetching a nar.
+ "proxy_read_timeout 60s;"
+ "proxy_send_timeout 60s;"
+
+ ;; Enable caching for nar files, to avoid reconstructing and
+ ;; recompressing archives.
+ "proxy_cache nar;"
+ "proxy_cache_valid 200 30d;" ; cache hits for 1 month
+ "proxy_cache_valid 504 3m;" ; timeout, when hydra.gnu.org is overloaded
+ "proxy_cache_valid any 1h;" ; cache misses/others for 1h.
+
+ "proxy_ignore_client_abort on;"
+
+ ;; Nars are already compressed.
+ "gzip off;"
+
+ ;; We need to hide and ignore the Set-Cookie header to enable
+ ;; caching.
+ "proxy_hide_header Set-Cookie;"
+ "proxy_ignore_headers Set-Cookie;"
+
+ ;; Provide a 'content-length' header so that 'guix
+ ;; substitute-binary' knows upfront how much it is downloading.
+ ;; "add_header Content-Length $body_bytes_sent;"
+ )))
+
+ (nginx-location-configuration
+ (uri "~ \\.narinfo$")
+ (body
+ (list
+ ;; Since 'guix publish' has its own caching, and since it relies
+ ;; on the atime of cached narinfos to determine whether a
+ ;; narinfo can be removed from the cache, don't do any caching
+ ;; here.
+ (string-append "proxy_pass " url ";")
+
+ ;; For HTTP pipelining. This has a dramatic impact on
+ ;; performance.
+ "client_body_buffer_size 128k;"
+
+ ;; Narinfos requests are short, serve many of them on a
+ ;; connection.
+ "keepalive_requests 600;"
+
+ ;; Do not tolerate slowness of hydra.gnu.org when fetching
+ ;; narinfos: better return 504 quickly than wait forever.
+ "proxy_connect_timeout 10s;"
+ "proxy_read_timeout 10s;"
+ "proxy_send_timeout 10s;"
+
+ ;; 'guix publish --ttl' produces a 'Cache-Control' header for
+ ;; use by 'guix substitute'. Let it through rather than use
+ ;; nginx's "expire" directive since the expiration time defined
+ ;; by 'guix publish' is the right one.
+ "proxy_pass_header Cache-Control;"
+
+ "proxy_ignore_client_abort on;"
+
+ ;; We need to hide and ignore the Set-Cookie header to enable
+ ;; caching.
+ "proxy_hide_header Set-Cookie;"
+ "proxy_ignore_headers Set-Cookie;")))
+
+ ;; Content-addressed files served by 'guix publish'.
+ (nginx-location-configuration
+ (uri "/file/")
+ (body
+ (list
+ (string-append "proxy_pass " url ";")
+
+ "proxy_cache cas;"
+ "proxy_cache_valid 200 200d;" ; cache hits
+ "proxy_cache_valid any 5m;" ; cache misses/others
+
+ "proxy_ignore_client_abort on;")))
+
+ ;; Try to prevent good-faith crawlers from downloading substitutes.
+ (nginx-location-configuration
+ (uri "= /robots.txt")
+ (body
+ (list
+ #~(string-append "try_files "
+ #$(plain-file "robots.txt" publish-robots.txt)
+ " =404;")
+ "root /;")))))
+
+;; TODO
+;; (define %ci-onion
+;; ;; Onion service name of ci.guix.
+;; "4zwzi66wwdaalbhgnix55ea3ab4pvvw66ll2ow53kjub6se4q2bclcyd.onion")
+
+(define (balg02-locations publish-url)
+ "Return nginx location blocks with 'guix publish' reachable at
+PUBLISH-URL."
+ (append (publish-locations publish-url)
+ (list
+ ;; Cuirass.
+ (nginx-location-configuration
+ (uri "/")
+ (body (list "proxy_pass http://localhost:8081;"
+ ;; ;; See
+ ;; ;; <https://community.torproject.org/onion-services/advanced/onion-location/>.
+ ;; (string-append
+ ;; "add_header Onion-Location http://" %ci-onion
+ ;; "$request_uri;")
+ )))
+ (nginx-location-configuration
+ (uri "~ ^/admin")
+ (body
+ (list "if ($ssl_client_verify != SUCCESS) { return 403; } proxy_pass http://localhost:8081;")))
+
+ (nginx-location-configuration
+ (uri "/static")
+ (body
+ (list
+ "proxy_pass http://localhost:8081;"
+ ;; Cuirass adds a 'Cache-Control' header, honor it.
+ "proxy_cache static;"
+ "proxy_cache_valid 200 2d;"
+ "proxy_cache_valid any 10m;"
+ "proxy_ignore_client_abort on;")))
+
+ (nginx-location-configuration
+ (uri "/download") ;Cuirass "build products"
+ (body
+ (list
+ "proxy_pass http://localhost:8081;"
+ "expires 10d;" ;override 'Cache-Control'
+ "proxy_cache static;"
+ "proxy_cache_valid 200 30d;"
+ "proxy_cache_valid any 10m;"
+ "proxy_ignore_client_abort on;")))
+
+ (nginx-location-configuration ;certbot
+ (uri "/.well-known")
+ (body (list "root /var/www;"))))))
+
+(define %publish-url "http://localhost:3000")
+
+;; Taken from https://git.savannah.gnu.org/cgit/guix/maintenance.git/tree/hydra/modules/sysadmin/nginx.scm
+(define %tls-settings
+ (list
+ ;; Make sure SSL is disabled.
+ "ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;"
+ ;; Disable weak cipher suites.
+ "ssl_ciphers HIGH:!aNULL:!MD5;"
+ "ssl_prefer_server_ciphers on;"
+
+ ;; TODO: these need to be generated
+ ;; Use our own DH parameters created with:
+ ;; openssl dhparam -out dhparams.pem 2048
+ ;; as suggested at <https://weakdh.org/sysadmin.html>.
+ "ssl_dhparam /etc/dhparams.pem;"))
+
+;; Taken from https://git.savannah.gnu.org/cgit/guix/maintenance.git/tree/hydra/modules/sysadmin/nginx.scm
+(define* (le host #:optional privkey)
+ (string-append "/etc/letsencrypt/live/"
+ host "/"
+ (if privkey "privkey" "fullchain")
+ ".pem"))
+
+;; Taken from https://git.savannah.gnu.org/cgit/guix/maintenance.git/tree/hydra/modules/sysadmin/nginx.scm
+(define languages-to-accept
+ ;; List of languages for redirection; see 'accept-languages' further
+ ;; below.
+ '(("en")
+ ("de")
+ ("eo")
+ ("es")
+ ("fr")
+ ("ja")
+ ("ko")
+ ("ru")
+ ("sk")
+ ("tr")
+ ("zh-CN" "zh" "zh-Hans" "zh-Hans-CN")
+ ("zh-TW" "zh-Hant" "zh-Hant-TW")))
+
+;; Taken from https://git.savannah.gnu.org/cgit/guix/maintenance.git/tree/hydra/modules/sysadmin/nginx.scm
+(define* (accept-languages
+ #:optional (language-lists
+ languages-to-accept))
+ "Returns nginx configuration code to set up the $lang variable
+according to the Accept-Language header in the HTTP request. The
+requesting user agent will be served the files at /$lang/some/url.
+Each list in LANGUAGE-LISTS starts with the $lang and is followed by
+synonymous IETF language tags that should be mapped to the same $lang."
+ (define (language-mappings language-list)
+ (define (language-mapping language)
+ (string-join (list " " language (car language-list) ";")))
+ (string-join (map language-mapping language-list) "\n"))
+
+ (let ((directives
+ `(,(string-join
+ `("set_from_accept_language $lang_unmapped"
+ ,@(map string-join language-lists)
+ ";"))
+ "map $lang_unmapped $lang {"
+ ,@(map language-mappings language-lists)
+ "}")))
+ (string-join directives "\n")))
+
+
+(define %balg02-servers
+ (list
+ ;; Redirect domains that don't explicitly support HTTP (below) to HTTPS.
+ (nginx-server-configuration
+ (listen '("80"))
+ (raw-content
+ (list "return 308 https://$host$request_uri;")))
+
+ ;; Domains that still explicitly support plain HTTP.
+ (nginx-server-configuration
+ (listen '("80"))
+ (server-name `("ci.guix.gnu.org"
+ ;; <https://logs.guix.gnu.org/guix/2021-11-20.log#155427>
+ "~[0-9]$"
+; TODO: onion
+; ,(regexp-quote %ci-onion)
+ ))
+ (locations (balg02-locations %publish-url))
+ (raw-content
+ (list
+ "access_log /var/run/anonip/http.access.log;"
+ "proxy_set_header X-Forwarded-Host $host;"
+ "proxy_set_header X-Forwarded-Port $server_port;"
+ "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;")))
+
+ ;; HTTPS servers
+ (nginx-server-configuration
+ (listen '("443 ssl"))
+ (server-name '("ci.guix.gnu.org"))
+ (ssl-certificate (le "ci.guix.gnu.org"))
+ (ssl-certificate-key (le "ci.guix.gnu.org" 'key))
+ (locations (balg02-locations %publish-url))
+ (raw-content
+ (append
+ %tls-settings
+ (list
+ "access_log /var/run/anonip/https.access.log;"
+ "proxy_set_header X-Forwarded-Host $host;"
+ "proxy_set_header X-Forwarded-Port $server_port;"
+ "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;"
+ ;; For Cuirass admin interface authentication
+ "ssl_client_certificate /etc/ssl-ca/certs/ca.crt;"
+ "ssl_verify_client optional;"))))))
+
+(define %extra-content
+ (list
+ "default_type application/octet-stream;"
+ "sendfile on;"
+
+ (accept-languages)
+
+ ;; Maximum chunk size to send. Partly this is a workaround for
+ ;; <http://bugs.gnu.org/19939>, but also the nginx docs mention that
+ ;; "Without the limit, one fast connection may seize the worker
+ ;; process entirely."
+ ;; <http://nginx.org/en/docs/http/ngx_http_core_module#sendfile_max_chunk>
+ "sendfile_max_chunk 1m;"
+
+ "keepalive_timeout 65;"
+
+ ;; Use HTTP 1.1 to talk to the backend so we benefit from keep-alive
+ ;; connections and chunked transfer encoding. The latter allows us to
+ ;; make sure we do not cache partial downloads.
+ "proxy_http_version 1.1;"
+
+ ;; The 'inactive' parameter for caching is not very useful in our
+ ;; case: all that matters is that LRU sweeping happens when 'max_size'
+ ;; is hit.
+
+ ;; cache for nar files
+ "proxy_cache_path /var/cache/nginx/nar"
+ " levels=2"
+ " inactive=8d" ; inactive keys removed after 8d
+ " keys_zone=nar:4m" ; nar cache meta data: ~32K keys
+ " max_size=10g;" ; total cache data size max
+
+ ;; cache for content-addressed files
+ "proxy_cache_path /var/cache/nginx/cas"
+ " levels=2"
+ " inactive=180d" ; inactive keys removed after 180d
+ " keys_zone=cas:8m" ; nar cache meta data: ~64K keys
+ " max_size=50g;" ; total cache data size max
+
+ ;; cache for build logs
+ "proxy_cache_path /var/cache/nginx/logs"
+ " levels=2"
+ " inactive=60d" ; inactive keys removed after 60d
+ " keys_zone=logs:8m" ; narinfo meta data: ~64K keys
+ " max_size=4g;" ; total cache data size max
+
+ ;; cache for static data
+ "proxy_cache_path /var/cache/nginx/static"
+ " levels=1"
+ " inactive=10d" ; inactive keys removed after 10d
+ " keys_zone=static:1m" ; nar cache meta data: ~8K keys
+ " max_size=200m;" ; total cache data size max
+
+ ;; If Hydra cannot honor these delays, then something is wrong and
+ ;; we'd better drop the connection and return 504.
+ "proxy_connect_timeout 10s;"
+ "proxy_read_timeout 10s;"
+ "proxy_send_timeout 10s;"
+
+ ;; Cache timeouts for a little while to avoid increasing pressure.
+ "proxy_cache_valid 504 30s;"))
+
+(define %nginx-configuration
+ (nginx-configuration
+ (server-blocks %balg02-servers)
+ (server-names-hash-bucket-size 128)
+ (modules
+ (list
+ ;; Module to redirect users to the localized pages of their choice.
+ (file-append nginx-accept-language-module
+ "/etc/nginx/modules/ngx_http_accept_language_module.so")))
+ (global-directives
+ '((worker_processes . 16)
+ (pcre_jit . on)
+ (events . ((worker_connections . 1024)))))
+ (extra-content
+ (string-join %extra-content "\n"))))
+
+(define %nginx-cache-activation
+ ;; Make sure /var/cache/nginx exists on the first run.
+ (simple-service 'nginx-/var/cache/nginx
+ activation-service-type
+ (with-imported-modules '((guix build utils))
+ #~(begin
+ (use-modules (guix build utils))
+ (mkdir-p "/var/cache/nginx")))))
+
+(define %nginx-deploy-hook
+ (program-file
+ "nginx-deploy-hook"
+ #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read)))
+ (kill pid SIGHUP))))
(define (balg02 efi-boot-uuid)
(operating-system
@@ -76,7 +462,7 @@
file-systems)))))
(users (cons* (user-account
- (name %automation-user)
+ (name "auto")
(comment "Automation User")
(group "users")
(shell #~(string-append #$bash "/bin/bash"))
@@ -112,7 +498,7 @@
(packages
(append
(map specification->package
- '("nss-certs"
+ '("btrfs-progs"
"recutils"
"openssh"
"tmux"
@@ -137,8 +523,7 @@
,(local-file "../../../.pubkeys/pjotr-gaeta.pub")
,(local-file "../../../.pubkeys/pjotr-napoli.pub")
,(local-file "../../../.pubkeys/pjotr-stromboli.pub")
- ,(local-file "../../../.pubkeys/pjotr-tb-arm-01.pub"))
- ("root" ,(local-file "../../../.pubkeys/collin.pub"))))))
+ ,(local-file "../../../.pubkeys/pjotr-tb-arm-01.pub"))))))
(service static-networking-service-type
(list (static-networking
(addresses
@@ -150,7 +535,29 @@
(destination "default")
(gateway "216.37.76.1"))))
(name-servers '("216.37.64.2" "216.37.64.3")))))
- (service ntp-service-type))
+ (service ntp-service-type)
+
+ (service certbot-service-type
+ (certbot-configuration
+ (email "collin@rekahsoft.ca")
+ (certificates
+ (list
+ (certificate-configuration
+ (domains '("cuirass.genenetwork.org"))
+ (deploy-hook %nginx-deploy-hook))))))
+
+ (service cuirass-service-type
+ (cuirass-configuration
+ (host "localhost")
+ (specifications %cuirass-specs)))
+
+ %nginx-cache-activation
+ (service nginx-service-type %nginx-configuration)
+
+ (service guix-publish-service-type
+ (guix-publish-configuration
+ (port 3000)
+ (cache "/var/cache/guix/publish"))))
%base-services))))
(define %system (balg02 "3AF8-9E67"))