diff options
| author | wrobell <wrobell@riseup.net> | 2026-06-16 20:17:41 +0100 |
|---|---|---|
| committer | Nguyễn Gia Phong <cnx@loang.net> | 2026-07-26 15:23:19 +0900 |
| commit | ce8df300216b308720903e6da9e01d246143b47f (patch) | |
| tree | 6184790b895796fd3621bf753daddc4471449ee3 | |
| parent | 47b41dced835020f803dc56f52e949c94d2f7061 (diff) | |
services: Add epmd-service-type.
Add Erlang Port Mapper Daemon (epmd) service.
Run the service on localhost by default.
* gnu/services/high-availability.scm (<epmd-configuration>): New record.
(epmd-service-type): New variable.
* gnu/tests/high-availability.scm (run-epmd-test): New procedure.
(%epmd-os, %tests-epmd): New variables.
* doc/gnu.texi (High Availability Services): Document it.
Merges: https://codeberg.org/guix/guix/pulls/9607
References: https://www.rabbitmq.com/blog/2024/12/18/epmd-public-exposure
References: https://erlef.org/blog/eef/epmd-public-exposure
Signed-off-by: Nguyễn Gia Phong <cnx@loang.net>
| -rw-r--r-- | doc/guix.texi | 54 | ||||
| -rw-r--r-- | gnu/services/high-availability.scm | 81 | ||||
| -rw-r--r-- | gnu/tests/high-availability.scm | 81 |
3 files changed, 203 insertions, 13 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index 0db590aa5f7..12eca80ed3c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -37746,16 +37746,60 @@ Extra configuration parameters as a list of strings. | |||
| 37746 | @node High Availability Services | 37746 | @node High Availability Services |
| 37747 | @subsection High Availability Services | 37747 | @subsection High Availability Services |
| 37748 | 37748 | ||
| 37749 | @cindex Message broker | 37749 | The @code{(gnu services high-availability)} module provides services for |
| 37750 | @cindex Message streaming | 37750 | Erlang Port Mapper Daemon (epmd) and RabbitMQ broker. |
| 37751 | The @code{(gnu services high-availability)} module provides RabbitMQ | 37751 | |
| 37752 | message broker service. | 37752 | @anchor{epmd} |
| 37753 | @subsubheading Erlang Port Mapper Daemon (epmd) | ||
| 37754 | |||
| 37755 | @defvar epmd-service-type | ||
| 37756 | Service type for the | ||
| 37757 | @uref{https://www.erlang.org/doc/apps/erts/epmd_cmd.html,Erlang Port Mapper | ||
| 37758 | Daemon (epmd)}. | ||
| 37759 | The value for this service type is a @code{<epmd-configuration>} record. | ||
| 37760 | |||
| 37761 | Below is an example configuration: | ||
| 37762 | |||
| 37763 | @lisp | ||
| 37764 | (service epmd-service-type) | ||
| 37765 | @end lisp | ||
| 37766 | @end defvar | ||
| 37767 | |||
| 37768 | @c %start of fragment | ||
| 37769 | |||
| 37770 | @deftp {Data Type} epmd-configuration | ||
| 37771 | Available @code{epmd-configuration} fields are: | ||
| 37772 | |||
| 37773 | @table @asis | ||
| 37774 | @item @code{user} (default: @code{"epmd"}) (type: string) | ||
| 37775 | The user running epmd. | ||
| 37776 | |||
| 37777 | @item @code{group} (default: @code{"epmd"}) (type: string) | ||
| 37778 | The user group running epmd. | ||
| 37779 | |||
| 37780 | @item @code{address} (default: @code{("127.0.0.1" "::1")}) (type: list-of-strings) | ||
| 37781 | List of addresses for epmd to listen on. Set it to false (@code{#f}) to | ||
| 37782 | listen on all available addresses. Note that epmd cannot start on | ||
| 37783 | @code{"0.0.0.0"} address. | ||
| 37784 | |||
| 37785 | @item @code{port} (default: @code{4369}) (type: integer) | ||
| 37786 | Default port for epmd to listen on. | ||
| 37787 | |||
| 37788 | @end table | ||
| 37789 | |||
| 37790 | @end deftp | ||
| 37791 | |||
| 37792 | |||
| 37793 | @c %end of fragment | ||
| 37753 | 37794 | ||
| 37754 | @anchor{RabbitMQ} | 37795 | @anchor{RabbitMQ} |
| 37755 | @subsubheading RabbitMQ | 37796 | @subsubheading RabbitMQ |
| 37756 | 37797 | ||
| 37798 | @cindex Message broker | ||
| 37799 | @cindex Message streaming | ||
| 37800 | |||
| 37757 | @defvar rabbitmq-service-type | 37801 | @defvar rabbitmq-service-type |
| 37758 | Service type for the @uref{https://www.rabbitmq.com/,RabbitMQ} web server. | 37802 | Service type for the @uref{https://www.rabbitmq.com/,RabbitMQ} server. |
| 37759 | The value for this service type is a @code{<rabbitmq-configuration>} record. | 37803 | The value for this service type is a @code{<rabbitmq-configuration>} record. |
| 37760 | 37804 | ||
| 37761 | A simple example configuration is given below. | 37805 | A simple example configuration is given below. |
diff --git a/gnu/services/high-availability.scm b/gnu/services/high-availability.scm index 73d534cf020..8b928e76168 100644 --- a/gnu/services/high-availability.scm +++ b/gnu/services/high-availability.scm | |||
| @@ -20,8 +20,10 @@ | |||
| 20 | 20 | ||
| 21 | (define-module (gnu services high-availability) | 21 | (define-module (gnu services high-availability) |
| 22 | #:use-module (gnu packages admin) | 22 | #:use-module (gnu packages admin) |
| 23 | #:use-module (gnu packages erlang) | ||
| 23 | #:use-module (gnu packages high-availability) | 24 | #:use-module (gnu packages high-availability) |
| 24 | #:use-module (gnu services) | 25 | #:use-module (gnu services) |
| 26 | #:use-module (gnu services configuration) | ||
| 25 | #:use-module (gnu services shepherd) | 27 | #:use-module (gnu services shepherd) |
| 26 | #:use-module (gnu system shadow) | 28 | #:use-module (gnu system shadow) |
| 27 | #:use-module (guix gexp) | 29 | #:use-module (guix gexp) |
| @@ -30,13 +32,78 @@ | |||
| 30 | #:use-module (ice-9 match) | 32 | #:use-module (ice-9 match) |
| 31 | #:use-module (ice-9 format) | 33 | #:use-module (ice-9 format) |
| 32 | 34 | ||
| 33 | #:export (rabbitmq-configuration rabbitmq-configuration? | 35 | #:export (epmd-configuration |
| 34 | rabbitmq-configuration-rabbitmq | 36 | epmd-configuration-fields |
| 35 | rabbitmq-configuration-node-name | 37 | epmd-configuration? |
| 36 | rabbitmq-configuration-config-file | 38 | epmd-configuration-user |
| 37 | rabbitmq-configuration-env-config-file | 39 | epmd-configuration-group |
| 38 | rabbitmq-configuration-plugins | 40 | epmd-configuration-address |
| 39 | rabbitmq-service-type)) | 41 | epmd-configuration-port |
| 42 | epmd-service-type | ||
| 43 | |||
| 44 | rabbitmq-configuration | ||
| 45 | rabbitmq-configuration? | ||
| 46 | rabbitmq-configuration-rabbitmq | ||
| 47 | rabbitmq-configuration-node-name | ||
| 48 | rabbitmq-configuration-config-file | ||
| 49 | rabbitmq-configuration-env-config-file | ||
| 50 | rabbitmq-configuration-plugins | ||
| 51 | rabbitmq-service-type)) | ||
| 52 | |||
| 53 | (define-configuration/no-serialization epmd-configuration | ||
| 54 | (user (string "epmd") "The user running epmd.") | ||
| 55 | (group (string "epmd") "The user group running epmd.") | ||
| 56 | ;; The address default works for IPv4-only or IPv6-only systems. For example, | ||
| 57 | ;; epmd shows warning for ::1 on IPv4-only system, but starts anyway. | ||
| 58 | (address (list-of-strings (list "127.0.0.1" "::1")) | ||
| 59 | "List of addresses for epmd to listen on. Set it to false | ||
| 60 | (@code{#f}) to listen on all available addresses. Note that epmd cannot start | ||
| 61 | on @code{\"0.0.0.0\"} address.") | ||
| 62 | (port (integer 4369) "Default port for epmd to listen on.")) | ||
| 63 | |||
| 64 | (define (epmd-accounts config) | ||
| 65 | (match-record config <epmd-configuration> (user group) | ||
| 66 | (list (user-group (name group) | ||
| 67 | (system? #t)) | ||
| 68 | (user-account (name user) | ||
| 69 | (group group) | ||
| 70 | (system? #t) | ||
| 71 | (comment "Erlang Port Mapper Daemon user") | ||
| 72 | (home-directory "/var/empty") | ||
| 73 | (shell (file-append shadow "/sbin/nologin")))))) | ||
| 74 | |||
| 75 | (define (epmd-shepherd-service config) | ||
| 76 | (match-record config <epmd-configuration> | ||
| 77 | (address port) | ||
| 78 | (let ((address-list (if address (string-join address ",") #f))) | ||
| 79 | (with-imported-modules | ||
| 80 | (source-module-closure '((gnu build shepherd))) | ||
| 81 | (list | ||
| 82 | (shepherd-service | ||
| 83 | (provision '(epmd)) | ||
| 84 | (documentation "Run the Erlang Port Mapper Daemon (epmd).") | ||
| 85 | (requirement '(user-processes loopback)) | ||
| 86 | (modules '((gnu build shepherd))) | ||
| 87 | (start | ||
| 88 | #~(make-forkexec-constructor | ||
| 89 | (append (list #$(file-append erlang "/bin/epmd") | ||
| 90 | "-port" | ||
| 91 | #$(number->string port)) | ||
| 92 | (if #$address-list | ||
| 93 | (list "-address" #$address-list) | ||
| 94 | (list))) | ||
| 95 | #:user "epmd" | ||
| 96 | #:group "epmd")) | ||
| 97 | (stop #~(make-kill-destructor)))))))) | ||
| 98 | |||
| 99 | (define epmd-service-type | ||
| 100 | (service-type | ||
| 101 | (name 'epmd) | ||
| 102 | (description "Run the Erlang Port Mapper Daemon (epmd).") | ||
| 103 | (extensions (list (service-extension shepherd-root-service-type | ||
| 104 | epmd-shepherd-service) | ||
| 105 | (service-extension account-service-type epmd-accounts))) | ||
| 106 | (default-value (epmd-configuration)))) | ||
| 40 | 107 | ||
| 41 | ;; By default, start messaging and inter-node RabbitMQ listeners on local | 108 | ;; By default, start messaging and inter-node RabbitMQ listeners on local |
| 42 | ;; interfaces only, see also: | 109 | ;; interfaces only, see also: |
diff --git a/gnu/tests/high-availability.scm b/gnu/tests/high-availability.scm index 6eb13d1a068..faa657bfc3c 100644 --- a/gnu/tests/high-availability.scm +++ b/gnu/tests/high-availability.scm | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | (define-module (gnu tests high-availability) | 20 | (define-module (gnu tests high-availability) |
| 21 | #:use-module (gnu tests) | 21 | #:use-module (gnu tests) |
| 22 | #:use-module (gnu packages erlang) | ||
| 22 | #:use-module (gnu packages high-availability) | 23 | #:use-module (gnu packages high-availability) |
| 23 | #:use-module (gnu system) | 24 | #:use-module (gnu system) |
| 24 | #:use-module (gnu system file-systems) | 25 | #:use-module (gnu system file-systems) |
| @@ -29,7 +30,85 @@ | |||
| 29 | #:use-module (gnu services networking) | 30 | #:use-module (gnu services networking) |
| 30 | #:use-module (guix gexp) | 31 | #:use-module (guix gexp) |
| 31 | #:use-module (guix store) | 32 | #:use-module (guix store) |
| 32 | #:export (%test-rabbitmq)) | 33 | #:export (%test-epmd |
| 34 | %test-rabbitmq)) | ||
| 35 | |||
| 36 | ;;; | ||
| 37 | ;;; Erlang Port Mapper Daemon (epmd) service. | ||
| 38 | ;;; | ||
| 39 | (define %epmd-os | ||
| 40 | (simple-operating-system | ||
| 41 | (service epmd-service-type | ||
| 42 | (epmd-configuration (port 14369))))) | ||
| 43 | |||
| 44 | (define* (run-epmd-test #:key (epmd-port 14369)) | ||
| 45 | "Run tests in %EPMD-OS, forwarding PORT." | ||
| 46 | (define os | ||
| 47 | (marionette-operating-system | ||
| 48 | %epmd-os | ||
| 49 | #:imported-modules '((gnu services herd) | ||
| 50 | (guix combinators)))) | ||
| 51 | |||
| 52 | (define forwarded-port 14369) | ||
| 53 | |||
| 54 | (define vm | ||
| 55 | (virtual-machine | ||
| 56 | (operating-system os) | ||
| 57 | (memory-size 512) | ||
| 58 | (port-forwardings `((,epmd-port . ,forwarded-port))))) | ||
| 59 | |||
| 60 | (define test | ||
| 61 | (with-imported-modules '((gnu build marionette)) | ||
| 62 | #~(begin | ||
| 63 | (use-modules (srfi srfi-64) | ||
| 64 | (gnu build marionette) | ||
| 65 | (ice-9 rdelim)) | ||
| 66 | |||
| 67 | (define marionette | ||
| 68 | (make-marionette (list #$vm))) | ||
| 69 | |||
| 70 | (mkdir #$output) | ||
| 71 | (chdir #$output) | ||
| 72 | |||
| 73 | (test-runner-current (system-test-runner #$output)) | ||
| 74 | (test-begin "epmd") | ||
| 75 | |||
| 76 | ;; Wait for epmd to be up and running. | ||
| 77 | (test-assert "service running" | ||
| 78 | (marionette-eval | ||
| 79 | '(begin | ||
| 80 | (use-modules (gnu services herd)) | ||
| 81 | (match (start-service 'epmd) | ||
| 82 | (#f #f) | ||
| 83 | (('service response-parts ...) | ||
| 84 | (match (assq-ref response-parts 'running) | ||
| 85 | ((#t) #t) | ||
| 86 | ((pid) pid))))) | ||
| 87 | marionette)) | ||
| 88 | |||
| 89 | (test-assert "epmd port ready" | ||
| 90 | (wait-for-tcp-port #$forwarded-port marionette)) | ||
| 91 | |||
| 92 | (test-assert "epmd connection is successful" | ||
| 93 | (marionette-eval | ||
| 94 | '(begin | ||
| 95 | (use-modules (guix build utils)) | ||
| 96 | |||
| 97 | (current-output-port (open-file "/dev/console" "w0")) | ||
| 98 | (invoke #$(file-append erlang "/bin/epmd") | ||
| 99 | "-port" | ||
| 100 | "14369" | ||
| 101 | "-names")) | ||
| 102 | marionette)) | ||
| 103 | (test-end)))) | ||
| 104 | |||
| 105 | (gexp->derivation "epmd-test" test)) | ||
| 106 | |||
| 107 | (define %test-epmd | ||
| 108 | (system-test | ||
| 109 | (name "epmd") | ||
| 110 | (description "Connect to a running epmd service.") | ||
| 111 | (value (run-epmd-test)))) | ||
| 33 | 112 | ||
| 34 | (define %rabbitmq-config-file | 113 | (define %rabbitmq-config-file |
| 35 | (plain-file "rabbitmq.conf" " | 114 | (plain-file "rabbitmq.conf" " |
