Deploying Pantalaimon on my Matrix Test Rig

Last week I was setting up Draupnir on my matrix test rig, in order to become familiar with Draupnir deployment before I integrate it with PubHubs.

Now I need to address end-to-end-encryption (E2EE). PubHubs exclusively uses encrypted matrix rooms, and Draupnir doesn't yet have E2EE functionality built-in. (Why is that? Moderation in public rooms is Draupnir's main use case, and for several reasons public matrix rooms are usually not encrypted. However PubHubs is different.)

There is a generic solution for adding E2EE to a matrix bot, and it's called Pantalaimon, an "E2EE aware proxy daemon for matrix clients." So this week I'm setting up Pantalaimon.

The handy matrix-docker-ansible-deploy has no Pantalaimon role ... yet. I may be able to contribute one, but no promises. First I will make a stand-alone Pantalaimon setup role, in my quest to automate, with Ansible, as much as possible of the set-up.

Simple Ansible Role for Pantalaimon

I have made and published a simple Ansible role to run Pantalaimon. It consists of:

I use the role in my playbook like this:

  - name: "pantalaimon"
    include_role: name=trax_im.matrix_ansible.pantalaimon
      pantalaimon_docker_image: "{{ my_docker_registry_host }}/pantalaimon:latest"
      pantalaimon_docker_network: "{{ matrix_docker_network }}"
      pantalaimon_base_path: /srv/PubHubs/pantalaimon
      pantalaimon_log_level: Debug
      pantalaimon_homeserver_name: example
      pantalaimon_homeserver_url: ""

My intention is to run Pantalaimon in a container, managed by Docker (alternatives like Podman should work similarly), on the target machine where the matrix server runs. Note that, in general, to minimise exposure of encrypted data, Pantalaimon should be run "close to" the bot or client that uses it. At least the unencrypted connection between the bot or client and Pantalaimon should be secured.

There is no Pantalaimon docker image published by its creators, so my role builds it, and pushes it to my private registry. (You could delegate the building to a different machine such as localhost; that's commented out in tasks/main.yml in v1.1.0. Or, building on the target machine, you could avoid using a registry if you set my_docker_registry_host to localhost, I think; you might need to disable the 'push' option in the build task as well.)

Connecting Draupnir to Pantalaimon

To connect Draupnir to Pantalaimon, I am going to show a playbook task that invokes the existing draupnir role. (Usually to set up a regular matrix system I run the 'matrix-docker-ansible-deploy' playbook as a whole. Invoking a role individually from another playbook is working towards using it with PubHubs rather than a regular matrix system.)

The key part here is to override the Draupnir config's homeserverUrl to point to Pantalaimon, while leaving the Draupnir config's rawHomeserverUrl pointing to the matrix server's public client-server API, as documented in Draupnir's example config.

  - name: "draupnir" 
    include_role: name=playbooks-from/matrix-docker-ansible-deploy/roles/custom/matrix-bot-draupnir 
      matrix_bot_draupnir_access_token: "{{ matrix_draupnir_bot_access_token }}"  # using value generated by login step earlier; alternatively read it from a vault-var
      matrix_bot_draupnir_management_room: "{{ matrix_draupnir_management_room_id }}"  # using value generated by room-creation step earlier; alternatively read it from an inventory var
      matrix_bot_draupnir_configuration_extension_yaml: | 
        homeserverUrl: "http://pantalaimon:8009" 
          use: true 
          username: "bot.draupnir-admin" 
          password: "{{ matrix_draupnir_bot_password }}"  # using an inventory vault-var
        protectAllJoinedRooms: true  # my preference
          allowNoPrefix: true  # my preference
        - docker.service 
        - matrix-synapse.service 
        - matrix-pantalaimon.service 

These vars would better be placed in the inventory than here. To use the role stand-alone like this we also need to set a few other base variables from matrix-docker-ansible-deploy, which we can do like this:

  vars_files:  # defined at the playbook level
    - playbooks-from/matrix-docker-ansible-deploy/roles/galaxy/com.devture.ansible.role.playbook_help/defaults/main.yml
    - playbooks-from/matrix-docker-ansible-deploy/roles/galaxy/com.devture.ansible.role.systemd_docker_base/defaults/main.yml
    - playbooks-from/matrix-docker-ansible-deploy/roles/custom/matrix-base/defaults/main.yml

  vars:  # defined at the task or block level
    matrix_user_uid: 991  # to match our existing matrix installation
    matrix_user_gid: 991
    matrix_homeserver_url: "https://matrix.example"

We have looked at a simple stand-alone Pantalaimon role. Now to integrate it in matrix-docker-ansible-deploy.

M-D-A-D Playbook Role for Pantalaimon

The first draft of a suitable role is published on TraxLab: roles/matrix_pantalaimon.

[2023-10-19] I prepared a merge request to the m-d-a-d playbook:

Pantalaimon role is activated by matrix_pantalaimon_enabled and connects to the homeserver by default. No further config is needed. Integration with Draupnir is included, activated by matrix_bot_draupnir_use_pantalaimon. No integration with Mjolnir or anything else. Alternatively Pantalaimon can be configured alone, and then whatever component is meant to talk to it, in or out of the playbook, may be configured separately/manually.

... and Slavi has responded to me with a bunch of good review comments which I need to address.

UPDATE 2023-12-21: Addressed those review comments.

UPDATE 2024-03-29: This is now accepted and included in matrix-docker-ansible-deploy.

#matrix #awesomeFOSS #Draupnir #PubHubs