You've already forked guix-tribes
284 lines
11 KiB
Scheme
284 lines
11 KiB
Scheme
(define-module (tribes services tribes)
|
|
#:use-module (gnu services)
|
|
#:use-module (gnu services base)
|
|
#:use-module (gnu services databases)
|
|
#:use-module (gnu services shepherd)
|
|
#:use-module (gnu packages admin)
|
|
#:use-module (gnu system shadow)
|
|
#:use-module (guix gexp)
|
|
#:use-module (guix records)
|
|
#:use-module (ice-9 match)
|
|
#:use-module (srfi srfi-13)
|
|
#:export (tribes-configuration
|
|
tribes-configuration?
|
|
tribes-configuration-package
|
|
tribes-configuration-user
|
|
tribes-configuration-group
|
|
tribes-configuration-working-directory
|
|
tribes-configuration-plugin-directory
|
|
tribes-configuration-host
|
|
tribes-configuration-scheme
|
|
tribes-configuration-port
|
|
tribes-configuration-relay-url
|
|
tribes-configuration-host-manifest
|
|
tribes-configuration-admin-pubkeys
|
|
tribes-configuration-sync-overlap-seconds
|
|
tribes-configuration-database-user
|
|
tribes-configuration-database-name
|
|
tribes-configuration-parrhesia-database-name
|
|
tribes-configuration-database-host
|
|
tribes-configuration-secret-key-base-file
|
|
tribes-configuration-token-signing-secret-file
|
|
tribes-configuration-dns-cluster-query
|
|
tribes-configuration-extra-environment-variables
|
|
tribes-configuration-log-file
|
|
tribes-service-type))
|
|
|
|
(define-record-type* <tribes-configuration>
|
|
tribes-configuration make-tribes-configuration
|
|
tribes-configuration?
|
|
(package tribes-configuration-package
|
|
(default #f))
|
|
(user tribes-configuration-user
|
|
(default "tribes"))
|
|
(group tribes-configuration-group
|
|
(default "tribes"))
|
|
(working-directory tribes-configuration-working-directory
|
|
(default "/var/lib/tribes"))
|
|
(plugin-directory tribes-configuration-plugin-directory
|
|
(default "/var/lib/tribes/plugins"))
|
|
(host tribes-configuration-host
|
|
(default "localhost"))
|
|
(scheme tribes-configuration-scheme
|
|
(default "http"))
|
|
(port tribes-configuration-port
|
|
(default 4000))
|
|
(relay-url tribes-configuration-relay-url
|
|
(default #f))
|
|
(host-manifest tribes-configuration-host-manifest
|
|
(default #f))
|
|
(admin-pubkeys tribes-configuration-admin-pubkeys
|
|
(default '()))
|
|
(sync-overlap-seconds tribes-configuration-sync-overlap-seconds
|
|
(default 300))
|
|
(database-user tribes-configuration-database-user
|
|
(default "tribes"))
|
|
(database-name tribes-configuration-database-name
|
|
(default "tribes"))
|
|
(parrhesia-database-name tribes-configuration-parrhesia-database-name
|
|
(default "parrhesia"))
|
|
(database-host tribes-configuration-database-host
|
|
(default "/var/run/postgresql"))
|
|
(secret-key-base-file tribes-configuration-secret-key-base-file
|
|
(default "/var/lib/tribes/secrets/secret_key_base"))
|
|
(token-signing-secret-file tribes-configuration-token-signing-secret-file
|
|
(default "/var/lib/tribes/secrets/token_signing_secret"))
|
|
(dns-cluster-query tribes-configuration-dns-cluster-query
|
|
(default #f))
|
|
(extra-environment-variables tribes-configuration-extra-environment-variables
|
|
(default '()))
|
|
(log-file tribes-configuration-log-file
|
|
(default "/var/log/tribes/tribes.log")))
|
|
|
|
(define (tribes-accounts config)
|
|
(list
|
|
(user-group
|
|
(name (tribes-configuration-group config))
|
|
(system? #t))
|
|
(user-account
|
|
(name (tribes-configuration-user config))
|
|
(group (tribes-configuration-group config))
|
|
(system? #t)
|
|
(comment "Tribes service user")
|
|
(home-directory (tribes-configuration-working-directory config))
|
|
(shell (file-append shadow "/sbin/nologin")))))
|
|
|
|
(define (tribes-relay-url config)
|
|
(or (tribes-configuration-relay-url config)
|
|
(let* ((scheme (tribes-configuration-scheme config))
|
|
(host (tribes-configuration-host config))
|
|
(port (tribes-configuration-port config))
|
|
(ws-scheme (if (string=? scheme "https") "wss" "ws"))
|
|
(default-port?
|
|
(or (and (string=? scheme "https") (= port 443))
|
|
(and (string=? scheme "http") (= port 80)))))
|
|
(if default-port?
|
|
(string-append ws-scheme "://" host "/nostr/relay")
|
|
(string-append ws-scheme "://" host ":" (number->string port)
|
|
"/nostr/relay")))))
|
|
|
|
(define (tribes-database-url config database-name)
|
|
(let ((user (tribes-configuration-database-user config))
|
|
(host (tribes-configuration-database-host config)))
|
|
(if (string-prefix? "/" host)
|
|
(string-append "ecto://"
|
|
user
|
|
"@localhost/"
|
|
database-name
|
|
"?socket_dir="
|
|
host)
|
|
(string-append "ecto://"
|
|
user
|
|
"@"
|
|
host
|
|
"/"
|
|
database-name))))
|
|
|
|
(define (tribes-launcher config command args)
|
|
(define package
|
|
(tribes-configuration-package config))
|
|
(define env-setters
|
|
(append
|
|
(list
|
|
#~(setenv "HOME" #$(tribes-configuration-working-directory config))
|
|
#~(setenv "PHX_SERVER" "true")
|
|
#~(setenv "PORT" #$(number->string (tribes-configuration-port config)))
|
|
#~(setenv "PHX_HOST" #$(tribes-configuration-host config))
|
|
#~(setenv "DATABASE_URL"
|
|
#$(tribes-database-url
|
|
config
|
|
(tribes-configuration-database-name config)))
|
|
#~(setenv "PARRHESIA_DATABASE_URL"
|
|
#$(tribes-database-url
|
|
config
|
|
(tribes-configuration-parrhesia-database-name config)))
|
|
#~(setenv "PARRHESIA_RELAY_URL" #$(tribes-relay-url config))
|
|
#~(setenv "TRIBES_PLUGIN_DIR" #$(tribes-configuration-plugin-directory config))
|
|
#~(setenv "TRIBES_SYNC_OVERLAP_SECONDS"
|
|
#$(number->string
|
|
(tribes-configuration-sync-overlap-seconds config)))
|
|
#~(setenv "TRIBES_ADMIN_PUBKEYS"
|
|
#$(string-join
|
|
(tribes-configuration-admin-pubkeys config)
|
|
","))
|
|
#~(setenv "SSL_CERT_DIR" "/etc/ssl/certs")
|
|
#~(setenv "SSL_CERT_FILE" "/etc/ssl/certs/ca-certificates.crt"))
|
|
(if (tribes-configuration-host-manifest config)
|
|
(list #~(setenv "TRIBES_HOST_MANIFEST"
|
|
#$(tribes-configuration-host-manifest config)))
|
|
'())
|
|
(if (tribes-configuration-dns-cluster-query config)
|
|
(list #~(setenv "DNS_CLUSTER_QUERY"
|
|
#$(tribes-configuration-dns-cluster-query config)))
|
|
'())
|
|
(map (lambda (entry)
|
|
#~(let* ((entry #$entry)
|
|
(parts (string-split entry #\=))
|
|
(name (car parts))
|
|
(value (string-join (cdr parts) "=")))
|
|
(setenv name value)))
|
|
(tribes-configuration-extra-environment-variables config))))
|
|
(program-file
|
|
(string-append "tribes-" command)
|
|
#~(begin
|
|
(use-modules (ice-9 textual-ports)
|
|
(srfi srfi-13))
|
|
|
|
(define (read-secret path)
|
|
(string-trim-right (call-with-input-file path get-string-all)))
|
|
|
|
(define secret-key-file
|
|
#$(tribes-configuration-secret-key-base-file config))
|
|
(define token-file
|
|
#$(tribes-configuration-token-signing-secret-file config))
|
|
|
|
(unless (file-exists? secret-key-file)
|
|
(format (current-error-port)
|
|
"missing Tribes secret file: ~a~%"
|
|
secret-key-file)
|
|
(exit 1))
|
|
|
|
(unless (file-exists? token-file)
|
|
(format (current-error-port)
|
|
"missing Tribes token-signing secret file: ~a~%"
|
|
token-file)
|
|
(exit 1))
|
|
|
|
(setenv "SECRET_KEY_BASE" (read-secret secret-key-file))
|
|
(setenv "TOKEN_SIGNING_SECRET" (read-secret token-file))
|
|
#$@env-setters
|
|
(apply execl
|
|
#$(file-append package "/bin/tribes")
|
|
"tribes"
|
|
(cons #$command '#$args)))))
|
|
|
|
(define (tribes-activation config)
|
|
#~(begin
|
|
(use-modules (guix build utils)
|
|
(ice-9 match)
|
|
(srfi srfi-1))
|
|
(let* ((user (getpwnam #$(tribes-configuration-user config)))
|
|
(uid (passwd:uid user))
|
|
(gid (passwd:gid user))
|
|
(dirs (list #$(tribes-configuration-working-directory config)
|
|
#$(tribes-configuration-plugin-directory config)
|
|
(dirname #$(tribes-configuration-log-file config))
|
|
(dirname #$(tribes-configuration-secret-key-base-file config))
|
|
(dirname #$(tribes-configuration-token-signing-secret-file config)))))
|
|
(for-each
|
|
(lambda (dir)
|
|
(mkdir-p dir)
|
|
(chown dir uid gid))
|
|
dirs))))
|
|
|
|
(define (tribes-migrations-shepherd-service config)
|
|
(let ((launcher (tribes-launcher
|
|
config
|
|
"eval"
|
|
'("Tribes.Release.migrate_with_storage_up()"))))
|
|
(list
|
|
(shepherd-service
|
|
(documentation "Run Tribes database migrations.")
|
|
(provision '(tribes-migrations))
|
|
(requirement '(postgres user-processes))
|
|
(one-shot? #t)
|
|
(start
|
|
#~(lambda _
|
|
(zero? (spawn-command
|
|
(list #$launcher)
|
|
#:user #$(tribes-configuration-user config)
|
|
#:group #$(tribes-configuration-group config)))))
|
|
(respawn? #f)))))
|
|
|
|
(define (tribes-shepherd-service config)
|
|
(let ((launcher (tribes-launcher config "start" '())))
|
|
(list
|
|
(shepherd-service
|
|
(documentation "Run the Tribes application service.")
|
|
(provision '(tribes))
|
|
(requirement '(tribes-migrations networking user-processes))
|
|
(start
|
|
#~(make-forkexec-constructor
|
|
(list #$launcher)
|
|
#:user #$(tribes-configuration-user config)
|
|
#:group #$(tribes-configuration-group config)
|
|
#:log-file #$(tribes-configuration-log-file config)))
|
|
(stop #~(make-kill-destructor))
|
|
(respawn? #f)))))
|
|
|
|
(define (tribes-root-shepherd-services config)
|
|
(append (tribes-migrations-shepherd-service config)
|
|
(tribes-shepherd-service config)))
|
|
|
|
(define (tribes-profile-packages config)
|
|
(match (tribes-configuration-package config)
|
|
(#f '())
|
|
(package (list package))))
|
|
|
|
(define tribes-service-type
|
|
(service-type
|
|
(name 'tribes)
|
|
(extensions
|
|
(list (service-extension account-service-type
|
|
tribes-accounts)
|
|
(service-extension activation-service-type
|
|
tribes-activation)
|
|
(service-extension shepherd-root-service-type
|
|
tribes-root-shepherd-services)
|
|
(service-extension profile-service-type
|
|
tribes-profile-packages)))
|
|
(default-value (tribes-configuration))
|
|
(description
|
|
"Run a Tribes release with PostgreSQL-backed storage, Parrhesia, and
|
|
cluster runtime configuration sourced from files and service settings.")))
|