aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--inventory-example/10-hosts1
-rw-r--r--inventory-example/20-by-hostname.yml1
-rw-r--r--inventory-example/40-groups3
-rw-r--r--inventory-example/group_vars/all/firefox.yml2
-rw-r--r--inventory-example/group_vars/all/freeipa.yml6
-rw-r--r--inventory-example/group_vars/all/nsd.yml3
-rw-r--r--inventory-example/group_vars/all/synapse.yml8
-rw-r--r--inventory-example/group_vars/all/vault.yml9
-rw-r--r--playbooks/matrix.yml37
-rw-r--r--playbooks/site.yml1
-rw-r--r--playbooks/webserver_public_example.yml23
-rw-r--r--roles/apache/README.md2
-rw-r--r--roles/apache/defaults/main.yml6
-rw-r--r--roles/apache/tasks/main.yml14
-rw-r--r--roles/apache/templates/etc/httpd/conf.d/ssl.conf.j24
-rw-r--r--roles/apache/templates/etc/httpd/conf/httpd.conf.j24
-rw-r--r--roles/apache_vhost/README.md4
-rw-r--r--roles/apache_vhost/defaults/main.yml3
-rw-r--r--roles/apache_vhost/templates/etc/httpd/conf.d/vhost.conf.j214
-rw-r--r--roles/freeipa_server/files/usr/local/share/dirsrv/schema/matrix.ldif3
-rw-r--r--roles/freeipa_server/tasks/custom_schema.yml62
-rw-r--r--roles/synapse/defaults/main.yml58
-rw-r--r--roles/synapse/handlers/main.yml4
-rw-r--r--roles/synapse/meta/main.yml5
-rw-r--r--roles/synapse/tasks/database.yml21
-rw-r--r--roles/synapse/tasks/element.yml17
-rw-r--r--roles/synapse/tasks/freeipa.yml37
-rw-r--r--roles/synapse/tasks/main.yml67
-rw-r--r--roles/synapse/templates/etc/systemd/system/synapse.service.j242
-rw-r--r--roles/synapse/templates/var/lib/synapse/homeserver.yaml.j296
-rw-r--r--roles/synapse/templates/var/lib/synapse/logging.config.j223
-rw-r--r--roles/synapse/templates/var/www/element/config.json.j245
-rw-r--r--roles/synapse/vars/main.yml47
34 files changed, 655 insertions, 18 deletions
diff --git a/README.md b/README.md
index efed02f..18d5c53 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ variables it accepts.
[rspamd](roles/rspamd) | [Rspamd](https://rspamd.com/) spam filtering system
[sabredav](roles/sabredav) | [sabre/dav](https://sabre.io/) CalDAV and CardDAV server with custom FreeIPA integration
[prosody](roles/prosody) | [Prosody](https://prosody.im/) XMPP server
+[synapse](roles/synapse) | [Matrix](https://matrix.org/) homeserver
[gitolite](roles/gitolite) | Git repository with [Gitolite](https://gitolite.com/gitolite/index.html) access control
[cgit](roles/cgit) | [cgit](https://git.zx2c4.com/cgit/) web frontend for Git
[vaultwarden](roles/vaultwarden) | [Bitwarden-compatible password manager](https://github.com/dani-garcia/vaultwarden)
diff --git a/inventory-example/10-hosts b/inventory-example/10-hosts
index d8c4cc6..90e1acf 100644
--- a/inventory-example/10-hosts
+++ b/inventory-example/10-hosts
@@ -35,6 +35,7 @@ dmz-www1 ip=10.10.19.4
dmz-xmpp1 ip=10.10.19.5 cname=xmpp
dmz-turn1 ip=10.10.19.6 cname=turn
dmz-git1 ip=10.10.19.13
+dmz-matrix1 ip=10.10.19.14 cores=4 ram=8g disk=256g
dmz-asterisk1 ip=10.10.14.10 cname=asterisk cores=4
[unmanaged]
diff --git a/inventory-example/20-by-hostname.yml b/inventory-example/20-by-hostname.yml
index 165bd37..db1ba15 100644
--- a/inventory-example/20-by-hostname.yml
+++ b/inventory-example/20-by-hostname.yml
@@ -41,3 +41,4 @@ groups:
authoritative_nameservers: inventory_hostname is match('(dmz-)?dns[0-9]')
turn_servers: inventory_hostname is match('(dmz-)?turn[0-9]')
asterisk_servers: inventory_hostname is match('(dmz-)?asterisk[0-9]')
+ matrix_servers: inventory_hostname is match('(dmz-)?matrix[0-9]')
diff --git a/inventory-example/40-groups b/inventory-example/40-groups
index d4646ad..098c743 100644
--- a/inventory-example/40-groups
+++ b/inventory-example/40-groups
@@ -65,6 +65,9 @@ rsyslog_forward = no
[nagios_servers:vars]
apache_gssapi = True
+[matrix_servers:vars]
+apache_ssl_listen_ports='[443,{{ synapse_client_port }},{{ synapse_federation_port }}]'
+
[opnsense_firewalls:vars]
ansible_python_interpreter = /usr/local/bin/python3
diff --git a/inventory-example/group_vars/all/firefox.yml b/inventory-example/group_vars/all/firefox.yml
index 5ebc61b..07d227b 100644
--- a/inventory-example/group_vars/all/firefox.yml
+++ b/inventory-example/group_vars/all/firefox.yml
@@ -49,6 +49,8 @@ firefox_managed_bookmarks:
url: 'https://invidious.{{ domain }}'
- name: Jellyfin
url: 'https://jellyfin.{{ domain }}'
+ - name: Matrix
+ url: 'https://matrix.{{ domain }}'
- name: Nagios
url: 'https://nagios.{{ domain }}'
- name: Nitter
diff --git a/inventory-example/group_vars/all/freeipa.yml b/inventory-example/group_vars/all/freeipa.yml
index 3501061..15b7259 100644
--- a/inventory-example/group_vars/all/freeipa.yml
+++ b/inventory-example/group_vars/all/freeipa.yml
@@ -12,6 +12,7 @@ freeipa_users:
sn: Doe
mail: john@example.com
jid: john@example.com
+ mxid: johnnybravo
mail_aliases:
- john.nickname@example.com
- john.alias@exmaple.com
@@ -21,12 +22,14 @@ freeipa_users:
sn: Tables
mail: btables@example.com
jid: btables@example.com
+ mxid: aMatrixUsername
- name: janedoe
givenname: Jane
sn: Doe
mail: jane@example.com
jid: jane@example.com
+ mxid: plainjane
freeipa_groups:
# built-in freeipa admin group - be careful!
@@ -125,6 +128,9 @@ freeipa_groups:
- name: role-git-admin
group: sysadmins
+ - name: role-matrix-access
+ group: doefamily
+
freeipa_hbac_rules:
- name: sysadmins_ssh_and_console_to_all
description: allow sysadmins to ssh to all hosts
diff --git a/inventory-example/group_vars/all/nsd.yml b/inventory-example/group_vars/all/nsd.yml
index ff1afe6..d40351b 100644
--- a/inventory-example/group_vars/all/nsd.yml
+++ b/inventory-example/group_vars/all/nsd.yml
@@ -34,6 +34,7 @@ nsd_zones:
xmpp1 IN A 203.0.113.57
turn1 IN A 203.0.113.58
pbx1 IN A 203.0.113.59
+ matrix IN A 203.0.113.60
www IN CNAME www1
xmpp IN CNAME xmpp1
conference IN CNAME xmpp1
@@ -52,3 +53,5 @@ nsd_zones:
_sip._udp IN SRV 0 5 5060 pbx1
_sip._tcp IN SRV 0 5 5060 pbx1
_sip._tls IN SRV 0 5 5061 pbx1
+
+ _matrix._tcp IN SRV 0 5 8448 matrix
diff --git a/inventory-example/group_vars/all/synapse.yml b/inventory-example/group_vars/all/synapse.yml
new file mode 100644
index 0000000..ac3b4d5
--- /dev/null
+++ b/inventory-example/group_vars/all/synapse.yml
@@ -0,0 +1,8 @@
+synapse_registration_shared_secret: '{{ vault_synapse_registration_shared_secret }}'
+synapse_macaroon_secret_key: '{{ vault_synapse_macaroon_secret_key }}'
+synapse_form_secret: '{{ vault_synapse_form_secret }}'
+synapse_sysaccount_password: '{{ vault_synapse_sysaccount_password }}'
+
+synapse_domain: example.com
+synapse_server_name: matrix.example.com
+synapse_enable_registration: no
diff --git a/inventory-example/group_vars/all/vault.yml b/inventory-example/group_vars/all/vault.yml
index c3e29c5..58b597a 100644
--- a/inventory-example/group_vars/all/vault.yml
+++ b/inventory-example/group_vars/all/vault.yml
@@ -117,8 +117,17 @@ vault_rspamd_dkim_keys: # generate with `rspamadm dkim_keygen`
AAAAAAAAAAAAAAAAchangeme
-----END RSA PRIVATE KEY-----
+
+# synapse
+vault_synapse_sysaccount_password: changeme
+vault_synapse_registration_shared_secret: changeme
+vault_synapse_macaroon_secret_key: changeme
+vault_synapse_form_secret: changeme
+
+
# teddit
vault_teddit_reddit_app_id: changeme
+
# vaultwarden
vault_vaultwarden_admin_token: changeme # generate with `openssl rand -base64 48`
diff --git a/playbooks/matrix.yml b/playbooks/matrix.yml
new file mode 100644
index 0000000..8ddbc47
--- /dev/null
+++ b/playbooks/matrix.yml
@@ -0,0 +1,37 @@
+- name: configure matrix servers
+ hosts: matrix_servers
+ roles:
+ - role: common
+ tags: common
+
+ - role: synapse
+ tags: synapse
+
+ - role: apache_vhost
+ apache_server_name: '{{ synapse_server_name }}'
+ apache_server_aliases: []
+ apache_ssl_only: yes
+ apache_letsencrypt: yes
+ apache_listen_port: '{{ synapse_federation_port }}'
+ apache_config: '{{ synapse_apache_federation_config }}'
+ apache_config_name: '{{ synapse_server_name }}-federation'
+ tags: apache
+
+ - role: apache_vhost
+ apache_server_name: '{{ synapse_server_name }}'
+ apache_server_aliases: []
+ apache_ssl_only: yes
+ apache_letsencrypt: yes
+ apache_listen_port: '{{ synapse_client_port }}'
+ apache_config: '{{ synapse_apache_client_config }}'
+ apache_config_name: '{{ synapse_server_name }}-client'
+ tags: apache
+
+ - role: apache_vhost
+ apache_server_name: '{{ synapse_server_name }}'
+ apache_server_aliases: []
+ apache_letsencrypt: yes
+ apache_redirect_to_https: yes
+ apache_document_root: '{{ synapse_element_webroot }}'
+ apache_config_name: '{{ synapse_server_name }}-element'
+ tags: apache
diff --git a/playbooks/site.yml b/playbooks/site.yml
index d4bcd11..fa79f8d 100644
--- a/playbooks/site.yml
+++ b/playbooks/site.yml
@@ -35,3 +35,4 @@
- import_playbook: turn.yml
- import_playbook: xmpp.yml
- import_playbook: asterisk.yml
+- import_playbook: matrix.yml
diff --git a/playbooks/webserver_public_example.yml b/playbooks/webserver_public_example.yml
index b509e85..d9cb468 100644
--- a/playbooks/webserver_public_example.yml
+++ b/playbooks/webserver_public_example.yml
@@ -10,6 +10,8 @@
apache_canonical_hostname: www.example.com
apache_letsencrypt: yes
apache_document_root: /var/www/www.example.com
+ apache_config: |
+ Alias /.well-known/matrix /var/www/well-known/example.com/matrix
tags: apache
- role: archive_job
@@ -35,3 +37,24 @@
group: webmasters
mode: 02770
tags: apache
+
+ - name: create well-known directories
+ file:
+ path: '/var/www/well-known/{{ item }}'
+ state: directory
+ recurse: yes
+ loop:
+ - example.com/matrix
+ tags: apache
+
+ - name: create .well-known/matrix/server for example.com
+ copy:
+ content: '{"m.server": "matrix.example.com:8448"}'
+ dest: /var/www/well-known/example.com/matrix/server
+ tags: apache
+
+ - name: create .well-known/matrix/client for example.com
+ copy:
+ content: '{"m.homeserver": {"base_url": "https://matrix.example.com:8443"}}'
+ dest: /var/www/well-known/example.com/matrix/client
+ tags: apache
diff --git a/roles/apache/README.md b/roles/apache/README.md
index 77f0ec9..ce203d3 100644
--- a/roles/apache/README.md
+++ b/roles/apache/README.md
@@ -14,6 +14,8 @@ This role **accepts** the following variables:
Variable | Default | Description
---------------------------------|-----------|------------
+`apache_listen_ports` | `[80]` | HTTP ports to listen on
+`apache_ssl_listen_ports` | `[443]` | HTTPS ports to listen on
`apache_use_nfs` | no | Value of the `httpd_use_nfs` SELinux boolean
`apache_can_network_relay` | yes | Value of the `httpd_can_network_relay` SELinux boolean
`apache_can_network_connect` | no | Value of the `httpd_can_network_connect` SELinux boolean
diff --git a/roles/apache/defaults/main.yml b/roles/apache/defaults/main.yml
index b0605ba..b5dad87 100644
--- a/roles/apache/defaults/main.yml
+++ b/roles/apache/defaults/main.yml
@@ -6,6 +6,12 @@ apache_can_connect_ldap: no
apache_can_sendmail: no
apache_gssapi: no
+apache_listen_ports:
+ - 80
+
+apache_ssl_listen_ports:
+ - 443
+
apache_sysaccount_username: apache
apache_backup_dirs: []
diff --git a/roles/apache/tasks/main.yml b/roles/apache/tasks/main.yml
index 4892782..dacd9cb 100644
--- a/roles/apache/tasks/main.yml
+++ b/roles/apache/tasks/main.yml
@@ -45,6 +45,14 @@
import_tasks: gssapi.yml
when: apache_gssapi or apache_use_nfs
+- name: set http_port_t selinux context for http ports
+ seport:
+ ports: '{{ apache_listen_ports + apache_ssl_listen_ports }}'
+ proto: tcp
+ setype: http_port_t
+ state: present
+ tags: selinux
+
- name: enable apache
systemd:
name: httpd
@@ -53,11 +61,9 @@
- name: open firewall ports
firewalld:
- service: '{{ item }}'
+ port: '{{ item }}/tcp'
permanent: yes
immediate: yes
state: enabled
- loop:
- - http
- - https
+ loop: '{{ apache_listen_ports + apache_ssl_listen_ports }}'
tags: firewalld
diff --git a/roles/apache/templates/etc/httpd/conf.d/ssl.conf.j2 b/roles/apache/templates/etc/httpd/conf.d/ssl.conf.j2
index eb85a29..31e91d1 100644
--- a/roles/apache/templates/etc/httpd/conf.d/ssl.conf.j2
+++ b/roles/apache/templates/etc/httpd/conf.d/ssl.conf.j2
@@ -1,4 +1,6 @@
-Listen 443 https
+{% for port in apache_ssl_listen_ports %}
+Listen {{ port }} https
+{% endfor %}
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
diff --git a/roles/apache/templates/etc/httpd/conf/httpd.conf.j2 b/roles/apache/templates/etc/httpd/conf/httpd.conf.j2
index d34c4a9..6e52049 100644
--- a/roles/apache/templates/etc/httpd/conf/httpd.conf.j2
+++ b/roles/apache/templates/etc/httpd/conf/httpd.conf.j2
@@ -1,6 +1,8 @@
ServerRoot "/etc/httpd"
-Listen 80
+{% for port in apache_listen_ports %}
+Listen {{ port }}
+{% endfor %}
Include conf.modules.d/*.conf
diff --git a/roles/apache_vhost/README.md b/roles/apache_vhost/README.md
index 186ef4b..7d05b2e 100644
--- a/roles/apache_vhost/README.md
+++ b/roles/apache_vhost/README.md
@@ -18,13 +18,15 @@ Variable | Default | Desc
`apache_server_name` | `{{ ansible_fqdn }}` | [ServerName](https://httpd.apache.org/docs/2.4/mod/core.html#servername) value
`apache_server_aliases` | `[]` if `apache_letsencrypt`, else `cnames` | [ServerAlias](https://httpd.apache.org/docs/2.4/mod/core.html#serveralias) values
`apache_config_name` | `{{ apache_server_name }}` | Name of config file in `/etc/httpd/conf.d`
-`apache_listen` | `*` | Network interface for VirtualHost
+`apache_listen_ip` | `*` | Listening IP for virtual host
+`apache_listen_port` | `80` for HTTP, `443` for HTTPS | Listening port for virtual host
`apache_default_vhost` | no | Make this VirtualHost the default if no other VirtualHosts match the request
`apache_document_root` |   | Path to [DocumentRoot](https://httpd.apache.org/docs/2.4/mod/core.html#documentroot)
`apache_autoindex` | no | Automatically generate file listings
`apache_use_ssl` | yes | Enable HTTPS
`apache_letsencrypt` | no | Use LetsEncrypt (rather than FreeIPA) to acquire certificates
`apache_redirect_to_https` | yes | 301 redirect HTTP requests to HTTPS
+`apache_ssl_only` | yes | Disable HTTP listener
`apache_use_http2` | yes | Enable HTTP2 protocol
`apache_canonical_hostname` |   | 301 redirect all requests to this hostname
`apache_config` |   | VirtualHost config block (see usage below)
diff --git a/roles/apache_vhost/defaults/main.yml b/roles/apache_vhost/defaults/main.yml
index 9a91522..c941e8c 100644
--- a/roles/apache_vhost/defaults/main.yml
+++ b/roles/apache_vhost/defaults/main.yml
@@ -4,7 +4,7 @@ apache_server_aliases: '{{ [] if apache_letsencrypt else cnames }}'
apache_default_vhost: no
apache_config_name: '{{ apache_server_name }}'
-apache_listen: '*'
+apache_listen_ip: '*'
apache_autoindex: no
@@ -12,5 +12,6 @@ apache_letsencrypt: no
apache_use_ssl: yes
apache_use_http2: yes
apache_redirect_to_https: yes
+apache_ssl_only: no
apache_config: ''
diff --git a/roles/apache_vhost/templates/etc/httpd/conf.d/vhost.conf.j2 b/roles/apache_vhost/templates/etc/httpd/conf.d/vhost.conf.j2
index 12a682e..4eae9af 100644
--- a/roles/apache_vhost/templates/etc/httpd/conf.d/vhost.conf.j2
+++ b/roles/apache_vhost/templates/etc/httpd/conf.d/vhost.conf.j2
@@ -1,5 +1,5 @@
-{% if apache_use_ssl and apache_redirect_to_https %}
-<VirtualHost {{ apache_listen }}:80>
+{% if apache_use_ssl and apache_redirect_to_https and not apache_ssl_only %}
+<VirtualHost {{ apache_listen_ip }}:80>
ServerName {{ apache_server_name }}
{% for alias in apache_server_aliases %}
ServerAlias {{ alias }}
@@ -15,10 +15,10 @@
RewriteRule (.*) https://%{HTTP_HOST}$1 [R=permanent,L]
</VirtualHost>
-{% else %}
+{% elif not apache_ssl_only %}
{% if apache_canonical_hostname is defined and (apache_server_aliases | length > 0) %}
-<VirtualHost {{ apache_listen }}:80>
+<VirtualHost {{ apache_listen_ip }}:{{ apache_listen_port | default(80) }}>
{% for alias in ([apache_server_name] + apache_server_aliases) | reject('equalto', apache_canonical_hostname) | list %}
{% if loop.first %}
ServerName {{ alias }}
@@ -36,7 +36,7 @@
</VirtualHost>
{% endif %}
-<VirtualHost {{ apache_listen }}:80>
+<VirtualHost {{ apache_listen_ip }}:{{ apache_listen_port | default(80) }}>
{% if apache_document_root is defined %}
DocumentRoot "{{ apache_document_root }}"
{% endif %}
@@ -73,7 +73,7 @@
{% if apache_use_ssl %}
{% if apache_canonical_hostname is defined and (apache_server_aliases | length > 0) %}
-<VirtualHost {{ apache_listen }}:443>
+<VirtualHost {{ apache_listen_ip }}:{{ apache_listen_port | default(443) }}>
{% for alias in ([apache_server_name] + apache_server_aliases) | reject('equalto', apache_canonical_hostname) | list %}
{% if loop.first %}
ServerName {{ alias }}
@@ -96,7 +96,7 @@
</VirtualHost>
{% endif %}
-<VirtualHost {{ apache_listen }}:443>
+<VirtualHost {{ apache_listen_ip }}:{{ apache_listen_port | default(443) }}>
{% if apache_document_root is defined %}
DocumentRoot "{{ apache_document_root }}"
{% endif %}
diff --git a/roles/freeipa_server/files/usr/local/share/dirsrv/schema/matrix.ldif b/roles/freeipa_server/files/usr/local/share/dirsrv/schema/matrix.ldif
new file mode 100644
index 0000000..dc6a611
--- /dev/null
+++ b/roles/freeipa_server/files/usr/local/share/dirsrv/schema/matrix.ldif
@@ -0,0 +1,3 @@
+dn: cn=config
+attributetypes: ( 2.25.10508909625911985622145696820691585120.2 NAME 'matrixUsername' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Extending FreeIPA' )
+objectclasses: ( 2.25.10508909625911985622145696820691585120.1 NAME 'matrixUser' AUXILIARY MAY matrixUsername X-ORIGIN 'Extending FreeIPA' )
diff --git a/roles/freeipa_server/tasks/custom_schema.yml b/roles/freeipa_server/tasks/custom_schema.yml
index e5bca0d..73456e3 100644
--- a/roles/freeipa_server/tasks/custom_schema.yml
+++ b/roles/freeipa_server/tasks/custom_schema.yml
@@ -4,11 +4,16 @@
state: directory
recurse: yes
-- name: copy jid schema
+- name: copy custom schemas
copy:
- src: '{{ freeipa_custom_schema_dir[1:] }}/jid.ldif'
- dest: '{{ freeipa_custom_schema_dir }}/jid.ldif'
+ src: '{{ freeipa_custom_schema_dir[1:] }}/{{ item }}.ldif'
+ dest: '{{ freeipa_custom_schema_dir }}/{{ item }}.ldif'
+ loop:
+ - jid
+ - matrix
+
+# begin JIDObject schema
- name: check if JIDObject exists in schema
shell: ldapsearch -QLLL -s base -b cn=schema objectclasses | grep -q JIDObject
changed_when: no
@@ -54,6 +59,55 @@
bind_pw: '{{ freeipa_ds_password }}'
server_uri: ldaps://{{ ipa_host }}
when: jid_index.changed
+# end JIDObject schema
+
+# begin matrixUser schema
+- name: check if matrixUser exists in schema
+ shell: ldapsearch -QLLL -s base -b cn=schema objectclasses | grep -q matrixUser
+ changed_when: no
+ failed_when: no
+ register: ldapsearch_matrixuser
+
+- block:
+ - name: extend freeipa schema for matrix usernames
+ command: ipa-ldap-updater --schema-file '{{ freeipa_custom_schema_dir }}/matrix.ldif'
+
+ - name: restart httpd
+ systemd:
+ name: httpd
+ state: restarted
+ when: ldapsearch_matrixuser.rc != 0
+
+- name: add index to matrixUsername attribute
+ ldap_entry:
+ dn: 'cn=matrixUsername,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config'
+ objectClass:
+ - top
+ - nsIndex
+ attributes:
+ cn: matrixUsername
+ nsSystemIndex: false
+ nsIndexType: eq
+ bind_dn: cn=Directory Manager
+ bind_pw: '{{ freeipa_ds_password }}'
+ server_uri: ldaps://{{ ipa_host }}
+ register: matrixusername_index
+
+- name: regenerate indexes for matrixUsername attribute
+ ldap_entry:
+ dn: cn=matrixusernameindex,cn=index,cn=tasks,cn=config
+ objectClass:
+ - top
+ - extensibleObject
+ attributes:
+ cn: matrixusernameindex
+ nsInstance: userRoot
+ nsIndexAttribute: 'matrixUsername:eq'
+ bind_dn: cn=Directory Manager
+ bind_pw: '{{ freeipa_ds_password }}'
+ server_uri: ldaps://{{ ipa_host }}
+ when: matrixusername_index.changed
+# end matrixUser schema
- name: add default user object classes
ldap_attrs:
@@ -62,6 +116,7 @@
ipaUserObjectClasses:
- mailRecipient
- JIDObject
+ - matrixUser
state: present
bind_dn: cn=Directory Manager
bind_pw: '{{ freeipa_ds_password }}'
@@ -86,6 +141,7 @@
attrs:
- mailAlternateAddress
- jid
+ - matrixUsername
action: member
state: present
diff --git a/roles/synapse/defaults/main.yml b/roles/synapse/defaults/main.yml
new file mode 100644
index 0000000..230871b
--- /dev/null
+++ b/roles/synapse/defaults/main.yml
@@ -0,0 +1,58 @@
+synapse_version: 1.84.1
+synapse_ldap_version: 0.2.2
+synapse_element_version: 1.11.31
+synapse_local_client_port: 8008
+synapse_local_federation_port: 8009
+synapse_client_port: 8443
+synapse_federation_port: 8448
+
+synapse_user: s-synapse
+synapse_access_group: role-matrix-access
+
+synapse_db_host: '{{ postgresql_host }}'
+synapse_db_name: synapse
+
+synapse_sysaccount_username: synapse
+#synapse_sysaccount_password
+
+synapse_domain: '{{ email_domain }}'
+
+synapse_server_name: '{{ ansible_fqdn }}'
+
+#synapse_registration_shared_secret
+#synapse_macaroon_secret_key
+#synapse_form_secret
+
+synapse_turn_host: '{{ coturn_realm }}'
+synapse_turn_secret: '{{ coturn_auth_secret }}'
+
+synapse_enable_email_notifications: yes
+synapse_email_from: 'Matrix <matrix-noreply@{{ email_domain }}>'
+
+synapse_enable_registration: no
+
+synapse_max_upload_size: 50m
+
+synapse_auto_join_rooms: []
+
+synapse_url_preview_whitelist: []
+synapse_url_preview_blacklist:
+ - '127.0.0.0/8'
+ - '10.0.0.0/8'
+ - '172.16.0.0/12'
+ - '192.168.0.0/16'
+ - '100.64.0.0/10'
+ - '192.0.0.0/24'
+ - '169.254.0.0/16'
+ - '192.88.99.0/24'
+ - '198.18.0.0/15'
+ - '192.0.2.0/24'
+ - '198.51.100.0/24'
+ - '203.0.113.0/24'
+ - '224.0.0.0/4'
+ - '::1/128'
+ - 'fe80::/10'
+ - 'fc00::/7'
+ - '2001:db8::/32'
+ - 'ff00::/8'
+ - 'fec0::/10'
diff --git a/roles/synapse/handlers/main.yml b/roles/synapse/handlers/main.yml
new file mode 100644
index 0000000..36abf64
--- /dev/null
+++ b/roles/synapse/handlers/main.yml
@@ -0,0 +1,4 @@
+- name: restart synapse
+ systemd:
+ name: synapse
+ state: restarted
diff --git a/roles/synapse/meta/main.yml b/roles/synapse/meta/main.yml
new file mode 100644
index 0000000..b06a498
--- /dev/null
+++ b/roles/synapse/meta/main.yml
@@ -0,0 +1,5 @@
+dependencies:
+ - role: freeipa_system_account
+ system_account_username: '{{ synapse_sysaccount_username }}'
+ system_account_password: '{{ synapse_sysaccount_password }}'
+
diff --git a/roles/synapse/tasks/database.yml b/roles/synapse/tasks/database.yml
new file mode 100644
index 0000000..0494882
--- /dev/null
+++ b/roles/synapse/tasks/database.yml
@@ -0,0 +1,21 @@
+- name: create database
+ postgresql_db:
+ name: '{{ synapse_db_name }}'
+ encoding: UTF-8
+ lc_collate: C
+ lc_ctype: C
+ template: template0
+ state: present
+ delegate_to: "{{ postgresql_inventory_host }}"
+ become: yes
+ become_user: postgres
+
+- name: create database user
+ postgresql_user:
+ name: '{{ synapse_user }}'
+ db: '{{ synapse_db_name }}'
+ priv: ALL
+ state: present
+ delegate_to: "{{ postgresql_inventory_host }}"
+ become: yes
+ become_user: postgres
diff --git a/roles/synapse/tasks/element.yml b/roles/synapse/tasks/element.yml
new file mode 100644
index 0000000..cfc8eff
--- /dev/null
+++ b/roles/synapse/tasks/element.yml
@@ -0,0 +1,17 @@
+- name: create element webroot
+ file:
+ path: '{{ synapse_element_webroot }}'
+ state: directory
+
+- name: extract element tarball
+ unarchive:
+ src: '{{ synapse_element_url }}'
+ remote_src: yes
+ dest: '{{ synapse_element_webroot }}'
+ extra_opts:
+ - '--strip-components=1'
+
+- name: generate element configuration
+ template:
+ src: '{{ synapse_element_webroot[1:] }}/config.json.j2'
+ dest: '{{ synapse_element_webroot }}/config.json'
diff --git a/roles/synapse/tasks/freeipa.yml b/roles/synapse/tasks/freeipa.yml
new file mode 100644
index 0000000..7e6cc02
--- /dev/null
+++ b/roles/synapse/tasks/freeipa.yml
@@ -0,0 +1,37 @@
+- name: create user
+ ipauser:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ synapse_user }}'
+ loginshell: /sbin/nologin
+ homedir: '{{ synapse_home }}'
+ givenname: Synapse
+ sn: Service Account
+ state: present
+ run_once: yes
+
+- name: retrieve user keytab
+ include_role:
+ name: freeipa_keytab
+ vars:
+ keytab_principal: '{{ synapse_user }}'
+ keytab_path: '{{ synapse_keytab }}'
+
+- name: configure gssproxy for kerberized postgres
+ include_role:
+ name: gssproxy_client
+ vars:
+ gssproxy_name: synapse
+ gssproxy_section: service/synapse
+ gssproxy_client_keytab: '{{ synapse_keytab }}'
+ gssproxy_cred_usage: initiate
+ gssproxy_euid: '{{ synapse_user }}'
+
+- name: create access group
+ ipagroup:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ synapse_access_group }}'
+ nonposix: yes
+ state: present
+ run_once: yes
diff --git a/roles/synapse/tasks/main.yml b/roles/synapse/tasks/main.yml
new file mode 100644
index 0000000..bf0002d
--- /dev/null
+++ b/roles/synapse/tasks/main.yml
@@ -0,0 +1,67 @@
+- name: install packages
+ dnf:
+ name: '{{ synapse_packages }}'
+ state: present
+
+- import_tasks: freeipa.yml
+
+- name: create home directory
+ file:
+ path: '{{ item }}'
+ owner: '{{ synapse_user }}'
+ group: '{{ synapse_user }}'
+ mode: 0700
+ state: directory
+ loop:
+ - '{{ synapse_home }}'
+ - '{{ synapse_venv }}'
+
+- name: install synapse
+ pip:
+ name: '{{ synapse_pip_packages }}'
+ virtualenv: '{{ synapse_venv }}'
+ state: latest
+ become: yes
+ become_user: '{{ synapse_user }}'
+
+- name: generate synapse configuration
+ template:
+ src: '{{ synapse_home[1:] }}/{{ item }}.j2'
+ dest: '{{ synapse_home }}/{{ item }}'
+ owner: '{{ synapse_user }}'
+ group: '{{ synapse_user }}'
+ mode: 0600
+ notify: restart synapse
+ loop:
+ - homeserver.yaml
+ - logging.config
+
+- name: generate signing key
+ shell:
+ cmd: >-
+ source {{ synapse_venv }}/bin/activate &&
+ python -m synapse.app.homeserver --config-path {{ synapse_home }}/homeserver.yaml --generate-keys
+ creates: '{{ synapse_home }}/{{ synapse_domain }}.signing.key'
+ become: yes
+ become_user: '{{ synapse_user }}'
+
+- name: create systemd unit
+ template:
+ src: etc/systemd/system/synapse.service.j2
+ dest: /etc/systemd/system/synapse.service
+ notify: restart synapse
+
+- name: reload systemd daemons
+ systemd:
+ daemon_reload: yes
+
+- import_tasks: database.yml
+
+- name: enable systemd unit
+ systemd:
+ name: synapse
+ enabled: yes
+ state: started
+
+- import_tasks: element.yml
+ tags: element
diff --git a/roles/synapse/templates/etc/systemd/system/synapse.service.j2 b/roles/synapse/templates/etc/systemd/system/synapse.service.j2
new file mode 100644
index 0000000..84ab9f3
--- /dev/null
+++ b/roles/synapse/templates/etc/systemd/system/synapse.service.j2
@@ -0,0 +1,42 @@
+[Unit]
+Description=Synapse Matrix Homeserver
+Documentation=https://github.com/matrix-org/synapse
+Wants=gssproxy.service
+After=network-online.target nss-user-lookup.target gssproxy.service
+
+[Service]
+NoNewPrivileges=yes
+PrivateTmp=yes
+PrivateDevices=yes
+DevicePolicy=closed
+ProtectSystem=strict
+ProtectHome=yes
+ProtectControlGroups=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+RestrictNamespaces=yes
+RestrictRealtime=yes
+RestrictSUIDSGID=yes
+LockPersonality=yes
+ReadWritePaths={{ synapse_home }}
+
+User={{ synapse_user }}
+Group={{ synapse_user }}
+
+Type=notify
+NotifyAccess=main
+WorkingDirectory={{ synapse_home }}
+Environment=GSS_USE_PROXY=yes
+EnvironmentFile=-/etc/sysconfig/synapse
+
+ExecStart={{ synapse_venv }}/bin/python -m synapse.app.homeserver --config-path={{ synapse_home }}/homeserver.yaml
+ExecReload=/bin/kill -HUP $MAINPID
+
+Restart=always
+RestartSec=3
+
+SyslogIdentifier=synapse
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/synapse/templates/var/lib/synapse/homeserver.yaml.j2 b/roles/synapse/templates/var/lib/synapse/homeserver.yaml.j2
new file mode 100644
index 0000000..8aefce7
--- /dev/null
+++ b/roles/synapse/templates/var/lib/synapse/homeserver.yaml.j2
@@ -0,0 +1,96 @@
+server_name: {{ synapse_domain }}
+
+pid_file: {{ synapse_runtime_dir }}/homeserver.pid
+
+public_baseurl: https://{{ synapse_server_name }}:{{ synapse_client_port }}/
+
+listeners:
+ - port: {{ synapse_local_client_port }}
+ tls: false
+ type: http
+ x_forwarded: true
+ bind_addresses: ['::1', '127.0.0.1']
+ resources:
+ - names: [client]
+ compress: false
+
+ - port: {{ synapse_local_federation_port }}
+ tls: false
+ type: http
+ x_forwarded: true
+ bind_addresses: ['::1', '127.0.0.1']
+ resources:
+ - names: [federation]
+ compress: false
+
+email:
+ smtp_host: 127.0.0.1
+ smtp_port: 25
+ enable_tls: false
+ notif_from: {{ synapse_email_from | to_yaml }}
+ enable_notifs: {{ synapse_enable_email_notifications | bool | to_yaml }}
+
+client_base_url: https://{{ synapse_server_name }}
+
+database:
+ name: psycopg2
+ args:
+ user: '{{ synapse_user }}'
+ database: '{{ synapse_db_name }}'
+ host: '{{ synapse_db_host }}'
+ cp_min: 5
+ cp_max: 10
+ keepalives_idle: 10
+ keepalives_interval: 10
+ keepalives_count: 3
+
+log_config: {{ synapse_home }}/logging.config
+
+media_store_path: {{ synapse_home }}/media_store
+max_upload_size: {{ synapse_max_upload_size | human_to_bytes }}
+
+url_preview_enabled: true
+url_preview_ip_range_blacklist: {{ synapse_url_preview_blacklist | to_yaml }}
+url_preview_ip_range_whitelist: {{ synapse_url_preview_whitelist | to_yaml }}
+
+enable_registration: {{ synapse_enable_registration | bool | to_yaml }}
+registration_shared_secret: {{ synapse_registration_shared_secret | to_yaml }}
+
+{% if synapse_auto_join_rooms %}
+auto_join_rooms:
+{% for room in synapse_auto_join_rooms %}
+ - '#{{ room }}:{{ synapse_domain }}'
+{% endfor %}
+{% endif %}
+autocreate_auto_join_rooms: true
+autocreate_auto_join_rooms_federated: false
+
+turn_uris: ['turn:{{ synapse_turn_host }}']
+turn_shared_secret: {{ synapse_turn_secret }}
+turn_allow_guests: false
+
+report_stats: false
+
+macaroon_secret_key: {{ synapse_macaroon_secret_key | to_yaml }}
+form_secret: {{ synapse_form_secret | to_yaml }}
+
+signing_key_path: {{ synapse_home }}/{{ synapse_domain }}.signing.key
+
+trusted_key_servers:
+ - server_name: matrix.org
+suppress_key_server_warning: true
+
+modules:
+ - module: ldap_auth_provider.LdapAuthProviderModule
+ config:
+ enabled: true
+ uri: {{ freeipa_ldap_uri | split | to_yaml }}
+ start_tls: true
+ base: {{ freeipa_user_basedn }}
+ attributes:
+ uid: matrixUsername
+ mail: mail
+ name: matrixUsername
+ bind_dn: uid={{ synapse_sysaccount_username }},{{ freeipa_sysaccount_basedn }}
+ bind_password: {{ synapse_sysaccount_password }}
+ filter: '(memberOf=cn={{ synapse_access_group }},{{ freeipa_group_basedn }})'
diff --git a/roles/synapse/templates/var/lib/synapse/logging.config.j2 b/roles/synapse/templates/var/lib/synapse/logging.config.j2
new file mode 100644
index 0000000..216e9e8
--- /dev/null
+++ b/roles/synapse/templates/var/lib/synapse/logging.config.j2
@@ -0,0 +1,23 @@
+version: 1
+
+formatters:
+ journal_fmt:
+ format: '%(name)s: [%(request)s] %(message)s'
+
+filters:
+ context:
+ (): synapse.logging.context.LoggingContextFilter
+ request: ""
+
+handlers:
+ journal:
+ class: systemd.journal.JournalHandler
+ formatter: journal_fmt
+ filters: [context]
+ SYSLOG_IDENTIFIER: synapse
+
+root:
+ level: INFO
+ handlers: [journal]
+
+disable_existing_loggers: False
diff --git a/roles/synapse/templates/var/www/element/config.json.j2 b/roles/synapse/templates/var/www/element/config.json.j2
new file mode 100644
index 0000000..3556704
--- /dev/null
+++ b/roles/synapse/templates/var/www/element/config.json.j2
@@ -0,0 +1,45 @@
+{
+ "default_server_config": {
+ "m.homeserver": {
+ "base_url": "https://{{ synapse_server_name }}:{{ synapse_client_port }}",
+ "server_name": "{{ synapse_domain }}"
+ },
+ "m.identity_server": {
+ "base_url": null
+ }
+ },
+ "disable_custom_urls": true,
+ "disable_guests": true,
+ "disable_login_language_selector": false,
+ "disable_3pid_login": true,
+ "brand": "Element",
+ "integrations_ui_url": null,
+ "integrations_rest_url": null,
+ "integrations_widgets_urls": null,
+ "bug_report_endpoint_url": null,
+ "uisi_autorageshake_app": "element-auto-uisi",
+ "default_country_code": "US",
+ "show_labs_settings": false,
+ "features": {},
+ "default_federate": true,
+ "default_theme": "light",
+ "room_directory": {
+ "servers": ["{{ synapse_domain }}", "matrix.org"]
+ },
+ "enable_presence_by_hs_url": {
+ "https://matrix.org": false,
+ "https://matrix-client.matrix.org": false
+ },
+ "setting_defaults": {
+ "breadcrumbs": true
+ },
+ "jitsi": {
+ "preferred_domain": "meet.element.io"
+ },
+ "element_call": {
+ "url": "https://call.element.io",
+ "participant_limit": 8,
+ "brand": "Element Call"
+ },
+ "map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
+}
diff --git a/roles/synapse/vars/main.yml b/roles/synapse/vars/main.yml
new file mode 100644
index 0000000..43c04d9
--- /dev/null
+++ b/roles/synapse/vars/main.yml
@@ -0,0 +1,47 @@
+synapse_packages:
+ - libtiff-devel
+ - libjpeg-devel
+ - libzip-devel
+ - freetype-devel
+ - libwebp-devel
+ - libxml2-devel
+ - libxslt-devel
+ - libpq-devel
+ - python3-virtualenv
+ - libffi-devel
+ - openssl-devel
+ - python3-devel
+ - libicu-devel
+ - python3-psycopg2
+ - systemd-devel
+ - gcc
+
+synapse_pip_packages:
+ - 'matrix-synapse[postgres]=={{ synapse_version }}'
+ - 'matrix-synapse-ldap3=={{ synapse_ldap_version }}'
+ - lxml
+ - systemd-python
+
+synapse_home: /var/lib/synapse
+synapse_keytab: /var/lib/gssproxy/clients/{{ synapse_user }}.keytab
+synapse_venv: '{{ synapse_home }}/venv'
+synapse_runtime_dir: /run/synapse
+synapse_element_url: https://github.com/vector-im/element-web/releases/download/v{{ synapse_element_version }}/element-v{{ synapse_element_version }}.tar.gz
+synapse_element_webroot: /var/www/element
+
+synapse_apache_client_config: |
+ LimitRequestBody {{ synapse_max_upload_size | human_to_bytes }}
+ AllowEncodedSlashes NoDecode
+ {{ apache_proxy_config }}
+ <Location />
+ ProxyPass http://127.0.0.1:{{ synapse_local_client_port }}/ nocanon
+ ProxyPassReverse http://127.0.0.1:{{ synapse_local_client_port }}/
+ </Location>
+
+synapse_apache_federation_config: |
+ AllowEncodedSlashes NoDecode
+ {{ apache_proxy_config }}
+ <Location />
+ ProxyPass http://127.0.0.1:{{ synapse_local_federation_port }}/ nocanon
+ ProxyPassReverse http://127.0.0.1:{{ synapse_local_federation_port }}/
+ </Location>