diff --git a/group_vars/synapse/main.yml b/group_vars/synapse/main.yml
new file mode 100644
index 0000000..6f0ab1f
--- /dev/null
+++ b/group_vars/synapse/main.yml
@@ -0,0 +1,9 @@
+apache_default_ssl_vhost: false
+matrix_server_name: hatch.chat
+synapse_ldap_enabled: true
+synapse_ldap_uri: ldap://dc0.pyrocufflink.blue:389
+synapse_ldap_base: DC=pyrocufflink,DC=blue
+synapse_ldap_bind_dn: CN=svc.synapse,CN=Users,DC=pyrocufflink,DC=blue
+synapse_ldap_bind_password: '{{ vault_synapse_ldap_bind_password }}'
+matrix_tls_cert: websites/hatch.chat.cer
+matrix_tls_key: websites/hatch.chat.key
diff --git a/group_vars/synapse/secrets b/group_vars/synapse/secrets
new file mode 100644
index 0000000..7af7e5b
--- /dev/null
+++ b/group_vars/synapse/secrets
@@ -0,0 +1,9 @@
+$ANSIBLE_VAULT;1.1;AES256
+63353463626538346438303931303537663265346634313861653364333635323337666634303136
+3036343162343532306263653634376132663836393962640a623738393633336437643330656264
+66633166306532373631323236346237626239643839313934383264393231313134323761313163
+6464626566623466630a313363386332613637346638333439666438383939306632666466353966
+30323538326462313836306563353233663935636130636361353938623331396432356436383137
+30336464646136633931613763363464373165386435613939656435663332326432396539633037
+30373035663336613937383038363032373330316137333333303632353839643338393938343238
+34393634643139323066
diff --git a/hosts b/hosts
index 0615398..4e48fc7 100644
--- a/hosts
+++ b/hosts
@@ -121,6 +121,7 @@ smtp1.pyrocufflink.blue
[squid]
+[synapse]
[vm-hosts]
diff --git a/roles/synapse/defaults/main.yml b/roles/synapse/defaults/main.yml
new file mode 100644
index 0000000..80ad8ea
--- /dev/null
+++ b/roles/synapse/defaults/main.yml
@@ -0,0 +1,5 @@
+synapse_ldap_enabled: false
+synapse_ldap_attributes:
+ uid: sAMAccountName
+ mail: mail
+ name: cn
diff --git a/roles/synapse/handlers/main.yml b/roles/synapse/handlers/main.yml
new file mode 100644
index 0000000..7a14c35
--- /dev/null
+++ b/roles/synapse/handlers/main.yml
@@ -0,0 +1,4 @@
+- name: restart synapse
+ service:
+ name: synapse
+ state: restarted
diff --git a/roles/synapse/tasks/main.yml b/roles/synapse/tasks/main.yml
new file mode 100644
index 0000000..2989693
--- /dev/null
+++ b/roles/synapse/tasks/main.yml
@@ -0,0 +1,49 @@
+- name: ensure synapse is installed
+ package:
+ name: matrix-synapse
+ state: present
+ tags:
+ - install
+
+- name: ensure synapse is configured
+ template:
+ src: homeserver.yaml.j2
+ dest: /etc/synapse/homeserver.yaml
+ owner: root
+ group: synapse
+ mode: '0750'
+ notify: restart synapse
+ tags:
+ - config
+
+- name: ensure apache is configured to proxy for synapse
+ template:
+ src: matrix.httpd.conf.j2
+ dest: /etc/httpd/conf.d/matrix.conf
+ mode: '0644'
+ notify: reload httpd
+ tags: httpd-conf
+
+- name: ensure apache can bind to synapse port
+ seport:
+ ports: 8448
+ proto: tcp
+ setype: http_port_t
+ state: present
+ tags:
+ - selinux
+ - seport
+
+- name: ensure apache is allowed to proxy for synapse
+ seboolean:
+ name: httpd_can_network_connect
+ persistent: true
+ state: true
+ tags:
+ - selinux
+ - seboolean
+
+- name: ensure synapse starts at boot
+ service:
+ name: synapse
+ enabled: true
diff --git a/roles/synapse/templates/homeserver.yaml.j2 b/roles/synapse/templates/homeserver.yaml.j2
new file mode 100644
index 0000000..09068a7
--- /dev/null
+++ b/roles/synapse/templates/homeserver.yaml.j2
@@ -0,0 +1,81 @@
+# vim: set ft=yaml :
+
+server_name: "{{ matrix_server_name }}"
+
+federation_ip_range_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'
+- '169.254.0.0/16'
+- '::1/128'
+- 'fe80::/64'
+- 'fc00::/7'
+
+listeners:
+- port: 8008
+ tls: false
+ type: http
+ x_forwarded: true
+ bind_addresses: ['::1', '127.0.0.1']
+ resources:
+ - names: [client, federation]
+ compress: false
+
+retention:
+
+database:
+ name: sqlite3
+ args:
+ database: /var/lib/synapse/homeserver.db
+
+log_config: /etc/synapse/log_config.yaml
+
+media_store_path: /var/lib/synapse/media_store
+
+registration_shared_secret: '{{ synapse_registration_shared_secret }}'
+
+account_threepid_delegates:
+
+metrics_flags:
+
+report_stats: false
+
+macaroon_secret_key: '{{ synapse_macaroon_secret_key }}'
+
+form_secret: '{{ synapse_form_secret }}'
+
+signing_key_path: /etc/synapse/{{ matrix_server_name }}.signing.key
+old_signing_keys:
+
+trusted_key_servers:
+- server_name: matrix.org
+
+saml2_config:
+ user_mapping_provider:
+ config:
+
+password_config:
+
+opentracing:
+
+{% if synapse_ldap_enabled %}
+password_providers:
+ - module: ldap_auth_provider.LdapAuthProvider
+ config:
+ enabled: true
+ uri: {{ synapse_ldap_uri }}
+ start_tls: true
+ base: '{{ synapse_ldap_base }}'
+ attributes:
+{% for key, value in synapse_ldap_attributes|dictsort %}
+ {{ key }}: {{ value }}
+{% endfor %}
+{% if synapse_ldap_bind_dn|d %}
+ bind_dn: '{{ synapse_ldap_bind_dn }}'
+{% if synapse_ldap_bind_password|d %}
+ bind_password: '{{ synapse_ldap_bind_password }}'
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/roles/synapse/templates/matrix.httpd.conf.j2 b/roles/synapse/templates/matrix.httpd.conf.j2
new file mode 100644
index 0000000..b3ec10e
--- /dev/null
+++ b/roles/synapse/templates/matrix.httpd.conf.j2
@@ -0,0 +1,40 @@
+
+ ServerName {{ matrix_server_name }}
+
+ Include conf.d/ssl.include
+ # This certificate must contain the hostname of THIS MACHINE in its
+ # subject/subjectAltName, so it can be validated by the reverse
+ # proxy. The reverse proxy presents the "real" certificate to
+ # clients on the Internet.
+ SSLCertificateKeyFile {{ apache_ssl_certificate_key }}
+ SSLCertificateFile {{ apache_ssl_certificate }}
+
+ AllowEncodedSlashes NoDecode
+ ProxyPass /_matrix http://127.0.0.1:8008/_matrix nocanon
+ ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix
+
+
+Listen 8448
+
+
+ ServerName {{ matrix_server_name }}
+
+ Include conf.d/ssl.include
+{% if matrix_tls_key is defined %}
+ # This certificate is the "real" certificate, as clients on the
+ # Internet connect to this virtual host directly, not through the
+ # reverse proxy.
+ SSLCertificateKeyFile /etc/pki/tls/private/{{ matrix_tls_key|basename }}
+{% else %}
+ SSLCertificateKeyFile {{ apache_ssl_certificate_key }}
+{% endif %}
+{% if matrix_tls_cert is defined %}
+ SSLCertificateFile /etc/pki/tls/certs/{{ matrix_tls_cert|basename }}
+{% else %}
+ SSLCertificateFile {{ apache_ssl_certificate }}
+{% endif %}
+
+ AllowEncodedSlashes NoDecode
+ ProxyPass /_matrix http://127.0.0.1:8008/_matrix nocanon
+ ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix
+
diff --git a/synapse.yml b/synapse.yml
new file mode 100644
index 0000000..bcd1691
--- /dev/null
+++ b/synapse.yml
@@ -0,0 +1,19 @@
+- hosts: synapse
+ vars_files:
+ - vault/synapse/{{ matrix_server_name }}
+ roles:
+ - role: cert
+ cert_src: '{{ matrix_tls_cert }}'
+ cert_dest: /etc/pki/tls/certs/{{ matrix_tls_cert|basename }}
+ cert_key_src: '{{ matrix_tls_key }}'
+ cert_key_dest: /etc/pki/tls/private/{{ matrix_tls_key|basename }}
+ when: matrix_tls_cert is defined
+ tags: cert
+ - apache
+ - synapse
+ tasks:
+ - meta: flush_handlers
+ - name: ensure synapse is running
+ service:
+ name: synapse
+ state: started
diff --git a/vault/synapse/hatch.chat b/vault/synapse/hatch.chat
new file mode 100644
index 0000000..4b925f1
--- /dev/null
+++ b/vault/synapse/hatch.chat
@@ -0,0 +1,18 @@
+$ANSIBLE_VAULT;1.1;AES256
+34636535316233646136616261343032313135656130353638623933663137346462633561646535
+3361366164613237353862626136653266306563386233350a356637623666353335313361306333
+35386532363863313533643037633664306134336362653462356561323562633734363931363530
+3133366137336334360a336636393639653738623036356438616564373637316633393339396633
+62386561623532393433376439386466383861313137363836323835393664393936663434633262
+33363130363532653462666432323266386632616165353334353730313139663061356662383535
+33633266613438373161313830393531363635633030373265616435636663613433336661636338
+33363930316333323239383035616135383939343037373435626664323963316662613137313737
+34396435343932653233616531353061393131353134623035393030383234343731333832633963
+38376232356138366634303137303432313166643132313936633937353862393431353632613963
+61353163333662643765373939666165616363656530353465323830623439623033396338663634
+66343730613634383937613435316163336434363938366338653937356666666130663364376264
+37353634643064613237646333623163643863643637313164643164393361323434373761633739
+35643434303563663831363566653662303737653139393831343538656666333165316262326463
+34316234616263636365363636373939373134333333666365333362643930666562616539643061
+64613166366164646239383865376364393533633430336338376264363465333237303061663262
+3436