diff options
author | EuAndreh <eu@euandre.org> | 2024-08-17 08:41:23 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2024-08-17 08:41:23 -0300 |
commit | 0cd15949089c3b92c128e92e3dfeb8ecfa78aaba (patch) | |
tree | b1dd94db2ba43eaa4a97601ef983b51303c21665 /src/org/euandre/services.scm | |
parent | Revert "queue.scm: Separate stdlib binaries into its own output" (diff) | |
download | package-repository-0cd15949089c3b92c128e92e3dfeb8ecfa78aaba.tar.gz package-repository-0cd15949089c3b92c128e92e3dfeb8ecfa78aaba.tar.xz |
Diffstat (limited to 'src/org/euandre/services.scm')
-rw-r--r-- | src/org/euandre/services.scm | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/src/org/euandre/services.scm b/src/org/euandre/services.scm new file mode 100644 index 0000000..4b62fc9 --- /dev/null +++ b/src/org/euandre/services.scm @@ -0,0 +1,518 @@ +(define-module (org euandre services) + #:use-module ((org euandre packages) #:prefix pkg:) + #:use-module ((org euandre queue) #:prefix q:) + #:use-module ((ice-9 match) #:prefix m:) + #:use-module ((ice-9 popen) #:prefix popen:) + #:use-module ((ice-9 textual-ports) #:prefix textual-ports:) + #:use-module ((gnu build linux-container) #:prefix container:) + #:use-module ((srfi srfi-1) #:prefix s1:) + #:use-module ((xyz euandreh heredoc) #:prefix heredoc:) + #:use-module (gnu) + #:use-module (guix build utils) + #:use-module (guix least-authority) + #:use-module (guix records) + #:export (<syskeep-configuration> + syskeep-configuration + make-syskeep-configuration + syskeep-configuration? + syskeep-configuration-package + syskeep-configuration-log-file + + <binder-configuration> + binder-configuration + make-binder-configuration + binder-configuration? + binder-configuration-name + binder-configuration-package + binder-configuration-user + binder-configuration-group + binder-configuration-log-file + binder-configuration-data-directory + binder-configuration-run-directory + binder-configuration-run-in-container? + binder-configuration-container-name + binder-configuration-extra-mappings + + <glaze-configuration> + glaze-configuration + make-glaze-configuration + glaze-configuration? + glaze-configuration-name + glaze-configuration-package + glaze-configuration-user + glaze-configuration-group + glaze-configuration-log-file + glaze-configuration-data-directory + glaze-configuration-run-directory + glaze-configuration-run-in-container? + glaze-configuration-container-name + glaze-configuration-extra-mappings + + <untls-configuration> + untls-configuration + make-untls-configuration + untls-configuration? + untls-configuration-name + untls-configuration-package + untls-configuration-user + untls-configuration-group + untls-configuration-log-file + untls-configuration-data-directory + untls-configuration-run-directory + untls-configuration-run-in-container? + untls-configuration-container-name + untls-configuration-extra-mappings + + <wscat-configuration> + wscat-configuration + make-wscat-configuration + wscat-configuration? + wscat-configuration-name + wscat-configuration-package + wscat-configuration-user + wscat-configuration-group + wscat-configuration-log-file + wscat-configuration-data-directory + wscat-configuration-run-directory + wscat-configuration-run-in-container? + wscat-configuration-container-name + wscat-configuration-extra-mappings + + <papod-configuration> + papod-configuration + make-papod-configuration + papod-configuration? + papod-configuration-name + papod-configuration-package + papod-configuration-user + papod-configuration-group + papod-configuration-log-file + papod-configuration-data-directory + papod-configuration-run-directory + papod-configuration-run-in-container? + papod-configuration-container-name + papod-configuration-extra-mappings)) +(use-package-modules + admin + version-control) +(use-service-modules + admin + mcron + shepherd) + + + +(define-public (slurp path) + (call-with-input-file + path + textual-ports:get-string-all)) + +(define-public (str . rest) + (apply string-append rest)) + +(define-public (fmt . rest) + (apply format #f rest)) + +(define-public (user-accounts users) + (map (lambda (user) + (let ((name (s1:first user)) + (comment (s1:second user)) + (groups (s1:third user))) + (user-account + (name name) + (comment comment) + (group "users") + (supplementary-groups groups)))) + users)) + +(define-public (users->keys users) + (let ((users-with-keys (filter (compose not null? cdddr) + users))) + (append + (map (lambda (user) + (let ((name (s1:first user)) + (key (s1:fourth user))) + `(,name ,(plain-file (str name "-id_rsa.pub") key)))) + users-with-keys) + `(("git" ,@(map (lambda (user) + (let ((name (s1:first user)) + (key (s1:fourth user))) + (plain-file (str name "-git-id_rsa.pub") + (slurp key)))) + users-with-keys)))))) + +(define (tuple->entry tuple) + (let* ((name (s1:first tuple)) + (package (s1:second tuple)) + (path (string-append "/etc/" name))) + (list + name + (computed-file + (string-append "syskeep-" name) + #~(begin + (use-modules + ((ice-9 textual-ports) #:prefix textual-ports:)) + + (define (slurp p) + (call-with-input-file p textual-ports:get-string-all)) + + (define (spit p s) + (call-with-output-file + p + (lambda (port) + (display s port)))) + + (spit #$output + (slurp #$(file-append package path)))))))) + +(define (etc-entries package paths) + (map + tuple->entry + (map (lambda (path) + (list path package)) + paths))) + +(define-public (package-set symbols records) + (append + records + (map + (compose list specification->package+output symbol->string) + symbols))) + +(define-public skeletons + (etc-entries + pkg:syskeep + '(".profile"))) + +(define-public base-services + (modify-services %base-services + (rottlog-service-type config => + (rottlog-configuration + (inherit config) + (rc-file + (file-append q:rottlog-mailutils-sendmail "/etc/rc")))))) + + + +(define-record-type* <syskeep-configuration> + syskeep-configuration + make-syskeep-configuration + syskeep-configuration? + (package syskeep-configuration-package (default pkg:syskeep)) + (log-file syskeep-configuration-log-file (default "/var/log/cronjobs/cronjobs.log"))) + +(define (syskeep-profile config) + (match-record config <syskeep-configuration> + (package) + (package-set + '(parted + guile-heredoc + acl + bind:utils + knot:tools + file + git + lsof + moreutils + mailutils-sendmail + curl + make + borg + rsync + sqlite + strace + rlwrap + trash-cli + tree) + (list + package)))) + +(define (syskeep-rotations config) + (match-record config <syskeep-configuration> + (log-file) + (list + (log-rotation + (frequency 'weekly) + (files (list log-file)) + (options '("rotate 52")))))) + +(define (syskeep-cronjobs config) + (match-record config <syskeep-configuration> + () + (list + #~(job "0 0 * * *" "cronjob check") + #~(job "0 1 * * *" "cronjob env BORG_REPO=/mnt/backup/borg backup -q cron") + #~(job "0 2 * * *" "cronjob backup -q cron") + #~(job "0 3 * * 0" "cronjob gc") + #~(job "0 4 * * *" "cronjob reconfigure -U")))) + +(define (syskeep-etc-files config) + (match-record config <syskeep-configuration> + (package) + (etc-entries + package + '("rc" + "known_hosts" + "ssh.conf" + "init.scm" + "gitconfig")))) + +(define (syskeep-accounts config) + (match-record config <syskeep-configuration> + () + (list + (user-account + (name "git") + (group "git") + (system? #t) + (comment "External SSH Git user") + (home-directory "/src/ĝit") + (create-home-directory? #f) + (shell + (file-append git "/bin/git-shell"))) + (user-group + (name "git") + (system? #t))))) + +(define-public syskeep-service-type + (service-type + (name 'syskeep) + (extensions + (list + (service-extension rottlog-service-type + syskeep-rotations) + (service-extension mcron-service-type + syskeep-cronjobs) + (service-extension etc-service-type + syskeep-etc-files) + (service-extension account-service-type + syskeep-accounts) + (service-extension profile-service-type + syskeep-profile))) + (default-value (syskeep-configuration)) + (description "Common configuration of maintained servers."))) + + + +(define-record-type* <binder-configuration> + binder-configuration + make-binder-configuration + binder-configuration? + (name binder-configuration-name (default "binder")) + (package binder-configuration-package (default pkg:binder)) + (user binder-configuration-user (default "binder")) + (group binder-configuration-group (default "binder")) + (log-file binder-configuration-log-file (default "/var/log/binder/binder.log")) + (data-directory binder-configuration-data-directory (default #f)) + (run-directory binder-configuration-run-directory (default "/var/run/binder")) + (run-in-container? binder-configuration-run-in-container? (default #t)) + (container-name binder-configuration-container-name (default "binder-container")) + (extra-mappings binder-configuration-extra-mappings (default '()))) + +(define-record-type* <glaze-configuration> + glaze-configuration + make-glaze-configuration + glaze-configuration? + (name glaze-configuration-name (default "glaze")) + (package glaze-configuration-package (default pkg:glaze)) + (user glaze-configuration-user (default "glaze")) + (group glaze-configuration-group (default "glaze")) + (log-file glaze-configuration-log-file (default "/var/log/glaze/glaze.log")) + (data-directory glaze-configuration-data-directory (default #f)) + (run-directory glaze-configuration-run-directory (default "/var/run/glaze")) + (run-in-container? glaze-configuration-run-in-container? (default #t)) + (container-name glaze-configuration-container-name (default "glaze-container")) + (extra-mappings glaze-configuration-extra-mappings (default '()))) + +(define-record-type* <untls-configuration> + untls-configuration + make-untls-configuration + untls-configuration? + (name untls-configuration-name (default "untls")) + (package untls-configuration-package (default pkg:untls)) + (user untls-configuration-user (default "untls")) + (group untls-configuration-group (default "untls")) + (log-file untls-configuration-log-file (default "/var/log/untls/untls.log")) + (data-directory untls-configuration-data-directory (default #f)) + (run-directory untls-configuration-run-directory (default "/var/run/untls")) + (run-in-container? untls-configuration-run-in-container? (default #t)) + (container-name untls-configuration-container-name (default "untls-container")) + (extra-mappings untls-configuration-extra-mappings (default '()))) + +(define-record-type* <wscat-configuration> + wscat-configuration + make-wscat-configuration + wscat-configuration? + (name wscat-configuration-name (default "wscat")) + (package wscat-configuration-package (default pkg:wscat)) + (user wscat-configuration-user (default "wscat")) + (group wscat-configuration-group (default "wscat")) + (log-file wscat-configuration-log-file (default "/var/log/wscat/wscat.log")) + (data-directory wscat-configuration-data-directory (default #f)) + (run-directory wscat-configuration-run-directory (default "/var/run/wscat")) + (run-in-container? wscat-configuration-run-in-container? (default #t)) + (container-name wscat-configuration-container-name (default "wscat-container")) + (extra-mappings wscat-configuration-extra-mappings (default '()))) + +(define-record-type* <papod-configuration> + papod-configuration + make-papod-configuration + papod-configuration? + (name papod-configuration-name (default "papod")) + (package papod-configuration-package (default pkg:papod)) + (user papod-configuration-user (default "papod")) + (group papod-configuration-group (default "papod")) + (log-file papod-configuration-log-file (default "/var/log/papod/papod.log")) + (data-directory papod-configuration-data-directory (default "/var/lib/papod")) + (run-directory papod-configuration-run-directory (default "/var/run/papod")) + (run-in-container? papod-configuration-run-in-container? (default #t)) + (container-name papod-configuration-container-name (default "papod-container")) + (extra-mappings papod-configuration-extra-mappings (default '()))) + + +(define-public (profile-for type) + (lambda (config) + (m:match config + (($ type _name package) + (list package))))) + +(define-public (rotations-for type) + (lambda (config) + (m:match config + (($ type _name _package _user _group log-file) + (list + (log-rotation + (frequency 'weekly) + (files (list log-file)) + (options '("rotate 5200")))))))) + +(define-public (activation-for type) + (lambda (config) + (m:match config + (($ type name _package user _group log-file data-directory run-directory) + #~(begin + (use-modules (guix build utils)) + (when #$log-file + (format (current-error-port) + "Creating ~a log directory for '~a'.~%" #$name #$log-file) + (mkdir-p (dirname #$log-file)) + (when (not (file-exists? #$log-file)) + (call-with-output-file #$log-file (const #t))) + (chmod #$log-file #o644)) + (let ((user (getpwnam #$user))) + (when #$data-directory + (format (current-error-port) + "Creating ~a data directory '~a'.~%" #$name #$data-directory) + (mkdir-p #$data-directory) + (chown #$data-directory (passwd:uid user) (passwd:gid user)) + (chmod #$data-directory #o750)) + (when #$run-directory + (format (current-error-port) + "Creating ~a run directory '~a'.~%" #$name #$run-directory) + (mkdir-p #$run-directory) + (chown #$run-directory (passwd:uid user) (passwd:gid user)) + (chmod #$run-directory #o755)))))))) + +(define-public (accounts-for type) + (lambda (config) + (m:match config + (($ type name _package user group) + (list + (user-group + (name group) + (system? #t)) + (user-account + (name user) + (group group) + (system? #t) + (comment (format #f "The user for runtime execution of ~a code" name)) + (home-directory "/var/empty") + (shell + (file-append shadow "/sbin/nologin")))))))) + +(define-public (shepherd-services-for type) + (lambda (config) + (m:match config + (($ type name package user group log-file data-directory _run-directory run-in-container? container-name extra-mappings) + (list + (shepherd-service + (provision (list (string->symbol name))) + (requirement '()) + (start + #~(make-forkexec-constructor ;; FIXME: add #:resource-limits + (list + #$(let ((bin (file-append package (string-append "/bin/" name)))) + (if (not run-in-container?) + bin + (least-authority-wrapper + bin + #:user user + #:group group + #:name container-name + #:directory (or data-directory "/") + #:preserved-environment-variables + '() + #:mappings + (append + (if data-directory + (list + (file-system-mapping + (source data-directory) + (target source) + (writable? #t))) + (list)) + extra-mappings))))) + #:user #$user + #:group #$group + #:log-file #$log-file + #:directory #$data-directory)) + (stop #~(make-kill-destructor SIGKILL)) + (documentation + (fmt "The Shepherd service that runs the server via \"~a\"." name)))))))) + +(define-public (service-type-for name type config extensions) + (service-type + (name name) + (extensions + (append + (list + (service-extension shepherd-root-service-type + (shepherd-services-for type)) + (service-extension profile-service-type + (profile-for type)) + (service-extension activation-service-type + (activation-for type)) + (service-extension account-service-type + (accounts-for type)) + (service-extension rottlog-service-type + (rotations-for type))) + extensions)) + (default-value config) + (description + (fmt "The top-level generic system service, generated for ~a code. + +It includes: +- the Shepherd service for starting, stopping and reloading the service; +- activation script for setting up the initial directories and permissions; +- the group and account for running the production service; +- log management (storage and rotation) for logs produced by the running services. + +The default configuration should provide sane values for all of these." + name)))) + + + +(define-public binder-service-type + (service-type-for 'binder <binder-configuration> (binder-configuration) '())) + +(define-public glaze-service-type + (service-type-for 'glaze <glaze-configuration> (glaze-configuration) '())) + +(define-public untls-service-type + (service-type-for 'untls <untls-configuration> (untls-configuration) '())) + +(define-public wscat-service-type + (service-type-for 'wscat <wscat-configuration> (wscat-configuration) '())) + +(define-public papod-service-type + (service-type-for 'papod <papod-configuration> (papod-configuration) '())) |