summaryrefslogtreecommitdiff
path: root/tw/services/matrix.scm
blob: 0e7cff61e4d4ae3c821c0f945b2fb7896deb9667 (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
(define-module (tw services matrix)
  #:use-module (gnu)
  #:use-module ((gnu packages admin) #:select (shadow))
  #:use-module (gnu services)
  #:use-module (gnu services certbot)
  #:use-module (gnu services configuration)
  #:use-module (gnu services databases)
  #:use-module (gnu services docker)
  #:use-module (gnu services web)
  #:use-module (guix records)
  #:use-module (tw services web)
  #:use-module (tw services docker)
  #:export (matrix-service-type
            matrix-configuration
            matrix-well-known-nginx-locations))

(define %matrix-user "matrix")
(define %matrix-uid 1337)   ; match Mautrix bridge containers
(define %conduit-port 6167)

(define-maybe/no-serialization string)

(define-configuration/no-serialization matrix-configuration
  (domain (string "localhost") "The external domain on which the Matrix server
will actually be hosted.  If a different display domain is desired for
usernames, use @code{matrix-well-known-nginx-locations}.")
  (server-name maybe-string "The external display name of the server where the
Matrix server is hosted.  Usernames will include this hostname.  If not given,
@code{domain} is used.")
  (data-path (string "/var/lib/matrix") "The path to store data inside."))

(define (matrix-oci-containers config)
  (match-record config <matrix-configuration> (domain server-name data-path)
    (list (oci-container-configuration
           (provision "conduit")
           (image "registry.gitlab.com/famedly/conduit/matrix-conduit:v0.6.0")
           ;; We can't use %matrix-user, since the container's internal user
           ;; has UID 1000, and that's already taken on the host system.
           (container-user (number->string %matrix-uid))
           (network "host")  ; allow access to localhost-bound conduit port
           ;; https://gitlab.com/famedly/conduit/-/blob/next/docker/README.md
           ;; https://gitlab.com/famedly/conduit/-/blob/next/conduit-example.toml
           (environment `(("CONDUIT_CONFIG" . "")  ; use only env vars
                          ("CONDUIT_SERVER_NAME" . ,(maybe-value server-name domain))
                          ("CONDUIT_ADDRESS" . "127.0.0.1")
                          ("CONDUIT_PORT" . ,(number->string %conduit-port))
                          ("CONDUIT_DATABASE_BACKEND" . "rocksdb")
                          ("CONDUIT_ALLOW_REGISTRATION" . "false")
                          ("CONDUIT_ALLOW_FEDERATION" . "false")
                          ("CONDUIT_ALLOW_CHECK_FOR_UPDATES" . "false")
                          ("CONDUIT_ENABLE_LIGHTNING_BOLT" . "false")
                          ("CONDUIT_MAX_REQUEST_SIZE" . "100_000_000")
                          ("CONDUIT_TRUSTED_SERVERS" . "[\"matrix.org\"]")))
           (volumes `((,(string-append data-path "/conduit") . "/var/lib/matrix-conduit")))))))

(define (matrix-accounts config)
  (match-record config <matrix-configuration> (data-path)
    (list (user-account
           (name %matrix-user)
           (uid %matrix-uid)
           (group "nogroup")
           (comment "Matrix server user")
           (system? #t)
           (home-directory data-path)
           (shell (file-append shadow "/sbin/nologin"))))))

(define (matrix-well-known-nginx-locations config)
  (match-record config <matrix-configuration> (domain)
    (list (nginx-location-configuration
           (uri "/.well-known/matrix/server")
           (body `(("return 200 '{\"m.server\": \"" ,domain "\"}';")
                   "types { } default_type \"application/json; charset=utf-8\";")))
          (nginx-location-configuration
           (uri "/.well-known/matrix/client")
           (body `("return 200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.twilken.net\"}}';"
                   "types { } default_type \"application/json; charset=utf-8\";"
                   "add_header \"Access-Control-Allow-Origin\" *;"))))))

(define (matrix-reverse-proxy config)
  (match-record config <matrix-configuration> (domain)
    ;; https://gitlab.com/famedly/conduit/-/blob/next/DEPLOY.md#nginx
    (list (nginx-server-configuration
           (listen '("443 ssl http2" "8448 ssl http2"))
           (server-name (list domain))
           (ssl-certificate (string-append "/etc/letsencrypt/live/" domain "/fullchain.pem"))
           (ssl-certificate-key (string-append "/etc/letsencrypt/live/" domain "/privkey.pem"))
           (server-tokens? #f)
           (locations
            (list (nginx-location-configuration
                   (uri "/_matrix")
                   (body `(("proxy_pass http://127.0.0.1:"
                            ,(number->string %conduit-port) "$request_uri;")
                           "proxy_set_header Host $http_host;"
                           "proxy_buffering off;"
                           "proxy_read_timeout 5m;")))))))))

(define (matrix-certificates config)
  (match-record config <matrix-configuration> (domain)
    (list (certificate-configuration
           (domains (list domain))
           (deploy-hook %nginx-cert-deploy-hook)))))

(define matrix-service-type
  (service-type
   (name 'matrix)
   (extensions
    (list (service-extension oci-container-service-type matrix-oci-containers)
          (service-extension account-service-type matrix-accounts)
          ;; Synapse can't access certbot certs, but nginx can, so proxy HTTPS
          ;; access through. Also, it's good to have Synapse available on :443.
          (service-extension nginx-service-type matrix-reverse-proxy)
          (service-extension certbot-service-type matrix-certificates)))
   (default-value (matrix-configuration))
   (description "Run a matrix server with various bridges.")))