diff --git a/PORT_MAP.md b/PORT_MAP.md
index 058a146..e9fa782 100644
--- a/PORT_MAP.md
+++ b/PORT_MAP.md
@@ -35,6 +35,7 @@ Rule of thumb: keep ports below 10000 free for stuff that reserves ports.
| 11332-11334 | rspamd | rspamd |
| 20000 | mx-puppet-discord | Bridge |
| 20010 | mautrix-telegram | Bridge |
+| 20020 | mautrix-whatsapp | Bridge |
| 20080 | matrix-synapse | client, federation |
| 20081 | matrix-synapse | prometheus metrics |
| 22000 | gitea | gitea |
diff --git a/bundles/mautrix-whatsapp/files/config.yaml b/bundles/mautrix-whatsapp/files/config.yaml
new file mode 100644
index 0000000..ba28cc8
--- /dev/null
+++ b/bundles/mautrix-whatsapp/files/config.yaml
@@ -0,0 +1,108 @@
+homeserver:
+ address: ${node.metadata['mautrix-whatsapp']['homeserver']['url']}
+ domain: ${node.metadata['mautrix-whatsapp']['homeserver']['domain']}
+
+appservice:
+ address: http://${node.metadata['mautrix-whatsapp'].get('listen-addr', '127.0.0.1')}:${node.metadata['mautrix-whatsapp'].get('port', 20020)}
+ hostname: ${node.metadata['mautrix-whatsapp'].get('listen-addr', '127.0.0.1')}
+ port: ${node.metadata['mautrix-whatsapp'].get('port', 20020)}
+ database:
+ type: postgres
+ uri: postgres://${node.metadata['mautrix-whatsapp']['database']['user']}:${node.metadata['mautrix-whatsapp']['database']['password']}@${node.metadata['mautrix-whatsapp']['database'].get('host', 'localhost')}/${node.metadata['mautrix-whatsapp']['database']['database']}
+ max_open_conns: 20
+ max_idle_conns: 2
+ provisioning:
+ prefix: /_matrix/provision/v1
+% if node.metadata['mautrix-whatsapp']['provisioning']['enabled']:
+ shared_secret: ${node.metadata['mautrix-whatsapp']['provisioning']['shared_secret']}
+% else:
+ shared_secret: disable
+% endif
+ id: whatsapp
+ bot:
+ username: whatsappbot
+ displayname: WhatsApp bridge bot
+ avatar: mxc://maunium.net/NeXNQarUbrlYBiPCpprYsRqr
+ as_token: ${node.metadata['mautrix-whatsapp']['as_token']}
+ hs_token: ${node.metadata['mautrix-whatsapp']['hs_token']}
+
+metrics:
+ enabled: false
+ listen: 127.0.0.1:8001
+
+whatsapp:
+ os_name: Mautrix-WhatsApp bridge
+ browser_name: mx-wa
+
+bridge:
+ username_template: whatsapp_{{.}}
+ displayname_template: "{{if .Notify}}{{.Notify}}{{else}}{{.Jid}}{{end}} (WhatsApp)"
+ community_template: whatsapp_{{.Localpart}}={{.Server}}
+ connection_timeout: 20
+ fetch_message_on_timeout: false
+ delivery_receipts: true
+ login_qr_regen_count: 2
+ max_connection_attempts: 3
+ connection_retry_delay: -1
+ report_connection_retry: true
+ chat_list_wait: 30
+ portal_sync_wait: 600
+ user_message_buffer: 1024
+ portal_message_buffer: 128
+ call_notices:
+ start: true
+ end: true
+ initial_chat_sync_count: 20
+ initial_history_fill_count: 50
+ initial_history_disable_notifications: false
+ recovery_chat_sync_limit: -1
+ recovery_history_backfill: true
+ sync_max_chat_age: ${node.metadata['mautrix-whatsapp'].get('sync_max_days', 7)*24*60*60}
+ sync_with_custom_puppets: true
+ sync_direct_chat_list: false
+ default_bridge_receipts: true
+ default_bridge_presence: true
+ login_shared_secret: null
+ invite_own_puppet_for_backfilling: true
+ private_chat_portal_meta: false
+ resend_bridge_info: false
+ whatsapp_thumbnail: false
+ allow_user_invite: false
+ command_prefix: "!wa"
+ encryption:
+ allow: false # requires login_shared_secret to be set
+ default: false
+ key_sharing:
+ allow: false
+ require_cross_signing: false
+ require_verification: true
+ permissions:
+% for user, permission in node.metadata['mautrix-whatsapp']['permissions'].items():
+ ${user}: ${permission}
+% endfor
+ relaybot:
+ enabled: false
+ management: "!whatsapp-relaybot:${node.metadata['mautrix-whatsapp']['homeserver']['domain']}"
+ invites:
+% for user, permission in node.metadata['mautrix-whatsapp']['permissions'].items():
+% if permission > 50:
+ - ${user}
+% endif
+% endfor
+ message_formats:
+ m.text: "{{ .Sender.Displayname }}: {{ .Message }}"
+ m.notice: "{{ .Sender.Displayname }}: {{ .Message }}"
+ m.emote: "* {{ .Sender.Displayname }} {{ .Message }}"
+ m.file: "{{ .Sender.Displayname }} sent a file"
+ m.image: "{{ .Sender.Displayname }} sent an image"
+ m.audio: "{{ .Sender.Displayname }} sent an audio file"
+ m.video: "{{ .Sender.Displayname }} sent a video"
+ m.location: "{{ .Sender.Displayname }} sent a location"
+
+logging:
+ directory: /opt/mautrix-whatsapp/logs
+ file_name_format: "{{.Date}}-{{.Index}}.log"
+ file_date_format: 2006-01-02
+ file_mode: 0600
+ timestamp_format: Jan _2, 2006 15:04:05
+ print_level: info
diff --git a/bundles/mautrix-whatsapp/files/mautrix-whatsapp.service b/bundles/mautrix-whatsapp/files/mautrix-whatsapp.service
new file mode 100644
index 0000000..af9c97c
--- /dev/null
+++ b/bundles/mautrix-whatsapp/files/mautrix-whatsapp.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Matrix WhatsApp Bridge
+After=network.target
+
+[Service]
+User=mautrix-whatsapp
+Group=mautrix-whatsapp
+ExecStart=/opt/mautrix-whatsapp/src/mautrix-whatsapp --config /opt/mautrix-whatsapp/config.yaml --registration /opt/mautrix-whatsapp/registration.yaml
+WorkingDirectory=/opt/mautrix-whatsapp/src
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/bundles/mautrix-whatsapp/files/registration.yaml b/bundles/mautrix-whatsapp/files/registration.yaml
new file mode 100644
index 0000000..cd77be1
--- /dev/null
+++ b/bundles/mautrix-whatsapp/files/registration.yaml
@@ -0,0 +1,10 @@
+id: whatsapp
+url: http://${node.metadata['mautrix-whatsapp'].get('listen-addr', '127.0.0.1')}:${node.metadata['mautrix-whatsapp'].get('port', 20020)}
+as_token: ${node.metadata['mautrix-whatsapp']['as_token']}
+hs_token: ${node.metadata['mautrix-whatsapp']['hs_token']}
+sender_localpart: whatsappbot
+rate_limited: false
+namespaces:
+ users:
+ - regex: ^@whatsapp_[0-9]+:${node.metadata['mautrix-whatsapp']['homeserver']['domain']}$
+ exclusive: true
diff --git a/bundles/mautrix-whatsapp/items.py b/bundles/mautrix-whatsapp/items.py
new file mode 100644
index 0000000..df88ab7
--- /dev/null
+++ b/bundles/mautrix-whatsapp/items.py
@@ -0,0 +1,70 @@
+users = {
+ 'mautrix-whatsapp': {
+ 'home': '/opt/mautrix-whatsapp',
+ },
+}
+
+directories = {
+ '/opt/mautrix-whatsapp/src': {},
+ '/opt/mautrix-whatsapp/logs': {
+ 'owner': 'mautrix-whatsapp',
+ },
+}
+
+git_deploy = {
+ '/opt/mautrix-whatsapp/src': {
+ 'repo': 'https://github.com/tulir/mautrix-whatsapp.git',
+ 'rev': node.metadata['mautrix-whatsapp']['version'],
+ 'triggers': {
+ 'action:mautrix-whatsapp_build',
+ 'svc_systemd:mautrix-whatsapp:restart',
+ },
+ },
+}
+
+actions = {
+ 'mautrix-whatsapp_build': {
+ 'command': 'cd /opt/mautrix-whatsapp/src && go build',
+ 'triggered': True,
+ 'needs': {
+ 'pkg_apt:golang-go',
+ },
+ },
+}
+
+svc_systemd = {
+ 'mautrix-whatsapp': {
+ 'needs': {
+ 'action:mautrix-whatsapp_build',
+ 'directory:/opt/mautrix-whatsapp/logs',
+ 'file:/etc/systemd/system/mautrix-whatsapp.service',
+ 'file:/opt/mautrix-whatsapp/config.yaml',
+ 'postgres_db:mautrix-whatsapp',
+ 'postgres_role:mautrix-whatsapp',
+ },
+ },
+}
+
+files = {
+ '/opt/mautrix-whatsapp/registration.yaml': {
+ 'content_type': 'mako',
+ 'triggers': {
+ 'svc_systemd:mautrix-whatsapp:restart',
+ },
+ },
+ '/opt/mautrix-whatsapp/config.yaml': {
+ 'content_type': 'mako',
+ 'triggers': {
+ 'svc_systemd:mautrix-whatsapp:restart',
+ },
+ },
+ '/etc/systemd/system/mautrix-whatsapp.service': {
+ 'triggers': {
+ 'action:systemd-reload',
+ 'svc_systemd:mautrix-whatsapp:restart',
+ },
+ },
+}
+
+if node.has_bundle('matrix-synapse'):
+ files['/opt/mautrix-whatsapp/registration.yaml']['triggers'].add('svc_systemd:matrix-synapse:restart')
diff --git a/bundles/mautrix-whatsapp/metadata.py b/bundles/mautrix-whatsapp/metadata.py
new file mode 100644
index 0000000..c41c141
--- /dev/null
+++ b/bundles/mautrix-whatsapp/metadata.py
@@ -0,0 +1,64 @@
+defaults = {
+ 'apt': {
+ 'packages': {
+ 'libolm-dev': {},
+ 'golang-go': {},
+ },
+ },
+ 'icinga2_api': {
+ 'mautrix-whatsapp': {
+ 'services': {
+ 'MAUTRIX-WHATSAPP PROCESS': {
+ 'command_on_monitored_host': '/usr/lib/nagios/plugins/check_procs -C mautrix-whatsapp -c 1:',
+ },
+ },
+ },
+ },
+ 'matrix-synapse': {
+ 'appservice_configs': {
+ '/opt/mautrix-whatsapp/registration.yaml',
+ },
+ },
+ 'mautrix-whatsapp': {
+ 'database': {
+ 'user': 'mautrix-whatsapp',
+ 'password': repo.vault.password_for('{} postgresql mautrix-whatsapp'.format(node.name)),
+ 'database': 'mautrix-whatsapp',
+ },
+ 'as_token': repo.vault.password_for('{} mautrix-whatsapp as_token'.format(node.name)),
+ 'hs_token': repo.vault.password_for('{} mautrix-whatsapp hs_token'.format(node.name)),
+ 'sender_localpart': repo.vault.password_for('{} mautrix-whatsapp sender_localpart'.format(node.name)),
+ 'provisioning': {
+ 'enabled': False,
+ },
+ },
+ 'postgresql': {
+ 'roles': {
+ 'mautrix-whatsapp': {
+ 'password': repo.vault.password_for('{} postgresql mautrix-whatsapp'.format(node.name)),
+ },
+ },
+ 'databases': {
+ 'mautrix-whatsapp': {
+ 'owner': 'mautrix-whatsapp',
+ },
+ },
+ },
+}
+
+
+@metadata_reactor
+def icinga_check_for_new_release(metadata):
+ return {
+ 'icinga2_api': {
+ 'mautrix-whatsapp': {
+ 'services': {
+ 'MAUTRIX-WHATSAPP UPDATE': {
+ 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_github_for_new_release tulir/mautrix-whatsapp {}'.format(metadata.get('mautrix-whatsapp/version')),
+ 'vars.notification.mail': True,
+ 'check_interval': '60m',
+ },
+ },
+ },
+ },
+ }
diff --git a/nodes/htz/ex42-1048908.py b/nodes/htz/ex42-1048908.py
index 45bd175..d26d1df 100644
--- a/nodes/htz/ex42-1048908.py
+++ b/nodes/htz/ex42-1048908.py
@@ -5,6 +5,7 @@ nodes['htz.ex42-1048908'] = {
'jenkins-ci',
'matrix-synapse',
'mautrix-telegram',
+ 'mautrix-whatsapp',
'miniflux',
'mx-puppet-discord',
'nodejs',
@@ -111,10 +112,6 @@ nodes['htz.ex42-1048908'] = {
'server_name': 'franzi.business',
'baseurl': 'matrix.franzi.business',
'admin_contact': 'mailto:hostmaster@kunbox.net',
- 'appservice_configs': {
- # TODO move to bundles
- '/opt/matrix-bridges/mautrix-whatsapp/registration.yaml',
- },
'trusted_key_servers': {
'matrix.org',
'finallycoffee.eu',
@@ -143,6 +140,16 @@ nodes['htz.ex42-1048908'] = {
'bot_token': vault.decrypt('encrypt$gAAAAABfVK51ErJ6gfsOOkbRxSHDnVYmf7EihAQf7Uwj9og3TlAw64WRsA6ZVEgTSvOdLB3SMKZ-cTEhwkCOpbymq-_WLhes-hZALhN-H_oXHaxTQErJ0lARynKmjM-4ZhoGlUWlfh4Q'),
},
},
+ 'mautrix-whatsapp': {
+ 'version': 'v0.1.5',
+ 'homeserver': {
+ 'domain': 'franzi.business',
+ 'url': 'https://matrix.franzi.business',
+ },
+ 'permissions': {
+ "'@kunsi:franzi.business'": 100,
+ },
+ },
'miniflux': {
'domain': 'rss.kunsmann.eu',
},