Personal Pleroma Instance Setup

I wanted to join the Fediverse for a while but had a preference for self-hosting my own instance and now I’ve finally got around to doing it. I’m not going to go into what the Fediverse/ActivityPub is in this post, there’s already other posts about that. This post details how I set up and configured the Pleroma instance at social.0daysto.live in a Docker container with webfinger (so that my account will be @0daysto.live instead of @social.0daysto.live ) and Cloudflare Tunnel (so that it doesn’t need to use any ports on the VPS since I have other things on it).

Why Pleroma?

So one thing that irks me is how everyone says “Mastodon” when the network you are actually joining is the Fediverse. It’s like saying Gmail instead of email. I think for the network to be healthy there should be more than one piece of software using the protocol to avoid problems around having a software monoculture.

So what are the options we have to choose from?

I’m going to ignore things like Peertube and Pixelfed as they differ from what I’m looking for - microblogging and status updates. Here are the options I came across:

I chose Pleroma primarily for performance reasons, I want it to be performant enough that I can put it on a VPS with other small projects I have and not overuse resources. I could have chose something more minimalistic but for now I want to try out the available features and use something that is a bit more well supported so I don’t run into compatibility problems.


For my installation I chose to use angristan’s Docker repo.

First I need to install Docker. The version of docker-compose on the Debian repository was too old so I had to install docker-compose from the git repo instead.

VERSION=$(curl --silent https://api.github.com/repos/docker/compose/releases/latest | grep -Po '"tag_name": "\K.*\d')
sudo curl -L https://github.com/docker/compose/releases/download/${VERSION}/docker-compose-$(uname -s)-$(uname -m) -o $DESTINATION
sudo chmod 755 $DESTINATION

A lot of the next steps are from the git repo. First we’ll get it running with default configuration then we’ll make our custom changes and restart it.

Clone the git repo:

git clone https://github.com/angristan/docker-pleroma.git

Make a folder for your pleroma instance and copy files from the git repo into it:

mkdir mypleroma # m-m-m-my pleroma
cp Dockerfile config.exs docker-compose.yml mypleroma

Change the POSTGRES_PASSWORD in the docker-compose.yml file, just make it a long random string you won’t need to remember it.

Now would be a good time to make the configuration changes for your instance. I detailed changes I made in different sections below so you can pick and choose those changes and come back to here.

Make some folders the install will need and assign permissions so they can be written into:

mkdir uploads config static
chown -R 911:911 uploads static

Pleroma needs the citext PostgreSQL extension, you can add it by running the following:

docker-compose up -d db
docker exec -i pleroma_db psql -U pleroma -c "CREATE EXTENSION IF NOT EXISTS citext;"
docker-compose down

Next build the docker image and start it.

docker build -t pleroma .
docker-compose up -d

It will automatically set up the database tables on the first run, you can check the logs to see that everything is ok with this command:

docker logs -f pleroma_web

Make your admin account:

docker exec -it pleroma_web sh ./bin/pleroma_ctl user new YOURUSERNAME [email protected] --admin

This command should give you the link to set the account password.

Oh no I messed up and its not working

The nice thing about using Docker is that if it’s not working when doing intial set up of something you can just yeet the whole thing into the sun and start again. To reset you just need to delete the postgres folder and delete the docker containers:

rm -rf postgres
docker rm pleroma_web pleroma_db

Restarting After Configuration Changes

Sometimes you might want to restart to apply changes or upgrades. I have to following saved as a bash script for that:

docker-compose down
docker build -t pleroma .
docker-compose up -d

Cloudflare Tunnel / Cloudflared

The VPS I’m using has things running on the common ports and I don’t want Pleroma to interfere with that. One option I considered was renting another IP and attaching it to this VPS but that costs money and is complicated to set up. Then I found I could use Cloudflare Tunnel to expose the website to the internet and not have it available from my server IP. This is quite nice as it also means you could use it to host on a server that doesn’t have a public IP or on your home network if you so wished. It could also be a security measure to protect the backend IP of your Pleroma instance to avoid DDoS attacks.

I followed the offical docs to set up Cloudflare Tunnel

The gist of it:

wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && dpkg -i cloudflared-linux-amd64.deb
cloudflared tunnel login
cloudflared tunnel create pleroma
cloudflared tunnel list
nano ~/.cloudflared/config.yml
cloudflared tunnel route dns pleroma social.0daysto.live
cloudflared tunnel run pleroma

My cloudflared/config.yml file looks like:

url: http://localhost:4000
tunnel: <Tunnel-UUID>
credentials-file: /root/.cloudflared/<Tunnel-UUID>.json

In my docker-compose.yml I changed

      - '4000:4000'


      - ''

so that the docker only listens to the port on localhost. On localhost cloudflared is able to interact with it and tunnel it.


The domain I wanted to set up my Fediverse instance is 0daysto.live but I also want to use the main domain for this blog. The solution to this is using webfinger. I can install Pleroma at social.0daysto.live and have a webfinger config on 0daysto.live pointing to it. This allows me to have the username [email protected] instead of the uglier [email protected]. So how do we do that? I’m using Cloudflare on my main domain so I decided to use a Page Rule. The Page Rule does a 301 redirect of https://0daysto.live/.well-known/host-meta to https://social.0daysto.live/.well-known/host-meta. There’s other ways to accomplish this, I could for example put a file at that location with the content that my Pleroma instance serves. If you’re using a webserver like nginx you could add this to your config for the same effect:

location = /.well-known/host-meta {
       return 301 https://pleroma.example.org$request_uri;

You also need to add the following line to your config.exs file:

config :pleroma, Pleroma.Web.WebFinger, domain: "0daysto.live"

The offical docs for setting up Pleroma with Webfinger: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/docs/configuration/how_to_serve_another_domain_for_webfinger.md

Pleroma Configuration

Standard Stuff

In docker-compose.yml I set my domain, instance name, admin emails:

      DOMAIN: social.0daysto.live
      INSTANCE_NAME: 0daysto.live
      ADMIN_EMAIL: [email protected]
      NOTIFY_EMAIL: [email protected]

I’m not configuring my instance to send emails so they don’t really matter but valid format emails must be used or you will have errors. Also note that the domain used is the subdomain that I’m going to have pleroma on and not the webfinger domain.

Disable Registration

As I’ve stated I don’t intend to have other users so I’m disabling registration. I set registrations_open: false in the config :pleroma, :instance section.

Settings in Admin Panel

By default settings can only be controlled from the server or a config file, to make them accessible in the admin panel you have to add this line to your config.exs file:

config :pleroma, configurable_from_database: true

If you previously set up your instance and visited the admin panel before making this change then you will need to clear the cookies for it to work.

CSP Problems

When I initially set up Pleroma I was getting CSP errors like: Content Security Policy: The page’s settings blocked the loading of a resource at inline (“script-src”). To avoid this for now I just disabled the CSP entirely by adding this line to my config:

config :pleroma, :http_security, enabled: false

There’s a few open issues on the git about CSP that may help with this in the future:


My instance is a single user instance so there is no need for a shoutbox (live chat between people on the same instance) so I disabled it with this line:

config :pleroma, :shout,
  enabled: false


Okay now you should have your Pleroma instance set up with you account set up on it. Initially your timeline will be empty but thats just how federation works. You should start following people to build up your feed/network. Assuming you’re moving from Twitter there is a few different services that will help you find the fediverse handles for people you already follow:

As for mobile apps I’ve been trying Tusky and it works great. You can get a list of clients that support Pleroma here

You can follow me at [email protected]