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
					
				
					 4 changed files with 1122 additions and 1 deletions
				
			
		
							
								
								
									
										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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										726
									
								
								gnu/services/messaging.scm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										726
									
								
								gnu/services/messaging.scm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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"))
 | 
			
		||||
		Reference in a new issue