Self-Hosting with systemd

Running as a service

It is recommended to host cactus-appservice with docker as described here.

This page describes an experimental approach for running the appservice as a systemd service using Python’s virtualenv. If you have any suggestions for how to improve this, please don’t hesitate to contribute!


You need a host that uses systemd as a service manager. You’ll also need Python 3.9 or newer and pip.


Basic self-host configuration

Please follow the configuration steps of the main self-host document, except of course the docker part.

Setup the appservice’s directory

You need to decide where to store the appservice. Reasonable parent folder examples are /opt, /srv/www, /var/www/. Assuming you are in the chosen folder, first clone the repo:

$ git clone
$ cd cactus-appservice

Second, create a python virtualenv, and activate it:

$ virtualenv env
$ source env/bin/activate

Third, install the dependencies in the virtualenv:

$ pip install -r requirements.txt

You can leave the virtualenv now:

$ deactivate

Adjust the environment file

Create the environment file as described in the self host page.

To make the setup self-contained (and separate from the git repo), move the file to the env folder created by virtualenv (which is .gitignored), and name it appservice.env. It should be readable only by the user running systemd daemon: root!

$ mv <path-to-created-env-file> env/appservice.env
$ chown root. $_
$ chmod o-rwx $_

Next, set $PATH in the environment file, so that it points to <chekout-path>/env/bin.

The extended file could look like this (if you chose /srv/www as the repo’s parent folder):


Copy and adjust systemd service file

There is a systemd unit file in the appservice repo, that is almost ready-to-use out of the box.

Install it so systemd can find it with cp:

$ sudo cp cactus-comments.example.service /etc/systemd/system/cactus-comments.service

You need to change the following parameters (marked by # Adjust this!) in the service file:

  • set EnvironmentFile to the full path of appservice.env (the file you adjusted previously)
  • set WorkingDirectory to the full path of the local appservice repo.

For example the new file’s first lines should look like this (if you chose /srv/www as the repo’s parent folder):

Description=Cactus Comments appservice: Matrix powered embeddable comment backend

ExecStart=/bin/bash -c 'gunicorn -w 4 -b --timeout 500 "app:create_app_from_env()"'
# Adjust this!
# Adjust this!

Save your changes, then let systemd know about the new service:

$ sudo systemctl daemon-reload

Start the service!

If you’ve also configured synapse, Cactus Comments should be ready to run as a service! You can enable and start the service in one fell swoop:

$ sudo systemctl enable --now cactus-comments

Check the logs:

$ sudo journalctl -u cactus-comments

The last lines should be something like:

Apr 06 01:04:27 bash[5189]: [2022-04-06 01:04:27,041] INFO in app: Created application!

Hooray! It runs!