~ruther/guix-local

b6d2930d1fbe99172f0d1c96c3347e2ac34f35f5 — nee 8 years ago 6692d84
services: Add murmur.

* gnu/services/telephony.scm: New file.
* gnu/local.mk: Add it.
* doc/guix.texi (Telephony Services): New node.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
3 files changed, 514 insertions(+), 0 deletions(-)

M doc/guix.texi
M gnu/local.mk
A gnu/services/telephony.scm
M doc/guix.texi => doc/guix.texi +208 -0
@@ 221,6 221,7 @@ Services
* Database Services::           SQL databases, key-value stores, etc.
* Mail Services::               IMAP, POP3, SMTP, and all that.
* Messaging Services::          Messaging services.
* Telephony Services::          Telephony services.
* Monitoring Services::         Monitoring services.
* Kerberos Services::           Kerberos services.
* Web Services::                Web servers.


@@ 9308,6 9309,7 @@ declaration.
* Database Services::           SQL databases, key-value stores, etc.
* Mail Services::               IMAP, POP3, SMTP, and all that.
* Messaging Services::          Messaging services.
* Telephony Services::          Telephony services.
* Monitoring Services::         Monitoring services.
* Kerberos Services::           Kerberos services.
* Web Services::                Web servers.


@@ 14189,6 14191,212 @@ string, you could instantiate a prosody service like this:
          (prosody.cfg.lua "")))
@end example


@node Telephony Services
@subsubsection Telephony Services

