]> git.ekhem.eu.org Git - guix.git/commitdiff
[vps] Serve website from nginx via upstream config package
authorJakub Czajka <jakub@ekhem.eu.org>
Fri, 31 Jul 2026 09:39:21 +0000 (09:39 +0000)
committerJakub Czajka <jakub@ekhem.eu.org>
Mon, 24 Aug 2026 14:59:46 +0000 (14:59 +0000)
conf/vps/website.scm [new file with mode: 0644]
tests/common.scm

diff --git a/conf/vps/website.scm b/conf/vps/website.scm
new file mode 100644 (file)
index 0000000..9e507f3
--- /dev/null
@@ -0,0 +1,149 @@
+;;; Copyright (c) 2026 Jakub Czajka <jakub@ekhem.eu.org>
+;;; License: GPL-3.0 or later.
+;;;
+;;; website.scm — Static website package served via nginx with SSI.
+
+(define-module (conf vps website)
+  #:use-module (gnu packages web)
+  #:use-module (guix build-system trivial)
+  #:use-module (ice-9 string-fun)
+  #:use-module (guix gexp)
+  #:use-module (guix git-download)
+  #:use-module (guix packages)
+  #:use-module ((guix licenses)
+                #:prefix license:)
+  #:export (website %public-domain %nginx-site-config))
+
+(define %public-domain
+  "example.org")
+
+(define website
+  (package
+    (name "website")
+    (version "20240511")
+    (source
+     (origin
+       (method git-fetch)
+       (uri (git-reference
+             (url "https://git.ekhem.eu.org/website.git")
+             (commit "0a48cd756788223be5a2c1c3865b65fb9a8476c8")))
+       (sha256
+        (base32 "10038b680vq39ar0r0f2v2br7803r3531zyknycf6zbih6bjyvx5"))))
+    (build-system trivial-build-system)
+    (arguments
+     (list
+      #:modules '((guix build utils))
+      #:builder
+      #~(begin
+          (use-modules (guix build utils))
+          (let ((out (string-append #$output "/share/website")))
+            (mkdir-p out)
+            (copy-recursively #$source out)
+            (for-each (lambda (f)
+                        (when (file-exists? (string-append out "/" f))
+                          (delete-file (string-append out "/" f))))
+                      '("views.sh" "revision.sh" "create.sql" "drop.sql"))))))
+    (home-page "https://git.ekhem.eu.org")
+    (synopsis "Static website files served via nginx with SSI")
+    (description "HTML and media files for a personal website,
+served by nginx with Server-Side Includes.")
+    (license license:gpl3+)))
+
+(define %nginx-site-config
+  (package
+    (name "nginx-site-config")
+    (version "0")
+    (source
+     #f)
+    (build-system trivial-build-system)
+    (inputs (list website nginx))
+    (arguments
+     (list
+      #:modules '((guix build utils)
+                  (ice-9 rdelim)
+                  (ice-9 string-fun))
+      #:builder
+      #~(begin
+          (use-modules (guix build utils)
+                       (ice-9 rdelim)
+                       (ice-9 string-fun))
+          (let* ((domain #$%public-domain)
+                 (webroot (string-append #$website "/share/website"))
+                 (conf-in (string-append webroot "/website.conf"))
+                 (out-dir (string-append #$output "/share/nginx"))
+                 (out-file (string-append out-dir "/site.conf"))
+                 (mime-types (string-append #$nginx
+                                            "/share/nginx/conf/mime.types"))
+                 (skip? #f)
+                 (in-location? #f))
+            (mkdir-p out-dir)
+            (call-with-output-file out-file
+              (lambda (out)
+                (format out
+                 "user nginx nginx;
+pid /var/run/nginx/pid;
+error_log /var/log/nginx/error.log error;
+events {}
+http {
+    client_body_temp_path /var/run/nginx/client_body_temp;
+    proxy_temp_path /var/run/nginx/proxy_temp;
+    fastcgi_temp_path /var/run/nginx/fastcgi_temp;
+    uwsgi_temp_path /var/run/nginx/uwsgi_temp;
+    scgi_temp_path /var/run/nginx/scgi_temp;
+    access_log /var/log/nginx/access.log combined;
+    include ~a;
+
+"
+                 mime-types)
+                (call-with-input-file conf-in
+                  (lambda (in)
+                    (let lp
+                      ((line (read-line in)))
+                      (unless (eof-object? line)
+                        (set! line
+                              (string-replace-substring line "${dollar}" "$"))
+                        (set! line
+                              (string-replace-substring line
+                                                        "${public_domain}"
+                                                        domain))
+                        (set! line
+                              (string-replace-substring line "${prod_dir}/www"
+                                                        webroot))
+                        (set! line
+                              (string-replace-substring line "${prod_dir}"
+                                                        webroot))
+                        (set! line
+                              (string-replace-substring line
+                               "${website_log_file}"
+                               "/var/log/nginx/website-access.log"))
+                        (cond
+                          ((or (string-contains line "/views/")
+                               (string-contains line "/revision/"))
+                           (set! in-location? #t))
+                          ((and in-location?
+                                (string-contains line "}"))
+                           (set! in-location? #f))
+                          (in-location? #f)
+                          ((string-contains line "return 301 https")
+                           (set! skip? #t))
+                          ((and skip?
+                                (string-contains line "}"))
+                           (set! skip? #f))
+                          (skip? #f)
+                          ((or (string-contains line "443")
+                               (string-contains line "ssl_certificate")
+                               (string-contains line "ssl_trusted")
+                               (string-contains line "userid"))
+                           #f)
+                          ((string-contains line "[::]:80")
+                           #f)
+                          ((string-contains line "listen 80")
+                           (display "    listen 80;\n" out))
+                          (else (display line out)
+                                (newline out)))
+                        (lp (read-line in))))))
+                (display "}\n" out)))))))
+    (home-page #f)
+    (synopsis "Nginx configuration for the website")
+    (description #f)
+    (license license:gpl3+)))
index 1b07d6159c8883626c5156fc75390acc4f99c4ef..f24f0ce2b40eaf9561e49b59103189d621c99e88 100644 (file)
@@ -5,7 +5,7 @@
 
 (define-module (tests common)
   #:use-module (guix gexp)
-  #:export (assert-service-running assert-binary-exists))
+  #:export (assert-service-running assert-binary-exists assert-http-200))
 
 (define (assert-service-running label service-name marionette-gexp)
   "Return a gexp that asserts the Shepherd service SERVICE-NAME is
@@ -22,3 +22,26 @@ running."
                  (marionette-eval '(file-exists? (string-append #$pkg "/bin/"
                                                                 #$binary-name))
                                   #$marionette-gexp)))
+
+(define (assert-http-200 label uri marionette-gexp)
+  "Return a gexp that asserts an HTTP GET to URI returns 200."
+  (let ((body `(begin
+                 (use-modules (ice-9 rdelim)
+                              (srfi srfi-13))
+                 (let* ((req (string-append "GET "
+                                            ,uri " HTTP/1.0\r\n\r\n"))
+                        (s (socket PF_INET SOCK_STREAM 0))
+                        (addr (make-socket-address AF_INET INADDR_LOOPBACK 80)))
+                   (catch 'system-error
+                          (lambda ()
+                            (connect s addr)
+                            (display req s)
+                            (force-output s)
+                            (let ((rsp (read-line s)))
+                              (close-port s)
+                              (string-contains rsp "200")))
+                          (lambda (key . args)
+                            (close-port s) #f))))))
+    #~(test-assert #$label
+                   (marionette-eval '#$body
+                                    #$marionette-gexp))))