summaryrefslogtreecommitdiff
path: root/tw/services/web.scm
blob: 835aebd3a1890b9a9d3477fd1a9870a5bd94a5db (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
(define-module (tw services web)
  #:use-module (gnu services)
  #:use-module (gnu services configuration)
  #:use-module (gnu services certbot)
  #:use-module (gnu services web)
  #:use-module (guix gexp)
  #:use-module (guix records)
  #:use-module ((srfi srfi-1) #:select (concatenate))
  #:export (%nginx-cert-deploy-hook
            https-reverse-proxy-service-type
            https-reverse-proxy-configuration))

(define %nginx-cert-deploy-hook
  (program-file "nginx-cert-deploy-hook"
    #~(kill (call-with-input-file "/var/run/nginx/pid" read) SIGHUP)))

(define-configuration/no-serialization https-reverse-proxy-configuration
  (domains list-of-strings "List of domain names that nginx should proxy
requests for.")
  (destination-port integer "The port number of the service that should be
proxied to.")
  (destination-ip (string "127.0.0.1") "The IP address of the server that
should be proxied to.  Usually, this should be localhost.")
  (destination-protocol (string "http") "The protocol that the proxied service
speaks.  Set to @code{\"https\"} if you want to proxy HTTPS-to-HTTPS."))

(define (reverse-proxy-certificate config)
  (match-record config <https-reverse-proxy-configuration> (domains)
    (certificate-configuration
     (domains domains)
     (deploy-hook %nginx-cert-deploy-hook))))

(define (reverse-proxy-nginx-server config)
  (match-record config <https-reverse-proxy-configuration>
                (domains destination-port destination-ip)
    (nginx-server-configuration
     (listen '("443 ssl http2"))
     (server-name domains)
     (ssl-certificate (string-append "/etc/letsencrypt/live/" (car domains) "/fullchain.pem"))
     (ssl-certificate-key (string-append "/etc/letsencrypt/live/" (car domains) "/privkey.pem"))
     (server-tokens? #f)
     (locations
      (list (nginx-location-configuration
             (uri "/")
             (body `(("proxy_pass http://" ,destination-ip ":"
                      ,(number->string destination-port) ";")
                     ;; For Grafana: https://grafana.com/tutorials/run-grafana-behind-a-proxy/#configure-nginx
                     "proxy_set_header Host $http_host;"))))))))

(define (reverse-proxy-certificates configs)
  (map reverse-proxy-certificate configs))

(define (reverse-proxy-nginx-servers configs)
  (map reverse-proxy-nginx-server configs))

(define https-reverse-proxy-service-type
  (service-type
   (name 'reverse-proxy)
   (extensions (list (service-extension nginx-service-type reverse-proxy-nginx-servers)
                     (service-extension certbot-service-type reverse-proxy-certificates)))
   (default-value '())
   (compose concatenate)
   (extend append)
   (description "Configure nginx as a reverse proxy proxying external HTTPS
requests to another host or a local port over plain HTTP.")))