Deploying the Takahē Fediverse server on Debian 11


I have a Mastodon server, but I’m always on the lookout for more lightweight Fediverse software. Recently I was made aware of Takahē, a Django Fediverse server application written in Python.

The official installation instructions are high-level and require a fair bit of understanding of Linux system administration. In this article I show the individual commands I used to set up my Takahē instance, cockatoot.city.

Virtual machine

The VM I used is a Linode 1 GB shared Nanode running a Debian 11 image.

Since Takahē requires HTTPS, the VM requires DNS records. Set up A and AAAA records in your DNS hosting interface.

Takahē sends email, so set up SPF and DKIM records in your DNS hosting interface.

Host setup

Run everything as root. Substitute italicized text for your own situation.

Set a hostname:

hostnamectl set-hostname cockatoot

Edit /etc/hosts for local DNS resolution:

  • Add to 127.0.0.1 after localhost: cockatoot cockatoot.city
  • Add to ::1 after localhost: cockatoot cockatoot.city

Create an admin user that can sudo to root. After this step you can log out, log back in as the admin user, and sudo -s for the remainder of the steps.

adduser localadmin
adduser localadmin sudo
mkdir ~localadmin/.ssh
chmod 700 ~localadmin/.ssh
chown localadmin:localadmin ~localadmin/.ssh

Create ~localadmin/.ssh/authorized_keys and put your SSH public key into it.

chown localadmin:localadmin ~localadmin/.ssh/authorized_keys
chmod 600 ~localadmin/.ssh/authorized_keys

Install the Docker system

Takahē comes as a Docker image. The standard Debian 11 docker.io package is good enough (but you can install the official Docker packages if you prefer).

apt-get install docker.io

Docker creates a bridge interface for containers to talk to the host. Find out what it is:

docker network inspect bridge

The Gateway line in the output lists the host’s address on the bridge:

"Gateway": "172.17.0.1"

Use the shown address in the remaining instructions if yours is different to 172.17.0.1.

Install mail transport agent

Takahē relies on email to send password-reset notifications and account confirmations. These instructions will vary depending on your upstream mail transport configuration. I use Fastmail, which allows me to create a specific application password for an SMTP client.

You may want to have Takahē talk straight to your smarthost. If this is an option for you, you might not need to configure email on your VM at all, and you can skip the patching of settings.py below.

apt-get install exim4
dpkg-reconfigure exim4-config
  • Mail sent by smarthost
  • System name = cockatoot.city
  • Visible domain name = cockatoot.city
  • smarthost = smtps-proxy.fastmail.com::4465
  • Don’t split config
  • Listen on 127.0.0.1; ::1; 172.17.0.1
  • Relay for network 172.17.0.0/16

Edit /etc/exim4/passwd.client and add the authorization for Fastmail:

*:MY@FASTMAIL_ACCOUNT:FASTMAIL_APP_PASSWORD

Edit /etc/email-addresses, which translates outgoing email addresses in From headers:

root:majormitchell@cockatoot.city

Debian 11 exim4 installations require some hand-editing of configuration files for smarthost handling. Follow these steps.

Edit /etc/aliases so that mail to root and localadmin goes upstream:

root: majormitchell@cockatoot.city
localadmin: root

Reprocess the aliases file:

newaliases

Test sending an email now.

Database

Debian 11 comes with Postgres 13, and Takahē asks for Postgres 15, so install the Postgres official packages.

apt-get install gnupg

Follow the Postgres instructions to add the official repository.

Install postgres:

apt-get install postgresql

Create /etc/postgresql/15/main/conf.d/listen-on-bridge.conf:

listen_addresses = '127.0.0.1,::1,172.17.0.1'

Edit /etc/postgresql/15/main/pg_hba.conf and add Docker bridge IP range

host	all	all	172.17.0.1/16	scram-sha-256

By default, the postgres user does not have a password (it connects by a socket), so give it a password. Also create the empty takahe database.

sudo -u postgres psql
# ALTER USER postgres PASSWORD ‘POSTGRES_PASSWORD’;
# CREATE DATABASE takahe;
# \q

