aboutsummaryrefslogtreecommitdiff
path: root/guix/forge/tissue.scm
diff options
context:
space:
mode:
Diffstat (limited to 'guix/forge/tissue.scm')
-rw-r--r--guix/forge/tissue.scm138
1 files changed, 112 insertions, 26 deletions
diff --git a/guix/forge/tissue.scm b/guix/forge/tissue.scm
index 4ece204..1608728 100644
--- a/guix/forge/tissue.scm
+++ b/guix/forge/tissue.scm
@@ -1,5 +1,5 @@
;;; guix-forge --- Guix software forge meta-service
-;;; Copyright © 2022, 2023 Arun Isaac <arunisaac@systemreboot.net>
+;;; Copyright © 2022, 2023, 2025 Arun Isaac <arunisaac@systemreboot.net>
;;;
;;; This file is part of guix-forge.
;;;
@@ -19,13 +19,16 @@
(define-module (forge tissue)
#:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
#:use-module ((forge guile-git) #:select (guile-git))
+ #:use-module (forge nginx)
#:use-module (forge socket)
#:use-module (gnu build linux-container)
#:use-module ((gnu packages admin) #:select (shadow))
#:use-module ((gnu packages web) #:select (tissue) #:prefix guix:)
#:use-module (gnu services)
#:use-module (gnu services shepherd)
+ #:use-module (gnu services web)
#:use-module (gnu system file-systems)
#:use-module (gnu system shadow)
#:use-module (guix gexp)
@@ -34,6 +37,7 @@
#:use-module (guix modules)
#:use-module (guix packages)
#:use-module (guix records)
+ #:use-module (ice-9 match)
#:export (tissue-service-type
<tissue-configuration>
tissue-configuration
@@ -46,14 +50,19 @@
tissue-host
tissue-host?
tissue-host-name
- tissue-host-user
- tissue-host-upstream-repository))
+ tissue-host-projects
+ <tissue-project>
+ tissue-project
+ tissue-project-name
+ tissue-project-user
+ tissue-project-base-path
+ tissue-project-upstream-repository))
;; Run an updated version of tissue until the the 0.1.1 release is
;; out.
(define-public tissue
- (let ((commit "0c3d6cb7d781fbc0c12eba1563cc7b7ebb370ba9")
- (revision "1"))
+ (let ((commit "a9187595cccca4954c7d4920b93b922ea190e179")
+ (revision "2"))
(package
(inherit guix:tissue)
(name "tissue")
@@ -66,7 +75,7 @@
(file-name (git-file-name name version))
(sha256
(base32
- "0hdqa5n8dm2nc4ccx39xclgajv3ivwpb1hbz9kpbbv25iizqhnv2"))))
+ "0pgdznck8vwmbccmpcqd3xnikbgzb2phxik7bcm80dls6g4n3py2"))))
(inputs
(modify-inputs (package-inputs guix:tissue)
(replace "guile-git" guile-git))))))
@@ -88,9 +97,22 @@
tissue-host make-tissue-host
tissue-host?
(name tissue-host-name)
- (user tissue-host-user
+ (projects tissue-host-projects
+ (default '())))
+
+(define-record-type* <tissue-project>
+ tissue-project make-tissue-project
+ tissue-project?
+ this-tissue-project
+ (name tissue-project-name)
+ (user tissue-project-user
(default "tissue"))
- (upstream-repository tissue-host-upstream-repository))
+ (base-path tissue-project-base-path
+ (default (string-append "/"
+ (tissue-project-name this-tissue-project)
+ "/"))
+ (thunked))
+ (upstream-repository tissue-project-upstream-repository))
(define %tissue-accounts
(list (user-account
@@ -105,6 +127,19 @@
(system? #t))))
(define (tissue-conf-gexp config)
+ (define project->alist
+ (match-record-lambda <tissue-project>
+ (name base-path upstream-repository)
+ `(,name
+ (base-path . ,base-path)
+ (upstream-repository . ,upstream-repository))))
+
+ (define host->alist
+ (match-record-lambda <tissue-host>
+ (name projects)
+ `(,name
+ (projects . ,(map project->alist projects)))))
+
(match-record config <tissue-configuration>
(socket state-directory hosts)
#~(begin
@@ -129,11 +164,7 @@
"Socket must be a <forge-ip-socket> or <forge-unix-socket> record")
(make-irritants-condition socket))))))
(state-directory . #$state-directory)
- (hosts . #$(map (lambda (host)
- (match-record host <tissue-host>
- (name upstream-repository)
- `(,name (upstream-repository . ,upstream-repository))))
- hosts)))
+ (hosts . #$(map host->alist hosts)))
port))))))
;; We cannot just pass the configuration file on the command-line
@@ -162,22 +193,23 @@
;; the tissue user.
(mkdir-p #$state-directory)
(chown #$state-directory (passwd:uid user) (passwd:gid user)))
- ;; Create host directories if they don't exist, and set
- ;; permissions. Each host directory may be owned by its own
- ;; user.
+ ;; Create project directories if they don't exist, and set
+ ;; permissions. Each project directory may be owned by its
+ ;; own user.
(for-each (match-lambda
- ((hostname username)
- (let ((host-directory (string-append #$state-directory "/" hostname))
+ ((project-name username)
+ (let ((project-directory (string-append #$state-directory "/" project-name))
(user (getpw username)))
- (mkdir-p host-directory)
+ (mkdir-p project-directory)
(for-each (lambda (file)
(chown file (passwd:uid user) (passwd:gid user)))
- (find-files host-directory #:directories? #t)))))
- '#$(map (lambda (host)
- (match-record host <tissue-host>
- (name user)
- (list name user)))
- hosts))))))
+ (find-files project-directory #:directories? #t)))))
+ '#$(append-map (lambda (host)
+ (map (match-record-lambda <tissue-project>
+ (name user)
+ (list name user))
+ (tissue-host-projects host)))
+ hosts))))))
(define (tissue-shepherd-service config)
(match-record config <tissue-configuration>
@@ -216,6 +248,58 @@
#:log-file "/var/log/tissue.log")))
(stop #~(make-kill-destructor)))))
+(define (socket->proxy-pass socket)
+ "Serialize @var{socket}, a forge socket, to an nginx @code{proxy_pass}
+directive."
+ (string-append
+ "proxy_pass "
+ (match socket
+ (($ <forge-host-socket> hostname port)
+ (string-append "http://" hostname ":" (number->string port)))
+ (($ <forge-ip-socket> (? ipv4-address? ip) port)
+ (string-append "http://" ip ":" (number->string port)))
+ (($ <forge-ip-socket> (? ipv6-address? ip) port)
+ (string-append "http://[" ip "]:" (number->string port)))
+ (($ <forge-unix-socket> path)
+ (string-append "http://unix:" path ":")))
+ ";"))
+
+(define (tissue-nginx-server-blocks config)
+ "Return list of @code{<nginx-server-configuration>} extensions for
+tissue configuration @var{config}."
+ (define (project->location state-directory project)
+ (nginx-location-configuration
+ (uri (tissue-project-base-path project))
+ (body (list (string-append "alias "
+ state-directory
+ "/"
+ (tissue-project-name project)
+ "/website/;")
+ "try_files $uri $uri.html $uri/ @tissue-search;"))))
+
+ (match-record config <tissue-configuration>
+ (socket state-directory hosts)
+ (map (match-record-lambda <tissue-host>
+ (name projects)
+ (nginx-server-configuration
+ (server-name (list name))
+ (locations
+ (cons (nginx-location-configuration
+ (uri "@tissue-search")
+ (body (list (socket->proxy-pass socket)
+ "proxy_set_header Host $host;")))
+ (append (map (cut project->location state-directory <>)
+ projects)
+ ;; Reject all other locations, unless there
+ ;; is a project with / as its base path.
+ (if (member "/" (map tissue-project-base-path
+ projects))
+ (list)
+ (list (nginx-location-configuration
+ (uri "/")
+ (body (list "return 404;"))))))))))
+ hosts)))
+
(define tissue-service-type
(service-type
(name 'tissue)
@@ -228,7 +312,9 @@
(service-extension activation-service-type
tissue-activation)
(service-extension shepherd-root-service-type
- (compose list tissue-shepherd-service))))
+ (compose list tissue-shepherd-service))
+ (service-extension forge-nginx-service-type
+ tissue-nginx-server-blocks)))
(compose concatenate)
(extend (lambda (config host-extensions)
(tissue-configuration