(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 (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" . "100000000") ("CONDUIT_TRUSTED_SERVERS" . "[\"matrix.org\"]"))) (volumes `((,(string-append data-path "/conduit") . "/var/lib/matrix-conduit"))))))) (define (matrix-accounts config) (match-record config (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 (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 (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 (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.")))