Postgres normally listens on TCP port 5432. Check this, and adjust accordingly from now on:

grep '^port' /etc/postgresql/15/main/postgresql.conf
port = 5432 # (change requires restart)

Firewall

None of the services on the VM will be exposed to the outside (except the web server), so you can skip this section (but don’t).

apt-get install ufw
ufw enable
ufw allow ssh
ufw allow to 172.17.0.0/16 port 5432 proto tcp
ufw allow to 172.17.0.0/16 port smtp proto tcp
ufw allow http
ufw allow https

Web server

Takahē needs a web server that can operate in reverse-proxy mode, passing requests on HTTPS port 443 down to the Takahē webserver container on port 8000.

Install a Let’s Encrypt certificate.

apt-get install nginx python3-certbot-nginx
certbot run --nginx -d cockatoot.city -m MY@EMAIL_ADDRESS --agree-tos

Edit /etc/nginx/sites-enabled/default and modify the location / { } to point to the yet-to-be-created webserver Docker image:

location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://172.17.0.2:8000/; 
}

Restart the web server:

systemctl restart nginx

S3 object storage

Takahē can be configured to store media on Amazon S3-compatible storage. Set up a bucket (here called BUCKET) and create an access keypair (S3_ACCESS_KEY, S3_ACCESS_SECRET).

Takahē environment

A number of environment variables need to be passed to the Takahē containers. It’s easiest to put them into a file and invoke Docker with the --env-file option.

mkdir /etc/takahe

Edit /etc/takahe/environment and fill it with lots of secret information:

TAKAHE_SECRET_KEY=BIG_LONG_RANDOM_STRING
TAKAHE_MEDIA_BACKEND=s3://S3_ACCESS_KEY:S3_ACCESS_SECRET@S3_ENDPOINT_HOST/BUCKET
TAKAHE_MAIN_DOMAIN=cockatoot.city
TAKAHE_EMAIL_SERVER=smtp://172.17.0.1:25/
TAKAHE_EMAIL_FROM=majormitchell@cockatoot.city
TAKAHE_AUTO_ADMIN_EMAIL=majormitchell@cockatoot.city
TAKAHE_USE_PROXY_HEADERS=true
TAKAHE_CSRF_HOSTS=["https://cockatoot.city"]
PGHOST=172.17.0.1
PGUSER=postgres
PGPORT=5432
PGPASSWORD=POSTGRES_PASSWORD

Install Takahē image

Fetch the Takahē image:

docker pull jointakahe/takahe

Create the first Takahē containers from the image, for the webserver, but don’t run it yet:

docker create --env-file=/etc/takahe/environment --name=webserver jointakahe/takahe

Create the second Takahē container, for the worker:

docker create --env-file=/etc/takahe/environment --name=worker --restart=always jointakahe/takahe python3 manage.py runstator --liveness-file /var/run/takahe-watchdog

Takahē doesn’t allow an unauthenticated SMTP relay, so one file inside the container needs to be modified. The webserver container doesn’t try to send email so it doesn’t need to be changed.

docker cp worker:/takahe/takahe/settings.py /tmp/settings.py

Edit /tmp/settings.py and alter two lines:

EMAIL_HOST_USER = urllib.parse.unquote(parsed.username) if parsed.username is not None else None
EMAIL_HOST_PASSWORD = urllib.parse.unquote(parsed.password) if parsed.password is not None else None

And copy the modified file back:

docker cp /tmp/settings.py worker:/takahe/takahe/settings.py

Run, once, the initial database scheme migration:

docker exec -it worker python3 manage.py migrate

Start the two containers:

docker start webserver
docker start worker

Try it out

Go to https://cockatoot.city/auth/signup/ and sign up with the address that you set as the TAKAHE_AUTO_ADMIN_EMAIL account. You should receive an email with a link to set your password.

Next steps

To do:

  • systemd units to start and stop the containers
  • Bulk defederate from unwanted instances

Leave a Reply

Your email address will not be published. Required fields are marked *