Initial commit with previous code

This commit is contained in:
Antonio J. Delgado 2022-10-11 10:19:07 +03:00
commit 64a7dcf56b
59 changed files with 2120 additions and 0 deletions

72
.travis.yml Normal file
View file

@ -0,0 +1,72 @@
---
version: ~> 1.0
os: linux
language: shell
env:
- docker_repo: resin/rpi-raspbian
- docker_repo: geerlingguy/docker-debian10-ansible
- docker_repo: geerlingguy/docker-debian9-ansible
- docker_repo: geerlingguy/docker-centos7-ansible
- docker_repo: geerlingguy/docker-fedora30-ansible
- docker_repo: geerlingguy/docker-ubuntu1804-ansible
- docker_repo: geerlingguy/docker-ubuntu1604-ansible
jobs:
# TODO: Fix these failures?
allow_failures:
# TODO: Fixing the Raspbian build is going to require QEMU and
# binfmt_misc support. See:
# https://www.balena.io/blog/building-arm-containers-on-any-x86-machine-even-dockerhub/
# In the mean time, allow this to fail.
- env: docker_repo=resin/rpi-raspbian
- env: docker_repo=geerlingguy/docker-centos7-ansible
- env: docker_repo=geerlingguy/docker-fedora30-ansible
install:
- docker image pull ${docker_repo}
- container_id=$(mktemp)
- >
docker container run --detach --privileged
--volume /sys/fs/cgroup:/sys/fs/cgroup:ro
--volume ${PWD}:/etc/ansible/roles/ansible-role-prosody:ro
--publish 5222:5222
--publish 5269:5269
${docker_repo}:latest > ${container_id}
# Bootstrap to ensure Ansible is available in the container.
# This is to ensure that the containers not already pre-imaged with
# Ansible installed (i.e., Raspbian image) will have it available.
- >
docker container exec --tty $(cat ${container_id}) env TERM=xterm
pip install ansible
script:
# Check Ansible role/playbook syntax.
- >
docker container exec --tty "$(cat ${container_id})" env TERM=xterm
ansible-playbook --syntax-check /etc/ansible/roles/ansible-role-prosody/tests/test.yaml
# Ensure the role/playbook runs without errors or failures.
- >
docker exec --tty "$(cat ${container_id})" env TERM=xterm
ansible-playbook /etc/ansible/roles/ansible-role-prosody/tests/test.yaml
# Run the role/playbook again to test idempotence.
- idempotence=$(mktemp)
- >
docker exec "$(cat ${container_id})"
ansible-playbook /etc/ansible/roles/ansible-role-prosody/tests/test.yaml
| tee -a ${idempotence}
- >
tail ${idempotence}
| grep -q 'changed=0.*failed=0'
&& (echo 'Idempotence test: pass' && exit 0)
|| (echo 'Idempotence test: fail' && exit 1)
- nc -vz localhost 5222
- nc -vz localhost 5269
after_script:
- docker container rm -f "$(cat ${container_id})"

224
README.md Normal file
View file

