1
0
mirror of https://codeberg.org/hako/Rosenthal.git synced 2025-07-11 18:56:32 +00:00
Rosenthal/modules/rosenthal/services/web.scm
Hilton Chain fbef0d3861
utils: Update serializers from RDE.
* modules/rosenthal/utils/serializers/ini.scm: New file.
* modules/rosenthal/utils/serializers/utils.scm: New file.
* modules/rosenthal/utils/serializers/yaml.scm: New file.
* modules/rosenthal/utils/home-services-utils.scm: Delete file.
* modules/rosenthal/services/child-error.scm (home-wakapi-shepherd-service):
Use the new serializer.
* modules/rosenthal/services/web.scm (misskey-oci-containers): Likewise.
2025-05-28 23:37:55 +08:00

624 lines
19 KiB
Scheme
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;; SPDX-FileCopyrightText: 2024 Hilton Chain <hako@ultrarare.space>
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
(define-module (rosenthal services web)
#:use-module (guix gexp)
#:use-module (guix modules)
#:use-module (guix records)
#:use-module (gnu packages admin)
#:use-module (gnu packages version-control)
#:use-module (gnu packages video)
#:use-module (rosenthal packages binaries)
#:use-module (rosenthal packages web)
#:use-module (gnu services)
#:use-module (gnu services admin)
#:use-module (gnu services configuration)
#:use-module (gnu services databases)
#:use-module (gnu services docker)
#:use-module (gnu services shepherd)
#:use-module (gnu system privilege)
#:use-module (gnu system shadow)
#:use-module (rosenthal utils serializers yaml)
#:export (caddy-configuration
caddy-service-type
forgejo-configuration
forgejo-service-type
jellyfin-configuration
jellyfin-service-type
komga-configuration
komga-service-type
misskey-configuration
misskey-service-type
navidrome-configuration
navidrome-service-type
vaultwarden-configuration
vaultwarden-service-type))
;;;
;;; Caddy
;;;
(define-configuration/no-serialization caddy-configuration
(caddy
(file-like caddy)
"")
(caddyfile
file-like
""))
(define (caddy-accounts config)
(list (user-group (name "caddy") (system? #t))
(user-account
(name "caddy")
(group "caddy")
(system? #t)
(comment "Caddy user")
(home-directory "/var/lib/caddy"))))
(define caddy-privileged-programs
(match-record-lambda <caddy-configuration>
(caddy)
(list (privileged-program
(program (file-append caddy "/bin/caddy"))
(capabilities "cap_net_bind_service=+ep")))))
(define caddy-activation
(match-record-lambda <caddy-configuration>
(caddyfile)
(with-imported-modules
(source-module-closure '((guix build utils)
(gnu build activation)))
#~(begin
(use-modules (srfi srfi-26)
(guix build utils)
(gnu build activation))
(let* ((config-dir "/etc/caddy")
(data-dir "/var/lib/caddy")
(config-file (in-vicinity config-dir "Caddyfile"))
(user (getpwnam "caddy")))
(for-each (cut mkdir-p/perms <> user #o750)
(list config-dir data-dir))
(copy-file #$caddyfile config-file)
(for-each
(lambda (file)
(chown file (passwd:uid user) (passwd:gid user)))
(find-files data-dir #:directories? #t)))))))
(define (caddy-shepherd-services config)
(list (shepherd-service
(provision '(caddy))
(requirement '(user-processes loopback))
(start
#~(make-forkexec-constructor
(list "/run/privileged/bin/caddy" "run"
"--environ" "--config" "/etc/caddy/Caddyfile")
#:user "caddy"
#:group "caddy"
#:directory "/var/lib/caddy"
#:log-file "/var/log/caddy.log"
#:resource-limits '((nofile 1048576 1048576))
#:environment-variables '("HOME=/var/lib/caddy")))
(stop
#~(make-kill-destructor)))))
(define caddy-service-type
(service-type
(name 'caddy)
(extensions
(list (service-extension account-service-type
caddy-accounts)
(service-extension privileged-program-service-type
caddy-privileged-programs)
(service-extension activation-service-type
caddy-activation)
(service-extension shepherd-root-service-type
caddy-shepherd-services)))
(default-value #f)
(description "")))
;;
;; Forgejo
;;
(define (file-object? val)
(or (string? val)
(file-like? val)))
(define list-of-file-likes?
(list-of file-like?))
(define-configuration forgejo-configuration
(forgejo
(file-like forgejo)
"Package to provide @file{/bin/forgejo}.")
(git-packages
(list-of-file-likes (list git git-lfs))
"@code{git} and extension packages to install.")
(config-file
(file-object "/var/lib/forgejo/app.ini")
"Filesystem path or file-like object of Forgejo configuration,
@file{app.ini}.")
(no-serialization))
(define %forgejo-accounts
(list (user-group (name "forgejo") (system? #t))
(user-account
(name "forgejo")
(group "forgejo")
(system? #t)
(comment "Forgejo user")
(home-directory "/var/lib/forgejo"))))
(define %forgejo-postgresql-role
(list (postgresql-role
(name "forgejo")
(create-database? #t))))
(define forgejo-activation
#~(begin
(use-modules (guix build utils))
(let ((dir "/var/lib/forgejo")
(user (getpwnam "forgejo")))
(mkdir-p dir)
(chown dir (passwd:uid user) (passwd:gid user))
(chmod dir #o750))))
(define forgejo-shepherd-service
(match-record-lambda <forgejo-configuration>
(forgejo config-file)
(list (shepherd-service
(documentation "Run Forgejo.")
(provision '(forgejo))
(requirement '(loopback postgresql))
(start
#~(make-forkexec-constructor
(list #$(file-append forgejo "/bin/forgejo")
"--config" #$config-file)
#:user "forgejo"
#:group "forgejo"
#:log-file "/var/log/forgejo.log"
#:environment-variables
'("GIT_EXEC_PATH=/run/current-system/profile/libexec/git-core"
"GIT_SSL_CAINFO=/run/current-system/profile/etc/ssl/certs/ca-certificates.crt"
"HOME=/var/lib/forgejo"
"PATH=/run/current-system/profile/bin"
"SSL_CERT_DIR=/run/current-system/profile/etc/ssl/certs"
"SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt")
#:resource-limits '((nofile 524288 524288))))
(stop
#~(make-kill-destructor))
(actions
(list (shepherd-configuration-action config-file)))))))
(define forgejo-service-type
(service-type
(name 'forgejo)
(extensions
(list (service-extension account-service-type
(const %forgejo-accounts))
(service-extension postgresql-role-service-type
(const %forgejo-postgresql-role))
(service-extension profile-service-type
forgejo-configuration-git-packages)
(service-extension activation-service-type
(const forgejo-activation))
(service-extension shepherd-root-service-type
forgejo-shepherd-service)))
(default-value (forgejo-configuration))
(description "Run Forgejo.")))
;;
;; Jellyfin
;;
(define-maybe string)
(define-configuration jellyfin-configuration
(cache-directory
(string "/var/cache/jellyfin")
"Path to cache directory.")
(config-directory
(string "/var/lib/jellyfin")
"Path to configuration directory.")
(proxy-url
maybe-string
"Proxy URL.")
(log-file
(string "/var/log/jellyfin.log")
"Path to log file.")
(auto-start?
(boolean #t)
"Whether to start automatically.")
(extra-options
(list '())
"List of extra options.")
(no-serialization))
(define %jellyfin-accounts
(list (user-account
(name "jellyfin")
(group "docker")
(system? #t)
(home-directory "/var/empty")
(shell (file-append shadow "/sbin/nologin")))))
(define jellyfin-activation
(match-record-lambda <jellyfin-configuration>
(cache-directory config-directory)
#~(let ((user (getpwnam "jellyfin")))
(for-each
(lambda (directory)
(unless (file-exists? directory)
(mkdir-p directory)
(chown directory (passwd:uid user) (passwd:gid user))))
'#$(list cache-directory config-directory)))))
(define jellyfin-oci-containers
(match-record-lambda <jellyfin-configuration>
(cache-directory config-directory
proxy-url log-file auto-start? extra-options)
(list (oci-container-configuration
(user "jellyfin")
(group "docker")
(environment
(if (maybe-value-set? proxy-url)
`(("http_proxy" . ,proxy-url)
("https_proxy" . ,proxy-url))
'()))
(image "jellyfin/jellyfin:latest")
(provision "jellyfin")
(log-file log-file)
(auto-start? auto-start?)
(respawn? #t)
(network "host")
(volumes
`((,cache-directory . "/cache")
(,config-directory . "/config")))
(extra-arguments extra-options)))))
(define jellyfin-service-type
(service-type
(name 'jellyfin)
(extensions
(list (service-extension account-service-type
(const %jellyfin-accounts))
(service-extension activation-service-type
jellyfin-activation)
(service-extension log-rotation-service-type
(compose list jellyfin-configuration-log-file))
(service-extension oci-container-service-type
jellyfin-oci-containers)))
(default-value (jellyfin-configuration))
(description "Run Jellyfin, a media system.")))
;;;
;;; Komga
;;;
(define-configuration komga-configuration
(komga
(file-like komga-bin)
"Package to provide @file{/bin/komga}.")
(port
(integer 25600)
"Port to listen to for the API and web interface.")
(auto-start?
(boolean #t)
"Whether to start automatically.")
(no-serialization))
(define %komga-accounts
(list (user-group (name "komga") (system? #t))
(user-account
(name "komga")
(group "komga")
(system? #t)
(comment "Komga user")
(home-directory "/var/lib/komga"))))
(define komga-shepherd-service
(match-record-lambda <komga-configuration>
(komga port auto-start?)
(list (shepherd-service
(documentation "Run Komga.")
(provision '(komga))
(requirement '(loopback))
(start
#~(make-forkexec-constructor
(list #$(file-append komga "/bin/komga"))
#:user "komga"
#:group "komga"
#:log-file "/var/log/komga.log"
#:environment-variables
'("KOMGA_CONFIGDIR=/var/lib/komga"
#$(string-append "SERVER_PORT=" (number->string port)))))
(stop
#~(make-kill-destructor))
(auto-start? auto-start?)))))
(define komga-service-type
(service-type
(name 'komga)
(extensions
(list (service-extension account-service-type
(const %komga-accounts))
(service-extension shepherd-root-service-type
komga-shepherd-service)))
(default-value (komga-configuration))
(description "Run Komga.")))
;;
;; Misskey
;;
(define-configuration misskey-configuration
(image
(string "misskey/misskey:latest")
"Misskey docker image to use.")
(config
(yaml-config '())
"Alist of Misskey configuration, to be serialized to YAML format.")
(data-directory
(string "/var/lib/misskey")
"Directory to store @file{files} in.")
(log-file
(string "/var/log/misskey.log")
"Log file to use.")
(no-serialization))
(define %misskey-accounts
(list (user-account
(name "misskey")
(group "docker")
(system? #t)
(home-directory "/var/empty")
(shell (file-append shadow "/sbin/nologin")))))
(define %misskey-postgresql-role
(list (postgresql-role
(name "misskey")
(create-database? #t))))
(define misskey-activation
(match-record-lambda <misskey-configuration>
(data-directory)
#~(begin
(use-modules (guix build utils))
(let ((user (getpwnam "misskey")))
(unless (file-exists? #$data-directory)
(mkdir-p #$data-directory)
(chown #$data-directory (passwd:uid user) (passwd:gid user)))))))
(define misskey-oci-containers
(match-record-lambda <misskey-configuration>
(image config data-directory log-file )
(let ((config-file
(mixed-text-file
"misskey.yaml"
#~(string-append #$@(yaml-serialize config) "\n"))))
(list (oci-container-configuration
(user "misskey")
(group "docker")
(image image)
(provision "misskey")
(requirement '(postgresql redis))
(log-file log-file)
(respawn? #t)
(network "host")
(volumes
`((,(string-append data-directory "/files") . "/misskey/files")
(,config-file . "/misskey/.config/default.yml"))))))))
(define misskey-service-type
(service-type
(name 'misskey)
(extensions
(list (service-extension account-service-type
(const %misskey-accounts))
(service-extension postgresql-role-service-type
(const %misskey-postgresql-role))
(service-extension log-rotation-service-type
(compose list misskey-configuration-log-file))
(service-extension activation-service-type
misskey-activation)
(service-extension oci-container-service-type
misskey-oci-containers)))
(default-value (misskey-configuration))
(description "Run Misskey, an interplanetary microblogging platform.")))
;;;
;;; Navidrome
;;;
(define-configuration navidrome-configuration
(navidrome
(file-like navidrome-bin)
"")
(ffmpeg
(file-like ffmpeg)
"")
(auto-start?
(boolean #t)
"")
(extra-config
(string "")
"")
(no-serialization))
(define %navidrome-accounts
(list (user-group (name "navidrome") (system? #t))
(user-account
(name "navidrome")
(group "navidrome")
(system? #t)
(comment "Navidrome user")
(home-directory "/var/lib/navidrome"))))
(define navidrome-shepherd-service
(match-record-lambda <navidrome-configuration>
(navidrome ffmpeg auto-start? extra-config)
(let ((config-file
(mixed-text-file
"navidrome.toml"
"DataFolder = '/var/lib/navidrome'\n"
"CacheFolder = '/var/lib/navidrome/cache'\n"
"EnableInsightsCollector = false\n"
extra-config)))
(list (shepherd-service
(documentation "Run Navidrome.")
(provision '(navidrome))
(requirement '(loopback user-processes))
(start
#~(make-forkexec-constructor
(list #$(file-append navidrome "/bin/navidrome")
"--configfile" #$config-file)
#:user "navidrome"
#:group "navidrome"
#:log-file "/var/log/navidrome.log"
#:environment-variables
(list "LC_ALL=C.UTF-8"
(string-append "PATH=" #$ffmpeg "/bin"))))
(stop
#~(make-kill-destructor))
(auto-start? auto-start?)
(actions
(list (shepherd-configuration-action config-file))))))))
(define navidrome-service-type
(service-type
(name 'navidrome)
(extensions
(list (service-extension account-service-type
(const %navidrome-accounts))
(service-extension shepherd-root-service-type
navidrome-shepherd-service)))
(default-value (navidrome-configuration))
(description "Run Navidrome.")))
;;
;; Vaultwarden
;;
(define-configuration vaultwarden-configuration
(admin-token
maybe-string
"Token for the admin interface, preferably an Argon2 PCH string.")
(database-url
(string "postgresql://user:password@host:port/database")
"Database URL.")
(port
(integer 8000)
"Port to listen on.")
(data-directory
(string "/var/lib/vaultwarden")
"Main data folder.")
(log-file
(string "/var/log/vaultwarden.log")
"Logging to this file.")
(proxy-url
maybe-string
"Proxy URL to use.")
(extra-options
(alist '())
"Extra options.")
(no-serialization))
(define %vaultwarden-accounts
(list (user-account
(name "vaultwarden")
(group "docker")
(system? #t)
(home-directory "/var/empty")
(shell (file-append shadow "/sbin/nologin")))))
(define %vaultwarden-postgresql-role
(list (postgresql-role
(name "vaultwarden")
(create-database? #t))))
(define vaultwarden-activation
(match-record-lambda <vaultwarden-configuration>
(data-directory log-file)
#~(begin
(use-modules (guix build utils))
(let ((user (getpwnam "vaultwarden")))
(unless (file-exists? #$data-directory)
(mkdir-p #$data-directory)
(chown #$data-directory (passwd:uid user) (passwd:gid user)))
(unless (file-exists? #$log-file)
(mkdir-p (dirname #$log-file))
(call-with-output-file #$log-file
(lambda (port)
(write-char #\newline port)))
(chown #$log-file (passwd:uid user) (passwd:gid user)))))))
(define vaultwarden-oci-containers
(match-record-lambda <vaultwarden-configuration>
(admin-token database-url port data-directory log-file proxy-url extra-options)
(list (oci-container-configuration
(user "vaultwarden")
(group "docker")
(host-environment
`(,@(if (maybe-value-set? admin-token)
`(("ADMIN_TOKEN" . ,admin-token))
'())
("DATABASE_URL" . ,database-url)))
(environment
`(,@(if (maybe-value-set? proxy-url)
`(("HTTP_PROXY" . ,proxy-url))
'())
("LOG_FILE" . "vaultwarden.log")
("ROCKET_PORT" . ,(number->string port))
("USE_SYSLOG" . "True")
,@extra-options))
(image "vaultwarden/server:latest-alpine")
(provision "vaultwarden")
(requirement '(postgresql))
(respawn? #t)
(network "host")
(volumes
`((,data-directory . "/data")
(,log-file . "/vaultwarden.log")))
(extra-arguments
`(,@(if (maybe-value-set? admin-token)
'("--env" "ADMIN_TOKEN")
'())
"--env" "DATABASE_URL"))))))
(define vaultwarden-service-type
(service-type
(name 'vaultwarden)
(extensions
(list (service-extension account-service-type
(const %vaultwarden-accounts))
(service-extension postgresql-role-service-type
(const %vaultwarden-postgresql-role))
(service-extension activation-service-type
vaultwarden-activation)
(service-extension log-rotation-service-type
(compose list vaultwarden-configuration-log-file))
(service-extension oci-container-service-type
vaultwarden-oci-containers)))
(default-value (vaultwarden-configuration))
(description "Run Vaultwarden, a Bitwarden compatible server.")))