Compare commits

..

11 Commits

Author SHA1 Message Date
Hilton Chain 1deb97ada4
services: Add jellyfin-service-type. 2 months ago
Hilton Chain fa1bcd5018
services: cloudflare-warp: Don't log stdout. 2 months ago
Hilton Chain 21ba2f200f
services: Add home-qbittorrent-service-type. 2 months ago
Hilton Chain bd6508000e
services: Add misskey-service-type. 2 months ago
Hilton Chain a367c5c974
services: Add vaultwarden-service-type. 2 months ago
Hilton Chain 7409288c70
services: tailscale: Reduce configuration fields. 2 months ago
Hilton Chain 1d40787105
services: miniflux: Support proxy. 2 months ago
Hilton Chain f42f8e258b
services: cloudflare-tunnel: Reduce configuration fields. 2 months ago
Hilton Chain f9dc2afc50
rosenthal: cloudflared: Update to 2024.9.1. 2 months ago
Hilton Chain 82619c24fe
rosenthal: tailscale-bin: Update to 1.74.1. 2 months ago
Hilton Chain 81d1a87938
rosenthal: mihomo-bin: Update to 1.18.9. 2 months ago
  1. 8
      rosenthal/packages/binaries.scm
  2. 6
      rosenthal/packages/networking.scm
  3. 42
      rosenthal/services/bittorrent.scm
  4. 43
      rosenthal/services/child-error.scm
  5. 66
      rosenthal/services/networking.scm
  6. 311
      rosenthal/services/web.scm

