gnu: Add Prosody service.
* gnu/services/messaging.scm: New file. * gnu/services/configuration.scm: New exported procedures. * gnu/local.mk (GNU_SYSTEM_MODULES): Add gnu/services/messaging.scm. * doc/guix.texi (Messaging Services): New section. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
parent
84bf2a2e74
commit
78cef99b98
393
doc/guix.texi
393
doc/guix.texi
|
@ -29,7 +29,8 @@ Copyright @copyright{} 2016 John Darrington@*
|
|||
Copyright @copyright{} 2016 ng0@*
|
||||
Copyright @copyright{} 2016 Jan Nieuwenhuizen@*
|
||||
Copyright @copyright{} 2016 Julien Lepiller@*
|
||||
Copyright @copyright{} 2016 Alex ter Weele
|
||||
Copyright @copyright{} 2016 Alex ter Weele@*
|
||||
Copyright @copyright{} 2017 Clément Lassieur
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
|
@ -204,6 +205,7 @@ Services
|
|||
* Desktop Services:: D-Bus and desktop services.
|
||||
* Database Services:: SQL databases.
|
||||
* Mail Services:: IMAP, POP3, SMTP, and all that.
|
||||
* Messaging Services:: Messaging services.
|
||||
* Kerberos Services:: Kerberos services.
|
||||
* Web Services:: Web servers.
|
||||
* Network File System:: NFS related services.
|
||||
|
@ -8110,6 +8112,7 @@ declaration.
|
|||
* Desktop Services:: D-Bus and desktop services.
|
||||
* Database Services:: SQL databases.
|
||||
* Mail Services:: IMAP, POP3, SMTP, and all that.
|
||||
* Messaging Services:: Messaging services.
|
||||
* Kerberos Services:: Kerberos services.
|
||||
* Web Services:: Web servers.
|
||||
* Network File System:: NFS related services.
|
||||
|
@ -11724,6 +11727,394 @@ remote servers. Run @command{man smtpd.conf} for more information.
|
|||
@end table
|
||||
@end deftp
|
||||
|
||||
@node Messaging Services
|
||||
@subsubsection Messaging Services
|
||||
|
||||
@cindex messaging
|
||||
@cindex jabber
|
||||
@cindex XMPP
|
||||
The @code{(gnu services messaging)} module provides Guix service
|
||||
definitions for messaging services: currently only Prosody is supported.
|
||||
|
||||
@subsubheading Prosody Service
|
||||
|
||||
@deffn {Scheme Variable} prosody-service-type
|
||||
This is the type for the @uref{http://prosody.im, Prosody XMPP
|
||||
communication server}. Its value must be a @code{prosody-configuration}
|
||||
record as in this example:
|
||||
|
||||
@example
|
||||
(service prosody-service-type
|
||||
(prosody-configuration
|
||||
(modules-enabled (cons "groups" %default-modules-enabled))
|
||||
(int-components
|
||||
(list
|
||||
(int-component-configuration
|
||||
(hostname "conference.example.net")
|
||||
(plugin "muc")
|
||||
(mod-muc (mod-muc-configuration)))))
|
||||
(virtualhosts
|
||||
(list
|
||||
(virtualhost-configuration
|
||||
(domain "example.net"))))))
|
||||
@end example
|
||||
|
||||
See below for details about @code{prosody-configuration}.
|
||||
|
||||
@end deffn
|
||||
|
||||
By default, Prosody does not need much configuration. Only one
|
||||
@code{virtualhosts} field is needed: it specifies the domain you wish
|
||||
Prosody to serve.
|
||||
|
||||
Prosodyctl will help you generate X.509 certificates and keys:
|
||||
|
||||
@example
|
||||
prosodyctl cert request example.net
|
||||
@end example
|
||||
|
||||
The available configuration parameters follow. Each parameter
|
||||
definition is preceded by its type; for example, @samp{string-list foo}
|
||||
indicates that the @code{foo} parameter should be specified as a list of
|
||||
strings. Types starting with @code{maybe-} denote parameters that won't
|
||||
show up in @code{prosody.cfg.lua} when their value is @code{'disabled}.
|
||||
|
||||
There is also a way to specify the configuration as a string, if you
|
||||
have an old @code{prosody.cfg.lua} file that you want to port over from
|
||||
some other system; see the end for more details.
|
||||
|
||||
@c The following documentation was initially generated by
|
||||
@c (generate-documentation) in (gnu services messaging). Manually maintained
|
||||
@c documentation is better, so we shouldn't hesitate to edit below as
|
||||
@c needed. However if the change you want to make to this documentation
|
||||
@c can be done in an automated way, it's probably easier to change
|
||||
@c (generate-documentation) than to make it below and have to deal with
|
||||
@c the churn as Prosody updates.
|
||||
|
||||
Available @code{prosody-configuration} fields are:
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} package prosody
|
||||
The Prosody package.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} file-name data-path
|
||||
Location of the Prosody data storage directory. See
|
||||
@url{http://prosody.im/doc/configure}.
|
||||
Defaults to @samp{"/var/lib/prosody"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} file-name-list plugin-paths
|
||||
Additional plugin directories. They are searched in all the specified
|
||||
paths in order. See @url{http://prosody.im/doc/plugins_directory}.
|
||||
Defaults to @samp{()}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} string-list admins
|
||||
This is a list of accounts that are admins for the server. Note that you
|
||||
must create the accounts separately. See @url{http://prosody.im/doc/admins} and
|
||||
@url{http://prosody.im/doc/creating_accounts}.
|
||||
Example: @code{(admins '("user1@@example.com" "user2@@example.net"))}
|
||||
Defaults to @samp{()}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} boolean use-libevent?
|
||||
Enable use of libevent for better performance under high load. See
|
||||
@url{http://prosody.im/doc/libevent}.
|
||||
Defaults to @samp{#f}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} module-list modules-enabled
|
||||
This is the list of modules Prosody will load on startup. It looks for
|
||||
@code{mod_modulename.lua} in the plugins folder, so make sure that exists too.
|
||||
Documentation on modules can be found at: @url{http://prosody.im/doc/modules}.
|
||||
Defaults to @samp{%default-modules-enabled}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} string-list modules-disabled
|
||||
@samp{"offline"}, @samp{"c2s"} and @samp{"s2s"} are auto-loaded, but
|
||||
should you want to disable them then add them to this list.
|
||||
Defaults to @samp{()}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} file-name groups-file
|
||||
Path to a text file where the shared groups are defined. If this path is
|
||||
empty then @samp{mod_groups} does nothing. See
|
||||
@url{http://prosody.im/doc/modules/mod_groups}.
|
||||
Defaults to @samp{"/var/lib/prosody/sharedgroups.txt"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} boolean allow-registration?
|
||||
Disable account creation by default, for security. See
|
||||
@url{http://prosody.im/doc/creating_accounts}.
|
||||
Defaults to @samp{#f}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} maybe-ssl-configuration ssl
|
||||
These are the SSL/TLS-related settings. Most of them are disabled so to
|
||||
use Prosody's defaults. If you do not completely understand these options, do
|
||||
not add them to your config, it is easy to lower the security of your server
|
||||
using them. See @url{http://prosody.im/doc/advanced_ssl_config}.
|
||||
|
||||
Available @code{ssl-configuration} fields are:
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-string protocol
|
||||
This determines what handshake to use.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} file-name key
|
||||
Path to your private key file, relative to @code{/etc/prosody}.
|
||||
Defaults to @samp{"/etc/prosody/certs/key.pem"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} file-name certificate
|
||||
Path to your certificate file, relative to @code{/etc/prosody}.
|
||||
Defaults to @samp{"/etc/prosody/certs/cert.pem"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} file-name capath
|
||||
Path to directory containing root certificates that you wish Prosody to
|
||||
trust when verifying the certificates of remote servers.
|
||||
Defaults to @samp{"/etc/ssl/certs"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-file-name cafile
|
||||
Path to a file containing root certificates that you wish Prosody to trust.
|
||||
Similar to @code{capath} but with all certificates concatenated together.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-string-list verify
|
||||
A list of verification options (these mostly map to OpenSSL's
|
||||
@code{set_verify()} flags).
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-string-list options
|
||||
A list of general options relating to SSL/TLS. These map to OpenSSL's
|
||||
@code{set_options()}. For a full list of options available in LuaSec, see the
|
||||
LuaSec source.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-non-negative-integer depth
|
||||
How long a chain of certificate authorities to check when looking for a
|
||||
trusted root certificate.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-string ciphers
|
||||
An OpenSSL cipher string. This selects what ciphers Prosody will offer to
|
||||
clients, and in what order.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-file-name dhparam
|
||||
A path to a file containing parameters for Diffie-Hellman key exchange. You
|
||||
can create such a file with:
|
||||
@code{openssl dhparam -out /etc/prosody/certs/dh-2048.pem 2048}
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-string curve
|
||||
Curve for Elliptic curve Diffie-Hellman. Prosody's default is
|
||||
@samp{"secp384r1"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-string-list verifyext
|
||||
A list of "extra" verification options.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ssl-configuration} parameter} maybe-string password
|
||||
Password for encrypted private keys.
|
||||
@end deftypevr
|
||||
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} boolean c2s-require-encryption?
|
||||
Whether to force all client-to-server connections to be encrypted or not.
|
||||
See @url{http://prosody.im/doc/modules/mod_tls}.
|
||||
Defaults to @samp{#f}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} boolean s2s-require-encryption?
|
||||
Whether to force all server-to-server connections to be encrypted or not.
|
||||
See @url{http://prosody.im/doc/modules/mod_tls}.
|
||||
Defaults to @samp{#f}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} boolean s2s-secure-auth?
|
||||
Whether to require encryption and certificate authentication. This
|
||||
provides ideal security, but requires servers you communicate with to support
|
||||
encryption AND present valid, trusted certificates. See
|
||||
@url{http://prosody.im/doc/s2s#security}.
|
||||
Defaults to @samp{#f}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} string-list s2s-insecure-domains
|
||||
Many servers don't support encryption or have invalid or self-signed
|
||||
certificates. You can list domains here that will not be required to
|
||||
authenticate using certificates. They will be authenticated using DNS. See
|
||||
@url{http://prosody.im/doc/s2s#security}.
|
||||
Defaults to @samp{()}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} string-list s2s-secure-domains
|
||||
Even if you leave @code{s2s-secure-auth?} disabled, you can still require
|
||||
valid certificates for some domains by specifying a list here. See
|
||||
@url{http://prosody.im/doc/s2s#security}.
|
||||
Defaults to @samp{()}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} string authentication
|
||||
Select the authentication backend to use. The default provider stores
|
||||
passwords in plaintext and uses Prosody's configured data storage to store the
|
||||
authentication data. If you do not trust your server please see
|
||||
@url{http://prosody.im/doc/modules/mod_auth_internal_hashed} for information
|
||||
about using the hashed backend. See also
|
||||
@url{http://prosody.im/doc/authentication}
|
||||
Defaults to @samp{"internal_plain"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} maybe-string log
|
||||
Set logging options. Advanced logging configuration is not yet supported
|
||||
by the GuixSD Prosody Service. See @url{http://prosody.im/doc/logging}.
|
||||
Defaults to @samp{"*syslog"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} file-name pidfile
|
||||
File to write pid in. See @url{http://prosody.im/doc/modules/mod_posix}.
|
||||
Defaults to @samp{"/var/run/prosody/prosody.pid"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} virtualhost-configuration-list virtualhosts
|
||||
A host in Prosody is a domain on which user accounts can be created. For
|
||||
example if you want your users to have addresses like
|
||||
@samp{"john.smith@@example.com"} then you need to add a host
|
||||
@samp{"example.com"}. All options in this list will apply only to this host.
|
||||
|
||||
Note: the name "virtual" host is used in configuration to avoid confusion with
|
||||
the actual physical host that Prosody is installed on. A single Prosody
|
||||
instance can serve many domains, each one defined as a VirtualHost entry in
|
||||
Prosody's configuration. Conversely a server that hosts a single domain would
|
||||
have just one VirtualHost entry.
|
||||
|
||||
See @url{http://prosody.im/doc/configure#virtual_host_settings}.
|
||||
|
||||
Available @code{virtualhost-configuration} fields are:
|
||||
|
||||
all these @code{prosody-configuration} fields: @code{admins}, @code{use-libevent?}, @code{modules-enabled}, @code{modules-disabled}, @code{groups-file}, @code{allow-registration?}, @code{ssl}, @code{c2s-require-encryption?}, @code{s2s-require-encryption?}, @code{s2s-secure-auth?}, @code{s2s-insecure-domains}, @code{s2s-secure-domains}, @code{authentication}, @code{log}, plus:
|
||||
@deftypevr {@code{virtualhost-configuration} parameter} string domain
|
||||
Domain you wish Prosody to serve.
|
||||
@end deftypevr
|
||||
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} int-component-configuration-list int-components
|
||||
Components are extra services on a server which are available to clients,
|
||||
usually on a subdomain of the main server (such as
|
||||
@samp{"mycomponent.example.com"}). Example components might be chatroom
|
||||
servers, user directories, or gateways to other protocols.
|
||||
|
||||
Internal components are implemented with Prosody-specific plugins. To add an
|
||||
internal component, you simply fill the hostname field, and the plugin you wish
|
||||
to use for the component.
|
||||
|
||||
See @url{http://prosody.im/doc/components}.
|
||||
Defaults to @samp{()}.
|
||||
|
||||
Available @code{int-component-configuration} fields are:
|
||||
|
||||
all these @code{prosody-configuration} fields: @code{admins}, @code{use-libevent?}, @code{modules-enabled}, @code{modules-disabled}, @code{groups-file}, @code{allow-registration?}, @code{ssl}, @code{c2s-require-encryption?}, @code{s2s-require-encryption?}, @code{s2s-secure-auth?}, @code{s2s-insecure-domains}, @code{s2s-secure-domains}, @code{authentication}, @code{log}, plus:
|
||||
@deftypevr {@code{int-component-configuration} parameter} string hostname
|
||||
Hostname of the component.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{int-component-configuration} parameter} string plugin
|
||||
Plugin you wish to use for the component.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{int-component-configuration} parameter} maybe-mod-muc-configuration mod-muc
|
||||
Multi-user chat (MUC) is Prosody's module for allowing you to create
|
||||
hosted chatrooms/conferences for XMPP users.
|
||||
|
||||
General information on setting up and using multi-user chatrooms can be found
|
||||
in the "Chatrooms" documentation (@url{http://prosody.im/doc/chatrooms}),
|
||||
which you should read if you are new to XMPP chatrooms.
|
||||
|
||||
See also @url{http://prosody.im/doc/modules/mod_muc}.
|
||||
|
||||
Available @code{mod-muc-configuration} fields are:
|
||||
|
||||
@deftypevr {@code{mod-muc-configuration} parameter} string name
|
||||
The name to return in service discovery responses.
|
||||
Defaults to @samp{"Prosody Chatrooms"}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{mod-muc-configuration} parameter} string-or-boolean restrict-room-creation
|
||||
If @samp{#t}, this will only allow admins to create new chatrooms.
|
||||
Otherwise anyone can create a room. The value @samp{"local"} restricts room
|
||||
creation to users on the service's parent domain. E.g. @samp{user@@example.com}
|
||||
can create rooms on @samp{rooms.example.com}. The value @samp{"admin"}
|
||||
restricts to service administrators only.
|
||||
Defaults to @samp{#f}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{mod-muc-configuration} parameter} non-negative-integer max-history-messages
|
||||
Maximum number of history messages that will be sent to the member that has
|
||||
just joined the room.
|
||||
Defaults to @samp{20}.
|
||||
@end deftypevr
|
||||
|
||||
@end deftypevr
|
||||
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} ext-component-configuration-list ext-components
|
||||
External components use XEP-0114, which most standalone components
|
||||
support. To add an external component, you simply fill the hostname field. See
|
||||
@url{http://prosody.im/doc/components}.
|
||||
Defaults to @samp{()}.
|
||||
|
||||
Available @code{ext-component-configuration} fields are:
|
||||
|
||||
all these @code{prosody-configuration} fields: @code{admins}, @code{use-libevent?}, @code{modules-enabled}, @code{modules-disabled}, @code{groups-file}, @code{allow-registration?}, @code{ssl}, @code{c2s-require-encryption?}, @code{s2s-require-encryption?}, @code{s2s-secure-auth?}, @code{s2s-insecure-domains}, @code{s2s-secure-domains}, @code{authentication}, @code{log}, plus:
|
||||
@deftypevr {@code{ext-component-configuration} parameter} string component-secret
|
||||
Password which the component will use to log in.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{ext-component-configuration} parameter} string hostname
|
||||
Hostname of the component.
|
||||
@end deftypevr
|
||||
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} non-negative-integer-list component-ports
|
||||
Port(s) Prosody listens on for component connections.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{prosody-configuration} parameter} string component-interface
|
||||
Interface Prosody listens on for component connections.
|
||||
Defaults to @samp{"127.0.0.1"}.
|
||||
@end deftypevr
|
||||
|
||||
It could be that you just want to get a @code{prosody.cfg.lua}
|
||||
up and running. In that case, you can pass an
|
||||
@code{opaque-prosody-configuration} record as the value of
|
||||
@code{prosody-service-type}. As its name indicates, an opaque configuration
|
||||
does not have easy reflective capabilities.
|
||||
Available @code{opaque-prosody-configuration} fields are:
|
||||
|
||||
@deftypevr {@code{opaque-prosody-configuration} parameter} package prosody
|
||||
The prosody package.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr {@code{opaque-prosody-configuration} parameter} string prosody.cfg.lua
|
||||
The contents of the @code{prosody.cfg.lua} to use.
|
||||
@end deftypevr
|
||||
|
||||
For example, if your @code{prosody.cfg.lua} is just the empty
|
||||
string, you could instantiate a prosody service like this:
|
||||
|
||||
@example
|
||||
(service prosody-service-type
|
||||
(opaque-prosody-configuration
|
||||
(prosody.cfg.lua "")))
|
||||
@end example
|
||||
|
||||
@node Kerberos Services
|
||||
@subsubsection Kerberos Services
|
||||
@cindex Kerberos
|
||||
|
|
|
@ -414,6 +414,7 @@ GNU_SYSTEM_MODULES = \
|
|||
%D%/services/lirc.scm \
|
||||
%D%/services/mail.scm \
|
||||
%D%/services/mcron.scm \
|
||||
%D%/services/messaging.scm \
|
||||
%D%/services/networking.scm \
|
||||
%D%/services/nfs.scm \
|
||||
%D%/services/shepherd.scm \
|
||||
|
|
|
@ -28,10 +28,13 @@
|
|||
#:use-module (srfi srfi-35)
|
||||
#:export (configuration-field
|
||||
configuration-field-name
|
||||
configuration-field-type
|
||||
configuration-missing-field
|
||||
configuration-field-error
|
||||
configuration-field-serializer
|
||||
configuration-field-getter
|
||||
configuration-field-default-value-thunk
|
||||
configuration-field-documentation
|
||||
serialize-configuration
|
||||
define-configuration
|
||||
validate-configuration
|
||||
|
|
|
@ -0,0 +1,726 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>
|
||||
;;;
|
||||
;;; 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 messaging)
|
||||
#:use-module (gnu packages messaging)
|
||||
#:use-module (gnu packages admin)
|
||||
#:use-module (gnu services)
|
||||
#:use-module (gnu services shepherd)
|
||||
#:use-module (gnu services configuration)
|
||||
#:use-module (gnu system shadow)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix packages)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-35)
|
||||
#:use-module (ice-9 match)
|
||||
#:export (prosody-service-type
|
||||
prosody-configuration
|
||||
opaque-prosody-configuration
|
||||
|
||||
virtualhost-configuration
|
||||
int-component-configuration
|
||||
ext-component-configuration
|
||||
|
||||
mod-muc-configuration
|
||||
ssl-configuration
|
||||
|
||||
%default-modules-enabled))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
;;; Messaging services.
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(define (id ctx . parts)
|
||||
(datum->syntax ctx (apply symbol-append (map syntax->datum parts))))
|
||||
|
||||
(define-syntax define-maybe
|
||||
(lambda (x)
|
||||
(syntax-case x ()
|
||||
((_ stem)
|
||||
(with-syntax
|
||||
((stem? (id #'stem #'stem #'?))
|
||||
(maybe-stem? (id #'stem #'maybe- #'stem #'?))
|
||||
(serialize-stem (id #'stem #'serialize- #'stem))
|
||||
(serialize-maybe-stem (id #'stem #'serialize-maybe- #'stem)))
|
||||
#'(begin
|
||||
(define (maybe-stem? val)
|
||||
(or (eq? val 'disabled) (stem? val)))
|
||||
(define (serialize-maybe-stem field-name val)
|
||||
(when (stem? val) (serialize-stem field-name val)))))))))
|
||||
|
||||
(define-syntax define-all-configurations
|
||||
(lambda (stx)
|
||||
(define (make-pred arg)
|
||||
(lambda (field target)
|
||||
(and (memq (syntax->datum target) `(common ,arg)) field)))
|
||||
(syntax-case stx ()
|
||||
((_ stem (field (field-type def) doc target) ...)
|
||||
(with-syntax (((new-field-type ...)
|
||||
(map (lambda (field-type target)
|
||||
(if (and (eq? 'common (syntax->datum target))
|
||||
(not (string-prefix?
|
||||
"maybe-"
|
||||
(symbol->string
|
||||
(syntax->datum field-type)))))
|
||||
(id #'stem #'maybe- field-type) field-type))
|
||||
#'(field-type ...) #'(target ...)))
|
||||
((new-def ...)
|
||||
(map (lambda (def target)
|
||||
(if (eq? 'common (syntax->datum target))
|
||||
#''disabled def))
|
||||
#'(def ...) #'(target ...)))
|
||||
((new-doc ...)
|
||||
(map (lambda (doc target)
|
||||
(if (eq? 'common (syntax->datum target))
|
||||
"" doc))
|
||||
#'(doc ...) #'(target ...))))
|
||||
#`(begin
|
||||
(define common-fields
|
||||
'(#,@(filter-map (make-pred #f) #'(field ...) #'(target ...))))
|
||||
(define-configuration prosody-configuration
|
||||
#,@(filter-map (make-pred 'global)
|
||||
#'((field (field-type def) doc) ...)
|
||||
#'(target ...)))
|
||||
(define-configuration virtualhost-configuration
|
||||
#,@(filter-map (make-pred 'virtualhost)
|
||||
#'((field (new-field-type new-def) new-doc) ...)
|
||||
#'(target ...)))
|
||||
(define-configuration int-component-configuration
|
||||
#,@(filter-map (make-pred 'int-component)
|
||||
#'((field (new-field-type new-def) new-doc) ...)
|
||||
#'(target ...)))
|
||||
(define-configuration ext-component-configuration
|
||||
#,@(filter-map (make-pred 'ext-component)
|
||||
#'((field (new-field-type new-def) new-doc) ...)
|
||||
#'(target ...)))))))))
|
||||
|
||||
(define (uglify-field-name field-name)
|
||||
(let ((str (symbol->string field-name)))
|
||||
(string-join (string-split (if (string-suffix? "?" str)
|
||||
(substring str 0 (1- (string-length str)))
|
||||
str)
|
||||
#\-)
|
||||
"_")))
|
||||
|
||||
(define (serialize-field field-name val)
|
||||
(format #t "~a = ~a;\n" (uglify-field-name field-name) val))
|
||||
(define (serialize-field-list field-name val)
|
||||
(serialize-field field-name
|
||||
(with-output-to-string
|
||||
(lambda ()
|
||||
(format #t "{\n")
|
||||
(for-each (lambda (x)
|
||||
(format #t "~a;\n" x))
|
||||
val)
|
||||
(format #t "}")))))
|
||||
|
||||
(define (serialize-boolean field-name val)
|
||||
(serialize-field field-name (if val "true" "false")))
|
||||
(define-maybe boolean)
|
||||
|
||||
(define (string-or-boolean? val)
|
||||
(or (string? val) (boolean? val)))
|
||||
(define (serialize-string-or-boolean field-name val)
|
||||
(if (string? val)
|
||||
(serialize-string field-name val)
|
||||
(serialize-boolean field-name val)))
|
||||
|
||||
(define (non-negative-integer? val)
|
||||
(and (exact-integer? val) (not (negative? val))))
|
||||
(define (serialize-non-negative-integer field-name val)
|
||||
(serialize-field field-name val))
|
||||
(define-maybe non-negative-integer)
|
||||
|
||||
(define (non-negative-integer-list? val)
|
||||
(and (list? val) (and-map non-negative-integer? val)))
|
||||
(define (serialize-non-negative-integer-list field-name val)
|
||||
(serialize-field-list field-name val))
|
||||
(define-maybe non-negative-integer-list)
|
||||
|
||||
(define (enclose-quotes s)
|
||||
(format #f "\"~a\"" s))
|
||||
(define (serialize-string field-name val)
|
||||
(serialize-field field-name (enclose-quotes val)))
|
||||
(define-maybe string)
|
||||
|
||||
(define (string-list? val)
|
||||
(and (list? val)
|
||||
(and-map (lambda (x)
|
||||
(and (string? x) (not (string-index x #\,))))
|
||||
val)))
|
||||
(define (serialize-string-list field-name val)
|
||||
(serialize-field-list field-name (map enclose-quotes val)))
|
||||
(define-maybe string-list)
|
||||
|
||||
(define (module-list? val)
|
||||
(string-list? val))
|
||||
(define (serialize-module-list field-name val)
|
||||
(serialize-string-list field-name (cons "posix" val)))
|
||||
(define-maybe module-list)
|
||||
|
||||
(define (file-name? val)
|
||||
(and (string? val)
|
||||
(string-prefix? "/" val)))
|
||||
(define (serialize-file-name field-name val)
|
||||
(serialize-string field-name val))
|
||||
(define-maybe file-name)
|
||||
|
||||
(define (file-name-list? val)
|
||||
(and (list? val) (and-map file-name? val)))
|
||||
(define (serialize-file-name-list field-name val)
|
||||
(serialize-string-list field-name val))
|
||||
(define-maybe file-name)
|
||||
|
||||
(define-configuration mod-muc-configuration
|
||||
(name
|
||||
(string "Prosody Chatrooms")
|
||||
"The name to return in service discovery responses.")
|
||||
|
||||
(restrict-room-creation
|
||||
(string-or-boolean #f)
|
||||
"If @samp{#t}, this will only allow admins to create new chatrooms.
|
||||
Otherwise anyone can create a room. The value @samp{\"local\"} restricts room
|
||||
creation to users on the service's parent domain. E.g. @samp{user@@example.com}
|
||||
can create rooms on @samp{rooms.example.com}. The value @samp{\"admin\"}
|
||||
restricts to service administrators only.")
|
||||
|
||||
(max-history-messages
|
||||
(non-negative-integer 20)
|
||||
"Maximum number of history messages that will be sent to the member that has
|
||||
just joined the room."))
|
||||
(define (serialize-mod-muc-configuration field-name val)
|
||||
(serialize-configuration val mod-muc-configuration-fields))
|
||||
(define-maybe mod-muc-configuration)
|
||||
|
||||
(define-configuration ssl-configuration
|
||||
(protocol
|
||||
(maybe-string 'disabled)
|
||||
"This determines what handshake to use.")
|
||||
|
||||
(key
|
||||
(file-name "/etc/prosody/certs/key.pem")
|
||||
"Path to your private key file, relative to @code{/etc/prosody}.")
|
||||
|
||||
(certificate
|
||||
(file-name "/etc/prosody/certs/cert.pem")
|
||||
"Path to your certificate file, relative to @code{/etc/prosody}.")
|
||||
|
||||
(capath
|
||||
(file-name "/etc/ssl/certs")
|
||||
"Path to directory containing root certificates that you wish Prosody to
|
||||
trust when verifying the certificates of remote servers.")
|
||||
|
||||
(cafile
|
||||
(maybe-file-name 'disabled)
|
||||
"Path to a file containing root certificates that you wish Prosody to trust.
|
||||
Similar to @code{capath} but with all certificates concatenated together.")
|
||||
|
||||
(verify
|
||||
(maybe-string-list 'disabled)
|
||||
"A list of verification options (these mostly map to OpenSSL's
|
||||
@code{set_verify()} flags).")
|
||||
|
||||
(options
|
||||
(maybe-string-list 'disabled)
|
||||
"A list of general options relating to SSL/TLS. These map to OpenSSL's
|
||||
@code{set_options()}. For a full list of options available in LuaSec, see the
|
||||
LuaSec source.")
|
||||
|
||||
(depth
|
||||
(maybe-non-negative-integer 'disabled)
|
||||
"How long a chain of certificate authorities to check when looking for a
|
||||
trusted root certificate.")
|
||||
|
||||
(ciphers
|
||||
(maybe-string 'disabled)
|
||||
"An OpenSSL cipher string. This selects what ciphers Prosody will offer to
|
||||
clients, and in what order.")
|
||||
|
||||
(dhparam
|
||||
(maybe-file-name 'disabled)
|
||||
"A path to a file containing parameters for Diffie-Hellman key exchange. You
|
||||
can create such a file with:
|
||||
@code{openssl dhparam -out /etc/prosody/certs/dh-2048.pem 2048}")
|
||||
|
||||
(curve
|
||||
(maybe-string 'disabled)
|
||||
"Curve for Elliptic curve Diffie-Hellman. Prosody's default is
|
||||
@samp{\"secp384r1\"}.")
|
||||
|
||||
(verifyext
|
||||
(maybe-string-list 'disabled)
|
||||
"A list of \"extra\" verification options.")
|
||||
|
||||
(password
|
||||
(maybe-string 'disabled)
|
||||
"Password for encrypted private keys."))
|
||||
(define (serialize-ssl-configuration field-name val)
|
||||
(format #t "ssl = {\n")
|
||||
(serialize-configuration val ssl-configuration-fields)
|
||||
(format #t "};\n"))
|
||||
(define-maybe ssl-configuration)
|
||||
|
||||
(define %default-modules-enabled
|
||||
'("roster"
|
||||
"saslauth"
|
||||
"tls"
|
||||
"dialback"
|
||||
"disco"
|
||||
"private"
|
||||
"vcard"
|
||||
"version"
|
||||
"uptime"
|
||||
"time"
|
||||
"ping"
|
||||
"pep"
|
||||
"register"
|
||||
"admin_adhoc"))
|
||||
|
||||
;; Guile bug. Use begin wrapper, because otherwise virtualhost-configuration
|
||||
;; is assumed to be a function. See
|
||||
;; https://www.gnu.org/software/guile/manual/html_node/R6RS-Incompatibilities.html
|
||||
(begin
|
||||
(define (virtualhost-configuration-list? val)
|
||||
(and (list? val) (and-map virtualhost-configuration? val)))
|
||||
(define (serialize-virtualhost-configuration-list l)
|
||||
(for-each
|
||||
(lambda (val) (serialize-virtualhost-configuration val)) l))
|
||||
|
||||
(define (int-component-configuration-list? val)
|
||||
(and (list? val) (and-map int-component-configuration? val)))
|
||||
(define (serialize-int-component-configuration-list l)
|
||||
(for-each
|
||||
(lambda (val) (serialize-int-component-configuration val)) l))
|
||||
|
||||
(define (ext-component-configuration-list? val)
|
||||
(and (list? val) (and-map ext-component-configuration? val)))
|
||||
(define (serialize-ext-component-configuration-list l)
|
||||
(for-each
|
||||
(lambda (val) (serialize-ext-component-configuration val)) l))
|
||||
|
||||
(define-all-configurations prosody-configuration
|
||||
(prosody
|
||||
(package prosody)
|
||||
"The Prosody package."
|
||||
global)
|
||||
|
||||
(data-path
|
||||
(file-name "/var/lib/prosody")
|
||||
"Location of the Prosody data storage directory. See
|
||||
@url{http://prosody.im/doc/configure}."
|
||||
global)
|
||||
|
||||
(plugin-paths
|
||||
(file-name-list '())
|
||||
"Additional plugin directories. They are searched in all the specified
|
||||
paths in order. See @url{http://prosody.im/doc/plugins_directory}."
|
||||
global)
|
||||
|
||||
(admins
|
||||
(string-list '())
|
||||
"This is a list of accounts that are admins for the server. Note that you
|
||||
must create the accounts separately. See @url{http://prosody.im/doc/admins} and
|
||||
@url{http://prosody.im/doc/creating_accounts}.
|
||||
Example: @code{(admins '(\"user1@@example.com\" \"user2@@example.net\"))}"
|
||||
common)
|
||||
|
||||
(use-libevent?
|
||||
(boolean #f)
|
||||
"Enable use of libevent for better performance under high load. See
|
||||
@url{http://prosody.im/doc/libevent}."
|
||||
common)
|
||||
|
||||
(modules-enabled
|
||||
(module-list %default-modules-enabled)
|
||||
"This is the list of modules Prosody will load on startup. It looks for
|
||||
@code{mod_modulename.lua} in the plugins folder, so make sure that exists too.
|
||||
Documentation on modules can be found at: @url{http://prosody.im/doc/modules}.
|
||||
Defaults to @samp{%default-modules-enabled}."
|
||||
common)
|
||||
|
||||
(modules-disabled
|
||||
(string-list '())
|
||||
"@samp{\"offline\"}, @samp{\"c2s\"} and @samp{\"s2s\"} are auto-loaded, but
|
||||
should you want to disable them then add them to this list."
|
||||
common)
|
||||
|
||||
(groups-file
|
||||
(file-name "/var/lib/prosody/sharedgroups.txt")
|
||||
"Path to a text file where the shared groups are defined. If this path is
|
||||
empty then @samp{mod_groups} does nothing. See
|
||||
@url{http://prosody.im/doc/modules/mod_groups}."
|
||||
common)
|
||||
|
||||
(allow-registration?
|
||||
(boolean #f)
|
||||
"Disable account creation by default, for security. See
|
||||
@url{http://prosody.im/doc/creating_accounts}."
|
||||
common)
|
||||
|
||||
(ssl
|
||||
(maybe-ssl-configuration (ssl-configuration))
|
||||
"These are the SSL/TLS-related settings. Most of them are disabled so to
|
||||
use Prosody's defaults. If you do not completely understand these options, do
|
||||
not add them to your config, it is easy to lower the security of your server
|
||||
using them. See @url{http://prosody.im/doc/advanced_ssl_config}."
|
||||
common)
|
||||
|
||||
(c2s-require-encryption?
|
||||
(boolean #f)
|
||||
"Whether to force all client-to-server connections to be encrypted or not.
|
||||
See @url{http://prosody.im/doc/modules/mod_tls}."
|
||||
common)
|
||||
|
||||
(s2s-require-encryption?
|
||||
(boolean #f)
|
||||
"Whether to force all server-to-server connections to be encrypted or not.
|
||||
See @url{http://prosody.im/doc/modules/mod_tls}."
|
||||
common)
|
||||
|
||||
(s2s-secure-auth?
|
||||
(boolean #f)
|
||||
"Whether to require encryption and certificate authentication. This
|
||||
provides ideal security, but requires servers you communicate with to support
|
||||
encryption AND present valid, trusted certificates. See
|
||||
@url{http://prosody.im/doc/s2s#security}."
|
||||
common)
|
||||
|
||||
(s2s-insecure-domains
|
||||
(string-list '())
|
||||
"Many servers don't support encryption or have invalid or self-signed
|
||||
certificates. You can list domains here that will not be required to
|
||||
authenticate using certificates. They will be authenticated using DNS. See
|
||||
@url{http://prosody.im/doc/s2s#security}."
|
||||
common)
|
||||
|
||||
(s2s-secure-domains
|
||||
(string-list '())
|
||||
"Even if you leave @code{s2s-secure-auth?} disabled, you can still require
|
||||
valid certificates for some domains by specifying a list here. See
|
||||
@url{http://prosody.im/doc/s2s#security}."
|
||||
common)
|
||||
|
||||
(authentication
|
||||
(string "internal_plain")
|
||||
"Select the authentication backend to use. The default provider stores
|
||||
passwords in plaintext and uses Prosody's configured data storage to store the
|
||||
authentication data. If you do not trust your server please see
|
||||
@url{http://prosody.im/doc/modules/mod_auth_internal_hashed} for information
|
||||
about using the hashed backend. See also
|
||||
@url{http://prosody.im/doc/authentication}"
|
||||
common)
|
||||
|
||||
;; TODO: Handle more complicated log structures.
|
||||
(log
|
||||
(maybe-string "*syslog")
|
||||
"Set logging options. Advanced logging configuration is not yet supported
|
||||
by the GuixSD Prosody Service. See @url{http://prosody.im/doc/logging}."
|
||||
common)
|
||||
|
||||
(pidfile
|
||||
(file-name "/var/run/prosody/prosody.pid")
|
||||
"File to write pid in. See @url{http://prosody.im/doc/modules/mod_posix}."
|
||||
global)
|
||||
|
||||
(virtualhosts
|
||||
(virtualhost-configuration-list
|
||||
(list (virtualhost-configuration
|
||||
(domain "localhost"))))
|
||||
"A host in Prosody is a domain on which user accounts can be created. For
|
||||
example if you want your users to have addresses like
|
||||
@samp{\"john.smith@@example.com\"} then you need to add a host
|
||||
@samp{\"example.com\"}. All options in this list will apply only to this host.
|
||||
|
||||
Note: the name \"virtual\" host is used in configuration to avoid confusion with
|
||||
the actual physical host that Prosody is installed on. A single Prosody
|
||||
instance can serve many domains, each one defined as a VirtualHost entry in
|
||||
Prosody's configuration. Conversely a server that hosts a single domain would
|
||||
have just one VirtualHost entry.
|
||||
|
||||
See @url{http://prosody.im/doc/configure#virtual_host_settings}."
|
||||
global)
|
||||
|
||||
(int-components
|
||||
(int-component-configuration-list '())
|
||||
"Components are extra services on a server which are available to clients,
|
||||
usually on a subdomain of the main server (such as
|
||||
@samp{\"mycomponent.example.com\"}). Example components might be chatroom
|
||||
servers, user directories, or gateways to other protocols.
|
||||
|
||||
Internal components are implemented with Prosody-specific plugins. To add an
|
||||
internal component, you simply fill the hostname field, and the plugin you wish
|
||||
to use for the component.
|
||||
|
||||
See @url{http://prosody.im/doc/components}."
|
||||
global)
|
||||
|
||||
(ext-components
|
||||
(ext-component-configuration-list '())
|
||||
"External components use XEP-0114, which most standalone components
|
||||
support. To add an external component, you simply fill the hostname field. See
|
||||
@url{http://prosody.im/doc/components}."
|
||||
global)
|
||||
|
||||
(component-secret
|
||||
(string (configuration-missing-field 'ext-component 'component-secret))
|
||||
"Password which the component will use to log in."
|
||||
ext-component)
|
||||
|
||||
(component-ports
|
||||
(non-negative-integer-list '(5347))
|
||||
"Port(s) Prosody listens on for component connections."
|
||||
global)
|
||||
|
||||
(component-interface
|
||||
(string "127.0.0.1")
|
||||
"Interface Prosody listens on for component connections."
|
||||
global)
|
||||
|
||||
(domain
|
||||
(string (configuration-missing-field 'virtualhost 'domain))
|
||||
"Domain you wish Prosody to serve."
|
||||
virtualhost)
|
||||
|
||||
(hostname
|
||||
(string (configuration-missing-field 'int-component 'hostname))
|
||||
"Hostname of the component."
|
||||
int-component)
|
||||
|
||||
(plugin
|
||||
(string (configuration-missing-field 'int-component 'plugin))
|
||||
"Plugin you wish to use for the component."
|
||||
int-component)
|
||||
|
||||
(mod-muc
|
||||
(maybe-mod-muc-configuration 'disabled)
|
||||
"Multi-user chat (MUC) is Prosody's module for allowing you to create
|
||||
hosted chatrooms/conferences for XMPP users.
|
||||
|
||||
General information on setting up and using multi-user chatrooms can be found
|
||||
in the \"Chatrooms\" documentation (@url{http://prosody.im/doc/chatrooms}),
|
||||
which you should read if you are new to XMPP chatrooms.
|
||||
|
||||
See also @url{http://prosody.im/doc/modules/mod_muc}."
|
||||
int-component)
|
||||
|
||||
(hostname
|
||||
(string (configuration-missing-field 'ext-component 'hostname))
|
||||
"Hostname of the component."
|
||||
ext-component)))
|
||||
|
||||
;; Serialize Virtualhost line first.
|
||||
(define (serialize-virtualhost-configuration config)
|
||||
(define (rest? field)
|
||||
(not (memq (configuration-field-name field)
|
||||
'(domain))))
|
||||
(let ((domain (virtualhost-configuration-domain config))
|
||||
(rest (filter rest? virtualhost-configuration-fields)))
|
||||
(format #t "VirtualHost \"~a\"\n" domain)
|
||||
(serialize-configuration config rest)))
|
||||
|
||||
;; Serialize Component line first.
|
||||
(define (serialize-int-component-configuration config)
|
||||
(define (rest? field)
|
||||
(not (memq (configuration-field-name field)
|
||||
'(hostname plugin))))
|
||||
(let ((hostname (int-component-configuration-hostname config))
|
||||
(plugin (int-component-configuration-plugin config))
|
||||
(rest (filter rest? int-component-configuration-fields)))
|
||||
(format #t "Component \"~a\" \"~a\"\n" hostname plugin)
|
||||
(serialize-configuration config rest)))
|
||||
|
||||
;; Serialize Component line first.
|
||||
(define (serialize-ext-component-configuration config)
|
||||
(define (rest? field)
|
||||
(not (memq (configuration-field-name field)
|
||||
'(hostname))))
|
||||
(let ((hostname (ext-component-configuration-hostname config))
|
||||
(rest (filter rest? ext-component-configuration-fields)))
|
||||
(format #t "Component \"~a\"\n" hostname)
|
||||
(serialize-configuration config rest)))
|
||||
|
||||
;; Serialize virtualhosts and components last.
|
||||
(define (serialize-prosody-configuration config)
|
||||
(define (rest? field)
|
||||
(not (memq (configuration-field-name field)
|
||||
'(virtualhosts int-components ext-components))))
|
||||
(let ((rest (filter rest? prosody-configuration-fields)))
|
||||
(serialize-configuration config rest))
|
||||
(serialize-virtualhost-configuration-list
|
||||
(prosody-configuration-virtualhosts config))
|
||||
(serialize-int-component-configuration-list
|
||||
(prosody-configuration-int-components config))
|
||||
(serialize-ext-component-configuration-list
|
||||
(prosody-configuration-ext-components config)))
|
||||
|
||||
(define-configuration opaque-prosody-configuration
|
||||
(prosody
|
||||
(package prosody)
|
||||
"The prosody package.")
|
||||
|
||||
(prosody.cfg.lua
|
||||
(string (configuration-missing-field 'opaque-prosody-configuration
|
||||
'prosody.cfg.lua))
|
||||
"The contents of the @code{prosody.cfg.lua} to use."))
|
||||
|
||||
(define (prosody-shepherd-service config)
|
||||
"Return a <shepherd-service> for Prosody with CONFIG."
|
||||
(let* ((prosody (if (opaque-prosody-configuration? config)
|
||||
(opaque-prosody-configuration-prosody config)
|
||||
(prosody-configuration-prosody config)))
|
||||
(prosodyctl-bin (file-append prosody "/bin/prosodyctl"))
|
||||
(prosodyctl-action (lambda args
|
||||
#~(lambda _
|
||||
(zero? (system* #$prosodyctl-bin #$@args))))))
|
||||
(list (shepherd-service
|
||||
(documentation "Run the Prosody XMPP server")
|
||||
(provision '(prosody))
|
||||
(requirement '(networking syslogd user-processes))
|
||||
(start (prosodyctl-action "start"))
|
||||
(stop (prosodyctl-action "stop"))))))
|
||||
|
||||
(define %prosody-accounts
|
||||
(list (user-group (name "prosody") (system? #t))
|
||||
(user-account
|
||||
(name "prosody")
|
||||
(group "prosody")
|
||||
(system? #t)
|
||||
(comment "Prosody daemon user")
|
||||
(home-directory "/var/empty")
|
||||
(shell (file-append shadow "/sbin/nologin")))))
|
||||
|
||||
(define (prosody-activation config)
|
||||
"Return the activation gexp for CONFIG."
|
||||
(let* ((config-dir "/etc/prosody")
|
||||
(default-certs-dir "/etc/prosody/certs")
|
||||
(data-path (prosody-configuration-data-path config))
|
||||
(pidfile-dir (dirname (prosody-configuration-pidfile config)))
|
||||
(config-str
|
||||
(if (opaque-prosody-configuration? config)
|
||||
(opaque-prosody-configuration-prosody.cfg.lua config)
|
||||
(with-output-to-string
|
||||
(lambda ()
|
||||
(serialize-prosody-configuration config)))))
|
||||
(config-file (plain-file "prosody.cfg.lua" config-str)))
|
||||
#~(begin
|
||||
(define %user (getpw "prosody"))
|
||||
|
||||
(mkdir-p #$config-dir)
|
||||
(chown #$config-dir (passwd:uid %user) (passwd:gid %user))
|
||||
(copy-file #$config-file (string-append #$config-dir
|
||||
"/prosody.cfg.lua"))
|
||||
|
||||
(mkdir-p #$default-certs-dir)
|
||||
(chown #$default-certs-dir (passwd:uid %user) (passwd:gid %user))
|
||||
(chmod #$default-certs-dir #o750)
|
||||
|
||||
(mkdir-p #$data-path)
|
||||
(chown #$data-path (passwd:uid %user) (passwd:gid %user))
|
||||
(chmod #$data-path #o750)
|
||||
|
||||
(mkdir-p #$pidfile-dir)
|
||||
(chown #$pidfile-dir (passwd:uid %user) (passwd:gid %user)))))
|
||||
|
||||
(define prosody-service-type
|
||||
(service-type (name 'prosody)
|
||||
(extensions
|
||||
(list (service-extension shepherd-root-service-type
|
||||
prosody-shepherd-service)
|
||||
(service-extension account-service-type
|
||||
(const %prosody-accounts))
|
||||
(service-extension activation-service-type
|
||||
prosody-activation)))))
|
||||
|
||||
;; A little helper to make it easier to document all those fields.
|
||||
(define (generate-documentation)
|
||||
(define documentation
|
||||
`((prosody-configuration
|
||||
,prosody-configuration-fields
|
||||
(ssl ssl-configuration)
|
||||
(virtualhosts virtualhost-configuration)
|
||||
(int-components int-component-configuration)
|
||||
(ext-components ext-component-configuration))
|
||||
(ssl-configuration ,ssl-configuration-fields)
|
||||
(int-component-configuration ,int-component-configuration-fields
|
||||
(mod-muc mod-muc-configuration))
|
||||
(ext-component-configuration ,ext-component-configuration-fields)
|
||||
(mod-muc-configuration ,mod-muc-configuration-fields)
|
||||
(virtualhost-configuration ,virtualhost-configuration-fields)
|
||||
(opaque-prosody-configuration ,opaque-prosody-configuration-fields)))
|
||||
(define (generate configuration-name)
|
||||
(match (assq-ref documentation configuration-name)
|
||||
((fields . sub-documentation)
|
||||
(format #t "\nAvailable @code{~a} fields are:\n\n" configuration-name)
|
||||
(when (memq configuration-name
|
||||
'(virtualhost-configuration
|
||||
int-component-configuration
|
||||
ext-component-configuration))
|
||||
(format #t "all these @code{prosody-configuration} fields: ~a, plus:\n"
|
||||
(string-join (map (lambda (s)
|
||||
(format #f "@code{~a}" s)) common-fields)
|
||||
", ")))
|
||||
(for-each
|
||||
(lambda (f)
|
||||
(let ((field-name (configuration-field-name f))
|
||||
(field-type (configuration-field-type f))
|
||||
(field-docs (string-trim-both
|
||||
(configuration-field-documentation f)))
|
||||
(default (catch #t
|
||||
(configuration-field-default-value-thunk f)
|
||||
(lambda _ 'nope))))
|
||||
(define (escape-chars str chars escape)
|
||||
(with-output-to-string
|
||||
(lambda ()
|
||||
(string-for-each (lambda (c)
|
||||
(when (char-set-contains? chars c)
|
||||
(display escape))
|
||||
(display c))
|
||||
str))))
|
||||
(define (show-default? val)
|
||||
(or (string? default) (number? default) (boolean? default)
|
||||
(and (list? val) (and-map show-default? val))))
|
||||
(format #t "@deftypevr {@code{~a} parameter} ~a ~a\n~a\n"
|
||||
configuration-name field-type field-name field-docs)
|
||||
(when (show-default? default)
|
||||
(format #t "Defaults to @samp{~a}.\n"
|
||||
(escape-chars (format #f "~s" default)
|
||||
(char-set #\@ #\{ #\})
|
||||
#\@)))
|
||||
(for-each generate (or (assq-ref sub-documentation field-name) '()))
|
||||
(format #t "@end deftypevr\n\n")))
|
||||
(filter (lambda (f)
|
||||
(not (string=? "" (configuration-field-documentation f))))
|
||||
fields)))))
|
||||
(generate 'prosody-configuration)
|
||||
(format #t "It could be that you just want to get a @code{prosody.cfg.lua}
|
||||
up and running. In that case, you can pass an
|
||||
@code{opaque-prosody-configuration} record as the value of
|
||||
@code{prosody-service-type}. As its name indicates, an opaque configuration
|
||||
does not have easy reflective capabilities.")
|
||||
(generate 'opaque-prosody-configuration)
|
||||
(format #t "For example, if your @code{prosody.cfg.lua} is just the empty
|
||||
string, you could instantiate a prosody service like this:
|
||||
|
||||
@example
|
||||
(service prosody-service-type
|
||||
(opaque-prosody-configuration
|
||||
(prosody.cfg.lua \"\")))
|
||||
@end example"))
|
Loading…
Reference in New Issue