commit d6d9779df8c1c8d3220820c0aa7e1423ff5e51b0
parent 962dfd6b14869693b24967f94eedc311d0d5d4d2
Author: Luke Willis <lukejw@monastech.xyz>
Date:   Tue, 12 May 2026 18:40:38 -0400

andrew: Move to seperate repo

Diffstat:
Dmt/services/games.scm | 369-------------------------------------------------------------------------------
Dmt/system/andrew.scm | 322-------------------------------------------------------------------------------
Dmt/system/andrew/ci.scm | 195-------------------------------------------------------------------------------
3 files changed, 0 insertions(+), 886 deletions(-)

diff --git a/mt/services/games.scm b/mt/services/games.scm @@ -1,369 +0,0 @@ -(define-module (mt services games) - #:use-module (gnu services) - #:use-module (gnu services configuration) - #:use-module (gnu services shepherd) - #:use-module (gnu packages admin) - #:use-module (gnu packages java) - #:use-module (gnu system shadow) - #:use-module (guix gexp) - #:use-module (guix modules) - #:use-module (guix packages) - #:use-module (guix records) - #:use-module (guix download) - #:use-module (guix build-system copy) - #:use-module (mt utils) - #:use-module (mt packages games) - #:use-module (ice-9 match) - #:export (bta-configuration - bta-configuration? - bta-service-type - fabric-jar - %default-fabric-jar - modrinth-mod - minecraft-configuration - minecraft-configuration? - minecraft-service-type)) - -;;; -;;; Better Than Adventure! -;;; - -;; TODO: Add justauth support - -(define %bta-account - (list (user-account - (name "bta") - (group "bta") - (system? #t) - (comment "BTA server user") - (home-directory "/var/lib/bta") - (shell (file-append shadow "/sbin/nologin"))) - (user-group - (name "bta") - (system? #t)))) - -;; TODO: Review. Is copy-build-system / package really necessary? -(define bta-fabric-server - (package - (name "bta-fabric-server") - (version "7.3_04") - (build-system copy-build-system) - (source - (origin - (method url-fetch/zipbomb) - (uri (string-append - "https://github.com/Turnip-Labs/bta-fabric-instance-repo/releases/download/v" - version "/bta_fabric_server_" version ".zip")) - (sha256 - (base32 - "18170krqhg61zlsvh7z9c8932qwa3waxalhh7lqdjj0qyp4lc4gr")))) - (home-page #f) - (synopsis #f) - (description #f) - (license #f))) - -(define-record-type* <bta-configuration> - bta-configuration - make-bta-configuration - bta-configuration? - (jdk bta-configuration-jdk - (default openjdk17)) - (memory bta-configuration-memory - (default 4)) - (properties bta-configuration-properties - (default '())) - (ops bta-configuration-ops - (default '())) - (mods bta-configuration-mods - (default '())) - (home bta-configuration-home - (default "/var/lib/bta")) - (log-file bta-configuration-log-file - (default "/var/log/bta.log"))) - -(define bta-activation - (match-lambda - (($ <bta-configuration> jdk memory properties ops mods home log-file) - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils) - (ice-9 match)) - - (let ((user (getpwnam "bta")) - (server-launcher-properties - #$(string-append home "/fabric-server-launcher.properties")) - (server-properties #$(string-append home "/server.properties")) - (ops-txt #$(string-append home "/ops.txt")) - (mod-dir #$(string-append home "/mods/"))) - (match (primitive-fork) - (0 - (dynamic-wind - (const #t) - (lambda () - ;; Switch to the bta user - (setgid (passwd:gid user)) - (setuid (passwd:uid user)) - - ;; Write to fabric-server-launcher.properties - (call-with-output-file - server-launcher-properties - (lambda (port) - (format port "serverJar=~a\n" - #$(file-append bta-fabric-server - "/server.jar")))) - - ;; Write to server.properties - (call-with-output-file - server-properties - (lambda (port) - (for-each - (lambda (pair) - (format port "~a=~a\n" (car pair) (cdr pair))) - '#$properties))) - - ;; Initialize ops.txt - (unless (file-exists? ops-txt) - (call-with-output-file - ops-txt - (lambda (port) - (for-each - (lambda (uuid) - (format port "~a\n" uuid)) - '#$ops)))) - - ;; Link all mods into the mods folder - (if (file-exists? mod-dir) - (delete-file-recursively mod-dir)) - (mkdir mod-dir) - (for-each - (lambda (mod) - (symlink mod (string-append mod-dir (basename mod)))) - '#$mods) - - ;; Return to main thread - (primitive-exit 0)) - (lambda () - (primitive-exit 1)))) - (pid (waitpid pid))))))))) - -(define bta-shepherd-service - (match-lambda - (($ <bta-configuration> jdk memory properties ops mods home log-file) - (shepherd-service - (documentation "BTA server") - (provision '(bta)) - (requirement '(user-processes networking)) - (start #~(make-forkexec-constructor - (list #$(file-append jdk "/bin/java") - "-Dfabric.runtimeMappingNamespace=official" - #$(format #f "-Xmx~aG" memory) - "-jar" #$(file-append bta-fabric-server - "/fabric-server-launch.jar") - "nogui") - #:user "bta" - #:group "bta" - #:directory #$home - #:log-file #$log-file)) - (stop #~(make-kill-destructor SIGINT)))))) - -(define bta-service-type - (service-type - (name 'bta) - (extensions - (list (service-extension account-service-type - (const %bta-account)) - (service-extension activation-service-type - bta-activation) - (service-extension shepherd-root-service-type - (compose list bta-shepherd-service)))) - (default-value (bta-configuration)) - (description "Run a BTA server."))) - - -;;; -;;; Minecraft. -;;; - -;; TODO: Modrinth API helper - -(define* (fabric-jar hash - #:key (minecraft "26.1.2") - (loader "0.19.2") - (launcher "1.1.1")) - (origin - (method url-fetch) - (uri (string-append "https://meta.fabricmc.net/v2/versions/loader/" - minecraft "/" - loader "/" - launcher "/server/jar")) - (file-name (string-append "fabric-server-mc." minecraft - "-loader." loader - "-launcher." launcher - ".jar")) - (sha256 hash))) - -(define %default-fabric-jar - (fabric-jar (base32 "1gax8i1risr0irgcmbwc0jdf78yhahplsqiyhiblrq7hkydx26z9"))) - -;; TODO: Switch to define-configuration/no-serialization -(define-record-type* <minecraft-configuration> - minecraft-configuration - make-minecraft-configuration - minecraft-configuration? - (jdk minecraft-configuration-package - (default openjdk)) - (jar minecraft-configuration-jar - (default %default-fabric-jar)) - (memory minecraft-configuration-memory - (default 8)) - (properties minecraft-configuration-properties - (default '())) - (mods minecraft-configuration-mods - (default '())) - (log-file minecraft-configuration-log-file - (default "/var/log/minecraft.log")) - (home minecraft-configuration-home - (default "/var/lib/minecraft")) - (port minecraft-configuration-port - (default 25565))) - - -(define %minecraft-account - (list (user-account - (name "minecraft") - (group "minecraft") - (system? #t) - (comment "Minecraft server user") - (home-directory "/var/lib/minecraft") - (shell (file-append shadow "/sbin/nologin"))) - (user-group - (name "minecraft") - (system? #t)))) - -(define %minecraft-eula - (plain-file "eula.txt" "eula=true\n")) - -(define %rcon-password - (random-string 72)) - -(define minecraft-activation - (match-lambda - (($ <minecraft-configuration> jdk jar memory properties mods log-file home port) - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils) - (ice-9 match)) - - (let ((user (getpwnam "minecraft")) - (eula #$(string-append home "/eula.txt")) - (properties #$(string-append home "/server.properties")) - (mod-dir #$(string-append home "/mods/"))) - ;; TODO: Setup files as the root user - ;; Setup files as the git user. - (match (primitive-fork) - (0 - (dynamic-wind - (const #t) - (lambda () - ;; Switch to the minecraft user. - (setgid (passwd:gid user)) - (setuid (passwd:uid user)) - - ;; Placate the EULA requirement. - (if (not (file-exists? eula)) - (symlink #$%minecraft-eula eula)) - - ;; Write to server.properties. - (call-with-output-file - properties - (lambda (port) - (format port "server-port=~a\n" #$port) - (display "enable-rcon=true\n" port) - (format port "rcon.password=~a\n" #$%rcon-password) - (for-each - (lambda (pair) - (format port "~a=~a\n" (car pair) (cdr pair))) - '#$properties))) - - ;; TODO: Mod config - - ;; Symlink mods to the mods folder. - (if (file-exists? mod-dir) - (delete-file-recursively mod-dir)) - (mkdir mod-dir) - (for-each - (lambda (mod) - (symlink mod (string-append mod-dir (basename mod)))) - (list #$@mods)) - - ;; Return to main thread. - (primitive-exit 0)) - (lambda () - (primitive-exit 1)))) - (pid (waitpid pid))))) - )))) - -(define minecraft-shepherd-service - (match-lambda - (($ <minecraft-configuration> jdk jar memory properties mods log-file home port) - (shepherd-service - (documentation "Minecraft server") - (provision '(minecraft)) - (requirement '(user-processes networking)) - (start #~(make-forkexec-constructor - (list #$(file-append jdk "/bin/java") - #$(format #f "-Xmx~aG" memory) - "-jar" #$jar - "nogui") - #:user "minecraft" - #:group "minecraft" - #:directory #$home - #:log-file #$log-file)) - (stop #~(make-kill-destructor)) - (actions (list (shepherd-action - (name 'rcon) - (documentation "Run server commands via rcon.") - (procedure #~(lambda (running . args) - - (define (collect-lines port) - "Collect all lines from a port in a list" - (let loop ((line (read-line port)) - (acc '())) - (if (eof-object? line) - (begin (close-port port) - acc) - (loop (read-line port) - (cons line acc))))) - - (let ((output-pipe (pipe))) - (spawn #$(file-append mcrcon "/bin/mcrcon") - (cons "mcrcon" args) - #:output (cdr output-pipe) - #:error (cdr output-pipe) - #:environment - (list - #$(string-append "MCRCON_PASS=" - %rcon-password)) - #:search-path? #f) - (close-port (cdr output-pipe)) - (while #t - (let ((line (read-line (car output-pipe)))) - (if (eof-object? line) - (break)) - (display line) - (newline)))) - ;; TODO - ))))))))) - -(define minecraft-service-type - (service-type - (name 'minecraft) - (extensions - (list (service-extension account-service-type - (const %minecraft-account)) - (service-extension activation-service-type - minecraft-activation) - (service-extension shepherd-root-service-type - (compose list minecraft-shepherd-service)))) - (default-value (minecraft-configuration)) - (description "Run a Minecraft server."))) diff --git a/mt/system/andrew.scm b/mt/system/andrew.scm @@ -1,322 +0,0 @@ -(define-module (mt system andrew) - #:use-module (mt system andrew ci) - #:use-module (guix gexp) - #:use-module (guix packages) - #:use-module (guix modules) - #:use-module (guix git) - #:use-module (gnu bootloader) - #:use-module (gnu bootloader grub) - #:use-module (gnu services) - #:use-module (gnu services certbot) - #:use-module (gnu services networking) - #:use-module (gnu services version-control) - #:use-module (gnu services shepherd) - #:use-module (gnu services web) - #:use-module (gnu system) - #:use-module (gnu system keyboard) - #:use-module (gnu system shadow) - #:use-module (gnu packages rsync) - #:use-module (gnu packages version-control) - #:use-module (gnu packages wget) - #:use-module (nongnu packages linux) - #:use-module (nongnu system linux-initrd) - #:use-module (mt services) - #:use-module (mt services games) - #:use-module (mt services version-control) - #:use-module (mt system) - #:use-module (mt artwork) - #:use-module (mt utils) - #:export (andrew-os)) - -;;; -;;; OS Configuration -;;; - -(define %issue " -Welcome to \"andrew\" the, first MonasTech server. -") - -(define %nftables-ruleset - (plain-file "nftables.conf" "\ -# A simple and safe firewall -table inet filter { - chain input { - type filter hook input priority 0; policy drop; - - # early drop of invalid connections - ct state invalid drop - - # allow established/related connections - ct state { established, related } accept - - # allow from loopback - iif lo accept - # drop connections to lo not coming from lo - iif != lo ip daddr 127.0.0.1/8 drop - iif != lo ip6 daddr ::1/128 drop - - # allow icmp - ip protocol icmp accept - ip6 nexthdr icmpv6 accept - - # allow ssh - tcp dport ssh accept - - # allow git - tcp dport 9418 accept - - # allow ngninx - tcp dport { 80, 443 } accept - - # allow minecraft / voice chat - th dport { 25565, 24454 } accept - - # reject everything else - reject with icmpx type port-unreachable - } - chain forward { - type filter hook forward priority 0; policy drop; - } - chain output { - type filter hook output priority 0; policy accept; - } -} -")) - -(define %mod-list - '()) - -(define andrew-os - (operating-system - (host-name "andrew") - (timezone "America/New_York") ;; Located in vinthill - (locale "en_US.utf8") - - (issue %issue) - - (keyboard-layout (keyboard-layout "us")) - - (kernel linux-lts) - (initrd microcode-initrd) - (firmware (list linux-firmware)) - - (bootloader (bootloader-configuration - (bootloader grub-efi-bootloader) - (targets '("/boot/efi")) - (keyboard-layout keyboard-layout))) - - (swap-devices %mt-swap-devices) - - (file-systems %mt-file-systems) - - (users - (cons* - (user-account - (name "lukejw") - (comment "Luke Willis") - (group "users") - (home-directory "/home/lukejw") - (supplementary-groups '("wheel"))) - %base-user-accounts)) - - (packages - (cons* - rsync - %mt-base-packages)) - - (services - (append - (list (service nftables-service-type - (nftables-configuration - (ruleset %nftables-ruleset))) - (service bta-service-type - (bta-configuration - (properties `(("motd" . "MonasTech Private Server") - ("difficulty" . "3") - ("allow-flight" . "true") - ("white-list" . "true") - ("online-mode" . "false"))) - (ops '("1a68c56c-0bbc-413d-8fe1-10a2e4e04ad2")) - (mods %mod-list))) - (service update-channels-locked-service-type '()) - (service nginx-service-type - (nginx-configuration - (server-blocks - (list (nginx-server-configuration - (server-name '("monastech.xyz" "www.monastech.xyz")) - (listen '("443 ssl")) - (root "/var/www/monastech.xyz") - (ssl-certificate "/etc/dehydrated/certs/monastech.xyz/fullchain.pem") - (ssl-certificate-key "/etc/dehydrated/certs/monastech.xyz/privkey.pem")) - (nginx-server-configuration - (server-name '("git.monastech.xyz" "www.git.monastech.xyz")) - (listen '("443 ssl")) - (root "/var/www/git.monastech.xyz") - (ssl-certificate "/etc/dehydrated/certs/monastech.xyz/fullchain.pem") - (ssl-certificate-key "/etc/dehydrated/certs/monastech.xyz/privkey.pem")) - (nginx-server-configuration - (server-name '("loquat.dev" "www.loquat.dev")) - (listen '("443 ssl")) - (root "/var/www/loquat.dev") - (ssl-certificate "/etc/dehydrated/certs/loquat.dev/fullchain.pem") - (ssl-certificate-key "/etc/dehydrated/certs/loquat.dev/privkey.pem")) - (nginx-server-configuration - (server-name '("orthodox.kitchen" "www.orthodox.kitchen")) - (listen '("443 ssl")) - (root "/var/www/orthodox.kitchen") - (ssl-certificate "/etc/dehydrated/certs/orthodox.kitchen/fullchain.pem") - (ssl-certificate-key "/etc/dehydrated/certs/orthodox.kitchen/privkey.pem")) - (nginx-server-configuration - (server-name '("substitutes.monastech.xyz")) - (listen '("443 ssl")) - (ssl-certificate "/etc/dehydrated/certs/monastech.xyz/fullchain.pem") - (ssl-certificate-key "/etc/dehydrated/certs/monastech.xyz/privkey.pem") - (locations - (list (nginx-location-configuration - (uri "/") - (body (list "proxy_pass http://127.0.0.1:8080;")))))) - ;; Default HTTP server - (nginx-server-configuration - (server-name '("_")) - (listen '("80 default_server")) - (root "/var/www/monastech.xyz") - (locations - (list ;; Serve ACME challenges - (nginx-location-configuration - (uri "^~ /.well-known/acme-challenge") - (body (list "alias /var/www/dehydrated;"))) - ;; Redirect to HTTPS - (nginx-location-configuration - (uri "/") - (body (list "return 301 https://$host$request_uri;"))))))))))) - (stagit-services - (stagit-configuration - (admin-pubkey (plain-file - "lukejw.pub" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEZ2qcwpwPdMmrXNrrqjqtuBw8lG9gxlAE+vwcZAHM3L lukejw@moses")) - (www-home "/var/www/git.monastech.xyz") - (clone-domain "monastech.xyz") - (logo (file-append %mt-artwork "/logo-dynamic.svg")) - (stylesheet (plain-file "stylesheet.css" "\ -:root { - --bg: #FFFCF0; - --bg-2: #F2F0E5; - --ui: #E6E4D9; - --ui-2: #DAD8CE; - --ui-3: #CECDC3; - --tx: #100F0F; - --tx-2: #6F6E69; - --ye: #AD8301; - --ye-2: #D0A215; - --cy: #24837B; - --cy-2: #3AA99F; -} - -@media (prefers-color-scheme: dark) { - :root { - --bg: #100F0F; - --bg-2: #1C1B1A; - --ui: #282726; - --ui-2: #343331; - --ui-3: #403E3C; - --tx: #CECDC3; - --tx-2: #878580; - --ye: #D0A215; - --ye-2: #AD8301; - --cy: #3AA99F; - --cy-2: #24837B; - } -} - -html { - background-color: var(--bg); - color: var(--tx); - font-family: serif; -} - -body { - width: 100%; - max-width: 72rem; - margin-inline: auto; -} - -#header { - margin-inline: 1rem; -} - -hr { - border: 0.1rem solid var(--ui); - margin-inline: 1rem; -} - -#content { - margin-inline: 1rem; -} - -a { - color: var(--cy); - text-decoration: none; -} - -a:hover { - color: var(--cy-2); - text-decoration: underline; -} - -#header img { - width: 6.75rem; - height: 4.5rem; -} - -#header h1 { - margin: 0 0 0.5rem 0; - font-size: 2rem; - font-weight: normal; - border-bottom: 2px solid var(--ui); -} - -#header .desc { - color: var(--tx-2); -} - -#header tbody tr:last-child td { - padding-top: 0.4rem; -} - -#header .url > td:nth-child(2) { - font-family: monospace; - padding: 0.2rem 0.6rem; - border-radius: 0.5rem; - background-color: var(--bg-2); -} - -#files tbody { - font-family: monospace; -} - -#files tbody > tr td:first-child { - width: 0; - white-space: nowrap; - padding-right: 1rem; -} - -#content table { - width: 100%; - border-collapse: collapse; -} - -#content td { - padding: 1rem; -} - -#content tbody tr:hover { - background: var(--bg-2); -} - -#content td { - padding: 0.3rem; -} -")))) - %mt-bishop-services)))) - -andrew-os diff --git a/mt/system/andrew/ci.scm b/mt/system/andrew/ci.scm @@ -1,195 +0,0 @@ -(define-module (mt system andrew ci) - #:use-module (guix gexp) - #:use-module (guix modules) - #:use-module (gnu services) - #:use-module (gnu services shepherd) - #:use-module (gnu packages version-control) - #:export (update-channels-locked-service-type)) - -;;; CI - -;; TODO: Integrate with the gitolite-service-type - -;; TODO: Integrate VREFs - -(define (update-channels-locked-shepherd-service config) - (define gitolite-home "/var/lib/gitolite") - - (define code - (let ((gitolite-bin (file-append gitolite "/bin/gitolite")) - (git-bin (file-append git "/bin/git"))) - (with-imported-modules (source-module-closure '((guix build utils))) - #~(begin - (use-modules (guix build utils) - (ice-9 rdelim) - (ice-9 popen) - (ice-9 ftw) - (rnrs io ports)) - - (setvbuf (current-output-port) 'line) - (setvbuf (current-error-port) 'line) - - ;; Utility functions - (define (collect-lines port) - "Collect all lines from a port in a list" - (let loop ((line (read-line port)) - (acc '())) - (if (eof-object? line) - (begin (close-port port) - acc) - (loop (read-line port) - (cons line acc))))) - - (define (spawn* prog args search) - "Spawn a program and return success as #t or #f" - (zero? (cdr (waitpid - (spawn prog args - #:search-path? #t))))) - - (define (repo-path name) - (string-append #$gitolite-home "/repositories/" name ".git")) - - ;; Main code - (let ((ogdir (getcwd)) - (channeldir (mkdtemp "/tmp/mt-channel-XXXXXX"))) - ;; Initial setup - (unless (and (spawn* #$git-bin - (list "git" "clone" "--shared" - (repo-path "channel") - channeldir) - #f) - (spawn* "guix" - (list "guix" "pull" "-C" - (string-append channeldir - "/mt/channels.scm")) - #t) - (call-with-output-file - (string-append channeldir "/mt/channels-locked.scm") - (lambda (out) - (display "\ -(define-module (mt channels-locked) - #:use-module (guix channels) - #:export (%mt-channels-locked)) - -(define %mt-channels-locked\n" out) - (flush-output-port out) - (let ((result (waitpid - (spawn "guix" - '("guix" "describe" - "--format=channels") - #:output out)))) - (display ")\n\n%mt-channels-locked\n" out) - (flush-output-port out) - (zero? (cdr result)))))) - (display "Failed to pull / write new channels!\n" - (current-error-port)) - (delete-file-recursively channeldir) - (exit 1)) - - ;; Iterate over clients - (let ((output-pipe (pipe))) - (spawn #$gitolite-bin - '("gitolite" "list-members" "@client-repos") - #:output (cdr output-pipe) - #:search-path? #f) - (close-port (cdr output-pipe)) - - (for-each - (lambda (name) - (let* ((configdir (mkdtemp "/tmp/mt-config-XXXXXX")) - (systemdir (string-append configdir "/system/")) - (homedir (string-append configdir "/home/"))) - (if (spawn* #$git-bin - (list "git" "clone" - "--shared" - (repo-path name) - configdir) - #f) - (begin - (format #t "Building ~a's system configurations...\n" name) - (for-each - (lambda (file) - (format #t "~a: Building \"~a\"...\n" name file) - (if (spawn* "guix" - (list "guix" "system" "build" - "-L" channeldir - "-L" configdir - "--verbosity=0" - (string-append systemdir file)) - #t) - (format #t "~a: Built \"~a\"!\n" name file) - (format #t "~a: Failed to build \"~a\"!\n" name file))) - (scandir systemdir - (lambda (file) - (string-suffix? ".scm" file)))) - - (format #t "Building ~a's home configurations...\n" name) - (for-each - (lambda (file) - (format #t "~a: Building \"~a\"...\n" name file) - (if (spawn* "guix" - (list "guix" "home" "build" - "-L" channeldir - "-L" configdir - "--verbosity=0" - (string-append homedir file)) - #t) - (format #t "~a: Built \"~a\"!\n" name file) - (format #t "~a: Failed to build \"~a\"!\n" name file))) - (scandir homedir - (lambda (file) - (string-suffix? ".scm" file))))) - (format #t "Failed to clone ~a repo! Skipping...\n" name)) - - ;; Cleanup - (delete-file-recursively configdir))) - (collect-lines (car output-pipe)))) - - ;; Push changes - (chdir channeldir) - (unless (and (spawn* #$git-bin - '("git" "add" - "mt/channels-locked.scm") - #f) - (spawn* #$git-bin - '("git" "commit" - "-m" "channels: %mt-channels-locked") - #f) - (spawn* #$gitolite-bin - '("gitolite" "push") - #f)) - (display "Failed to push changes!\n" (current-error-port))) - (chdir ogdir) - - ;; Cleanup - (delete-file-recursively channeldir)))))) - - (list (shepherd-service - (provision '(update-channels-locked)) - (requirement '(user-processes networking)) - (modules '((shepherd service timer))) - (start #~(make-timer-constructor - (calendar-event #:hours '(0) #:minutes '(0) - #:days-of-week '(sunday)) - (command `(#$(program-file "update-channels-locked" code)) - ;; We need to use the user's current guix version, - ;; and the system default if there's not one yet. - #:environment-variables - `(#$(string-append "PATH=" gitolite-home "/.config/guix/current/bin" - ":" "/run/current-system/profile/bin") - #$(string-append "HOME=" gitolite-home)) - #:user "git" - #:group "git") - #:log-file "/var/log/update-channels-locked.log" - #:wait-for-termination? #t)) - (stop #~(make-timer-destructor)) - (actions (list shepherd-trigger-action))))) - -(define update-channels-locked-service-type - (service-type - (name 'update-channels-locked) - (extensions - (list (service-extension shepherd-root-service-type - update-channels-locked-shepherd-service))) - (description "Update the locked channels and build user configurations.") - (default-value '())))