@ -52,7 +52,7 @@ protocols out-of-the-box.")
(define-public mihomo-bin (define-public mihomo-bin
(package (package
(name "mihomo-bin") (name "mihomo-bin")
(version "1.18.7") (version "1.18.9")
(source (origin (source (origin
(method url-fetch) (method url-fetch)
(uri (string-append (uri (string-append
@ -60,7 +60,7 @@ protocols out-of-the-box.")
version "/mihomo-linux-amd64-v" version ".gz")) version "/mihomo-linux-amd64-v" version ".gz"))
(sha256 (sha256
(base32 (base32
"1mfbh21x1vzmi0vglk68r21rfbklllxpa5q4978li7n44r0v6hbr")))) "0xq2baqcfd6hnyl1h3q34ymqd227dm06r7dz76s46k7mx7yz7jsb"))))
(build-system copy-build-system) (build-system copy-build-system)
(arguments (arguments
(list #:install-plan (list #:install-plan
@ -242,14 +242,14 @@ monster-in-the-middle}.")
(define-public tailscale-bin (define-public tailscale-bin
(package (package
(name "tailscale-bin") (name "tailscale-bin")
(version "1.72.1") (version "1.74.1")
(source (origin (source (origin
(method url-fetch) (method url-fetch)
(uri (string-append "https://pkgs.tailscale.com" (uri (string-append "https://pkgs.tailscale.com"
"/stable/tailscale_" version "_amd64.tgz")) "/stable/tailscale_" version "_amd64.tgz"))
(sha256 (sha256
(base32 (base32
"1dngi0cs3p423b9j5ihypq3s95w4ns0pjlmyi54kpfwi31nk3s0i")))) "12196z8dhdzxq8mjj0rlvhr6wchmi6z33ym36yqqrp4m52xjz7q5"))))
(build-system copy-build-system) (build-system copy-build-system)
(arguments (arguments
(list #:install-plan (list #:install-plan

@ -14,7 +14,7 @@
(define-public cloudflared (define-public cloudflared
(package (package
(name "cloudflared") (name "cloudflared")
(version "2024.8.3") (version "2024.9.1")
(source (origin (source (origin
(method git-fetch) (method git-fetch)
(uri (git-reference (uri (git-reference
@ -26,10 +26,10 @@
;; (snippet '(delete-file-recursively "vendor")) ;; (snippet '(delete-file-recursively "vendor"))
(sha256 (sha256
(base32 (base32
"1q97279qjajbdblg6ggvgkw2x02p8vvzcv3f9jw5na9psdq6hif3")))) "0391nrvxi1hlqgd20p0jh0c8smgqfazviijs5ins8wsbszrbjmrw"))))
(build-system go-build-system) (build-system go-build-system)
(arguments (arguments
(list #:go go-1.22 (list #:go go-1.23
#:install-source? #f #:install-source? #f
#:import-path "github.com/cloudflare/cloudflared/cmd/cloudflared" #:import-path "github.com/cloudflare/cloudflared/cmd/cloudflared"
#:unpack-path "github.com/cloudflare/cloudflared" #:unpack-path "github.com/cloudflare/cloudflared"

@ -11,9 +11,12 @@
#:use-module (gnu services) #:use-module (gnu services)
#:use-module (gnu services configuration) #:use-module (gnu services configuration)
#:use-module (gnu services shepherd) #:use-module (gnu services shepherd)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (gnu system shadow) #:use-module (gnu system shadow)
#:export (qbittorrent-configuration #:export (qbittorrent-configuration
qbittorrent-service-type)) qbittorrent-service-type
home-qbittorrent-service-type))
;; ;;
;; qBittorrent ;; qBittorrent
@ -106,3 +109,40 @@ WebUI\\Password_PBKDF2=\"@ByteArray(ARQ77eY1NUZaQsuDHbIMCA==:0WMRkYTUWVT9wVvdDtH
(const %qbittorrent-accounts)))) (const %qbittorrent-accounts))))
(default-value (qbittorrent-configuration)) (default-value (qbittorrent-configuration))
(description "Run qBittorrent daemon."))) (description "Run qBittorrent daemon.")))
(define home-qbittorrent-activation
#~(let ((config-file
(string-append
(or (getenv "XDG_CONFIG_HOME")
(string-append user-homedir "/.config"))
"/qBittorrent/qBittorrent.conf")))
(unless (file-exists? config-file)
(mkdir-p (dirname config-file))
(copy-file #$%qbittorrent-default-config-file config-file))))
(define home-qbittorrent-shepherd-service
(match-record-lambda <qbittorrent-configuration>
(qbittorrent webui-port extra-options)
(list (shepherd-service
(documentation "Run qbittorrent.")
(provision '(qbittorrent))
(requirement '())
(start
#~(make-forkexec-constructor
(list
#$(file-append qbittorrent "/bin/qbittorrent-nox")
#$(string-append "--webui-port=" (number->string webui-port))
#$@extra-options)))
(stop #~(make-kill-destructor #:grace-period 1800))
(auto-start? #f)))))
(define home-qbittorrent-service-type
(service-type
(name 'qbittorrent)
(extensions
(list (service-extension home-activation-service-type
(const home-qbittorrent-activation))
(service-extension home-shepherd-service-type
home-qbittorrent-shepherd-service)))
(default-value (qbittorrent-configuration))
(description "Run qBittorrent daemon.")))

@ -146,9 +146,6 @@
"The cloudflared executable.") "The cloudflared executable.")
;; Tunnel options ;; Tunnel options
(metrics
(string "localhost:")
"Listen address for metrics reporting.")
(log-level (log-level
(string "info") (string "info")
"Application logging level (@code{debug}, @code{info}, @code{warn}, "Application logging level (@code{debug}, @code{info}, @code{warn},
@ -166,12 +163,6 @@ headers. This can expose sensitive information in your logs.")
(token (token
(string "") (string "")
"The Tunnel token.") "The Tunnel token.")
(http2-origin?
(boolean #f)
"Enable HTTP/2 origin servers.")
(post-quantum?
(boolean #f)
"Create an experimental post-quantum secure tunnel.")
(extra-options (extra-options
(list-of-strings '()) (list-of-strings '())
"List of extra options.") "List of extra options.")
@ -183,8 +174,8 @@ headers. This can expose sensitive information in your logs.")
(define cloudflare-tunnel-shepherd-service (define cloudflare-tunnel-shepherd-service
(match-record-lambda <cloudflare-tunnel-configuration> (match-record-lambda <cloudflare-tunnel-configuration>
(cloudflared metrics log-level log-file extra-tunnel-options (cloudflared log-level log-file extra-tunnel-options
token http2-origin? post-quantum? extra-options) token extra-options)
(list (shepherd-service (list (shepherd-service
(documentation "Run cloudflared.") (documentation "Run cloudflared.")
(provision '(cloudflare-tunnel)) (provision '(cloudflare-tunnel))
@ -193,17 +184,9 @@ headers. This can expose sensitive information in your logs.")
(list #$(file-append cloudflared "/bin/cloudflared") (list #$(file-append cloudflared "/bin/cloudflared")
"tunnel" "tunnel"
"--no-autoupdate" "--no-autoupdate"
"--metrics" #$metrics
"--loglevel" #$log-level "--loglevel" #$log-level
#$@extra-tunnel-options #$@extra-tunnel-options
"run" "run"
#$@(if http2-origin?
'("--http2-origin")
'())
#$@(if post-quantum?
'("--post-quantum")
'())
#$@extra-options) #$@extra-options)
#:user "nobody" #:user "nobody"
#:group "nogroup" #:group "nogroup"
@ -242,7 +225,10 @@ headers. This can expose sensitive information in your logs.")
(documentation "Run warp-svc.") (documentation "Run warp-svc.")
(provision '(cloudflare-warp)) (provision '(cloudflare-warp))
(start #~(make-forkexec-constructor (start #~(make-forkexec-constructor
(list #$(file-append cloudflare-warp "/bin/warp-svc")))) (list #$(file-append cloudflare-warp "/bin/warp-svc"))
;; Logs are written to
;; /var/lib/cloudflare-warp/cfwarp_service_log.txt.
#:log-file "/dev/null"))
(stop #~(make-kill-destructor)))))) (stop #~(make-kill-destructor))))))
(define cloudflare-warp-service-type (define cloudflare-warp-service-type
@ -263,6 +249,8 @@ headers. This can expose sensitive information in your logs.")
;; ;;
(define-maybe string)
(define-configuration miniflux-configuration (define-configuration miniflux-configuration
(miniflux (miniflux
(file-like miniflux) (file-like miniflux)
@ -270,6 +258,9 @@ headers. This can expose sensitive information in your logs.")
(log-file (log-file
(string "/var/log/miniflux.log") (string "/var/log/miniflux.log")
"Where the logs go.") "Where the logs go.")
(proxy-url
maybe-string
"Proxy URL to use.")
(options (options
(alist '()) (alist '())
"Association list of miniflux configuration options.") "Association list of miniflux configuration options.")
@ -290,7 +281,7 @@ headers. This can expose sensitive information in your logs.")
(define miniflux-shepherd-service (define miniflux-shepherd-service
(match-record-lambda <miniflux-configuration> (match-record-lambda <miniflux-configuration>
(miniflux log-file options) (miniflux log-file proxy-url options)
(let ((config-file (mixed-text-file (let ((config-file (mixed-text-file
"miniflux.conf" "miniflux.conf"
(apply string-append (apply string-append
@ -303,10 +294,16 @@ headers. This can expose sensitive information in your logs.")
(provision '(miniflux)) (provision '(miniflux))
(requirement '(postgres user-processes)) (requirement '(postgres user-processes))
(start #~(make-forkexec-constructor (start #~(make-forkexec-constructor
(list #$miniflux "-config-file" #$config-file) (list #$(file-append miniflux "/bin/miniflux")
"-config-file" #$config-file)
#:user "miniflux" #:user "miniflux"
#:group "nogroup" #:group "nogroup"
#:log-file #$log-file)) #:log-file #$log-file
#:environment-variables
'#$(if (maybe-value-set? proxy-url)
(list (string-append "HTTP_PROXY=" proxy-url)
(string-append "HTTPS_PROXY=" proxy-url))
'())))
(stop #~(make-kill-destructor))))))) (stop #~(make-kill-destructor)))))))
(define miniflux-service-type (define miniflux-service-type

@ -375,56 +375,23 @@ list, power save will be disabled."))
"The tailscale package to use.") "The tailscale package to use.")
(iptables (iptables
(file-like iptables) (file-like iptables-nft)
"The iptables package to use.") "The iptables package to use.")
(log-file (log-file
(string "/var/log/tailscaled.log") (string "/var/log/tailscaled.log")
"Path to log file.") "Path to log file.")
(bird-socket
maybe-string
"Path of the bird UNIX socket.")
(debug-server
maybe-string
"Listen address ([ip]:port) of optional debug server.")
(port
(integer 0)
"UDP port to listen for WireGuard and peer-to-peer traffic; 0 means
automatically select.")
(socket (socket
(string "/var/run/tailscale/tailscaled.sock") (string "/run/tailscale/tailscaled.sock")
"Path of the service UNIX socket.") "Path of the service UNIX socket.")
(http-proxy-server
maybe-string
"[ip]:port to run an outbound HTTP proxy (e.g. \"localhost:8080\").")
(socks5-server
maybe-string
"[ip]:port to run a SOCKS5 server (e.g. \"localhost:1080\").")
(state-directory (state-directory
(string "/var/lib/tailscale") (string "/var/lib/tailscale")
"Path to directory for storage of config state, TLS certs, temporary incoming "Path to directory for storage of config state, TLS certs, temporary incoming
Taildrop files, etc. If empty, it's derived from @code{state-file} when Taildrop files, etc. If empty, it's derived from @code{state-file} when
possible.") possible.")
(state-file
maybe-string
"Absolute path of state file; use @code{kube:<secret-name>} to use Kubernetes
secrets or @code{arn:aws:ssm:...} to store in AWS SSM; use 'mem:' to not store
state and register as an ephemeral node. If empty and @code{state-directory} is
provided, the default is @code{<state-directory>/tailscaled.state}.")
(tunnel-interface
(string "tailscale0")
"Tunnel interface name; use @code{\"userspace-networking\"} (beta) to not use
TUN.")
(upload-log? (upload-log?
(boolean #f) (boolean #f)
"Whether to upload logs or not, technical support is also disabled when set "Whether to upload logs or not, technical support is also disabled when set
@ -433,6 +400,10 @@ to #f.")
(verbosity (verbosity
(integer 0) (integer 0)
"Log verbosity level; 0 is default, 1 or higher are increasingly verbose.") "Log verbosity level; 0 is default, 1 or higher are increasingly verbose.")
(extra-options
(list-of-strings '())
"List of extra options.")
(no-serialization)) (no-serialization))
(define (tailscale-log-rotations config) (define (tailscale-log-rotations config)
@ -441,9 +412,8 @@ to #f.")
(define tailscale-shepherd-service (define tailscale-shepherd-service
(match-record-lambda <tailscale-configuration> (match-record-lambda <tailscale-configuration>
(tailscale iptables log-file bird-socket debug-server port socket (tailscale iptables log-file socket state-directory
http-proxy-server socks5-server state-directory state-file upload-log? verbosity extra-options)
tunnel-interface upload-log? verbosity)
(let ((environment (let ((environment
#~(list (string-append "PATH=" #~(list (string-append "PATH="
(string-join (string-join
@ -458,29 +428,13 @@ to #f.")
#~(make-forkexec-constructor #~(make-forkexec-constructor
(list (list
#$(file-append tailscale "/bin/tailscaled") #$(file-append tailscale "/bin/tailscaled")
#$@(if (maybe-value-set? bird-socket)
`("-bird-socket" ,bird-socket)
'())
#$@(if (maybe-value-set? debug-server)
`("-debug" ,debug-server)
'())
#$@(if upload-log? #$@(if upload-log?
'() '()
'("-no-logs-no-support")) '("-no-logs-no-support"))
#$@(if (maybe-value-set? http-proxy-server)
`("-outbound-http-proxy-listen" ,http-proxy-server)
'())
"-port" #$(number->string port)
"-socket" #$socket "-socket" #$socket
#$@(if (maybe-value-set? socks5-server)
`("-socks5-server" ,socks5-server)
'())
#$@(if (maybe-value-set? state-file)
`("-state" ,state-file)
'())
"-statedir" #$state-directory "-statedir" #$state-directory
"-tun" #$tunnel-interface "-verbose" #$(number->string verbosity)
"-verbose" #$(number->string verbosity)) #$@extra-options)
#:environment-variables #$environment #:environment-variables #$environment
#:log-file #$log-file)) #:log-file #$log-file))
(stop #~(make-kill-destructor))))))) (stop #~(make-kill-destructor)))))))

@ -0,0 +1,311 @@
;; 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 records)
#:use-module (gnu packages admin)
#: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 system shadow)
#:use-module (rosenthal utils home-services-utils)
#:export (jellyfin-configuration
jellyfin-service-type
misskey-configuration
misskey-service-type
vaultwarden-configuration
vaultwarden-service-type))
;;
;; 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.")
(extra-options
(list-of-strings '())
"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-log-rotations
(match-record-lambda <jellyfin-configuration>
(log-file)
(list (log-rotation
(files (list log-file))))))
(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 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)
(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 rottlog-service-type
jellyfin-log-rotations)
(service-extension oci-container-service-type
jellyfin-oci-containers)))
(default-value (jellyfin-configuration))
(description "Run Jellyfin, a media system.")))
;;
;; 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-log-rotations
(match-record-lambda <misskey-configuration>
(log-file)
(list (log-rotation
(files (list log-file))))))
(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 #$@(serialize-yaml-config 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 rottlog-service-type
misskey-log-rotations)
(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.")))
;;
;; 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-log-rotations
(match-record-lambda <vaultwarden-configuration>
(log-file)
(list (log-rotation
(files (list log-file))))))
(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 rottlog-service-type
vaultwarden-log-rotations)
(service-extension oci-container-service-type
vaultwarden-oci-containers)))
(default-value (vaultwarden-configuration))
(description "Run Vaultwarden, a Bitwarden compatible server.")))
Loading…
Cancel
Save