system-configuration/modules/config/static-web.scm

static-web.scm

1
;;; GNU Guix system administration tools.
2
;;;
3
;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
4
;;; Copyright © 2020 Ricardo Wurmus <rekado@elephly.net>
5
;;;
6
;;; This program is free software: you can redistribute it and/or modify
7
;;; it under the terms of the GNU General Public License as published by
8
;;; the Free Software Foundation, either version 3 of the License, or
9
;;; (at your option) any later version.
10
;;;
11
;;; This program is distributed in the hope that it will be useful,
12
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
;;; GNU General Public License for more details.
15
;;;
16
;;; You should have received a copy of the GNU General Public License
17
;;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
20
;;; NOTE: this file is taken from
21
;;; https://git.savannah.gnu.org/cgit/guix/maintenance.git/plain/hydra/modules/sysadmin/web.scm
22
23
(define-module (config static-web)
24
  #:use-module (guix git)
25
  #:use-module (guix gexp)
26
  #:use-module (guix modules)
27
  #:use-module (guix packages)
28
  #:use-module (guix records)
29
  #:use-module (guix git-download)
30
  #:use-module (gnu packages)
31
  #:use-module (gnu packages autotools)
32
  #:use-module (gnu packages graphviz)
33
  #:use-module (gnu packages guile)
34
  #:use-module (gnu packages guile-xyz)
35
  #:use-module (gnu packages package-management)
36
  #:use-module (gnu packages pkg-config)
37
  #:use-module (gnu packages texinfo)
38
  #:use-module (gnu services)
39
  #:use-module (gnu services mcron)
40
  #:use-module (gnu services shepherd)
41
  #:use-module (gnu services web)
42
  #:use-module (gnu system shadow)
43
  #:use-module (ice-9 match)
44
  #:export (build-program
45
46
            static-web-site-configuration
47
            static-web-site-configuration?
48
49
            static-web-site-service-type))
50
51
52
(define guix-extensions
53
  (match (package-transitive-propagated-inputs
54
          (specification->package "guix"))
55
    (((labels packages) ...)
56
     (cons (specification->package "guix") packages))))
57
58
(define* (build-program url root
59
                        #:key
60
                        (file "guix.scm")
61
                        (ref '(branch . "master"))
62
                        (name "build-program")
63
                        (environment-variables '())
64
                        (cache-directory #f))
65
  "Return a program that pulls code from URL, builds it by loading FILE from
66
that checkout (usually a 'guix.scm' file), and registers the result as
67
ROOT (an indirect GC root) upon success.  FILE is loaded in a content where
68
ENVIRONMENT-VARIABLES, a list of key/value pairs, are defined.
69
70
The typical use case is polling from the source repository of a web site
71
that's built with Haunt or similar."
72
  (define build
73
    (with-extensions guix-extensions
74
      #~(begin
75
          (use-modules (guix) (guix git) (guix ui)
76
                       (srfi srfi-11) (ice-9 match))
77
78
          (define (root-installed drv root)
79
            (mbegin %store-monad
80
              ((store-lift add-indirect-root) root)
81
              (let ((pivot (string-append root ".tmp")))
82
                (symlink (derivation->output-path drv) pivot)
83
                (rename-file pivot root)
84
                (return #t))))
85
86
          (define cache
87
            (and=> #$cache-directory
88
                   (lambda (directory)
89
                     ;; Interpret DIRECTORY as relative to $HOME/.cache.
90
                     (string-append (%repository-cache-directory)
91
                                    "/" directory))))
92
93
          (define-values (checkout commit relation)
94
            (apply update-cached-checkout #$url #:ref '#$ref
95
                   (if cache
96
                       `(#:cache-directory ,cache)
97
                       '())))
98
99
          (define obj
100
            (let ((variables '#$environment-variables))
101
              (for-each (match-lambda
102
                          ((name . value)
103
                           (setenv name value)))
104
                        variables)
105
              (primitive-load (string-append checkout "/" #$file))))
106
107
          (with-store store
108
            (run-with-store store
109
              (mlet %store-monad ((drv (lower-object obj)))
110
                (mbegin %store-monad
111
                  (show-what-to-build* (list drv))
112
                  (built-derivations (list drv))
113
                  (root-installed drv #$root))))))))
114
115
  (program-file name build
116
                #:guile guile-3.0-latest))
117
118

119
;;;
120
;;; Service.
121
;;;
122
123
(define-record-type* <static-web-site-configuration>
124
  static-web-site-configuration make-static-web-site-configuration
125
  static-web-site-configuration?
126
  (git-url     static-web-site-configuration-git-url)
127
  (git-ref     static-web-site-configuration-git-ref
128
               (default '(branch . "master")))
129
  (build-file  static-web-site-configuration-build-file
130
               (default "guix.scm"))
131
  (environment-variables static-web-site-configuration-environment-variable
132
                         (default '()))
133
  (cache-directory static-web-site-configuration-cache-directory
134
                   (default #f))
135
  (directory   static-web-site-configuration-directory
136
               (default "/srv/www")))
137
138
(define (static-web-site-mcron-jobs config)
139
  (define update
140
    (build-program (static-web-site-configuration-git-url config)
141
                   (static-web-site-configuration-directory config)
142
                   #:file (static-web-site-configuration-build-file config)
143
                   #:ref (static-web-site-configuration-git-ref config)
144
                   #:environment-variables
145
                   (static-web-site-configuration-environment-variable config)
146
                   #:cache-directory
147
                   (static-web-site-configuration-cache-directory config)
148
                   #:name (string-append
149
                           "update-"
150
                           (basename
151
                            (static-web-site-configuration-directory config)))))
152
153
  (list #~(job '(next-minute '(0)) #$update
154
               #:user "static-web-site")))
155
156
(define (static-web-site-activation config)
157
  (with-imported-modules '((guix build utils))
158
    #~(begin
159
        (use-modules (guix build utils))
160
161
        (let ((directory (dirname
162
                          #$(static-web-site-configuration-directory config))))
163
          (mkdir-p directory)
164
          (chown directory
165
                 (passwd:uid (getpw "static-web-site"))
166
                 (group:gid (getgr "static-web-site")))))))
167
168
(define (static-web-site-accounts config)
169
  (list (user-account
170
         (name "static-web-site")
171
         (group "static-web-site")
172
         (system? #t))
173
        (user-group
174
         (name "static-web-site")
175
         (system? #t))))
176
177
(define static-web-site-service-type
178
  (service-type (name 'static-web-site)
179
                (extensions
180
                 ;; TODO: Extend nginx directly from here?
181
                 (list (service-extension mcron-service-type
182
                                          static-web-site-mcron-jobs)
183
                       (service-extension account-service-type
184
                                          static-web-site-accounts)
185
                       (service-extension activation-service-type
186
                                          static-web-site-activation)))
187
                (description
188
                 "Update and publish a web site that is built from source
189
taken from a Git repository.")))
190