@ -0,0 +1,224 @@
# Anarcho-Tech NYC: Prosody [![Build Status](https://travis-ci.org/AnarchoTechNYC/ansible-role-prosody.svg?branch=master)](https://travis-ci.org/AnarchoTechNYC/ansible-role-prosody)
An [Ansible role](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html) for installing and configuring a [Prosody](https://prosody.im/) server. Notably, this role has been tested with [Raspbian](https://www.raspbian.org/) on [Raspberry Pi](https://www.raspberrypi.org/) hardware. This role's purpose is to make it simple to install and configure an [XMPP](https://xmpp.org/) server in a variety of small- to medium-sized deployments.
## Prosody server configuration
To configure a Prosody server, several default variables are defined:
* `prosody_server_username`: The OS-level user account name under which Prosody will run. This defaults to `prosody`. Don't change this if you are installing Prosody from the project's `deb` file, as this is the name of the account that is packaged with the Prosody distribution.
* `prosody_server_data_dir`: Path to the directory in which Prosody will store user information. This defaults to `/var/lib/{{ prosody_server_username }}`, which is also the `prosody` user's default `$HOME` directory.
* `prosody_server_run_dir`: Path to the server's runtime directory, which stores ephemeral files used while the server is running. This defaults to `/var/run/{{ prosody_server_username }}`.
* `prosody_plugins_src_base_url`: Base HTTP URL of the Prosody plugins (modules) repository from which to download new modules.
* `prosody_plugins`: List of community Prosody plugins to install. Defaults to the empty list (`[]`). To have any effect, you must also set the `prosody_config.plugins_path` variable, described below. Each item in this list is a dictionary with the following structure:
* `name`: Name of the plugin to download and install.
* `state`: Whether the plugin should be installed (`present`, the default), or uninstalled (`absent`).
* `version`: Branch or commit of the version of the community plugin to download and install.
* `checksum`: Optional verification digest in `<algorithm>:<digest>` notation to compare the downloaded plugin file against. For example, `sha1:6d84b4f4d5108bce25fa9103157ddfc519362460`. See the `checksum` parameter for Ansible's [`get_url` module](https://docs.ansible.com/ansible/latest/modules/get_url_module.html) for details.
* `prosody_plugin_paths`: List of additional directories searched for Prosody plugins (modules) to load. Defaults to `["/usr/local/lib/prosody/modules"]`.
* `prosody_virtualhost_onions`: List of Onion services exposing a Prosody-backed service. Each item in this list is a dictionary with the following structure:
* `name`: Name of the Tor Onion service whose `hostname` file to read for additional (`.onion`) domains to add as Prosody VirtualHosts.
* `options`: Dictionary of Prosody configuration options, same as the `prosody_config.VirtualHosts` variable described below, with which to configure the given Prosody VirtualHost Onion service.
The bulk of Prosody's configuration is handled by a dictionary variable called `prosody_config`. It describes the state of the Prosody server configuration file. The dictionary's keys map almost one-to-one to the [variables in the Prosody server configuration file](https://prosody.im/doc/configure).
An exception is the `VirtualHosts` key, which is a list of dictionaries each [describing a Prosody `VirtualHost` to configure](#configuring-prosody-virtualhosts). Another exception is the `Components` key, which is a list of dictionaries describing a given [Prosody Component](https://prosody.im/doc/components). Components must have a `hostname` key, and one of either `plugin` (for internal components) or `secret` (for external components). They may optionally also contain an `options` list, which is a dictionary of component options and their values.
Since the exact structure of the `prosody_config` dictionary is not always predictable (e.g., a given option may be defined as part of a `VirtualHost`-specific configuration rather than in the Prosody configuration's global section, or said option may be relevant only to a certain Prosody module), numerous convenience variables provide more easily accessible names for these cases. For example `prosody_http_files_dir` is a role default top-level variable that you can use as the default for [the `http_files_dir` option](https://prosody.im/doc/modules/mod_http_files) wherever it may happen to appear under `prosody_config`.
Among these convenience variables are:
* `prosody_admins`: List of bare JabberIDs (e.g., `admin@example.com`) granted administrative privileges. This can be used as the value of the `admins` configuration option in either the global section or a given `VirtualHost`. Defaults to an empty list (`[]`).
* `prosody_allow_registration`: Boolean indicating whether user registration is enabled by default. Defaults to `false`.
* `prosody_c2s_require_encryption`: Boolean indicating whether the server should enforce encrypted (`STARTTLS`) connections. Defaults to `true`.
* `prosody_c2s_ports`: List of ports to listen on for connections from XMPP clients. Defaults to `[5222]`.
* `prosody_s2s_require_encryption`: Boolean indicating whether the server should enforce encrypted (`STARTTLS`) connections with other XMPP servers. Defaults to `true`.
* `prosody_s2s_ports`: List of ports to listen on for connections from other XMPP servers. Defaults to `[5269]`.
* `prosody_s2s_secure_auth`: Boolean indicating whether or to restrict authentication of other XMPP servers to their presented TLS certificates. Defaults to `true`.
* `prosody_modules_enabled`: List of Prosody modules to enable. This can be used as the value of the `modules_enabled` configuration option in either the global section or a given `VirtualHost`.
* `prosody_modules_disabled`: List of Prosody modules to disable. This can be used as the value of the `modules_disabled` configuration option in either the global section or a given `VirtualHost`. Defaults to an empty list (`[]`).
* `prosody_http_files_dir`: Path to a directory from which Prosody's various HTTP modules should serve static files, i.e., [the Prosody HTTP server](https://prosody.im/doc/http) document root.
* `prosody_virtualhosts`: List of Prosody VirtualHosts dictionaries. This is used as the default value of the `prosody_config.VirtualHosts` key and can be used to override (or append to) the Prosody VirtualHosts list by a group- or host-specific inventory. The following example shows how to override the `prosody_config.VirtualHosts` key as well as how to extend (append to) the `prosody_plugins` list from a [group variables](https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#group-variables) file.
```yaml
# In `group_vars/all.yaml` file.
---
prosody_virtualhosts:
- domain: chat.example.com
# In `group_vars/public_chat_servers.yaml` file.
---
# Add the `mod_bookmarks` and `mod_default_bookmarks` plugins
# for Prosody servers in this group.
prosody_plugins: "{{ prosody_plugins + [{name: bookmarks}, {name: default_bookmarks}] }}"
# Override the Prosody configuration for VirtualHosts.
prosody_virtualhosts:
- domain: public-chat.example.com
default_bookmarks: # Configure `mod_default_bookmarks` plugin.
- jid: "help@conference.example.com"
```
The above configuration will result in the `chat.example.com` VirtualHost being configured for all servers *except* those in the `public_chat_servers` Ansible inventory group. The latter group will have all the same Prosody modules installed, as well as the `bookmarks` and `default_bookmarks` community modules. On hosts in the `public_chat_servers` Ansible inventory group, the configured Prosody VirtualHost will be `public-chat.example.com` and will include a `default_bookmarks` configuration.
* `prosody_components`: List of Prosody Components dictionaries. This is used as the default value of the `prosody_config.Components` key and can be used to override (or append to) the Prosody Components list in a similar fashion as the `prosody_virtualhosts` list can. Defaults to `[]`.
Refer to the [`defaults/main.yaml`](defaults/main.yaml) file for a complete accounting of these variables.
It may be helpful to see a few examples.
1. Default Prosody installation:
```yaml
prosody_config:
admins: []
modules_enabled:
- roster
- saslauth
- tls
- dialback
- disco
- carbons
- pep
- private
- blocklist
- vcard
- version
- uptime
- time
- ping
- register
- admin_adhoc
modules_disabled: []
allow_registration: false
c2s_require_encryption: true
s2s_require_encryption: true
s2s_secure_auth: false
pidfile: "{{ prosody_server_run_dir }}/prosody.pid"
authentication: internal_hashed
archive_expires_after: "1w"
certificates: certs
VirtualHosts:
- domain: localhost
```
This is equivalent to the Prosody 0.10 configuration file that ships with the project. If the above settings are what you desire, you need not include a `prosody_config` dictionary at all.
1. Prosody server responsible for two domains (`localhost` and `open-registration.local`), the latter of which allows in-band XMPP account registration while the former does not:
```yaml
admins:
- admin@localhost
allow_registration: false
VirtualHosts:
- domain: localhost
- domain: open-registration.local
allow_registration: true
```
1. Prosody server with [SQL-backed data store](https://prosody.im/doc/modules/mod_storage_sql) on PostgreSQL:
```yaml
storage: sql
sql:
driver: PostgreSQL
database: prosody_db
host: localhost
port: 3306
username: prosody
password: your_password
```
1. Prosody server with [certain user data pieces split across multiple storage backends](https://prosody.im/doc/storage):
```yaml
default_storage: internal
storage:
accounts: sql
roster: sql
sql:
driver: MySQL
database: prosody_db
host: localhost
port: 3306
username: prosody
password: your_password
```
The above will store user accounts and passwords, as well as user contact lists (rosters) in the MySQL database on the localhost, but other data, such as user's own profile information (vCards), will use the default `internal` (filesystem-based) storage backend.
1. Simple [multi-user chat (MUC)](https://prosody.im/doc/chatrooms) server with a few non-default options configured:
```yaml
Components:
- hostname: conference.example.com
plugin: muc
options:
max_history_messages: 5
muc_room_default_language: es
restrict_room_creation: local
```
1. Simple MUC-enabled server using the [ConverseJS Web-based chat front-end](https://conversejs.org/) served via both HTTP and HTTPS on their alternate ports (`8080` and `8443`), using the server root as the ConverseJS endpoint, with in-band user registration enabled:
```yaml
prosody_plugins_src_base_url: https://hg.prosody.im/prosody-modules/raw-file/
prosody_plugins:
- name: conversejs
version: tip
prosody_config:
plugin_paths:
- /usr/local/lib/prosody/modules
modules_enabled:
- saslauth
- tls
- disco
- register
- pep
- roster
- carbons
- vcard # Optional, but needed for ConverseJS avatar support.
allow_registration: true
pidfile: "{{ prosody_server_run_dir }}/prosody.pid"
authentication: internal_hashed
http_ports:
- 8080
https_ports:
- 8443
VirtualHosts:
- domain: example.com
modules_enabled:
- conversejs
http_paths:
conversejs: "/"
conversejs_options:
view_mode: fullscreen
conversejs_tags:
# This script provides Signal Protocol support (needed for OMEMO).
- '<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>'
Components:
- hostname: conference.example.com
plugin: muc
options:
restrict_room_creation: local
prosody_users:
- jid: alice@example.com
password: password
- jid: bob@example.com
password: password
```
The above configuration will ensure that `alice@example.com` can log in via the ConverseJS Web front-end at `http://example.com:8080/` with their initial account password of `password`, as well as providing a registration link for new users.
### Configuring Prosody VirtualHosts
A single Prosody XMPP server can serve multiple domains. That is to say, if your server is addressable on `example.com` but you want your users to have JabberIDs in the form of `user@otherdomain.com`, you can configure Prosody with `otherdomain.com` as a VirtualHost to claim responsibility for it, even though the server itself is available only at `example.com`. To do so, you will need to [configure Prosody VirtualHosts](https://prosody.im/doc/configure#adding_a_host).
In the `prosody_config` dictionary, a `VirtualHosts` list provides an interface to configuring any number of Prosody VirtualHosts. For the most part, an item in the `VirtualHosts` list is equivalent to a VirtualHost-specific configuration that overrides the same setting in the global configuration dictionary. This allows you to create a default (global) configuration that can have per-host overrides.
Each VirtualHost dictionary further accepts the following additional keys:
* `domain`: The fully-qualified domain name (FQDN) of the VirtualHost.
* `state`: Can be `present` (the default if undefined), in which case the VirtualHost-specific configuration will be written to disk, or `absent`, in which case it will be removed.
* `enabled`: Boolean that determines whether or not the VirtualHost will be active (loaded by Prosody and symlinked to [the `virtualhosts-enabled` directory](enabling-and-disabling-prosody-virtualhost-configurations)). Defaults to `true` if left undefined.
#### Enabling and disabling Prosody VirtualHost configurations
Individual VirtualHost configurations are stored in the `/etc/prosody/virtualhosts-available` directory when their `state` is set to `present`. For example, if you have a VirtualHost with a `domain` of `otherdomain.com`, the file `/etc/prosody/virtualhosts-available/otherdomain.com.cfg.lua` will be written. If this VirtualHost is also `enabled`, that file will be symlinked from `/etc/prosody/virtualhosts-enabled/otherdomain.com.cfg.lua`. The main prosody configuration file (`/etc/prosody/prosody.cfg.lua`) [`Include`'s](https://prosody.im/doc/packagers#including_separate_files) any file ending in `.cfg.lua` in the directory `/etc/prosody/virtualhosts-enabled` when the `prosody_config.VirtualHost` key is defined.
You can manually disable a Prosody VirtualHost by removing the symbolic link pointing to the VirtualHost configuration file and then reloading the server:
```sh
sudo -u prosody rm /etc/prosody/virtualhosts-enabled/otherdomain.cfg.lua
sudo prosodyctl reload
```
## Configuring Prosody user accounts
You can define a list of user accounts to ensure are present or absent from the Prosody server using the `prosody_users` list. The items in this list are dictionaries that describe the user account's properties. The keys of this dictionary are as follows:
* `jid`: The [bare JabberID](https://xmpp.org/rfcs/rfc3920.html#rfc.section.3.3) of the user account.
* `password`: The password for the user account. You should almost certainly [ensure this value is encrypted with Ansible Vault](https://docs.ansible.com/ansible/latest/user_guide/vault.html#encrypt-string-for-use-in-yaml).
* `state`: Can be `present` (the default), to ensure the user account exists, or `absent`, to ensure it does not.

177
defaults/main.yaml Normal file
View file

@ -0,0 +1,177 @@
---
prosody_server_username: prosody
prosody_server_data_dir: "/var/lib/{{ prosody_server_username }}"
prosody_server_run_dir: "/var/run/{{ prosody_server_username }}"
# Base HTTP URL of the Prosody plugins (modules) repository from which
# to download new modules.
prosody_plugins_src_base_url: https://hg.prosody.im/prosody-modules/raw-file/
# List of community Prosody plugins to install.
prosody_plugins: [] # Empty by default, structure like this:
# - name: conversejs # Name of the plugin to install.
# state: present # Whether the plugin should be installed or not.
# version: 2681f74750b2 # Branch or commit of the version to install.
# # If set, hash of the downloaded module file to compare against.
# checksum: sha1:6d84b4f4d5108bce25fa9103157ddfc519362460
# List of directories where Prosody plugins are searched.
prosody_plugin_paths:
- /usr/local/lib/prosody/modules
# List of JIDs granted administrative privileges to the XMPP server.
prosody_admins: []
# Whether or not to enable user registration by default.
prosody_allow_registration: false
# Whether to force TLS connections by default.
prosody_c2s_require_encryption: true
# List of ports to listen on for connections from XMPP clients.
prosody_c2s_ports:
- 5222
# Whether or not to require server-to-server connections to use TLS.
prosody_s2s_require_encryption: true
# List of ports to listen on for connections from XMPP servers.
prosody_s2s_ports:
- 5269
# Whether to authenticate other servers using only TLS certificates.
prosody_s2s_secure_auth: true
# List of Prosody modules enabled by default.
prosody_modules_enabled:
- roster
- saslauth
- tls
- dialback
- disco
- carbons
- pep
- private
- blocklist
- vcard
- version
- uptime
- time
- ping
- register
- admin_adhoc
# List of Prosody modules disabled by default.
prosody_modules_disabled: []
prosody_http_files_dir: "/var/www/prosody"
# List of Prosody VirtualHosts to configure.
prosody_virtualhosts:
- domain: localhost
#state: present
#enabled: true
#certificate: /etc/prosody/certs/localhost.crt
#key: /etc/prosody/certs/localhost.key
# The password should be encrypted with Ansible Vault.
#password: "passphrase to decrypt TLS key file"
# List of Prosody Components to configure.
prosody_components: []
# - hostname: conference.example.com
# plugin: muc
# options:
# restrict_room_creation: local
# List of Tor Onion service names whose onions should be added to the
# Prosody configuration's VirtualHosts list. This is mainly intended
# to make it possible to use Prosody HTTP modules that need to pass an
# HTTP Host header matching one of Tor's stealth Onion service onions.
#prosody_virtualhost_onions:
# - name: example-onion
# options: # Same as the `prosody_config.VirtualHost` keys.
# # The special string `__PROSODY_DOMAIN__` will be replaced with
# # the Onion domain extracted from the Tor `hostname` file.
# http_external_url: "http://__PROSODY_DOMAIN__/"
# Complete Prosody configuration.
prosody_config:
# Default TCP socket network interfaces to bind.
# See https://prosody.im/doc/ports#default_interfaces
#interfaces:
# - "*" # All IPv4 interfaces.
# - "::" # All IPv6 interfaces.
# Default private interfaces to bind to.
# See https://prosody.im/doc/ports#default_interfaces
#local_interfaces:
# - "127.0.0.1"
# - "::1"
admins: "{{ prosody_admins }}"
#data_path: "{{ prosody_server_data_dir }}"
plugin_paths: "{{ prosody_plugin_paths }}"
modules_enabled: "{{ prosody_modules_enabled }}"
modules_disabled: "{{ prosody_modules_disabled }}"
allow_registration: "{{ prosody_allow_registration }}"
# Client-to-server settings.
c2s_require_encryption: "{{ prosody_c2s_require_encryption }}"
c2s_ports: "{{ prosody_c2s_ports }}"
#c2s_interfaces:
# - "*"
# - "::"
# Server-to-server settings.
s2s_require_encryption: "{{ prosody_s2s_require_encryption }}"
s2s_secure_auth: "{{ prosody_s2s_secure_auth }}"
#s2s_insecure_domains: []
#s2s_secure_domains: []
s2s_ports: "{{ prosody_s2s_ports }}"
#s2s_interfaces:
# - "*"
# - "::"
pidfile: "{{ prosody_server_run_dir }}/prosody.pid"
authentication: internal_hashed
# See https://prosody.im/doc/storage
#default_storage: internal
#storage: internal
#sql_manage_tables: true
#sql:
#driver: SQLite3
#database: prosody.sqlite
#username: prosody
#password: secret
#host: localhost
archive_expires_after: "1w"
log:
info: "/var/log/prosody/prosody.log"
error: "/var/log/prosody/prosody.err"
#statistics: internal
#conflict_resolve: kick_old
#ignore_presence_priority: false
# Location of directory to find certificates in (relative to main config file)
certificates: certs
VirtualHosts: "{{ prosody_virtualhosts }}"
Components: "{{ prosody_components }}"
# List of user accounts registered with the Prosody server.
prosody_users: []
# - jid: admin@localhost
# password: password
# state: present
# - jid: test@localhost
# password: password
# state: absent

View file

@ -0,0 +1,2 @@
#!/bin/sh
/usr/bin/prosodyctl --root cert import /etc/letsencrypt/live

9
handlers/main.yaml Normal file
View file

@ -0,0 +1,9 @@
---
- name: Restart Prosody.
service:
name: prosody
state: restarted
- name: Restart SASLAuthd
service:
name: saslauthd
state: restarted

6
meta/main.yaml Normal file
View file

@ -0,0 +1,6 @@
---
galaxy_info:
role_name: prosody
company: Eat The Rich, Inc.
license: AGPL-3.0-or-later # SPDX tag from https://spdx.org/licenses/
min_ansible_version: 2.7

View file

@ -0,0 +1,42 @@
---
- name: Collect Prosody Onion domains.
register: onion_result
shell: >
cat {{ tor_onion_services_dir | default('/var/lib/tor') + '/' + item.name + '/hostname' | quote }}
| cut -d ' ' -f 1 | sort | uniq
loop: "{{ prosody_virtualhost_onions }}"
changed_when: false
- name: Register Prosody Onion VirtualHosts.
when: not ansible_check_mode
set_fact:
prosody_onion_virtualhosts: "{{ onion_result.results | map(attribute='stdout_lines') | list | flatten | unique }}"
# This task is a bit of a clever hack: it updates the `prosody_config`
# dictionary in-place by using the `|combine()` filter, after looping
# over the `options` dictionary in the `prosody_virtualhost_onions`
# variable. In order to do this entirely in a single task, some Jinja
# tricks are employed, notably using no-op `if` blocks to actually
# update the values of the items in the `item.1.options` dictionary.
- name: Insert Prosody Onion VirtualHosts to Prosody configuration.
when: prosody_onion_virtualhosts is defined
set_fact:
prosody_config: >-
{%- if item.1.options is defined -%}
{%- for k, v in item.1.options.items() -%}
{%- if v is string -%}
{%- if item.1.options.update({k: v | replace('__PROSODY_DOMAIN__', item.0)}) -%}{%- endif -%}
{%- elif v is mapping -%}{#- TODO: Handle dictionaries as well? -#}
{%- elif v is sequence -%}
{%- for x in v -%}
{%- if item.1.options[k].__setitem__(loop.index0, x | replace('__PROSODY_DOMAIN__', item.0)) -%}{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{{ prosody_config | combine({
'VirtualHosts': prosody_config.VirtualHosts + [{
'domain': item.0
} | combine(item.1.options | default({}), recursive=True)]
}, recursive=True) }}
loop: "{{ prosody_onion_virtualhosts | product(prosody_virtualhost_onions) | list }}"

82
tasks/configure_ldap.yml Normal file
View file

@ -0,0 +1,82 @@
---
# https://www.fyzix.net/index.php?title=Installing_and_configuring_Prosody_%2B_LDAP_support_%2B_Shared_groups_roster_generator
- name: Ensure SASL authd is configured to use LDAP
lineinfile:
path: /etc/default/saslauthd
regexp: '^MECHANISMS='
line: 'MECHANISMS="ldap"'
create: yes
owner: root
group: root
mode: '0644'
backup: yes
- name: Ensure SASL authd is enabled to use LDAP
lineinfile:
path: /etc/default/saslauthd
regexp: '^START='
line: 'START=yes'
create: yes
owner: root
group: root
mode: '0644'
backup: yes
- name: Ensure SASL authd has LDAP servers configured
lineinfile:
path: /etc/saslauthd.conf
regexp: '^ldap_servers: '
line: "ldap_servers: ldap://{{ ldap_config['server'] }}:{{ ldap_config['port'] }}/"
create: yes
owner: root
group: root
mode: '0644'
backup: yes
notify:
- Restart SASLAuthd
- name: Ensure SASL authd has LDAP search base configured
lineinfile:
path: /etc/saslauthd.conf
regexp: '^ldap_search_base: '
line: "ldap_search_base: {{ ldap_config['search'] }},{{ ldap_config['base_dn'] }}"
create: yes
owner: root
group: root
mode: '0644'
backup: yes
notify:
- Restart SASLAuthd
- name: Ensure SASL folder exists
file:
path: /etc/sasl
state: directory
- name: Ensure SASL XMPP password check is configured
lineinfile:
path: /etc/sasl/xmpp.conf
regexp: '^pwcheck_method: '
line: "pwcheck_method: saslauthd"
create: yes
owner: root
group: root
mode: '0644'
backup: yes
notify:
- Restart SASLAuthd
- name: Ensure SASL XMPP mechanism is configured
lineinfile:
path: /etc/sasl/xmpp.conf
regexp: '^mech_list: '
line: "mech_list: PLAIN"
create: yes
owner: root
group: root
mode: '0644'
backup: yes
notify:
- Restart SASLAuthd
- name: Ensure Prosody user is part of SASL
user:
name: prosody
append: yes
groups:
- sasl
notify:
- Restart Prosody.

35
tasks/install-debian.yaml Normal file
View file

@ -0,0 +1,35 @@
---
- name: Install Prosody apt dependencies.
apt:
name: apt-transport-https
- name: Install Prosody Python3 dependencies.
pip:
name: pexpect
state: latest
#executable: /usr/local/bin/pip3
- name: Add GPG key for Prosody package.
apt_key:
url: https://prosody.im/files/prosody-debian-packages.key
state: present
- name: Add Prosody package repository.
apt_repository:
#repo: "deb https://packages.prosody.im/debian {{ ansible_distribution_release | default('stretch') }} main"
repo: "deb https://packages.prosody.im/debian focal main"
state: present
- name: Install Prosody package.
apt:
update_cache: true
name: "{{ packages }}"
state: present
vars:
packages:
- prosody
- python-pexpect # For interacting with `prosodyctl`.
- liblua5.1-cyrussasl0
- libsasl2-modules-ldap
- libsasl2-2
- libsasl2-modules
- sasl2-bin

184
tasks/main.yaml Normal file
View file

@ -0,0 +1,184 @@
---
- name: Ensure XMPP ports are open
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
with_items:
- 5269
- 5222
- name: Configure Prosody VirtualHosts from Onion services.
when: prosody_virtualhost_onions is defined
import_tasks: configure-virtualhost-onions.yaml
- name: Install Prosody.
include_tasks: "install-{{ ansible_os_family | default('Debian') | lower }}.yaml"
- name: Import certificates from Let's Encrypt
shell: prosodyctl --root cert import /etc/letsencrypt/live
- name: Ensure Prosody TLS key is readable.
file:
path: /etc/prosody/certs/localhost.key
owner: "{{ prosody_server_username }}"
group: "{{ prosody_server_username }}"
mode: "400"
notify: Restart Prosody.
# FIXME: Variablize this so not only `localhost.{crt,key}` are used.
- name: Enable HTTPS TLS certificates.
file:
src: "{{ item.src }}"
dest: "/etc/prosody/certs/{{ item.dest }}"
state: link
loop:
- src: localhost.key
dest: https.key
- src: localhost.crt
dest: https.crt
- name: Ensure Prosody VirtualHost configuration directories exist.
file:
path: "/etc/prosody/{{ item }}"
state: directory
owner: "{{ prosody_server_username }}"
group: "{{ prosody_server_username }}"
mode: "700"
loop:
- virtualhosts-available
- virtualhosts-enabled
- name: Ensure Prosody plugin directories exist.
when: prosody_config.plugin_paths is defined
file:
path: "{{ item }}"
state: directory
owner: "{{ prosody_server_username }}"
group: "{{ prosody_server_username }}"
mode: "500"
loop: "{{ prosody_config.plugin_paths }}"
- name: Install Prosody plugin.
when:
- prosody_config.plugin_paths is defined
- prosody_plugins is defined
- item.state | default('present') == "present"
get_url:
url: "{{ prosody_plugins_src_base_url }}{{ item.version | default('tip') }}/mod_{{ item.name }}/mod_{{ item.name }}.lua"
# FIXME: Which plugin path? Just the first one, for now.
dest: "{{ prosody_config.plugin_paths[0] }}/mod_{{ item.name }}.lua"
checksum: "{{ item.checksum | default(omit) }}"
owner: "{{ prosody_server_username }}"
group: "{{ prosody_server_username }}"
mode: "400"
loop: "{{ prosody_plugins }}"
notify: Restart Prosody.
- name: Remove Prosody plugin.
when:
- prosody_config.plugin_paths is defined
- prosody_plugins is defined
- item.state | default('present') == "absent"
file:
# FIXME: Which plugin path? Just the first one, for now.
path: "{{ prosody_config.plugin_paths[0] }}/mod_{{ item.name }}.lua"
state: "{{ item.state | default('absent') }}"
loop: "{{ prosody_plugins }}"
- name: Add deploy hook to Let's Encrypt
copy:
src: files/prosody-deploy-hook.sh
dest: /etc/letsencrypt/renewal-hooks/deploy/prosody-deploy-hook.sh
mode: 0755
backup: yes
- name: Configure LDAP options
include_tasks: configure_ldap.yml
when: ldap_config is defined
# TODO(unknwon): Support variable directory placements.
# TODO(unknwon): Support specific TLS key/crt files rather than just `localhost`.
# - name: Manage VirtualHost TLS keys and certificates.
# vars:
# file_types:
# - key
# - crt
# block:
# - name: Link VirtualHost TLS keys and certificates.
# when:
# - prosody_config.VirtualHosts is defined
# - item.0.domain != "localhost"
# - item.0.state | default('present') == "present"
# file:
# path: "/etc/prosody/certs/{{ item.0.domain }}.{{ item.1 }}"
# state: link
# src: "localhost.{{ item.1 }}"
# loop: "{{ prosody_config.VirtualHosts | product(file_types) | list }}"
# - name: Remove TLS keys and certificates from absent VirtualHosts.
# when:
# - prosody_config.VirtualHosts is defined
# - item.0.domain != "localhost"
# - item.0.state | default('present') == "absent"
# file:
# path: "/etc/prosody/certs/{{ item.0.domain }}.{{ item.1 }}"
# state: absent
# loop: "{{ prosody_config.VirtualHosts | product(file_types) | list }}"
- name: Write Prosody configuration.
template:
src: prosody.cfg.lua.j2
dest: /etc/prosody/prosody.cfg.lua
owner: "{{ prosody_server_username }}"
group: "{{ prosody_server_username }}"
mode: "600"
# TODO(unknwon): Fix validation.
#validate: "prosodyctl --config %s check config"
notify: Restart Prosody.
- name: Write Prosody VirtualHost configuration.
when:
- prosody_config.VirtualHosts is defined
- item.state | default('present') == "present"
template:
src: prosody-virtualhost.cfg.lua.j2
dest: "/etc/prosody/virtualhosts-available/{{ item.domain }}.cfg.lua"
owner: "{{ prosody_server_username }}"
group: "{{ prosody_server_username }}"
mode: "600"
# TODO(unknwon): Fix validation.
#validate: "prosodyctl --config %s check config"
loop: "{{ prosody_config.VirtualHosts }}"
notify: Restart Prosody.
- name: Enable Prosody VirtualHost configuration.
when:
- prosody_config.VirtualHosts is defined
- item.enabled | default(true)
file:
path: "/etc/prosody/virtualhosts-enabled/{{ item.domain }}.cfg.lua"
state: link
src: "/etc/prosody/virtualhosts-available/{{ item.domain }}.cfg.lua"
loop: "{{ prosody_config.VirtualHosts }}"
notify: Restart Prosody.
- name: Remove absent Prosody VirtualHost configuration.
when:
- prosody_config.VirtualHosts is defined
- item.0.state | default('present') == "absent"
file:
path: "/etc/prosody/{{ item.1 }}/{{ item.0.domain }}.cfg.lua"
state: absent
loop: "{{ prosody_config.VirtualHosts | product(paths) | list }}"
vars:
paths:
- "virtualhosts-available"
- "virtualhosts-enabled"
notify: Restart Prosody.
- name: Set Prosody user accounts.
include_tasks: users.yaml
no_log: true
loop: "{{ prosody_users }}"
vars:
account_file: "{{ prosody_server_data_dir }}/{{ item.jid.split('@') | last | replace('.', '%2e') }}/accounts/{{ item.jid.split('@') | first }}.dat"

14
tasks/users.yaml Normal file
View file

@ -0,0 +1,14 @@
---
- name: Make Prosody user account.
when: item.state | default('present') == "present"
expect:
command: "prosodyctl adduser {{ item.jid | quote }}"
responses:
password: "{{ item.password }}"
creates: "{{ account_file }}"
- name: Remove absent Prosody user account.
when: item.state | default('present') == "absent"
command: "prosodyctl deluser {{ item.jid | quote }}"
args:
removes: "{{ account_file }}"

View file

@ -0,0 +1,3 @@
# Prosody module configuration templates
The `*.cfg.lua.j2` files in this folder are template fragments (`include`'d files) loaded by a parent template. Each template corresponds to the implementation of the various configuration options made available by the Prosody plugin ("module") named by the template file. For example, [the `mod_register.cfg.lua.j2` file](mod_register.cfg.lua.j2) implements the various options made available by [Prosody's `register` module](https://prosody.im/doc/modules/mod_register).

View file

@ -0,0 +1,13 @@
{#
Prosody server template fragment for the `admin_telnet` module.
For details, see:
https://prosody.im/doc/modules/mod_admin_telnet
#}
{% if cfg.console_ports is defined %}
console_ports = {
{% for port in cfg.console_ports %}
{{ port | int }};
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,32 @@
{#
Prosody server template fragment for the `bosh` module.
For details, see:
https://prosody.im/doc/modules/mod_bosh
#}
{% if cfg.bosh_max_inactivity is defined %}
bosh_max_inactivity = {{ cfg.bosh_max_inactivity | int }}
{% endif %}
{% if cfg.cross_domain_bosh is defined %}
cross_domain_bosh = {{ cfg.cross_domain_bosh | bool | lower }}
{% endif %}
{% if cfg.consider_bosh_secure is defined %}
consider_bosh_secure = {{ cfg.consider_bosh_secure | bool | lower }}
{% endif %}
{% if cfg.bosh_default_hold is defined %}
bosh_default_hold = {{ cfg.bosh_default_hold | int }}
{% endif %}
{% if cfg.bosh_max_requests is defined %}
bosh_max_requests = {{ cfg.bosh_max_requests | int }}
{% endif %}
{% if cfg.trusted_proxies is defined %}
trusted_proxies = {
{% for proxy in cfg.trusted_proxies %}
"{{ proxy }}";
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,21 @@
{#
Prosody server template fragment for the `c2s` module.
For details, see:
https://prosody.im/doc/modules/mod_c2s
#}
{% if cfg.c2s_ports is defined %}
c2s_ports = {
{% for port in cfg.c2s_ports %}
{{ port }},
{% endfor %}
}
{% endif %}
{% if cfg.c2s_interfaces is defined %}
c2s_interfaces = {
{% for addr in cfg.c2s_interfaces %}
"{{ addr }}",
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,9 @@
{#
Prosody server template fragment for the `compression` module.
For details, see:
https://prosody.im/doc/modules/mod_compression
#}
{% if cfg.compression_level is defined %}
compression_level = {{ cfg.compression_level | int }}
{% endif %}

View file

@ -0,0 +1,37 @@
{#
Prosody server template fragment for the `conversejs` module.
For details, see:
https://modules.prosody.im/mod_conversejs.html
#}
{% if cfg.conversejs_options is defined %}
conversejs_options = {
{% for k, v in cfg.conversejs_options.items() %}
{{ k }} = {% include "prosody-value.j2" %};
{% endfor %}
}
{% endif %}
{% if cfg.conversejs_cdn is defined %}
conversejs_cdn = "{{ cfg.conversejs_cdn }}"
{% endif %}
{% if cfg.conversejs_version is defined %}
conversejs_version = "{{ cfg.conversejs_version }}"
{% endif %}
{% if cfg.conversejs_script is defined %}
conversejs_script = "{{ cfg.conversejs_script }}"
{% endif %}
{% if cfg.conversejs_css is defined %}
conversejs_css = "{{ cfg.conversejs_css }}"
{% endif %}
{% if cfg.conversejs_tags is defined %}
conversejs_tags = {
{% for element in cfg.conversejs_tags %}
[[{{ element }}]];
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,9 @@
{#
Prosody server template fragment for the `csi_simple` module.
For details, see:
https://prosody.im/doc/modules/mod_csi_simple
#}
{% if cfg.csi_queue_size is defined %}
csi_queue_size = {{ cfg.csi_queue_size | int }}
{% endif %}

View file

@ -0,0 +1,23 @@
{#
Prosody server template fragment for the `default_bookmarks` module.
For details, see:
https://modules.prosody.im/mod_default_bookmarks.html
#}
{% if cfg.default_bookmarks is defined %}
default_bookmarks = {
{% for bookmark in cfg.default_bookmarks %}
{
{% if bookmark.jid is defined %}
jid = "{{ bookmark.jid }}";
{% endif %}
{% if bookmark.name is defined %}
name = "{{ bookmark.name }}";
{% endif %}
{% if bookmark.password is defined %}
password = "{{ bookmark.password }}";
{% endif %}
};
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,9 @@
{#
Prosody server template fragment for the `dialback` module.
For details, see:
https://prosody.im/doc/modules/mod_dialback
#}
{% if cfg.dialback_without_dialback is defined %}
dialback_without_dialback = {{ cfg.dialback_without_dialback | bool | lower }}
{% endif %}

View file

@ -0,0 +1,17 @@
{#
Prosody server template fragment for the `disco` module.
For details, see:
https://prosody.im/doc/modules/mod_disco
#}
{% if cfg.disco_items is defined %}
disco_items = {
{% for k, v in disco_items.items() %}
{"{{ k }}", "{{ v }}"};
{% endfor %}
}
{% endif %}
{% if cfg.disco_hidden is defined %}
disco_hidden = {{ cfg.disco_hidden | bool | lower }}
{% endif %}

View file

@ -0,0 +1,37 @@
{#
Prosody server template fragment for the `e2e_policy` module.
For details, see:
https://modules.prosody.im/mod_e2e_policy.html
#}
{% if cfg.e2e_policy_chat is defined %}
e2e_policy_chat = {{ cfg.e2e_policy_chat }}
{% endif %}
{% if cfg.e2e_policy_muc is defined %}
e2e_policy_muc = {{ cfg.e2e_policy_muc }}
{% endif %}
{% if cfg.e2e_policy_whitelist is defined %}
e2e_policy_whitelist = {
{% for jid in cfg.e2e_policy_whitelist %}
"{{ jid }}";
{% endfor %}
}
{% endif %}
{% if cfg.e2e_policy_message_optional_chat is defined %}
e2e_policy_message_optional_chat = {{ cfg.e2e_policy_message_optional_chat }}
{% endif %}
{% if cfg.e2e_policy_message_required_chat is defined %}
e2e_policy_message_required_chat = {{ cfg.e2e_policy_message_required_chat }}
{% endif %}
{% if cfg.e2e_policy_message_optional_muc is defined %}
e2e_policy_message_optional_muc = {{ cfg.e2e_policy_message_optional_muc }}
{% endif %}
{% if cfg.e2e_policy_message_required_muc is defined %}
e2e_policy_message_required_muc = {{ cfg.e2e_policy_message_required_muc }}
{% endif %}

View file

@ -0,0 +1,9 @@
{#
Prosody server template fragment for the `groups` module.
For details, see:
https://prosody.im/doc/modules/mod_groups
#}
{% if cfg.groups_file is defined %}
groups_file = "{{ cfg.groups_file }}"
{% endif %}

View file

@ -0,0 +1,74 @@
{#
Prosody server template fragment for the `http` module.
For details, see:
https://prosody.im/doc/modules/mod_http
#}
{% if cfg.http_default_host is defined %}
http_default_host = "{{ cfg.http_default_host }}"
{% endif %}
{% if cfg.http_ports is defined %}
http_ports = {
{% for port in cfg.http_ports %}
{{ port | int }};
{% endfor %}
}
{% endif %}
{% if cfg.http_interfaces is defined %}
http_interfaces = {
{% for interface in cfg.http_interfaces %}
{{ interface }};
{% endfor %}
}
{% endif %}
{% if cfg.https_ports is defined %}
https_ports = {
{% for port in cfg.https_ports %}
{{ port | int }};
{% endfor %}
}
{% endif %}
{% if cfg.https_interfaces is defined %}
https_interfaces = {
{% for interface in cfg.https_interfaces %}
{{ interface }};
{% endfor %}
}
{% endif %}
{% if cfg.https_certificate is defined %}
https_certificate = {% if cfg.https_certificate is string %}"{{ cfg.https_certificate }}"{% elif cfg.https_certificate is mapping %}
{
{% for port, path in cfg.https_certificate.items() %}
[{{ port | int }}] = "{{ path }}";
{% endfor %}
}
{% endif %}
{% endif %}
{% if cfg.https_ssl is defined %}
https_ssl = {
{% if cfg.https_ssl.certificate is defined %}
certificate = "{{ cfg.https_ssl.certificate }}";
{% endif %}
{% if cfg.https_ssl.key is defined %}
key = "{{ cfg.https_ssl.key }}";
{% endif %}
}
{% endif %}
{% if cfg.http_paths is defined %}
http_paths = {
{% for k, path in cfg.http_paths.items() %}
{{ k }} = "{{ path }}";
{% endfor %}
}
{% endif %}
{% if cfg.http_external_url is defined %}
http_external_url = "{{ cfg.http_external_url }}"
{% endif %}

View file

@ -0,0 +1,17 @@
{#
Prosody server template fragment for the `http_authentication` module.
For details, see:
https://modules.prosody.im/mod_http_authentication.html
#}
{% if cfg.http_credentials is defined %}
http_credentials = "{{ cfg.http_credentials }}"
{% endif %}
{% if cfg.unauthenticated_http_endpoints is defined %}
unauthenticated_http_endpoints = {
{% for endpoint in cfg.unauthenticated_http_endpoints %}
"{{ endpoint }}";
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,29 @@
{#
Prosody server template fragment for the `http_errors` module.
For details, see:
https://prosody.im/doc/modules/mod_http_errors
#}
{% if cfg.http_errors_detailed is defined %}
http_errors_detailed = {{ cfg.http_errors_detailed | bool | lower }}
{% endif %}
{% if cfg.http_errors_always_show is defined %}
http_errors_always_show = {{ cfg.http_errors_always_show | bool | lower }}
{% endif %}
{% if cfg.http_errors_default_message is defined %}
http_errors_default_message = [[{{ cfg.http_errors_default_message }}]]
{% endif %}
{% if cfg.http_errors_messages is defined %}
http_errors_messages = {
{% for code, msgs in cfg.http_errors_messages.items() %}
[{{ code | int }}] = {
{% for msg in msgs %}
[[{{ msg }}]];
{% endfor %}
};
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,9 @@
{#
Prosody server template fragment for the `http_favicon` module.
For details, see:
https://modules.prosody.im/mod_http_favicon.html
#}
{% if cfg.favicon is defined %}
favicon = "{{ cfg.favicon }}"
{% endif %}

View file

@ -0,0 +1,29 @@
{#
Prosody server template fragment for the `http_files` module.
For details, see:
https://prosody.im/doc/modules/mod_http_files
#}
{% if cfg.http_files_dir is defined %}
http_files_dir = "{{ cfg.http_files_dir }}"
{% endif %}
{% if cfg.http_index_files is defined %}
http_index_files = {
{% for file in cfg.http_index_files %}
"{{ file }}";
}
{% endfor %}
{% endif %}
{% if cfg.http_dir_listing is defined %}
http_dir_listing = {{ cfg.http_dir_listing | bool | lower }}
{% endif %}
{% if cfg.mime_types_file is defined %}
mime_types_file = "{{ cfg.mime_types_file }}"
{% endif %}
{% if cfg.http_files_cache_max_file_size is defined %}
http_files_cache_max_file_size = {{ cfg.http_files_cache_max_file_size | int }}
{% endif %}

View file

@ -0,0 +1,25 @@
{#
Prosody server template fragment for the `http_upload` module.
For details, see:
https://modules.prosody.im/mod_http_upload.html
#}
{% if cfg.http_max_content_size is defined %}
http_max_content_size = {{ cfg.http_max_content_size | int }}
{% endif %}
{% if cfg.http_upload_file_size is defined %}
http_upload_file_size = {{ cfg.http_upload_file_size | int }}
{% endif %}
{% if cfg.http_upload_expire_after is defined %}
http_upload_expire_after = {{ cfg.http_upload_expire_after | int }}
{% endif %}
{% if cfg.http_upload_quota is defined %}
http_upload_quota = {{ cfg.http_upload_quota | int }}
{% endif %}
{% if cfg.http_upload_path is defined %}
http_upload_path = "{{ cfg.http_upload_path }}"
{% endif %}

View file

@ -0,0 +1,13 @@
{#
Prosody server template fragment for the `lastlog` module.
For details, see:
https://modules.prosody.im/mod_lastlog.html
#}
{% if cfg.lastlog_ip_address is defined %}
lastlog_ip_address = {{ cfg.lastlog_ip_address | bool | lower }}
{% endif %}
{% if cfg.lastlog_stamp_offline is defined %}
lastlog_stamp_offline = {{ cfg.lastlog_stamp_offline | bool | lower }}
{% endif %}

View file

@ -0,0 +1,38 @@
{#
Prosody server template fragment for the `limits` module.
For details, see:
https://prosody.im/doc/modules/mod_limits
#}
{% if cfg.limits is defined %}
limits = {
{% if cfg.limits.c2s is defined %}
c2s = {
rate = "{{ cfg.limits.c2s.rate }}";
burst = "{{ cfg.limits.c2s.burst }}";
};
{% endif %}
{% if cfg.limits.s2sin is defined %}
s2sin = {
rate = "{{ cfg.limits.s2sin.rate }}";
burst = "{{ cfg.limits.s2sin.burst }}";
};
{% endif %}
{% if cfg.limits.s2sout is defined %}
s2sout = {
rate = "{{ cfg.limits.s2sout.rate }}";
burst = "{{ cfg.limits.s2sout.burst }}";
};
{% endif %}
{% if cfg.limits.component is defined %}
component = {
rate = "{{ cfg.limits.component.rate }}";
burst = "{{ cfg.limits.component.burst }}";
};
{% endif %}
}
{% endif %}
{% if cfg.limits_resolution is defined %}
limits_resolution = {{ cfg.limits_resolution | int }}
{% endif %}

View file

@ -0,0 +1,37 @@
{#
Prosody server template fragment for the `mam` module.
For details, see:
https://prosody.im/doc/modules/mod_mam
#}
{% if cfg.default_archive_policy is defined %}
default_archive_policy = {% with v=cfg.default_archive_policy %}{% include "../prosody-value.j2" %}{% endwith %}
{% endif %}
{% if cfg.archive_expires_after is defined %}
archive_expires_after = "{{ cfg.archive_expires_after }}"
{% endif %}
{% if cfg.archive_cleanup_interval is defined %}
archive_cleanup_interval = {{ cfg.archive_cleanup_interval | int }}
{% endif %}
{% if cfg.max_archive_query_results is defined %}
max_archive_query_results = {{ cfg.max_archive_query_results | int }}
{% endif %}
{% if cfg.archive_store is defined %}
archive_store = "{{ cfg.archive_store }}"
{% endif %}
{% if cfg.dont_archive_namespaces is defined %}
dont_archive_namespaces = {
{% for namespace in cfg.dont_archive_namespaces %}
"{{ namespace }}";
{% endfor %}
}
{% endif %}
{% if cfg.mam_smart_enable is defined %}
mam_smart_enable = {{ cfg.mam_smart_enable | bool | lower }}
{% endif %}

View file

@ -0,0 +1,13 @@
{#
Prosody server template fragment for the `motd` module.
For details, see:
https://prosody.im/doc/modules/mod_motd
#}
{% if cfg.motd_text is defined %}
motd_text = [[{{ cfg.motd_text }}]]
{% endif %}
{% if cfg.motd_jid is defined %}
motd_jid = "{{ cfg.motd_jid }}"
{% endif %}

View file

@ -0,0 +1,13 @@
{#
Prosody server template fragment for the `motd_sequential` module.
For details, see:
https://modules.prosody.im/mod_motd_sequential.html
#}
{% if cfg.motd_sequential_messages is defined %}
motd_sequential_messages = {
{% for m in cfg.motd_sequential_messages %}
[[{{ m }}]];
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,21 @@
{#
Prosody server template fragment for the `net_multiplex` module.
For details, see:
https://prosody.im/doc/modules/mod_net_multiplex
#}
{% if cfg.ports is defined %}
ports = {
{% for port in cfg.ports %}
{{ port | int }};
{% endfor %}
}
{% endif %}
{% if cfg.ssl_ports is defined %}
ssl_ports = {
{% for port in cfg.ssl_ports %}
{{ port | int }};
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,36 @@
{#
Prosody server template fragment for the `onions` module.
For details, see:
https://modules.prosody.im/mod_onions.html
#}
{% if cfg.onions_socks5_host is defined %}
onions_socks5_host = "{{ cfg.onions_socks5_host }}"
{% endif %}
{% if cfg.onions_socks5_port is defined %}
onions_socks5_port = {{ cfg.onions_socks5_port | int }}
{% endif %}
{% if cfg.onions_only is defined %}
onions_only = {{ cfg.onions_only | bool | lower }}
{% endif %}
{% if cfg.onions_tor_all is defined %}
onions_tor_all = {{ cfg.onions_tor_all | bool | lower }}
{% endif %}
{% if cfg.onions_map is defined %}
onions_map = {
{% for domain, onion in cfg.onions_map.items() %}
["{{ domain }}"] = {
{% if onion.host is defined %}
host = "{{ onion.host }}";
{% endif %}
{% if onion.port is defined %}
port = "{{ onion.port }}";
{% endif %}
};
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,9 @@
{#
Prosody server template fragment for the `pep` module.
For details, see:
https://prosody.im/doc/modules/mod_pep
#}
{% if cfg.pep_max_items is defined %}
pep_max_items = {{ cfg.pep_max_items | int }}
{% endif %}

View file

@ -0,0 +1,21 @@
{#
Prosody server template fragment for the `posix` module.
For details, see:
https://prosody.im/doc/modules/mod_posix
#}
{% if cfg.run_as_root is defined %}
run_as_root = {{ cfg.run_as_root | bool | lower }}
{% endif %}
{% if cfg.daemonize is defined %}
daemonize = {{ cfg.daemonize | bool | lower }}
{% endif %}
{% if cfg.pidfile is defined %}
pidfile = "{{ cfg.pidfile }}"
{% endif %}
{% if cfg.umask is defined %}
umask = "{{ cfg.umask }}"
{% endif %}

View file

@ -0,0 +1,57 @@
{#
Prosody server template fragment for the `register` module.
For details, see:
https://prosody.im/doc/modules/mod_register
#}
{% if cfg.registration_title is defined %}
registration_title = "{{ cfg.registration_title }}"
{% endif %}
{% if cfg.registration_instructions is defined %}
registration_instructions = "{{ cfg.registration_instructions }}"
{% endif %}
{% if cfg.allow_registration is defined %}
allow_registration = {{ cfg.allow_registration | bool | lower }}
{% endif %}
{% if cfg.registration_blacklist is defined %}
registration_blacklist = {
{% for ip_address in cfg.registration_blacklist %}
"{{ ip_address }}";
{% endfor %}
}
{% endif %}
{% if cfg.registration_whitelist is defined %}
registration_whitelist = {
{% for ip_address in cfg.registration_whitelist %}
"{{ ip_address }}";
{% endfor %}
}
{% endif %}
{% if cfg.whitelist_registration_only is defined %}
whitelist_registration_only = {{ cfg.whitelist_registration_only | bool | lower }}
{% endif %}
{% if cfg.min_seconds_between_registrations is defined %}
min_seconds_between_registrations = {{ cfg.min_seconds_between_registrations | int }}
{% endif %}
{% if cfg.registration_throttle_max is defined %}
registration_throttle_max = {{ cfg.registration_throttle_max | int }}
{% endif %}
{% if cfg.registration_throttle_period is defined %}
registration_throttle_period = {{ cfg.registration_throttle_period | int }}
{% endif %}
{% if cfg.registration_throttle_cache_size is defined %}
registration_throttle_cache_size = {{ cfg.registration_throttle_cache_size | int }}
{% endif %}
{% if cfg.blacklist_on_registration_throttle_overload is defined %}
blacklist_on_registration_throttle_overload = {{ cfg.blacklist_on_registration_throttle_overload | bool | lower }}
{% endif %}

View file

@ -0,0 +1,13 @@
{#
Prosody server template fragment for the `reload_modules` module.
For details, see:
https://modules.prosody.im/mod_reload_modules.html
#}
{% if cfg.reload_modules is defined %}
reload_modules = {
{% for m in cfg.reload_modules %}
"{{ m }}";
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,49 @@
{#
Prosody server template fragment for the `s2s` module.
For details, see:
https://prosody.im/doc/modules/mod_s2s
#}
{% if cfg.s2s_ports is defined %}
s2s_ports = {
{% for port in cfg.s2s_ports %}
{{ port }},
{% endfor %}
}
{% endif %}
{% if cfg.s2s_interfaces is defined %}
s2s_interfaces = {
{% for addr in cfg.s2s_interfaces %}
"{{ addr }}",
{% endfor %}
}
{% endif %}
{% if cfg.s2s_require_encryption is defined %}
s2s_require_encryption = {{ cfg.s2s_require_encryption | bool | lower }}
{% endif %}
{% if cfg.s2s_secure_auth is defined %}
s2s_secure_auth = {{ cfg.s2s_secure_auth | bool | lower }}
{% endif %}
{% if cfg.s2s_insecure_domains is defined %}
s2s_insecure_domains = {
{% for domain in cfg.s2s_insecure_domains %}
"{{ domain }}";
{% endfor %}
}
{% endif %}
{% if cfg.s2s_secure_domains is defined %}
s2s_secure_domains = {
{% for domain in cfg.s2s_secure_domains %}
"{{ domain }}";
{% endfor %}
}
{% endif %}
{% if cfg.allow_anonymous_s2s is defined %}
allow_anonymous_s2s = {{ cfg.allow_anonymous_s2s }}
{% endif %}

View file

@ -0,0 +1,25 @@
{#
Prosody server template fragment for the `saslauth` module.
For details, see:
https://prosody.im/doc/modules/mod_saslauth
#}
{% if cfg.allow_unencrypted_plain_auth is defined %}
allow_unencrypted_plain_auth = {{ cfg.allow_unencrypted_plain_auth | bool | lower }}
{% endif %}
{% if cfg.insecure_sasl_mechanisms is defined %}
insecure_sasl_mechanisms = {
{% for m in cfg.insecure_sasl_mechanisms %}
"{{ m }}";
{% endfor %}
}
{% endif %}
{% if cfg.disable_sasl_mechanisms is defined %}
disable_sasl_mechanisms = {
{% for m in cfg.disable_sasl_mechanisms %}
"{{ m }}";
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,52 @@
{#
Prosody server template fragment for the `server_contact_info` module.
For details, see:
https://prosody.im/doc/modules/mod_server_contact_info
#}
{% if cfg.contact_info is defined %}
contact_info = {
{% if cfg.contact_info.abuse is defined %}
abuse = {
{% for uri in cfg.contact_info.abuse %}
"{{ uri }}";
{% endfor %}
}
{% endif %}
{% if cfg.contact_info.admin is defined %}
admin = {
{% for uri in cfg.contact_info.admin %}
"{{ uri }}";
{% endfor %}
}
{% endif %}
{% if cfg.contact_info.feedback is defined %}
feedback = {
{% for uri in cfg.contact_info.feedback %}
"{{ uri }}";
{% endfor %}
}
{% endif %}
{% if cfg.contact_info.sales is defined %}
sales = {
{% for uri in cfg.contact_info.sales %}
"{{ uri }}";
{% endfor %}
}
{% endif %}
{% if cfg.contact_info.security is defined %}
security = {
{% for uri in cfg.contact_info.security %}
"{{ uri }}";
{% endfor %}
}
{% endif %}
{% if cfg.contact_info.support is defined %}
support = {
{% for uri in cfg.contact_info.support %}
"{{ uri }}";
{% endfor %}
}
{% endif %}
}
{% endif %}

View file

@ -0,0 +1,29 @@
{#
Prosody server template fragment for the `storage_sql` module.
For details, see:
https://prosody.im/doc/modules/mod_storage_sql
#}
{% if cfg.sql_manage_tables is defined %}
sql_manage_tables = {{ cfg.sql_manage_tables | bool | lower }}
{% endif %}
{% if cfg.sql is defined %}
sql = {
{% if cfg.sql.driver is defined %}
driver = "{{ cfg.sql.driver }}",
{% endif %}
{% if cfg.sql.database is defined %}
database = "{{ cfg.sql.database }}",
{% endif %}
{% if cfg.sql.username is defined %}
username = "{{ cfg.sql.username }}",
{% endif %}
{% if cfg.sql.password is defined %}
password = "{{ cfg.sql.password }}",
{% endif %}
{% if cfg.sql.host is defined %}
host = "{{ cfg.sql.host }}",
{% endif %}
}
{% endif %}

View file

@ -0,0 +1,9 @@
{#
Prosody server template fragment for the `strict_https` module.
For details, see:
https://modules.prosody.im/mod_strict_https.html
#}
{% if cfg.hsts_header is defined %}
hsts_header = "{{ cfg.hsts_header }}"
{% endif %}

View file

@ -0,0 +1,17 @@
{#
Prosody server template fragment for the `support_contact` module.
For details, see:
https://modules.prosody.im/mod_support_contact.html
#}
{% if cfg.support_contact is defined %}
support_contact = "{{ cfg.support_contact }}"
{% endif %}
{% if cfg.support_contact_nick is defined %}
support_contact_nick = "{{ cfg.support_contact_nick }}"
{% endif %}
{% if cfg.support_contact_group is defined %}
support_contact_group = "{{ cfg.support_contact_group }}"
{% endif %}

View file

@ -0,0 +1,17 @@
{#
Prosody server template fragment for the `support_room` module.
For details, see:
https://modules.prosody.im/mod_support_room.html
#}
{% if cfg.support_room is defined %}
support_room = "{{ cfg.support_room }}"
{% endif %}
{% if cfg.support_room_inviter is defined %}
support_room_inviter = "{{ cfg.support_room_inviter }}"
{% endif %}
{% if cfg.support_room_reason is defined %}
support_room_reason = "{{ cfg.support_room_reason }}"
{% endif %}

View file

@ -0,0 +1,13 @@
{#
Prosody server template fragment for the `tls` module.
For details, see:
https://prosody.im/doc/modules/mod_tls
#}
{% if cfg.c2s_require_encryption is defined %}
c2s_require_encryption = {{ cfg.c2s_require_encryption | bool | lower }}
{% endif %}
{% if cfg.s2s_require_encryption is defined %}
s2s_require_encryption = {{ cfg.s2s_require_encryption | bool | lower }}
{% endif %}

View file

@ -0,0 +1,49 @@
{#
Prosody server template fragment for the `tls_policy` module.
For details, see:
https://modules.prosody.im/mod_tls_policy.html
#}
{% if cfg.tls_policy is defined %}
tls_policy = {% if cfg.tls_policy is string %}"{{ cfg.tls_policy }}"{% else %}{
{% if cfg.tls_policy.c2s is defined %}
c2s = {
{% if cfg.tls_policy.c2s.cipher is defined %}
cipher = "{{ cfg.tls_policy.c2s.cipher }}";
{% endif %}
{% if cfg.tls_policy.c2s.encryption is defined %}
encryption = "{{ cfg.tls_policy.c2s.encryption }}";
{% endif %}
{% if cfg.tls_policy.c2s.protocol is defined %}
protocol = "{{ cfg.tls_policy.c2s.protocol }}";
{% endif %}
{% if cfg.tls_policy.c2s.bits is defined %}
bits = {{ cfg.tls_policy.c2s.bits | int }};
{% endif %}
{% if cfg.tls_policy.c2s.authentication is defined %}
authentication = "{{ cfg.tls_policy.c2s.authentication }}";
{% endif %}
};
{% endif %}
{% if cfg.tls_policy.s2s is defined %}
s2s = {
{% if cfg.tls_policy.s2s.cipher is defined %}
cipher = "{{ cfg.tls_policy.s2s.cipher }}";
{% endif %}
{% if cfg.tls_policy.s2s.encryption is defined %}
encryption = "{{ cfg.tls_policy.s2s.encryption }}";
{% endif %}
{% if cfg.tls_policy.s2s.protocol is defined %}
protocol = "{{ cfg.tls_policy.s2s.protocol }}";
{% endif %}
{% if cfg.tls_policy.s2s.bits is defined %}
bits = {{ cfg.tls_policy.s2s.bits | int }};
{% endif %}
{% if cfg.tls_policy.s2s.authentication is defined %}
authentication = "{{ cfg.tls_policy.s2s.authentication }}";
{% endif %}
};
{% endif %}
}
{% endif %}
{% endif %}

View file

@ -0,0 +1,13 @@
{#
Prosody server template fragment for the `version` module.
For details, see:
https://prosody.im/doc/modules/mod_version
#}
{% if cfg.hide_os_type is defined %}
hide_os_type = {{ cfg.hide_os_type | bool | lower }}
{% endif %}
{% if cfg.os_version_command is defined %}
os_version_command = {{ cfg.os_version_command }}
{% endif %}

View file

@ -0,0 +1,17 @@
{#
Prosody server template fragment for the `watchregistrations` module.
For details, see:
https://prosody.im/doc/modules/mod_watchregistrations
#}
{% if cfg.registration_watchers is defined %}
registration_watchers = {
{% for w in cfg.registration_watchers %}
"{{ w }}";
{% endfor %}
}
{% endif %}
{% if registration_notification is defined %}
registration_notification = [[{{ cfg.registration_notification }}]]
{% endif %}

View file

@ -0,0 +1,21 @@
{#
Prosody server template fragment for the `websocket` module.
For details, see:
https://prosody.im/doc/modules/mod_websocket
#}
{% if cfg.c2s_close_timeout is defined %}
c2s_close_timeout = {{ cfg.c2s_close_timeout | int }}
{% endif %}
{% if cfg.consider_websocket_secure is defined %}
consider_websocket_secure = {{ cfg.consider_websocket_secure | bool | lower }}
{% endif %}
{% if cfg.cross_domain_websocket is defined %}
cross_domain_websocket = {
{% for d in cfg.cross_domain_websocket %}
"{{ d }}";
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,9 @@
{#
Prosody server template fragment for the `welcome` module.
For details, see:
https://prosody.im/doc/modules/mod_welcom
#}
{% if cfg.welcome_message is defined %}
welcome_message = [[{{ cfg.welcome_message }}]]
{% endif %}

View file

@ -0,0 +1,13 @@
{#
Prosody server template fragment for the `xhtmlim` module.
For details, see:
https://modules.prosody.im/mod_xhtmlim.html
#}
{% if cfg.strip_xhtml_style is defined %}
strip_xhtml_style = {{ cfg.strip_xhtml_style | bool | lower }}
{% endif %}
{% if cfg.bounce_invalid_xhtml is defined %}
bounce_invalid_xhtml = {{ cfg.bounce_invalid_xhtml | bool | lower }}
{% endif %}

View file

@ -0,0 +1,31 @@
{#
Template fragment implementation Prosody configuration file
data types. This fragment parses the given value (`v`) and
performs the appropriate syntactic transformations in order to
write syntactically correct Lua configuration code.
FIXME: Boolean values should be treated as booleans.
Not sure why we need to detect a string here.
Is `sameas` not testing appropriately?
#}
{% if v is sameas true or "true" == v %}
true
{% elif v is sameas false or "false" == v%}
false
{% elif v is string %}
"{{ v }}"
{% elif v is number %}
{{ v }}
{% elif v is mapping %}
{
{% for x, y in v.items() %}
{% with v = y %}{% include "prosody-value.j2" %};{% endwith %}{{''}}
{% endfor %}
}
{% elif v is sequence %}
{
{% for x in v %}
{% with v = x %}{% include "prosody-value.j2" %};{% endwith %}{{''}}
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,11 @@
-- Prosody VirtualHost configuration.
-- {{ ansible_managed }}
VirtualHost "{{ item.domain }}"
{% if item.enabled is defined %}
enabled = {{ item.enabled | bool | lower }}
{% endif %}
{% if item.http_host is defined %}
http_host = "{{ item.http_host }}"
{% endif %}
{% with cfg=item %}{% include "prosody.inc.j2" %}{% endwith %}

View file

@ -0,0 +1,7 @@
-- Prosody XMPP Server Configuration
-- {{ ansible_managed }}
{% with cfg=prosody_config %}{% include "prosody.inc.j2" %}{% endwith %}
{% if prosody_config.VirtualHosts is defined %}
Include "/etc/prosody/virtualhosts-enabled/*.cfg.lua"
{% endif %}

198
templates/prosody.inc.j2 Normal file
View file

@ -0,0 +1,198 @@
{#
This is a template fragment (included file) for the Prosody
server's configuration. It handles writing Lua based on the
values of either the global section or a given VirtualHost.
This template is passed the `cfg` Jinja context variable, a
copy of the resolved `prosody_config` variable set by the
Ansible play. To implement configuration options for various
Prosody plugins ("modules"), it further includes a template
located in the `modules/` directory.
Core configuration options are defined directly in this file.
#}
admins = {
{% if cfg.admins is defined %}
{% for jid in cfg.admins %}
"{{ jid }}";
{% endfor %}
{% endif %}
} -- END admins
{% if cfg.data_path is defined %}
data_path = "{{ cfg.data_path }}"
{% endif %}
{% if cfg.plugin_paths is defined %}
plugin_paths = {
{% for path in cfg.plugin_paths %}
"{{ path }}";
{% endfor %}
}
{% endif %}
{% if cfg.modules_enabled is defined %}
modules_enabled = {
{% for module in cfg.modules_enabled %}
"{{ module }}";
{% endfor %}
}
{% endif %}
{% if cfg.modules_disabled is defined %}
modules_disabled = {
{% for module in cfg.modules_disabled %}
"{{ module }}";
{% endfor %}
}
{% endif %}
{% if cfg.authentication is defined %}
authentication = "{{ cfg.authentication }}"
{% endif %}
{% if cfg.default_storage is defined %}
default_storage = "{{ cfg.default_storage }}"
{% endif %}
{% if cfg.storage is defined %}
storage = {% if cfg.storage is mapping %}{
{% for store in cfg.storage %}{% for k, v in store.items() %}
{{ k }} = "{{ v }}";
{% endfor %}{% endfor %}
}{% else %}"{{ cfg.storage }}"{% endif %}
{% endif %}
{% if cfg.log is defined %}
{# TODO: Templatize advanced logging rules: https://prosody.im/doc/advanced_logging #}
log = {% if cfg.log is string %}"{{ cfg.log }}"{% elif cfg.log is mapping %}{
{% if cfg.log.debug is defined %}debug = "{{ cfg.log.debug }}";{% endif %}{{''}}
{% if cfg.log.info is defined %}info = "{{ cfg.log.info }}";{% endif %}{{''}}
{% if cfg.log.warn is defined %}warn = "{{ cfg.log.warn }}";{% endif %}{{''}}
{% if cfg.log.error is defined %}error = "{{ cfg.log.error }}";{% endif %}{{''}}
}
{% endif %}
{% endif %}
{% if cfg.statistics is defined %}
statistics = "{{ cfg.statistics }}"
{% endif %}
{% if cfg.statistics_config is defined %}
statistics_config = {
{% if cfg.statistics_config.statsd_server is defined %}
statsd_server = "{{ cfg.statistics_config.statsd_server }}";
{% endif %}
{% if cfg.statistics_config.statsd_port is defined %}
statsd_port = "{{ cfg.statistics_config.statsd_port }}";
{% endif %}
}
{% endif %}
{% if cfg.statistics_interval is defined %}
statistics_interval = {{ cfg.statistics_interval | int }}
{% endif %}
{% if cfg.conflict_resolve is defined %}
conflict_resolve = "{{ cfg.conflict_resolve }}"
{% endif %}
{% if cfg.ignore_presence_priority is defined %}
ignore_presence_priority = {{ cfg.ignore_presence_priority | bool | lower }}
{% endif %}
{% if cfg.certificates is defined %}
certificates = "{{ cfg.certificates }}"
{% endif %}
{% if cfg.certificate is defined %}
certificate = "{{ cfg.certificate }}"
{% endif %}
{% if cfg.key is defined %}
key = "{{ cfg.key }}"
{% endif %}
{% if cfg.password is defined %}
password = "{{ cfg.password }}"
{% endif %}
{########################################################
## PROSODY CORE MODULES: #
## Include configuration fragments for Prosody modules. #
#########################################################}
{% include "modules/mod_admin_telnet.cfg.lua.j2" %}
{% include "modules/mod_bosh.cfg.lua.j2" %}
{% include "modules/mod_c2s.cfg.lua.j2" %}
{% include "modules/mod_compression.cfg.lua.j2" %}
{% include "modules/mod_csi_simple.cfg.lua.j2" %}
{% include "modules/mod_dialback.cfg.lua.j2" %}
{% include "modules/mod_disco.cfg.lua.j2" %}
{% include "modules/mod_groups.cfg.lua.j2" %}
{% include "modules/mod_http.cfg.lua.j2" %}
{% include "modules/mod_http_errors.cfg.lua.j2" %}
{% include "modules/mod_http_files.cfg.lua.j2" %}
{% include "modules/mod_limits.cfg.lua.j2" %}
{% include "modules/mod_mam.cfg.lua.j2" %}
{% include "modules/mod_motd.cfg.lua.j2" %}
{% include "modules/mod_net_multiplex.cfg.lua.j2" %}
{% include "modules/mod_pep.cfg.lua.j2" %}
{% include "modules/mod_posix.cfg.lua.j2" %}
{% include "modules/mod_proxy65.cfg.lua.j2" ignore missing %}{# TODO: Not yet implemented. #}
{% include "modules/mod_register.cfg.lua.j2" %}
{% include "modules/mod_s2s.cfg.lua.j2" %}
{% include "modules/mod_server_contact_info.cfg.lua.j2" %}
{% include "modules/mod_storage_sql.cfg.lua.j2" %}
{% include "modules/mod_tls.cfg.lua.j2" %}
{% include "modules/mod_version.cfg.lua.j2" %}
{% include "modules/mod_watchregistrations.cfg.lua.j2" %}
{% include "modules/mod_websocket.cfg.lua.j2" %}
{% include "modules/mod_welcome.cfg.lua.j2" %}
{########################################################
## PROSODY COMMUNITY MODULES: #
## Include configuration fragments for Prosody modules. #
#########################################################}
{% include "modules/mod_conversejs.cfg.lua.j2" %}
{% include "modules/mod_default_bookmarks.cfg.lua.j2" %}
{% include "modules/mod_e2e_policy.cfg.lua.j2" %}
{% include "modules/mod_http_authentication.cfg.lua.j2" %}
{% include "modules/mod_http_favicon.cfg.lua.j2" %}
{% include "modules/mod_http_upload.cfg.lua.j2" %}
{% include "modules/mod_lastlog.cfg.lua.j2" %}
{% include "modules/mod_motd_sequential.cfg.lua.j2" %}
{% include "modules/mod_onions.cfg.lua.j2" %}
{% include "modules/mod_reload_modules.cfg.lua.j2" %}
{% include "modules/mod_strict_https.cfg.lua.j2" %}
{% include "modules/mod_support_contact.cfg.lua.j2" %}
{% include "modules/mod_support_room.cfg.lua.j2" %}
{% include "modules/mod_tls_policy.cfg.lua.j2" %}
{% include "modules/mod_xhtmlim.cfg.lua.j2" %}
{########################################################
## PROSODY COMPONENT OPTIONS: #
#########################################################}
{% if cfg.component_ports is defined %}
component_ports = {
{% for port in cfg.component_ports %}
{{ port | int }};
{% endfor %}
}
{% endif %}
{% if cfg.component_interface is defined %}
component_interface = "{{ cfg.component_interface }}"
{% endif %}
{% if cfg.Components is defined %}
{% for component in cfg.Components %}
Component "{{ component.hostname | default('localhost') }}"{% if component.plugin is defined %} "{{ component.plugin }}"{% endif %}{{''}}
{% if component.secret is defined %}
component_secret = "{{ component.secret }}"
{% endif %}
{% if component.options is defined %}
{% for k, v in component.options.items() %}
{{ k }} = {% include "prosody-value.j2" %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}

20
tests/test.yaml Normal file
View file

@ -0,0 +1,20 @@
# This Ansible playbook runs test plays to ensure the role works.
---
- name: Test role.
hosts: localhost
pre_tasks:
- name: Update APT cache (Debian).
when: ansible_os_family == "Debian"
apt:
update_cache: true
# FIXME: This is here due to a bug in Ansible: https://github.com/ansible/ansible/issues/27798
changed_when: false
- name: Install netcat.
package:
name: netcat
state: present
roles:
- ansible-role-prosody