diff options
| author | Nguyễn Gia Phong <mcsinyx@disroot.org> | 2025-11-17 15:46:53 +0900 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2026-03-11 18:27:46 +0100 |
| commit | 3433fb987bbc826a585a0d4d0a80e1f5369769a3 (patch) | |
| tree | 404bf5c6a53dd084bc4ab26506455077e9a8eef3 /gnu/services | |
| parent | 6eb6971f4d721fc8d648323f0dbd52d0697b2a7b (diff) | |
services: Add fossil-service-type.
* gnu/services/version-control.scm
(fossil-service-type, fossil-configuration): New public variables.
* gnu/tests/version-control.scm (%test-fossil): Add system tests.
* doc/guix.texi (Version Control Services): Add Fossil documentation.
Change-Id: I84e09fe8c11e161ed7c4bdba42b0ae38ef4c2096
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Diffstat (limited to 'gnu/services')
| -rw-r--r-- | gnu/services/version-control.scm | 257 |
1 files changed, 256 insertions, 1 deletions
diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm index a7f40812a6c..dba38faa460 100644 --- a/gnu/services/version-control.scm +++ b/gnu/services/version-control.scm | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | ;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu> | 7 | ;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu> |
| 8 | ;;; Copyright © 2025 Tomas Volf <~@wolfsden.cz> | 8 | ;;; Copyright © 2025 Tomas Volf <~@wolfsden.cz> |
| 9 | ;;; Copyright © 2025 Evgeny Pisemsky <mail@pisemsky.site> | 9 | ;;; Copyright © 2025 Evgeny Pisemsky <mail@pisemsky.site> |
| 10 | ;;; Copyright © 2026 Nguyễn Gia Phong <cnx@loang.net> | ||
| 10 | ;;; | 11 | ;;; |
| 11 | ;;; This file is part of GNU Guix. | 12 | ;;; This file is part of GNU Guix. |
| 12 | ;;; | 13 | ;;; |
| @@ -26,12 +27,14 @@ | |||
| 26 | (define-module (gnu services version-control) | 27 | (define-module (gnu services version-control) |
| 27 | #:use-module (gnu services) | 28 | #:use-module (gnu services) |
| 28 | #:use-module (gnu services base) | 29 | #:use-module (gnu services base) |
| 30 | #:use-module (gnu services configuration) | ||
| 29 | #:use-module (gnu services shepherd) | 31 | #:use-module (gnu services shepherd) |
| 30 | #:use-module (gnu services web) | 32 | #:use-module (gnu services web) |
| 31 | #:use-module (gnu system shadow) | 33 | #:use-module (gnu system shadow) |
| 32 | #:use-module (gnu packages version-control) | 34 | #:use-module (gnu packages version-control) |
| 33 | #:use-module (gnu packages admin) | 35 | #:use-module (gnu packages admin) |
| 34 | #:use-module (guix deprecation) | 36 | #:use-module (guix deprecation) |
| 37 | #:use-module (guix packages) | ||
| 35 | #:use-module (guix records) | 38 | #:use-module (guix records) |
| 36 | #:use-module (guix gexp) | 39 | #:use-module (guix gexp) |
| 37 | #:use-module (guix store) | 40 | #:use-module (guix store) |
| @@ -93,7 +96,44 @@ | |||
| 93 | gitile-configuration-footer | 96 | gitile-configuration-footer |
| 94 | gitile-configuration-nginx | 97 | gitile-configuration-nginx |
| 95 | 98 | ||
| 96 | gitile-service-type)) | 99 | gitile-service-type |
| 100 | |||
| 101 | fossil-configuration | ||
| 102 | fossil-configuration-fields | ||
| 103 | fossil-configuration? | ||
| 104 | fossil-configuration-package | ||
| 105 | fossil-configuration-user | ||
| 106 | fossil-configuration-group | ||
| 107 | fossil-configuration-log-file | ||
| 108 | fossil-configuration-repository | ||
| 109 | fossil-configuration-acme? | ||
| 110 | fossil-configuration-base-url | ||
| 111 | fossil-configuration-chroot | ||
| 112 | fossil-configuration-ckout-alias | ||
| 113 | fossil-configuration-compress? | ||
| 114 | fossil-configuration-create? | ||
| 115 | fossil-configuration-error-log-file | ||
| 116 | fossil-configuration-ext-root | ||
| 117 | fossil-configuration-files | ||
| 118 | fossil-configuration-from | ||
| 119 | fossil-configuration-jail? | ||
| 120 | fossil-configuration-js-mode | ||
| 121 | fossil-configuration-https? | ||
| 122 | fossil-configuration-ip | ||
| 123 | fossil-configuration-local-authentication? | ||
| 124 | fossil-configuration-main-menu | ||
| 125 | fossil-configuration-max-latency | ||
| 126 | fossil-configuration-port | ||
| 127 | fossil-configuration-list-repositories? | ||
| 128 | fossil-configuration-redirect-to-https? | ||
| 129 | fossil-configuration-skin | ||
| 130 | fossil-configuration-socket-file | ||
| 131 | fossil-configuration-socket-mode | ||
| 132 | fossil-configuration-th-trace? | ||
| 133 | fossil-configuration-tls-certificate | ||
| 134 | fossil-configuration-tls-private-key | ||
| 135 | |||
| 136 | fossil-service-type)) | ||
| 97 | 137 | ||
| 98 | ;;; Commentary: | 138 | ;;; Commentary: |
| 99 | ;;; | 139 | ;;; |
| @@ -603,3 +643,218 @@ on the web.") | |||
| 603 | gitile-shepherd-service) | 643 | gitile-shepherd-service) |
| 604 | (service-extension nginx-service-type | 644 | (service-extension nginx-service-type |
| 605 | gitile-nginx-server-block))))) | 645 | gitile-nginx-server-block))))) |
| 646 | |||
| 647 | |||
| 648 | ;;; | ||
| 649 | ;;; Fossil HTTP server. | ||
| 650 | ;;; | ||
| 651 | |||
| 652 | (define (port-number? n) | ||
| 653 | (and (integer? n) | ||
| 654 | (> n 0) | ||
| 655 | (< n (expt 2 16)))) | ||
| 656 | |||
| 657 | (define (mode-number? n) | ||
| 658 | (and (integer? n) | ||
| 659 | (>= n 0) | ||
| 660 | (<= n #o777))) | ||
| 661 | |||
| 662 | (define (fossil-js-mode? x) | ||
| 663 | (and (memq x '(inline separate bundled)) | ||
| 664 | #t)) | ||
| 665 | |||
| 666 | (define-maybe/no-serialization number) | ||
| 667 | (define-maybe/no-serialization string) | ||
| 668 | (define-maybe/no-serialization list-of-strings) | ||
| 669 | (define-maybe/no-serialization fossil-js-mode) | ||
| 670 | |||
| 671 | (define-configuration/no-serialization fossil-configuration | ||
| 672 | (package (package fossil) | ||
| 673 | "The Fossil package to use.") | ||
| 674 | (user (string "fossil") | ||
| 675 | "The user running the Fossil server.") | ||
| 676 | (group (string "fossil") | ||
| 677 | "The user group running the Fossil server.") | ||
| 678 | (log-file (string "/var/log/fossil.log") | ||
| 679 | "The path to the server's log.") | ||
| 680 | (repository (string "/var/lib/fossil") | ||
| 681 | "The name of the Fossil repository to be served, or a directory | ||
| 682 | containing one or more repositories with names ending in @code{.fossil}. | ||
| 683 | |||
| 684 | In the latter case, a prefix of the URL pathname is used | ||
| 685 | to search the directory for an appropriate repository. | ||
| 686 | Files not matching the pattern @code{*.fossil*} | ||
| 687 | will be served as static content. Invoke @command{fossil server --help} | ||
| 688 | for more information.") | ||
| 689 | (acme? (boolean #f) | ||
| 690 | "Deliver files from the @code{.well-known} subdirectory.") | ||
| 691 | (base-url maybe-string | ||
| 692 | "The URL used as the base (useful for reverse proxies)") | ||
| 693 | (chroot maybe-string | ||
| 694 | "The directory to use for chroot instead of @code{repository}.") | ||
| 695 | (ckout-alias maybe-string | ||
| 696 | "The @var{name} for @code{/doc/@var{name}/...} | ||
| 697 | to be treated as @code{/doc/ckout/...}.") | ||
| 698 | (compress? (boolean #t) "Compress HTTP response.") | ||
| 699 | (create? (boolean #f) | ||
| 700 | "Create a new @code{repository} if it does not already exist.") | ||
| 701 | (error-log-file maybe-string "The path for HTTP error log.") | ||
| 702 | (ext-root maybe-string "The document root for the /ext extension mechanism.") | ||
| 703 | (files maybe-list-of-strings "The glob patterns for static files.") | ||
| 704 | (from maybe-string | ||
| 705 | "The path to be used as the diff baseline for the /ckout page.") | ||
| 706 | (jail? (boolean #t) | ||
| 707 | "Whether to enter the chroot jail after dropping root privileges.") | ||
| 708 | (js-mode maybe-fossil-js-mode | ||
| 709 | "How JavaScript is delivered with pages, either @code{'inline} | ||
| 710 | at the end of the HTML file, as @code{'separate} HTTP requests, | ||
| 711 | or one single HTTP request for all JavaScript @code{'bundled} together. | ||
| 712 | |||
| 713 | Depending on the needs of any given page, @code{'inline} | ||
| 714 | and @code{'bundled} modes might result in a single amalgamated script | ||
| 715 | or several, but both approaches result in fewer HTTP requests | ||
| 716 | than the @code{'separate} mode.") | ||
| 717 | (https? (boolean #f) | ||
| 718 | "Indicate that the requests are coming through a reverse proxy | ||
| 719 | that has already translated HTTPS into HTTP.") | ||
| 720 | (ip maybe-string "The IP for the server to listen on.") | ||
| 721 | (local-authentication? (boolean #f) | ||
| 722 | "Enable automatic login for requests from localhost.") | ||
| 723 | (localhost? (boolean #f) "Listen on @code{127.0.0.1} only.") | ||
| 724 | (main-menu maybe-string ;TODO: structure | ||
| 725 | "The file whose contents is to override | ||
| 726 | the repository's @code{mainmenu} setting.") | ||
| 727 | (max-latency maybe-number | ||
| 728 | "The maximum latency in seconds for a single HTTP request.") | ||
| 729 | (port (port-number 8080) "The port number for the server to listen on.") | ||
| 730 | (list-repositories? (boolean #f) | ||
| 731 | "If @code{repository} is dir, URL @code{/} lists repos.") | ||
| 732 | (redirect-to-https? (boolean #t) | ||
| 733 | "If set to @code{#f}, do not force redirects to HTTPS | ||
| 734 | regardless of the repository setting @code{redirect-to-https}.") | ||
| 735 | (scgi? (boolean #f) "Accept SCGI rather than HTTP.") | ||
| 736 | (skin maybe-string "The skin label to use, overriding repository settings.") | ||
| 737 | (socket-file maybe-string | ||
| 738 | "The unix-domain socket to use instead of TCP/IP.") | ||
| 739 | (socket-mode (mode-number #o640) | ||
| 740 | "The file permissions to set for the unix socket.") | ||
| 741 | (th-trace? (boolean #f) | ||
| 742 | "Trace TH1 execution (for debugging purposes).") | ||
| 743 | (tls-certificate maybe-string | ||
| 744 | "The certicate file (@file{fullchain.pem}) | ||
| 745 | with which to enable TLS (HTTPS) encryption.") | ||
| 746 | (tls-private-key maybe-string "The file storing the TLS private key.")) | ||
| 747 | |||
| 748 | (define (fossil-accounts config) | ||
| 749 | (match-record config <fossil-configuration> (user group) | ||
| 750 | (list (user-group (name group) | ||
| 751 | (system? #t)) | ||
| 752 | (user-account (name user) | ||
| 753 | (group group) | ||
| 754 | (system? #t) | ||
| 755 | (comment "Fossil server user") | ||
| 756 | (home-directory "/var/empty") | ||
| 757 | (shell (file-append shadow "/sbin/nologin")))))) | ||
| 758 | |||
| 759 | (define (fossil-activation config) | ||
| 760 | (match-record config <fossil-configuration> (user create? repository) | ||
| 761 | (with-imported-modules '((guix build utils)) | ||
| 762 | #~(begin | ||
| 763 | (use-modules (guix build utils)) | ||
| 764 | (let* ((pw (getpwnam #$user)) | ||
| 765 | (uid (passwd:uid pw)) | ||
| 766 | (gid (passwd:gid pw))) | ||
| 767 | (unless #$create? (chown #$repository uid gid))))))) | ||
| 768 | |||
| 769 | (define (fossil-shepherd-service config) | ||
| 770 | (match-record config <fossil-configuration> | ||
| 771 | (package user group log-file repository acme? base-url | ||
| 772 | chroot ckout-alias compress? create? error-log-file ext-root | ||
| 773 | files from https? ip jail? js-mode list-repositories? | ||
| 774 | local-authentication? localhost? main-menu max-latency port | ||
| 775 | redirect-to-https? scgi? skin socket-file socket-mode | ||
| 776 | th-trace? tls-certificate tls-private-key) | ||
| 777 | (shepherd-service | ||
| 778 | (provision '(fossil)) | ||
| 779 | (requirement '(user-processes networking)) | ||
| 780 | (start #~(make-forkexec-constructor | ||
| 781 | (list #$(file-append package "/bin/fossil") | ||
| 782 | "server" | ||
| 783 | #$@(if acme? '("--acme") '()) | ||
| 784 | #$@(if (maybe-value-set? base-url) | ||
| 785 | (list "--baseurl" base-url) | ||
| 786 | '()) | ||
| 787 | #$@(if (maybe-value-set? chroot) | ||
| 788 | (list "--chroot" chroot) | ||
| 789 | '()) | ||
| 790 | #$@(if (maybe-value-set? ckout-alias) | ||
| 791 | (list "--ckout-alias" ckout-alias) | ||
| 792 | '()) | ||
| 793 | #$@(if compress? '() '("--nocompress")) | ||
| 794 | #$@(if create? '("--create") '()) | ||
| 795 | #$@(if (maybe-value-set? error-log-file) | ||
| 796 | (list "--errorlog" error-log-file) | ||
| 797 | '()) | ||
| 798 | #$@(if (maybe-value-set? ext-root) | ||
| 799 | (list "--extroot" ext-root) | ||
| 800 | '()) | ||
| 801 | #$@(if (maybe-value-set? files) | ||
| 802 | (list "--files" (string-join files ",")) | ||
| 803 | '()) | ||
| 804 | #$@(if (maybe-value-set? from) (list "--from" from) '()) | ||
| 805 | #$@(if https? '("--https") '()) | ||
| 806 | #$@(if jail? '() '("--nojail")) | ||
| 807 | #$@(if (maybe-value-set? js-mode) | ||
| 808 | (list "--jsmode" (symbol->string js-mode)) | ||
| 809 | '()) | ||
| 810 | #$@(if local-authentication? '("--localauth") '()) | ||
| 811 | #$@(if localhost? '("--localhost") '()) | ||
| 812 | #$@(if (maybe-value-set? main-menu) | ||
| 813 | (list "--mainmenu" main-menu) | ||
| 814 | '()) | ||
| 815 | #$@(if (maybe-value-set? max-latency) | ||
| 816 | (list "--max-latency" | ||
| 817 | (number->string max-latency)) | ||
| 818 | '()) | ||
| 819 | #$@(if redirect-to-https? '() '("--nossl")) | ||
| 820 | #$@(if scgi? '("--scgi") '()) | ||
| 821 | #$@(if list-repositories? '("--repolist") '()) | ||
| 822 | #$@(if (maybe-value-set? skin) (list "--skin" skin) '()) | ||
| 823 | #$@(if (maybe-value-set? socket-file) | ||
| 824 | (list "--socket-name" socket-file | ||
| 825 | "--socket-mode" socket-mode | ||
| 826 | "--socket-owner" | ||
| 827 | (simple-format #f "~a:~a" user group)) | ||
| 828 | (list "--port" | ||
| 829 | (if (maybe-value-set? ip) | ||
| 830 | (simple-format #f "~a:~a" ip port) | ||
| 831 | (number->string port)))) | ||
| 832 | #$@(if th-trace? '("--th-trace") '()) | ||
| 833 | #$@(if (maybe-value-set? tls-certificate) | ||
| 834 | (list "--cert" tls-certificate) | ||
| 835 | '()) | ||
| 836 | #$@(if (maybe-value-set? tls-private-key) | ||
| 837 | (list "--pkey" tls-private-key) | ||
| 838 | '()) | ||
| 839 | "--user" #$user | ||
| 840 | #$repository) | ||
| 841 | #:user #$user | ||
| 842 | #:group #$group | ||
| 843 | #:log-file #$log-file)) | ||
| 844 | (stop #~(make-kill-destructor)) | ||
| 845 | (documentation | ||
| 846 | "Run the HTTP server | ||
| 847 | for the Fossil software configuration management system.")))) | ||
| 848 | |||
| 849 | (define fossil-service-type | ||
| 850 | (service-type | ||
| 851 | (name 'fossil) | ||
| 852 | (extensions | ||
| 853 | (list (service-extension account-service-type fossil-accounts) | ||
| 854 | (service-extension activation-service-type fossil-activation) | ||
| 855 | (service-extension shepherd-root-service-type | ||
| 856 | (compose list fossil-shepherd-service)))) | ||
| 857 | (description | ||
| 858 | "Run the HTTP server for the Fossil software configuration management | ||
| 859 | system. In addition to distributed version control, Fossil also supports | ||
| 860 | bug tracking, wiki, forum, email alerts, chat, and technotes."))) | ||