@cindex Murmur (VoIP server)
@cindex VoIP server
This section describes how to set up and run a Murmur server.  Murmur is
the server of the @uref{https://mumble.info, Mumble} voice-over-IP
(VoIP) suite.

@deftp {Data Type} murmur-configuration
The service type for the Murmur server.  An example configuration can
look like this:

@example
(service murmur-service-type
         (murmur-configuration
          (welcome-text
            "Welcome to this Mumble server running on GuixSD!")
          (cert-required? #t) ;disallow text password logins
          (ssl-cert "/etc/letsencrypt/live/mumble.example.com/fullchain.pem")
          (ssl-key "/etc/letsencrypt/live/mumble.example.com/privkey.pem")))
@end example

After reconfiguring your system, you can manually set the murmur @code{SuperUser}
password with the command that is printed during the activation phase.

It is recommended to register a normal Mumble user account
and grant it admin or moderator rights.
You can use the @code{mumble} client to
login as new normal user, register yourself, and log out.
For the next step login with the name @code{SuperUser} use
the @code{SuperUser} password that you set previously,
and grant your newly registered mumble user administrator or moderator
rights and create some channels.

Available @code{murmur-configuration} fields are:

@table @asis
@item @code{package} (default: @code{mumble})
Package that contains @code{bin/murmurd}.

@item @code{user} (default: @code{"murmur"})
User who will run the Murmur server.

@item @code{group} (default: @code{"murmur"})
Group of the user who will run the murmur server.

@item @code{port} (default: @code{64738})
Port on which the server will listen.

@item @code{welcome-text} (default: @code{""})
Welcome text sent to clients when they connect.

@item @code{server-password} (default: @code{""})
Password the clients have to enter in order to connect.

@item @code{max-users} (default: @code{100})
Maximum of users that can be connected to the server at once.

@item @code{max-user-bandwidth} (default: @code{#f})
Maximum voice traffic a user can send per second.

@item @code{database-file} (default: @code{"/var/lib/murmur/db.sqlite"})
File name of the sqlite database.
The service's user will become the owner of the directory.

@item @code{log-file} (default: @code{"/var/log/murmur/murmur.log"})
File name of the log file.
The service's user will become the owner of the directory.

@item @code{autoban-attempts} (default: @code{10})
Maximum number of logins a user can make in @code{autoban-timeframe}
without getting auto banned for @code{autoban-time}.

@item @code{autoban-timeframe} (default: @code{120})
Timeframe for autoban in seconds.

@item @code{autoban-time} (default: @code{300})
Amount of time in seconds for which a client gets banned
when violating the autoban limits.

@item @code{opus-threshold} (default: @code{100})
Percentage of clients that need to support opus
before switching over to opus audio codec.

@item @code{channel-nesting-limit} (default: @code{10})
How deep channels can be nested at maximum.

@item @code{channelname-regex} (default: @code{#f})
A string in from of a Qt regular expression that channel names must conform to.

@item @code{username-regex} (default: @code{#f})
A string in from of a Qt regular expression that user names must conform to.

@item @code{text-message-length} (default: @code{5000})
Maximum size in bytes that a user can send in one text chat message.

@item @code{image-message-length} (default: @code{(* 128 1024)})
Maximum size in bytes that a user can send in one image message.

@item @code{cert-required?} (default: @code{#f})
If it is set to @code{#t} clients that use weak password authentification
will not be accepted. Users must have completed the certificate wizard to join.

@item @code{remember-channel?} (defualt @code{#f})
Should murmur remember the last channel each user was in when they disconnected
and put them into the remembered channel when they rejoin.

@item @code{allow-html?} (default: @code{#f})
Should html be allowed in text messages, user comments, and channel descriptions.

@item @code{allow-ping?} (default: @code{#f})
Setting to true exposes the current user count, the maximum user count, and
the server's maximum bandwidth per client to unauthenticated users. In the
Mumble client, this information is shown in the Connect dialog.

Disabling this setting will prevent public listing of the server.

@item @code{bonjour?} (default: @code{#f})
Should the server advertise itself in the local network through the bonjour protocol.

@item @code{send-version?} (default: @code{#f})
Should the murmur server version be exposed in ping requests.

@item @code{log-days} (default: @code{31})
Murmur also stores logs in the database, which are accessible via RPC.
The default is 31 days of months, but you can set this setting to 0 to keep logs forever,
or -1 to disable logging to the database.

@item @code{obfuscate-ips?} (default @code{#t})
Should logged ips be obfuscated to protect the privacy of users.

@item @code{ssl-cert} (default: @code{#f})
File name of the SSL/TLS certificate used for encrypted connections.

@example
(ssl-cert "/etc/letsencrypt/live/example.com/fullchain.pem")
@end example
@item @code{ssl-key} (default: @code{#f})
Filepath to the ssl private key used for encrypted connections.
@example
(ssl-key "/etc/letsencrypt/live/example.com/privkey.pem")
@end example

@item @code{ssl-dh-params} (default: @code{#f})
File name of a PEM-encoded file with Diffie-Hellman parameters
for the SSL/TLS encryption.  Alternatively you set it to
@code{"@@ffdhe2048"}, @code{"@@ffdhe3072"}, @code{"@@ffdhe4096"}, @code{"@@ffdhe6144"}
or @code{"@@ffdhe8192"} to use bundled parameters from RFC 7919.

@item @code{ssl-ciphers} (default: @code{#f})
The @code{ssl-ciphers} option chooses the cipher suites to make available for use
in SSL/TLS.

This option is specified using
@uref{https://www.openssl.org/docs/apps/ciphers.html#CIPHER-LIST-FORMAT,
OpenSSL cipher list notation}.

It is recommended that you try your cipher string using 'openssl ciphers <string>'
before setting it here, to get a feel for which cipher suites you will get.
After setting this option, it is recommend that you inspect your Murmur log
to ensure that Murmur is using the cipher suites that you expected it to.

Note: Changing this option may impact the backwards compatibility of your
Murmur server, and can remove the ability for older Mumble clients to be able
to connect to it.

@item @code{public-registration} (default: @code{#f})
Must be a @code{<murmur-public-registration-configuration>} record or @code{#f}.

You can optionally register your server in the public server list that the
@code{mumble} client shows on startup.
You cannot register your server if you have set a @code{server-password},
or set @code{allow-ping} to @code{#f}.

It might take a few hours until it shows up in the public list.

@item @code{file} (default: @code{#f})
Optional alternative override for this configuration.
@end table
@end deftp

@deftp {Data Type} murmur-public-registration-configuration
Configuration for public registration of a murmur service.

@table @asis
@item @code{name}
This is a display name for your server. Not to be confused with the hostname.

@item @code{password}
A password to identify your registration.
Subsequent updates will need the same password. Don't lose your password.

@item @code{url}
This should be a @code{http://} or @code{https://} link to your web
site.

@item @code{hostname} (default: @code{#f})
By default your server will be listed by its IP address.
If it is set your server will be linked by this host name instead.
@end table
@end deftp



@node Monitoring Services
@subsubsection Monitoring Services


M gnu/local.mk => gnu/local.mk +1 -0
@@ 461,6 461,7 @@ GNU_SYSTEM_MODULES =				\
  %D%/services/spice.scm				\
  %D%/services/ssh.scm				\
  %D%/services/sysctl.scm			\
  %D%/services/telephony.scm			\
  %D%/services/version-control.scm              \
  %D%/services/vpn.scm				\
  %D%/services/web.scm				\

A gnu/services/telephony.scm => gnu/services/telephony.scm +305 -0
@@ 0,0 1,305 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 nee  <nee-git@hidamari.blue>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu services telephony)
  #:use-module (gnu services)
  #:use-module (gnu services shepherd)
  #:use-module (gnu system shadow)
  #:use-module (gnu packages admin)
  #:use-module (gnu packages telephony)
  #:use-module (guix records)
  #:use-module (guix gexp)
  #:use-module (srfi srfi-1)
  #:use-module (ice-9 match)
  #:export (murmur-configuration
            make-murmur-configuration
            murmur-configuration?
            murmur-configuration-package
            murmur-configuration-user
            murmur-configuration-group
            murmur-configuration-port
            murmur-configuration-welcome-text
            murmur-configuration-server-password
            murmur-configuration-max-users
            murmur-configuration-max-user-bandwidth
            murmur-configuration-database-file
            murmur-configuration-log-file
            murmur-configuration-pid-file
            murmur-configuration-autoban-attempts
            murmur-configuration-autoban-timeframe
            murmur-configuration-autoban-time
            murmur-configuration-opus-threshold
            murmur-configuration-channel-nesting-limit
            murmur-configuration-channelname-regex
            murmur-configuration-username-regex
            murmur-configuration-text-message-length
            murmur-configuration-image-message-length
            murmur-configuration-cert-required?
            murmur-configuration-remember-channel?
            murmur-configuration-allow-html?
            murmur-configuration-allow-ping?
            murmur-configuration-bonjour?
            murmur-configuration-send-version?
            murmur-configuration-log-days
            murmur-configuration-obfuscate-ips?
            murmur-configuration-ssl-cert
            murmur-configuration-ssl-key
            murmur-configuration-ssl-dh-params
            murmur-configuration-ssl-ciphers
            murmur-configuration-public-registration
            murmur-configuration-file

            murmur-public-registration-configuration
            make-murmur-public-registration-configuration
            murmur-public-registration-configuration?
            murmur-public-registration-configuration-name
            murmur-public-registration-configuration-url
            murmur-public-registration-configuration-password
            murmur-public-registration-configuration-hostname

            murmur-service-type))

;; https://github.com/mumble-voip/mumble/blob/master/scripts/murmur.ini

(define-record-type* <murmur-configuration> murmur-configuration
  make-murmur-configuration
  murmur-configuration?
  (package               murmur-configuration-package ;<package>
                         (default mumble))
  (user                  murmur-configuration-user
                         (default "murmur"))
  (group                 murmur-configuration-group
                         (default "murmur"))
  (port                  murmur-configuration-port
                         (default 64738))
  (welcome-text          murmur-configuration-welcome-text
                         (default ""))
  (server-password       murmur-configuration-server-password
                         (default ""))
  (max-users             murmur-configuration-max-users
                         (default 100))
  (max-user-bandwidth    murmur-configuration-max-user-bandwidth
                         (default #f))
  (database-file         murmur-configuration-database-file
                         (default "/var/lib/murmur/db.sqlite"))
  (log-file              murmur-configuration-log-file
                         (default "/var/log/murmur/murmur.log"))
  (pid-file              murmur-configuration-pid-file
                         (default "/var/run/murmur/murmur.pid"))
  (autoban-attempts      murmur-configuration-autoban-attempts
                         (default 10))
  (autoban-timeframe     murmur-configuration-autoban-timeframe
                         (default 120))
  (autoban-time          murmur-configuration-autoban-time
                         (default 300))
  (opus-threshold        murmur-configuration-opus-threshold
                         (default 100)) ; integer percent
  (channel-nesting-limit murmur-configuration-channel-nesting-limit
                         (default 10))
  (channelname-regex     murmur-configuration-channelname-regex
                         (default #f))
  (username-regex        murmur-configuration-username-regex
                         (default #f))
  (text-message-length   murmur-configuration-text-message-length
                         (default 5000))
  (image-message-length  murmur-configuration-image-message-length
                         (default (* 128 1024))) ; 128 Kilobytes
  (cert-required?         murmur-configuration-cert-required?
                          (default #f))
  (remember-channel?     murmur-configuration-remember-channel?
                         (default #f))
  (allow-html?           murmur-configuration-allow-html?
                         (default #f))
  (allow-ping?           murmur-configuration-allow-ping?
                         (default #f))
  (bonjour?              murmur-configuration-bonjour?
                         (default #f))
  (send-version?         murmur-configuration-send-version?
                         (default #f))
  (log-days              murmur-configuration-log-days
                         (default 31))
  (obfuscate-ips?        murmur-obfuscate-ips?
                         (default #t))
  (ssl-cert              murmur-configuration-ssl-cert
                         (default #f))
  (ssl-key               murmur-configuration-ssl-key
                         (default #f))
  (ssl-dh-params         murmur-configuration-ssl-dh-params
                         (default #f))
  (ssl-ciphers           murmur-configuration-ssl-ciphers
                         (default #f))
  (public-registration   murmur-configuration-public-registration
                         (default #f))  ; <murmur-public-registration-configuration>
  (file                  murmur-configuration-file
                         (default #f)))

(define-record-type* <murmur-public-registration-configuration>
  murmur-public-registration-configuration
  make-murmur-public-registration-configuration
  murmur-public-registration-configuration?
  (name         murmur-public-registration-configuration-name)
  (password     murmur-public-registration-configuration-password)
  (url          murmur-public-registration-configuration-url)
  (hostname     murmur-public-registration-configuration-hostname
                (default #f)))

(define (flatten . lst)
  "Return a list that recursively concatenates all sub-lists of LST."
  (define (flatten1 head out)
    (if (list? head)
        (fold-right flatten1 out head)
        (cons head out)))
  (fold-right flatten1 '() lst))

(define (default-murmur-config config)
  (match-record
   config
   <murmur-configuration>
   (user port welcome-text server-password max-users max-user-bandwidth
    database-file log-file pid-file autoban-attempts autoban-timeframe
    autoban-time opus-threshold channel-nesting-limit channelname-regex
    username-regex text-message-length image-message-length cert-required?
    remember-channel? allow-html? allow-ping? bonjour? send-version?
    log-days obfuscate-ips? ssl-cert ssl-key ssl-dh-params ssl-ciphers
    public-registration)
   (apply mixed-text-file "murmur.ini"
          (flatten
           "welcometext=" welcome-text "\n"
           "port=" (number->string port) "\n"
           (if server-password (list "serverpassword=" server-password "\n") '())
           (if max-user-bandwidth (list "bandwidth=" (number->string max-user-bandwidth)) '())
           "users=" (number->string max-users) "\n"
           "uname=" user "\n"
           "database=" database-file "\n"
           "logfile=" log-file "\n"
           "pidfile=" pid-file "\n"
           (if autoban-attempts (list "autobanAttempts=" (number->string autoban-attempts) "\n") '())
           (if autoban-timeframe (list "autobanTimeframe=" (number->string autoban-timeframe) "\n") '())
           (if autoban-time (list "autobanTime=" (number->string autoban-time) "\n") '())
           (if opus-threshold (list "opusthreshold=" (number->string opus-threshold) "\n") '())
           (if channel-nesting-limit (list "channelnestinglimit=" (number->string channel-nesting-limit) "\n") '())
           (if channelname-regex (list "channelname=" channelname-regex "\n") '())
           (if username-regex (list "username=" username-regex "\n") '())
           (if text-message-length (list "textmessagelength=" (number->string text-message-length) "\n") '())
           (if image-message-length (list "imagemessagelength=" (number->string image-message-length) "\n") '())
           (if log-days (list "logdays=" (number->string log-days) "\n") '())
           "obfuscate=" (if obfuscate-ips? "true" "false") "\n"
           "certrequired=" (if cert-required? "true" "false") "\n"
           "rememberchannel=" (if remember-channel? "true" "false") "\n"
           "allowhtml=" (if allow-html? "true" "false") "\n"
           "allowping=" (if allow-ping? "true" "false") "\n"
           "bonjour=" (if bonjour? "true" "false") "\n"
           "sendversion=" (if send-version? "true" "false") "\n"
           (cond ((and ssl-cert ssl-key)
                  (list
                   "sslCert=" ssl-cert "\n"
                   "sslKey=" ssl-key "\n"))
                 ((or ssl-cert ssl-key)
                  (error "ssl-cert and ssl-key must both be set"
                         ssl-cert ssl-key))
                 (else '()))
           (if ssl-dh-params (list "sslDHParams=" ssl-dh-params) '())
           (if ssl-ciphers (list "sslCiphers=" ssl-ciphers) '())

           (match public-registration
             (#f '())
             (($ <murmur-public-registration-configuration>
                 name password url hostname)
              (if (and (or (not server-password) (string-null? server-password))
                       allow-ping?)
                  (list
                   "registerName=" name "\n"
                   "registerPassword=" password "\n"
                   "registerUrl=" url "\n"
                   (if hostname
                       (string-append "registerHostname=" hostname "\n")
                       ""))
                  (error "To publicly register your murmur server your server must be publicy visible
and users must be able to join without a password. To fix this set:
(allow-ping? #t)
(server-password \"\")
Or set public-registration to #f"))))))))

(define (murmur-activation config)
  #~(begin
      (use-modules (guix build utils))
      (let* ((log-dir (dirname #$(murmur-configuration-log-file config)))
             (pid-dir (dirname #$(murmur-configuration-pid-file config)))
             (db-dir (dirname #$(murmur-configuration-database-file config)))
             (user (getpwnam #$(murmur-configuration-user config)))
             (init-dir
              (lambda (name dir)
                (format #t "creating murmur ~a directory '~a'\n" name dir)
                (mkdir-p dir)
                (chown dir (passwd:uid user) (passwd:gid user))
                (chmod dir #o700)))
             (ini #$(or (murmur-configuration-file config)
                        (default-murmur-config config))))
        (init-dir "log" log-dir)
        (init-dir "pid" pid-dir)
        (init-dir "database" db-dir)

        (format #t "murmur: use config file: ~a~%\n" ini)
        (format #t "murmur: to set the SuperUser password run:
    `~a -ini ~a -readsupw`\n"
                #$(file-append (murmur-configuration-package config)
                               "/bin/murmurd") ini)
        #t)))

(define murmur-accounts
  (match-lambda
    (($ <murmur-configuration> _ user group)
     (list
      (user-group
       (name group)
       (system? #t))
      (user-account
       (name user)
       (group group)
       (system? #t)
       (comment "Murmur Daemon")
       (home-directory "/var/empty")
       (shell (file-append shadow "/sbin/nologin")))))))

(define (murmur-shepherd-service config)
  (list (shepherd-service
         (provision '(murmur))
         (documentation "Run the Murmur Mumble server.")
         (requirement '(networking))
         (start #~(make-forkexec-constructor
                   '(#$(file-append (murmur-configuration-package config)
                                    "/bin/murmurd")
                     "-ini"
                     #$(or (murmur-configuration-file config)
                           (default-murmur-config config)))
                   #:pid-file #$(murmur-configuration-pid-file config)))
         (stop #~(make-kill-destructor)))))

(define murmur-service-type
  (service-type (name 'murmur)
                (description
                 "Run the Murmur voice-over-IP (VoIP) server of the Mumble
suite.")
                (extensions
                 (list (service-extension shepherd-root-service-type
                                          murmur-shepherd-service)
                       (service-extension activation-service-type
                                          murmur-activation)
                       (service-extension account-service-type
                                          murmur-accounts)))
                (default-value (murmur-configuration))))