%%%---------------------------------------------------------------------- %%% ejabberd, Copyright (C) 2002-2022 ProcessOne %%% %%% This program 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 2 of the %%% License, or (at your option) any later version. %%% %%% This program 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 this program; if not, write to the Free Software Foundation, Inc., %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%---------------------------------------------------------------------- -module(ejabberd_options_doc). %% API -export([doc/0]). -include("translate.hrl"). %%%=================================================================== %%% API %%%=================================================================== doc() -> [{hosts, #{value => ?T("[Domain1, Domain2, ...]"), desc => ?T("The option defines a list containing one or more " "domains that 'ejabberd' will serve. This is a " "**mandatory** option.")}}, {listen, #{value => "[Options, ...]", desc => ?T("The option for listeners configuration. See the " "http://../listen/[Listen Modules] section " "for details.")}}, {modules, #{value => "{Module: Options}", desc => ?T("The option for modules configuration. See " "http://../modules/[Modules] section " "for details.")}}, {loglevel, #{value => "none | emergency | alert | critical | " "error | warning | notice | info | debug", desc => ?T("Verbosity of log files generated by ejabberd. " "The default value is 'info'. " "NOTE: previous versions of ejabberd had log levels " "defined in numeric format ('0..5'). The numeric values " "are still accepted for backward compatibility, but " "are not recommended.")}}, {cache_life_time, #{value => "timeout()", desc => ?T("The time of a cached item to keep in cache. " "Once it's expired, the corresponding item is " "erased from cache. The default value is '1 hour'. " "Several modules have a similar option; and some core " "ejabberd parts support similar options too, see " "_`auth_cache_life_time`_, _`oauth_cache_life_time`_, " "_`router_cache_life_time`_, and _`sm_cache_life_time`_.")}}, {cache_missed, #{value => "true | false", desc => ?T("Whether or not to cache missed lookups. When there is " "an attempt to lookup for a value in a database and " "this value is not found and the option is set to 'true', " "this attempt will be cached and no attempts will be " "performed until the cache expires (see _`cache_life_time`_). " "Usually you don't want to change it. Default is 'true'. " "Several modules have a similar option; and some core " "ejabberd parts support similar options too, see " "_`auth_cache_missed`_, _`oauth_cache_missed`_, " "_`router_cache_missed`_, and _`sm_cache_missed`_.")}}, {cache_size, #{value => "pos_integer() | infinity", desc => ?T("A maximum number of items (not memory!) in cache. " "The rule of thumb, for all tables except rosters, " "you should set it to the number of maximum online " "users you expect. For roster multiply this number " "by 20 or so. If the cache size reaches this threshold, " "it's fully cleared, i.e. all items are deleted, and " "the corresponding warning is logged. You should avoid " "frequent cache clearance, because this degrades " "performance. The default value is '1000'. " "Several modules have a similar option; and some core " "ejabberd parts support similar options too, see " "_`auth_cache_size`_, _`oauth_cache_size`_, " "_`router_cache_size`_, and _`sm_cache_size`_.")}}, {use_cache, #{value => "true | false", desc => ?T("Enable or disable cache. The default is 'true'. " "Several modules have a similar option; and some core " "ejabberd parts support similar options too, see " "_`auth_use_cache`_, _`oauth_use_cache`_, _`router_use_cache`_, " "and _`sm_use_cache`_.")}}, {default_db, #{value => "mnesia | sql", desc => ?T("Default persistent storage for ejabberd. " "Modules and other components (e.g. authentication) " "may have its own value. The default value is 'mnesia'.")}}, {default_ram_db, #{value => "mnesia | redis | sql", desc => ?T("Default volatile (in-memory) storage for ejabberd. " "Modules and other components (e.g. session management) " "may have its own value. The default value is 'mnesia'.")}}, {queue_type, #{value => "ram | file", desc => ?T("Default type of queues in ejabberd. " "Modules may have its own value of the option. " "The value of 'ram' means that queues will be kept in memory. " "If value 'file' is set, you may also specify directory " "in _`queue_dir`_ option where file queues will be placed. " "The default value is 'ram'.")}}, {version, #{value => "string()", desc => ?T("The option can be used to set custom ejabberd version, " "that will be used by different parts of ejabberd, for " "example by _`mod_version`_ module. The default value is " "obtained at compile time from the underlying version " "control system.")}}, {acl, #{value => "{ACLName: {ACLType: ACLValue}}", desc => ?T("The option defines access control lists: named sets " "of rules which are used to match against different targets " "(such as a JID or an IP address). Every set of rules " "has name 'ACLName': it can be any string except 'all' or 'none' " "(those are predefined names for the rules that match all or nothing " "respectively). The name 'ACLName' can be referenced from other " "parts of the configuration file, for example in _`access_rules`_ " "option. The rules of 'ACLName' are represented by mapping " "'pass:[{ACLType: ACLValue}]'. These can be one of the following:")}, [{user, #{value => ?T("Username"), desc => ?T("If 'Username' is in the form of \"user@server\", " "the rule matches a JID against this value. " "Otherwise, if 'Username' is in the form of \"user\", " "the rule matches any JID that has 'Username' in the node part " "as long as the server part of this JID is any virtual " "host served by ejabberd.")}}, {server, #{value => ?T("Server"), desc => ?T("The rule matches any JID from server 'Server'. " "The value of 'Server' must be a valid " "hostname or an IP address.")}}, {resource, #{value => ?T("Resource"), desc => ?T("The rule matches any JID with a resource 'Resource'.")}}, {ip, #{value => ?T("Network"), desc => ?T("The rule matches any IP address from the 'Network'.")}}, {user_regexp, #{value => ?T("Regexp"), desc => ?T("If 'Regexp' is in the form of \"regexp@server\", the rule " "matches any JID with node part matching regular expression " "\"regexp\" as long as the server part of this JID is equal " "to \"server\". If 'Regexp' is in the form of \"regexp\", the rule " "matches any JID with node part matching regular expression " "\"regexp\" as long as the server part of this JID is any virtual " "host served by ejabberd.")}}, {server_regexp, #{value => ?T("Regexp"), desc => ?T("The rule matches any JID from the server that " "matches regular expression 'Regexp'.")}}, {resource_regexp, #{value => ?T("Regexp"), desc => ?T("The rule matches any JID with a resource that " "matches regular expression 'Regexp'.")}}, {node_regexp, #{value => ?T("user_regexp@server_regexp"), desc => ?T("The rule matches any JID with node part matching regular " "expression 'user_regexp' and server part matching regular " "expression 'server_regexp'.")}}, {user_glob, #{value => ?T("Pattern"), desc => ?T("Same as 'user_regexp', but matching is performed on a " "specified 'Pattern' according to the rules used by the " "Unix shell.")}}, {server_glob, #{value => ?T("Pattern"), desc => ?T("Same as 'server_regexp', but matching is performed on a " "specified 'Pattern' according to the rules used by the " "Unix shell.")}}, {resource_glob, #{value => ?T("Pattern"), desc => ?T("Same as 'resource_regexp', but matching is performed on a " "specified 'Pattern' according to the rules used by the " "Unix shell.")}}, {node_glob, #{value => ?T("Pattern"), desc => ?T("Same as 'node_regexp', but matching is performed on a " "specified 'Pattern' according to the rules used by the " "Unix shell.")}}]}, {access_rules, #{value => "{AccessName: {allow|deny: ACLRules|ACLName}}", desc => ?T("This option defines " "http://../basic/#access-rules[Access Rules]. " "Each access rule is " "assigned a name that can be referenced from other parts " "of the configuration file (mostly from 'access' options of " "ejabberd modules). Each rule definition may contain " "arbitrary number of 'allow' or 'deny' sections, and each " "section may contain any number of ACL rules (see _`acl`_ option). " "There are no access rules defined by default."), example => ["access_rules:", " configure:", " allow: admin", " something:", " deny: someone", " allow: all", " s2s_banned:", " deny: problematic_hosts", " deny: banned_forever", " deny:", " ip: 222.111.222.111/32", " deny:", " ip: 111.222.111.222/32", " allow: all", " xmlrpc_access:", " allow:", " user: peter@example.com", " allow:", " user: ivone@example.com", " allow:", " user: bot@example.com", " ip: 10.0.0.0/24"]}}, {acme, #{value => ?T("Options"), desc => ?T("http://../basic/#acme[ACME] configuration, to automatically " "obtain SSL certificates for the domains served by ejabberd, " "which means that certificate requests and renewals are " "performed to some CA server (aka \"ACME server\") in a fully " "automated mode. The 'Options' are:"), example => ["acme:", " ca_url: https://acme-v02.api.letsencrypt.org/directory", " contact:", " - mailto:admin@domain.tld", " - mailto:bot@domain.tld", " auto: true", " cert_type: rsa"]}, [{ca_url, #{value => ?T("URL"), desc => ?T("The ACME directory URL used as an entry point " "for the ACME server. The default value is " " - " "the directory URL of Let's Encrypt authority.")}}, {contact, #{value => ?T("[Contact, ...]"), desc => ?T("A list of contact addresses (typically emails) " "where an ACME server will send notifications " "when problems occur. The value of 'Contact' must " "be in the form of \"scheme:address\" (e.g. " "\"mailto:user@domain.tld\"). The default " "is an empty list which means an ACME server " "will send no notices.")}}, {auto, #{value => "true | false", desc => ?T("Whether to automatically request certificates for " "all configured domains (that yet have no a certificate) " "on server start or configuration reload. The default is 'true'.")}}, {cert_type, #{value => "rsa | ec", desc => ?T("A type of a certificate key. Available values are " "'ec' and 'rsa' for EC and RSA certificates respectively. " "It's better to have RSA certificates for the purpose " "of backward compatibility with legacy clients and servers, " "thus the default is 'rsa'.")}}]}, {allow_contrib_modules, #{value => "true | false", desc => ?T("Whether to allow installation of third-party modules or not. " "The default value is 'true'.")}}, {allow_multiple_connections, #{value => "true | false", desc => ?T("This option is only used when the anonymous mode is enabled. " "Setting it to 'true' means that the same username can be " "taken multiple times in anonymous login mode if different " "resource are used to connect. This option is only useful " "in very special occasions. The default value is 'false'.")}}, {anonymous_protocol, #{value => "login_anon | sasl_anon | both", desc => [?T("Define what anonymous protocol will be used: "), "", ?T("* 'login_anon' means that the anonymous login method will be used. "), "", ?T("* 'sasl_anon' means that the SASL Anonymous method will be used. "), "", ?T("* 'both' means that SASL Anonymous and login anonymous are both " "enabled."), "", ?T("The default value is 'sasl_anon'."), ""]}}, {api_permissions, #{value => "[Permission, ...]", desc => ?T("Define the permissions for API access. Please consult the " "ejabberd Docs web -> For Developers -> ejabberd ReST API -> " "https://docs.ejabberd.im/developer/ejabberd-api/permissions/" "[API Permissions].")}}, {append_host_config, #{value => "{Host: Options}", desc => ?T("To define specific ejabberd modules in a virtual host, " "you can define the global 'modules' option with the common modules, " "and later add specific modules to certain virtual hosts. " "To accomplish that, 'append_host_config' option can be used.")}}, {auth_cache_life_time, #{value => "timeout()", desc => ?T("Same as _`cache_life_time`_, but applied to authentication cache " "only. If not set, the value from _`cache_life_time`_ will be used.")}}, {auth_cache_missed, #{value => "true | false", desc => ?T("Same as _`cache_missed`_, but applied to authentication cache " "only. If not set, the value from _`cache_missed`_ will be used.")}}, {auth_cache_size, #{value => "pos_integer() | infinity", desc => ?T("Same as _`cache_size`_, but applied to authentication cache " "only. If not set, the value from _`cache_size`_ will be used.")}}, {auth_method, #{value => "[mnesia | sql | anonymous | external | jwt | ldap | pam, ...]", desc => ?T("A list of authentication methods to use. " "If several methods are defined, authentication is " "considered successful as long as authentication of " "at least one of the methods succeeds. " "The default value is '[mnesia]'.")}}, {auth_opts, #{value => "[Option, ...]", desc => ?T("This is used by the contributed module " "'ejabberd_auth_http' that can be installed from the " "https://github.com/processone/ejabberd-contrib[ejabberd-contrib] " "Git repository. Please refer to that " "module's README file for details.")}}, {auth_password_format, #{value => "plain | scram", note => "improved in 20.01", desc => [?T("The option defines in what format the users passwords " "are stored:"), "", ?T("* 'plain': The password is stored as plain text " "in the database. This is risky because the passwords " "can be read if your database gets compromised. " "This is the default value. This format allows clients to " "authenticate using: the old Jabber Non-SASL (XEP-0078), " "SASL PLAIN, SASL DIGEST-MD5, and SASL SCRAM-SHA-1. "), "", ?T("* 'scram': The password is not stored, only some information " "that allows to verify the hash provided by the client. " "It is impossible to obtain the original plain password " "from the stored information; for this reason, when this " "value is configured it cannot be changed to plain anymore. " "This format allows clients to authenticate using: " "SASL PLAIN and SASL SCRAM-SHA-1."), ?T("The default value is 'plain'.")]}}, {auth_scram_hash, #{value => "sha | sha256 | sha512", desc => ?T("Hash algorithm that should be used to store password in SCRAM format. " "You shouldn't change this if you already have passwords generated with " "a different algorithm - users that have such passwords will not be able " "to authenticate. The default value is 'sha'.")}}, {auth_use_cache, #{value => "true | false", desc => ?T("Same as _`use_cache`_, but applied to authentication cache " "only. If not set, the value from _`use_cache`_ will be used.")}}, {c2s_cafile, #{value => ?T("Path"), desc => [?T("Full path to a file containing one or more CA certificates " "in PEM format. All client certificates should be signed by " "one of these root CA certificates and should contain the " "corresponding JID(s) in 'subjectAltName' field. " "There is no default value."), "", ?T("You can use http://../toplevel/#host-config[host_config] to specify this option per-vhost."), "", ?T("To set a specific file per listener, use the listener's http://../listen-options/#cafile[cafile] option. Please notice that 'c2s_cafile' overrides the listener's 'cafile' option."), "" ]}}, {c2s_ciphers, #{value => "[Cipher, ...]", desc => ?T("A list of OpenSSL ciphers to use for c2s connections. " "The default value is shown in the example below:"), example => ["c2s_ciphers:", " - HIGH", " - \"!aNULL\"", " - \"!eNULL\"", " - \"!3DES\"", " - \"@STRENGTH\""]}}, {c2s_dhfile, #{value => ?T("Path"), desc => ?T("Full path to a file containing custom DH parameters " "to use for c2s connections. " "Such a file could be created with the command \"openssl " "dhparam -out dh.pem 2048\". If this option is not specified, " "2048-bit MODP Group with 256-bit Prime Order Subgroup will be " "used as defined in RFC5114 Section 2.3.")}}, {c2s_protocol_options, #{value => "[Option, ...]", desc => ?T("List of general SSL options to use for c2s connections. " "These map to OpenSSL's 'set_options()'. The default value is " "shown in the example below:"), example => ["c2s_protocol_options:", " - no_sslv3", " - cipher_server_preference", " - no_compression"]}}, {c2s_tls_compression, #{value => "true | false", desc => ?T("Whether to enable or disable TLS compression for c2s connections. " "The default value is 'false'.")}}, {ca_file, #{value => ?T("Path"), desc => [?T("Path to a file of CA root certificates. " "The default is to use system defined file if possible."), "", ?T("For server connections, this 'ca_file' option is overridden by the http://../toplevel/#s2s-cafile[s2s_cafile] option."), "" ]}}, {captcha_cmd, #{value => ?T("Path"), desc => ?T("Full path to a script that generates http://../basic/#captcha[CAPTCHA] images. " "There is no default value: when this option is not " "set, CAPTCHA functionality is completely disabled.")}}, {captcha_limit, #{value => "pos_integer() | infinity", desc => ?T("Maximum number of http://../basic/#captcha[CAPTCHA] generated images per minute for " "any given JID. The option is intended to protect the server " "from CAPTCHA DoS. The default value is 'infinity'.")}}, {captcha_host, #{value => "String", desc => ?T("Deprecated. Use _`captcha_url`_ instead.")}}, {captcha_url, #{value => ?T("URL"), desc => ?T("An URL where http://../basic/#captcha[CAPTCHA] requests should be sent. NOTE: you need " "to configure 'request_handlers' for 'ejabberd_http' listener " "as well. There is no default value.")}}, {certfiles, #{value => "[Path, ...]", desc => ?T("The option accepts a list of file paths (optionally with " "wildcards) containing either PEM certificates or PEM private " "keys. At startup or configuration reload, ejabberd reads all " "certificates from these files, sorts them, removes duplicates, " "finds matching private keys and then rebuilds full certificate " "chains for the use in TLS connections. " "Use this option when TLS is enabled in either of " "ejabberd listeners: 'ejabberd_c2s', 'ejabberd_http' and so on. " "NOTE: if you modify the certificate files or change the value " "of the option, run 'ejabberdctl reload-config' in order to " "rebuild and reload the certificate chains."), example => [{?T("If you use https://letsencrypt.org[Let's Encrypt] certificates " "for your domain \"domain.tld\", the configuration will look " "like this:"), ["certfiles:", " - /etc/letsencrypt/live/domain.tld/fullchain.pem", " - /etc/letsencrypt/live/domain.tld/privkey.pem"]}]}}, {cluster_backend, #{value => ?T("Backend"), desc => ?T("A database backend to use for storing information about " "cluster. The only available value so far is 'mnesia'.")}}, {cluster_nodes, #{value => "[Node, ...]", desc => ?T("A list of Erlang nodes to connect on ejabberd startup. " "This option is mostly intended for ejabberd customization " "and sophisticated setups. The default value is an empty list.")}}, {define_macro, #{value => "{MacroName: MacroValue}", desc => ?T("Defines a macro. The value can be any valid arbitrary " "YAML value. For convenience, it's recommended to define " "a 'MacroName' in capital letters. Duplicated macros are not allowed. " "Macros are processed after additional configuration files have " "been included, so it is possible to use macros that are defined " "in configuration files included before the usage. " "It is possible to use a 'MacroValue' in the definition of another macro."), example => ["define_macro:", " DEBUG: debug", " LOG_LEVEL: DEBUG", " USERBOB:", " user: bob@localhost", "", "loglevel: LOG_LEVEL", "", "acl:", " admin: USERBOB"]}}, {disable_sasl_mechanisms, #{value => "[Mechanism, ...]", desc => ?T("Specify a list of SASL mechanisms (such as 'DIGEST-MD5' or " "'SCRAM-SHA1') that should not be offered to the client. " "For convenience, the value of 'Mechanism' is case-insensitive. " "The default value is an empty list, i.e. no mechanisms " "are disabled by default.")}}, {domain_balancing, #{value => "{Domain: Options}", desc => ?T("An algorithm to load balance the components that are plugged " "on an ejabberd cluster. It means that you can plug one or several " "instances of the same component on each ejabberd node and that " "the traffic will be automatically distributed. The algorithm " "to deliver messages to the component(s) can be specified by " "this option. For any component connected as 'Domain', available " "'Options' are:"), example => ["domain_balancing:", " component.domain.tld:", " type: destination", " component_number: 5", " transport.example.org:", " type: bare_source"]}, [{type, #{value => "random | source | destination | bare_source | bare_destination", desc => ?T("How to deliver stanzas to connected components: " "'random' - an instance is chosen at random; " "'destination' - an instance is chosen by the full JID of " "the packet's 'to' attribute; " "'source' - by the full JID of the packet's 'from' attribute; " "'bare_destination' - by the the bare JID (without resource) " "of the packet's 'to' attribute; " "'bare_source' - by the bare JID (without resource) of the " "packet's 'from' attribute is used. The default value is 'random'.")}}, {component_number, #{value => "2..1000", desc => ?T("The number of components to balance.")}}]}, {extauth_pool_name, #{value => ?T("Name"), desc => ?T("Define the pool name appendix, so the full pool name will be " "'extauth_pool_Name'. The default value is the hostname.")}}, {extauth_pool_size, #{value => ?T("Size"), desc => ?T("The option defines the number of instances of the same " "external program to start for better load balancing. " "The default is the number of available CPU cores.")}}, {extauth_program, #{value => ?T("Path"), desc => ?T("Indicate in this option the full path to the external " "authentication script. The script must be executable by ejabberd.")}}, {ext_api_headers, #{value => "Headers", desc => ?T("String of headers (separated with commas ',') that will be " "provided by ejabberd when sending ReST requests. " "The default value is an empty string of headers: '\"\"'.")}}, {ext_api_http_pool_size, #{value => "pos_integer()", desc => ?T("Define the size of the HTTP pool, that is, the maximum number " "of sessions that the ejabberd ReST service will handle " "simultaneously. The default value is: '100'.")}}, {ext_api_path_oauth, #{value => "Path", desc => ?T("Define the base URI path when performing OAUTH ReST requests. " "The default value is: '\"/oauth\"'.")}}, {ext_api_url, #{value => "URL", desc => ?T("Define the base URI when performing ReST requests. " "The default value is: '\"http://localhost/api\"'.")}}, {fqdn, #{value => ?T("Domain"), desc => ?T("A fully qualified domain name that will be used in " "SASL DIGEST-MD5 authentication. The default is detected " "automatically.")}}, {hide_sensitive_log_data, #{value => "true | false", desc => ?T("A privacy option to not log sensitive data " "(mostly IP addresses). The default value " "is 'false' for backward compatibility.")}}, {host_config, #{value => "{Host: Options}", desc => ?T("The option is used to redefine 'Options' for virtual host " "'Host'. In the example below LDAP authentication method " "will be used on virtual host 'domain.tld' and SQL method " "will be used on virtual host 'example.org'."), example => ["hosts:", " - domain.tld", " - example.org", "", "auth_method:", " - sql", "", "host_config:", " domain.tld:", " auth_method:", " - ldap"]}}, {include_config_file, #{value => "[Filename, ...\\] | {Filename: Options}", desc => ?T("Read additional configuration from 'Filename'. If the " "value is provided in 'pass:[{Filename: Options}]' format, the " "'Options' must be one of the following:")}, [{disallow, #{value => "[OptionName, ...]", desc => ?T("Disallows the usage of those options in the included " "file 'Filename'. The options that match this criteria " "are not accepted. The default value is an empty list.")}}, {allow_only, #{value => "[OptionName, ...]", desc => ?T("Allows only the usage of those options in the included " "file 'Filename'. The options that do not match this " "criteria are not accepted. The default value is to include " "all options.")}}]}, {jwt_auth_only_rule, #{value => ?T("AccessName"), desc => ?T("This ACL rule defines accounts that can use only this auth " "method, even if others are also defined in the ejabberd " "configuration file. In other words: if there are several auth " "methods enabled for this host (JWT, SQL, ...), users that " "match this rule can only use JWT. " "The default value is 'none'.")}}, {jwt_jid_field, #{value => ?T("FieldName"), desc => ?T("By default, the JID is defined in the '\"jid\"' JWT field. " "This option allows to specify other JWT field name " "where the JID is defined.")}}, {jwt_key, #{value => ?T("FilePath"), desc => ?T("Path to the file that contains the JWK Key. " "The default value is 'undefined'.")}}, {language, #{value => ?T("Language"), desc => ?T("The option defines the default language of server strings " "that can be seen by XMPP clients. If an XMPP client does not " "possess 'xml:lang' attribute, the specified language is used. " "The default value is '\"en\"'.")}}, {ldap_servers, #{value => "[Host, ...]", desc => ?T("A list of IP addresses or DNS names of your LDAP servers. " "The default value is '[localhost]'.")}}, {ldap_backups, #{value => "[Host, ...]", desc => ?T("A list of IP addresses or DNS names of LDAP backup servers. " "When no servers listed in _`ldap_servers`_ option are reachable, " "ejabberd will try to connect to these backup servers. " "The default is an empty list, i.e. no backup servers specified. " "WARNING: ejabberd doesn't try to reconnect back to the main " "servers when they become operational again, so the only way " "to restore these connections is to restart ejabberd. This " "limitation might be fixed in future releases.")}}, {ldap_encrypt, #{value => "tls | none", desc => ?T("Whether to encrypt LDAP connection using TLS or not. " "The default value is 'none'. NOTE: STARTTLS encryption " "is not supported.")}}, {ldap_tls_certfile, #{value => ?T("Path"), desc => ?T("A path to a file containing PEM encoded certificate " "along with PEM encoded private key. This certificate " "will be provided by ejabberd when TLS enabled for " "LDAP connections. There is no default value, which means " "no client certificate will be sent.")}}, {ldap_tls_verify, #{value => "false | soft | hard", desc => ?T("This option specifies whether to verify LDAP server " "certificate or not when TLS is enabled. When 'hard' is set, " "ejabberd doesn't proceed if the certificate is invalid. " "When 'soft' is set, ejabberd proceeds even if the check has failed. " "The default is 'false', which means no checks are performed.")}}, {ldap_tls_cacertfile, #{value => ?T("Path"), desc => ?T("A path to a file containing PEM encoded CA certificates. " "This option is required when TLS verification is enabled.")}}, {ldap_tls_depth, #{value => ?T("Number"), desc => ?T("Specifies the maximum verification depth when TLS verification " "is enabled, i.e. how far in a chain of certificates the " "verification process can proceed before the verification " "is considered to be failed. Peer certificate = 0, " "CA certificate = 1, higher level CA certificate = 2, etc. " "The value '2' thus means that a chain can at most contain " "peer cert, CA cert, next CA cert, and an additional CA cert. " "The default value is '1'.")}}, {ldap_port, #{value => "1..65535", desc => ?T("Port to connect to your LDAP server. The default port is " "'389' if encryption is disabled and '636' if encryption is " "enabled.")}}, {ldap_rootdn, #{value => "RootDN", desc => ?T("Bind Distinguished Name. The default value is an empty " "string, which means \"anonymous connection\".")}}, {ldap_password, #{value => ?T("Password"), desc => ?T("Bind password. The default value is an empty string.")}}, {ldap_deref_aliases, #{value => "never | always | finding | searching", desc => ?T("Whether to dereference aliases or not. " "The default value is 'never'.")}}, {ldap_base, #{value => "Base", desc => ?T("LDAP base directory which stores users accounts. " "There is no default value: you must set the option " "in order for LDAP connections to work properly.")}}, {ldap_uids, #{value => "[Attr\\] | {Attr: AttrFormat}", desc => ?T("LDAP attributes which hold a list of attributes to use " "as alternatives for getting the JID, where 'Attr' is " "an LDAP attribute which holds the user's part of the JID and " "'AttrFormat' must contain one and only one pattern variable " "\"%u\" which will be replaced by the user's part of the JID. " "For example, \"%u@example.org\". If the value is in the form " "of '[Attr]' then 'AttrFormat' is assumed to be \"%u\".")}}, {ldap_filter, #{value => ?T("Filter"), desc => ?T("An LDAP filter as defined in " "https://tools.ietf.org/html/rfc4515[RFC4515]. " "There is no default value. Example: " "\"(&(objectClass=shadowAccount)(memberOf=XMPP Users))\". " "NOTE: don't forget to close brackets and don't use superfluous " "whitespaces. Also you must not use \"uid\" attribute in the " "filter because this attribute will be appended to the filter " "automatically.")}}, {ldap_dn_filter, #{value => "{Filter: FilterAttrs}", desc => ?T("This filter is applied on the results returned by the main " "filter. The filter performs an additional LDAP lookup to make " "the complete result. This is useful when you are unable to " "define all filter rules in 'ldap_filter'. You can define " "\"%u\", \"%d\", \"%s\" and \"%D\" pattern variables in 'Filter': " "\"%u\" is replaced by a user's part of the JID, \"%d\" is " "replaced by the corresponding domain (virtual host), all \"%s\" " "variables are consecutively replaced by values from the attributes " "in 'FilterAttrs' and \"%D\" is replaced by Distinguished Name from " "the result set. There is no default value, which means the " "result is not filtered. WARNING: Since this filter makes " "additional LDAP lookups, use it only as the last resort: " "try to define all filter rules in _`ldap_filter`_ option if possible."), example => ["ldap_dn_filter:", " \"(&(name=%s)(owner=%D)(user=%u@%d))\": [sn]"]}}, {log_rotate_count, #{value => ?T("Number"), desc => ?T("The number of rotated log files to keep. " "The default value is '1', which means that only keeps " "`ejabberd.log.0`, `error.log.0` and `crash.log.0`.")}}, {log_rotate_size, #{value => "pos_integer() | infinity", desc => ?T("The size (in bytes) of a log file to trigger rotation. " "If set to 'infinity', log rotation is disabled. " "The default value is '10485760' (that is, 10 Mb).")}}, {max_fsm_queue, #{value => ?T("Size"), desc => ?T("This option specifies the maximum number of elements " "in the queue of the FSM (Finite State Machine). Roughly " "speaking, each message in such queues represents one " "XML stanza queued to be sent into its relevant outgoing " "stream. If queue size reaches the limit (because, for " "example, the receiver of stanzas is too slow), the FSM " "and the corresponding connection (if any) will be terminated " "and error message will be logged. The reasonable value for " "this option depends on your hardware configuration. " "The allowed values are positive integers. " "The default value is '10000'.")}}, {negotiation_timeout, #{value => "timeout()", desc => ?T("Time to wait for an XMPP stream negotiation to complete. " "When timeout occurs, the corresponding XMPP stream is closed. " "The default value is '30' seconds.")}}, {net_ticktime, #{value => "timeout()", desc => ?T("This option can be used to tune tick time parameter of " "'net_kernel'. It tells Erlang VM how often nodes should check " "if intra-node communication was not interrupted. This option " "must have identical value on all nodes, or it will lead to subtle " "bugs. Usually leaving default value of this is option is best, " "tweak it only if you know what you are doing. " "The default value is '1 minute'.")}}, {new_sql_schema, #{value => "true | false", desc => {?T("Whether to use 'new' SQL schema. All schemas are located " "at . " "There are two schemas available. The default legacy schema " "allows to store one XMPP domain into one ejabberd database. " "The 'new' schema allows to handle several XMPP domains in a " "single ejabberd database. Using this 'new' schema is best when " "serving several XMPP domains and/or changing domains from " "time to time. This avoid need to manage several databases and " "handle complex configuration changes. The default depends on " "configuration flag '--enable-new-sql-schema' which is set " "at compile time."), [binary:part(ejabberd_config:version(), {0,5})]}}}, {oauth_access, #{value => ?T("AccessName"), desc => ?T("By default creating OAuth tokens is not allowed. " "To define which users can create OAuth tokens, " "you can refer to an ejabberd access rule in the " "'oauth_access' option. Use 'all' to allow everyone " "to create tokens.")}}, {oauth_cache_life_time, #{value => "timeout()", desc => ?T("Same as _`cache_life_time`_, but applied to OAuth cache " "only. If not set, the value from _`cache_life_time`_ will be used.")}}, {oauth_cache_missed, #{value => "true | false", desc => ?T("Same as _`cache_missed`_, but applied to OAuth cache " "only. If not set, the value from _`cache_missed`_ will be used.")}}, {oauth_cache_rest_failure_life_time, #{value => "timeout()", note => "added in 21.01", desc => ?T("The time that a failure in OAuth ReST is cached. " "The default value is 'infinity'.")}}, {oauth_cache_size, #{value => "pos_integer() | infinity", desc => ?T("Same as _`cache_size`_, but applied to OAuth cache " "only. If not set, the value from _`cache_size`_ will be used.")}}, {oauth_client_id_check, #{value => "allow | db | deny", desc => ?T("Define whether the client authentication is always allowed, " "denied, or it will depend if the client ID is present in the " "database. The default value is 'allow'.")}}, {oauth_use_cache, #{value => "true | false", desc => ?T("Same as _`use_cache`_, but applied to OAuth cache " "only. If not set, the value from _`use_cache`_ will be used.")}}, {oauth_db_type, #{value => "mnesia | sql", desc => ?T("Database backend to use for OAuth authentication. " "The default value is picked from _`default_db`_ option, or " "if it's not set, 'mnesia' will be used.")}}, {oauth_expire, #{value => "timeout()", desc => ?T("Time during which the OAuth token is valid, in seconds. " "After that amount of time, the token expires and the delegated " "credential cannot be used and is removed from the database. " "The default is '4294967' seconds.")}}, {oom_killer, #{value => "true | false", desc => ?T("Enable or disable OOM (out-of-memory) killer. " "When system memory raises above the limit defined in " "_`oom_watermark`_ option, ejabberd triggers OOM killer " "to terminate most memory consuming Erlang processes. " "Note that in order to maintain functionality, ejabberd only " "attempts to kill transient processes, such as those managing " "client sessions, s2s or database connections. " "The default value is 'true'.")}}, {oom_queue, #{value => ?T("Size"), desc => ?T("Trigger OOM killer when some of the running Erlang processes " "have messages queue above this 'Size'. Note that " "such processes won't be killed if _`oom_killer`_ option is set " "to 'false' or if 'oom_watermark' is not reached yet.")}}, {oom_watermark, #{value => ?T("Percent"), desc => ?T("A percent of total system memory consumed at which " "OOM killer should be activated with some of the processes " "possibly be killed (see _`oom_killer`_ option). Later, when " "memory drops below this 'Percent', OOM killer is deactivated. " "The default value is '80' percents.")}}, {outgoing_s2s_families, #{value => "[ipv4 | ipv6, ...]", desc => ?T("Specify which address families to try, in what order. " "The default is '[ipv4, ipv6]' which means it first tries " "connecting with IPv4, if that fails it tries using IPv6.")}}, {outgoing_s2s_ipv4_address, #{value => "Address", note => "added in 20.12", desc => ?T("Specify the IPv4 address that will be used when establishing " "an outgoing S2S IPv4 connection, for example \"127.0.0.1\". " "The default value is 'undefined'.")}}, {outgoing_s2s_ipv6_address, #{value => "Address", note => "added in 20.12", desc => ?T("Specify the IPv6 address that will be used when establishing " "an outgoing S2S IPv6 connection, for example " "\"::FFFF:127.0.0.1\". The default value is 'undefined'.")}}, {outgoing_s2s_port, #{value => "1..65535", desc => ?T("A port number to use for outgoing s2s connections when the target " "server doesn't have an SRV record. The default value is '5269'.")}}, {outgoing_s2s_timeout, #{value => "timeout()", desc => ?T("The timeout in seconds for outgoing S2S connection attempts. " "The default value is '10' seconds.")}}, {pam_service, #{value => ?T("Name"), desc => ?T("This option defines the PAM service name. Refer to the PAM " "documentation of your operation system for more information. " "The default value is 'ejabberd'.")}}, {pam_userinfotype, #{value => "username | jid", desc => ?T("This option defines what type of information about the " "user ejabberd provides to the PAM service: only the username, " "or the user's JID. Default is 'username'.")}}, {pgsql_users_number_estimate, #{value => "true | false", desc => ?T("Whether to use PostgreSQL estimation when counting registered " "users. The default value is 'false'.")}}, {queue_dir, #{value => ?T("Directory"), desc => ?T("If _`queue_type`_ option is set to 'file', use this 'Directory' " "to store file queues. The default is to keep queues inside " "Mnesia directory.")}}, {redis_connect_timeout, #{value => "timeout()", desc => ?T("A timeout to wait for the connection to be re-established " "to the Redis server. The default is '1 second'.")}}, {redis_db, #{value => ?T("Number"), desc => ?T("Redis database number. The default is '0'.")}}, {redis_password, #{value => ?T("Password"), desc => ?T("The password to the Redis server. " "The default is an empty string, i.e. no password.")}}, {redis_pool_size, #{value => ?T("Number"), desc => ?T("The number of simultaneous connections to the Redis server. " "The default value is '10'.")}}, {redis_port, #{value => "1..65535", desc => ?T("The port where the Redis server is accepting connections. " "The default is '6379'.")}}, {redis_queue_type, #{value => "ram | file", desc => ?T("The type of request queue for the Redis server. " "See description of _`queue_type`_ option for the explanation. " "The default value is the value defined in _`queue_type`_ " "or 'ram' if the latter is not set.")}}, {redis_server, #{value => ?T("Hostname"), desc => ?T("A hostname or an IP address of the Redis server. " "The default is 'localhost'.")}}, {registration_timeout, #{value => "timeout()", desc => ?T("This is a global option for module _`mod_register`_. " "It limits the frequency of registrations from a given " "IP or username. So, a user that tries to register a " "new account from the same IP address or JID during " "this time after their previous registration " "will receive an error with the corresponding explanation. " "To disable this limitation, set the value to 'infinity'. " "The default value is '600 seconds'.")}}, {resource_conflict, #{value => "setresource | closeold | closenew", desc => ?T("NOTE: this option is deprecated and may be removed " "anytime in the future versions. The possible values " "match exactly the three possibilities described in " "https://tools.ietf.org/html/rfc6120#section-7.7.2.2" "[XMPP Core: section 7.7.2.2]. " "The default value is 'closeold'. If the client " "uses old Jabber Non-SASL authentication (XEP-0078), " "then this option is not respected, and the action performed " "is 'closeold'.")}}, {router_cache_life_time, #{value => "timeout()", desc => ?T("Same as _`cache_life_time`_, but applied to routing table cache " "only. If not set, the value from _`cache_life_time`_ will be used.")}}, {router_cache_missed, #{value => "true | false", desc => ?T("Same as _`cache_missed`_, but applied to routing table cache " "only. If not set, the value from _`cache_missed`_ will be used.")}}, {router_cache_size, #{value => "pos_integer() | infinity", desc => ?T("Same as _`cache_size`_, but applied to routing table cache " "only. If not set, the value from _`cache_size`_ will be used.")}}, {router_db_type, #{value => "mnesia | redis | sql", desc => ?T("Database backend to use for routing information. " "The default value is picked from _`default_ram_db`_ option, or " "if it's not set, 'mnesia' will be used.")}}, {router_use_cache, #{value => "true | false", desc => ?T("Same as _`use_cache`_, but applied to routing table cache " "only. If not set, the value from _`use_cache`_ will be used.")}}, {rpc_timeout, #{value => "timeout()", desc => ?T("A timeout for remote function calls between nodes " "in an ejabberd cluster. You should probably never change " "this value since those calls are used for internal needs " "only. The default value is '5' seconds.")}}, {s2s_access, #{value => ?T("Access"), desc => ?T("This http://../basic/#access-rules[Access Rule] defines to " "what remote servers can s2s connections be established. " "The default value is 'all'; no restrictions are applied, it is" " allowed to connect s2s to/from all remote servers.")}}, {s2s_cafile, #{value => ?T("Path"), desc => [?T("A path to a file with CA root certificates that will " "be used to authenticate s2s connections. If not set, " "the value of http://../toplevel/#ca-file[ca_file] will be used."), "", ?T("You can use http://../toplevel/#host-config[host_config] to specify this option per-vhost."), "" ]}}, {s2s_ciphers, #{value => "[Cipher, ...]", desc => ?T("A list of OpenSSL ciphers to use for s2s connections. " "The default value is shown in the example below:"), example => ["s2s_ciphers:", " - HIGH", " - \"!aNULL\"", " - \"!eNULL\"", " - \"!3DES\"", " - \"@STRENGTH\""]}}, {s2s_dhfile, #{value => ?T("Path"), desc => ?T("Full path to a file containing custom DH parameters " "to use for s2s connections. " "Such a file could be created with the command \"openssl " "dhparam -out dh.pem 2048\". If this option is not specified, " "2048-bit MODP Group with 256-bit Prime Order Subgroup will be " "used as defined in RFC5114 Section 2.3.")}}, {s2s_protocol_options, #{value => "[Option, ...]", desc => ?T("List of general SSL options to use for s2s connections. " "These map to OpenSSL's 'set_options()'. The default value is " "shown in the example below:"), example => ["s2s_protocol_options:", " - no_sslv3", " - cipher_server_preference", " - no_compression"]}}, {s2s_tls_compression, #{value => "true | false", desc => ?T("Whether to enable or disable TLS compression for s2s connections. " "The default value is 'false'.")}}, {s2s_dns_retries, #{value => ?T("Number"), desc => ?T("DNS resolving retries. The default value is '2'.")}}, {s2s_dns_timeout, #{value => "timeout()", desc => ?T("The timeout for DNS resolving. The default value is '10' seconds.")}}, {s2s_max_retry_delay, #{value => "timeout()", desc => ?T("The maximum allowed delay for s2s connection retry to connect after a " "failed connection attempt. The default value is '300' seconds " "(5 minutes).")}}, {s2s_queue_type, #{value => "ram | file", desc => ?T("The type of a queue for s2s packets. " "See description of _`queue_type`_ option for the explanation. " "The default value is the value defined in _`queue_type`_ " "or 'ram' if the latter is not set.")}}, {s2s_timeout, #{value => "timeout()", desc => ?T("A time to wait before closing an idle s2s connection. " "The default value is '10 minutes'.")}}, {s2s_use_starttls, #{value => "true | false | optional | required", desc => ?T("Whether to use STARTTLS for s2s connections. " "The value of 'false' means STARTTLS is prohibited. " "The value of 'true' or 'optional' means STARTTLS is enabled " "but plain connections are still allowed. And the value of " "'required' means that only STARTTLS connections are allowed. " "The default value is 'false' (for historical reasons).")}}, {s2s_zlib, #{value => "true | false", desc => ?T("Whether to use 'zlib' compression (as defined in " "https://xmpp.org/extensions/xep-0138.html[XEP-0138]) or not. " "The default value is 'false'. WARNING: this type " "of compression is nowadays considered insecure.")}}, {shaper, #{value => "{ShaperName: Rate}", desc => ?T("The option defines a set of shapers. Every shaper is assigned " "a name 'ShaperName' that can be used in other parts of the " "configuration file, such as _`shaper_rules`_ option. The shaper " "itself is defined by its 'Rate', where 'Rate' stands for the " "maximum allowed incoming rate in **bytes** per second. " "When a connection exceeds this limit, ejabberd stops reading " "from the socket until the average rate is again below the " "allowed maximum. In the example below shaper 'normal' limits " "the traffic speed to 1,000 bytes/sec and shaper 'fast' limits " "the traffic speed to 50,000 bytes/sec:"), example => ["shaper:", " normal: 1000", " fast: 50000"]}}, {shaper_rules, #{value => "{ShaperRuleName: {Number|ShaperName: ACLRule|ACLName}}", desc => ?T("An entry allowing to declaring shaper to use for matching user/hosts. " "Semantics is similar to _`access_rules`_ option, the only difference is " "that instead using 'allow' or 'deny', a name of a shaper (defined in " "_`shaper`_ option) or a positive number should be used."), example => ["shaper_rules:", " connections_limit:", " 10:", " user: peter@example.com", " 100: admin", " 5: all", " download_speed:", " fast: admin", " slow: anonymous_users", " normal: all", " log_days: 30"]}}, {sm_cache_life_time, #{value => "timeout()", desc => ?T("Same as _`cache_life_time`_, but applied to client sessions table cache " "only. If not set, the value from _`cache_life_time`_ will be used.")}}, {sm_cache_missed, #{value => "true | false", desc => ?T("Same as _`cache_missed`_, but applied to client sessions table cache " "only. If not set, the value from _`cache_missed`_ will be used.")}}, {sm_cache_size, #{value => "pos_integer() | infinity", desc => ?T("Same as _`cache_size`_, but applied to client sessions table cache " "only. If not set, the value from _`cache_size`_ will be used.")}}, {sm_db_type, #{value => "mnesia | redis | sql", desc => ?T("Database backend to use for client sessions information. " "The default value is picked from _`default_ram_db`_ option, or " "if it's not set, 'mnesia' will be used.")}}, {sm_use_cache, #{value => "true | false", desc => ?T("Same as _`use_cache`_, but applied to client sessions table cache " "only. If not set, the value from _`use_cache`_ will be used.")}}, {sql_type, #{value => "mssql | mysql | odbc | pgsql | sqlite", desc => ?T("The type of an SQL connection. The default is 'odbc'.")}}, {sql_connect_timeout, #{value => "timeout()", desc => ?T("A time to wait for connection to an SQL server to be " "established. The default value is '5' seconds.")}}, {sql_database, #{value => ?T("Database"), desc => ?T("An SQL database name. For SQLite this must be a full " "path to a database file. The default value is 'ejabberd'.")}}, {sql_keepalive_interval, #{value => "timeout()", desc => ?T("An interval to make a dummy SQL request to keep alive the " "connections to the database. There is no default value, so no " "keepalive requests are made.")}}, {sql_odbc_driver, #{value => "Path", note => "added in 20.12", desc => ?T("Path to the ODBC driver to use to connect to a Microsoft SQL " "Server database. This option is only valid if the _`sql_type`_ " "option is set to 'mssql'. " "The default value is: 'libtdsodbc.so'")}}, {sql_password, #{value => ?T("Password"), desc => ?T("The password for SQL authentication. The default is empty string.")}}, {sql_pool_size, #{value => ?T("Size"), desc => ?T("Number of connections to the SQL server that ejabberd will " "open for each virtual host. The default value is 10. WARNING: " "for SQLite this value is '1' by default and it's not recommended " "to change it due to potential race conditions.")}}, {sql_port, #{value => "1..65535", desc => ?T("The port where the SQL server is accepting connections. " "The default is '3306' for MySQL, '5432' for PostgreSQL and " "'1433' for MS SQL. The option has no effect for SQLite.")}}, {sql_prepared_statements, #{value => "true | false", note => "added in 20.01", desc => ?T("This option is 'true' by default, and is useful to disable " "prepared statements. The option is valid for PostgreSQL.")}}, {sql_query_timeout, #{value => "timeout()", desc => ?T("A time to wait for an SQL query response. " "The default value is '60' seconds.")}}, {sql_queue_type, #{value => "ram | file", desc => ?T("The type of a request queue for the SQL server. " "See description of _`queue_type`_ option for the explanation. " "The default value is the value defined in _`queue_type`_ " "or 'ram' if the latter is not set.")}}, {sql_server, #{value => ?T("Host"), desc => ?T("A hostname or an IP address of the SQL server. " "The default value is 'localhost'.")}}, {sql_ssl, #{value => "true | false", note => "improved in 20.03", desc => ?T("Whether to use SSL encrypted connections to the " "SQL server. The option is only available for MySQL and " "PostgreSQL. The default value is 'false'.")}}, {sql_ssl_cafile, #{value => ?T("Path"), desc => ?T("A path to a file with CA root certificates that will " "be used to verify SQL connections. Implies _`sql_ssl`_ " "and _`sql_ssl_verify`_ options are set to 'true'. " "There is no default which means " "certificate verification is disabled.")}}, {sql_ssl_certfile, #{value => ?T("Path"), desc => ?T("A path to a certificate file that will be used " "for SSL connections to the SQL server. Implies _`sql_ssl`_ " "option is set to 'true'. There is no default which means " "ejabberd won't provide a client certificate to the SQL " "server.")}}, {sql_ssl_verify, #{value => "true | false", desc => ?T("Whether to verify SSL connection to the SQL server against " "CA root certificates defined in _`sql_ssl_cafile`_ option. " "Implies _`sql_ssl`_ option is set to 'true'. " "The default value is 'false'.")}}, {sql_start_interval, #{value => "timeout()", desc => ?T("A time to wait before retrying to restore failed SQL connection. " "The default value is '30' seconds.")}}, {sql_username, #{value => ?T("Username"), desc => ?T("A user name for SQL authentication. " "The default value is 'ejabberd'.")}}, {trusted_proxies, #{value => "all | [Network1, Network2, ...]", desc => ?T("Specify what proxies are trusted when an HTTP request " "contains the header 'X-Forwarded-For'. You can specify " "'all' to allow all proxies, or specify a list of IPs, " "possibly with masks. The default value is an empty list. " "This allows, if enabled, to be able to know the real IP " "of the request, for admin purpose, or security configuration " "(for example using 'mod_fail2ban'). IMPORTANT: The proxy MUST " "be configured to set the 'X-Forwarded-For' header if you " "enable this option as, otherwise, the client can set it " "itself and as a result the IP value cannot be trusted for " "security rules in ejabberd.")}}, {validate_stream, #{value => "true | false", desc => ?T("Whether to validate any incoming XML packet according " "to the schemas of " "https://github.com/processone/xmpp#supported-xmpp-elements" "[supported XMPP extensions]. WARNING: the validation is only " "intended for the use by client developers - don't enable " "it in production environment. The default value is 'false'.")}}, {websocket_origin, #{value => "ignore | URL", desc => ?T("This option enables validation for 'Origin' header to " "protect against connections from other domains than given " "in the configuration file. In this way, the lower layer load " "balancer can be chosen for a specific ejabberd implementation " "while still providing a secure WebSocket connection. " "The default value is 'ignore'. An example value of the 'URL' is " "\"https://test.example.org:8081\".")}}, {websocket_ping_interval, #{value => "timeout()", desc => ?T("Defines time between pings sent by the server to a client " "(WebSocket level protocol pings are used for this) to keep " "a connection active. If the client doesn't respond to two " "consecutive pings, the connection will be assumed as closed. " "The value of '0' can be used to disable the feature. This option " "makes the server sending pings only for connections using the RFC " "compliant protocol. For older style connections the server " "expects that whitespace pings would be used for this purpose. " "The default value is '60' seconds.")}}, {websocket_timeout, #{value => "timeout()", desc => ?T("Amount of time without any communication after which the " "connection would be closed. The default value is '300' seconds.")}}]. %%%=================================================================== %%% Internal functions %%%===================================================================