Installing an Akkoma Instance
Series: Akkoma
I’ve decided to self-host my own Akkoma (a hard fork of Pleroma) instance, after actively and happily using Mastodon for 2.5 years. Inspired by The Teabag Ninja’s awesome and detailed writeup on Akkoma’s OTP install, I’m also sharing my source installation notes along the way for all the folks on the internet, including my future self – since I did have a few surprises during the process.
Unless otherwise noted, all commands below are tested on an ARM-based machine with Ubuntu 22.04, for an Akkoma install from source.
A Word of Warning: Hosting the Instance on a (Sub)domain With a Different Account Identifier
I’m putting this down first, because this burnt me so bad, that I had to tear down the entire installation, and re-install the instance under a different subdomain. Read this if you’re like me, who:
- already hosts content on
domain.com
, - is thinking of hosting the instance under
subdomain.domain.com
, - while ensuring your username has the form
@user@domain.com
instead of@user@subdomain.domain.com
.
TL;DR: this is achievable on Akkoma (or any fediverse software that supports this), but with a few very important caveats:
- You need to have the ability to set up multiple external 301 redirects for
domain.com
. The Pleroma/Akkoma doc explains why with the WebFinger protocol, but turns out you will have to proxy/redirect not only.well-known/host-meta
, but all three different well-known endpoints(reference):host-meta
,nodeinfo
, andwebfinger
. Especially thewebfinger
endpoint mentioned in the docs of Mastodon and GoToSocial – which Akkoma/Pleroma docs seem to be missing. - You have only one chance to configure this right – before your instance starts federating with other instances. Otherwise, the other instaces will be confused about the identity of users on your instance, and there’s no way to ask them to correct it – because you don’t control those other instances.
Since my contents on domain.com
is hosted on Gitlab Pages, which per their instructions does not support external redirects (yet), here are my alternatives:
- Serving static assets for
host-meta
,nodeinfo
(these two are just static content), and each user on my instance forwebfinger
(this endpoint has query parameters), so that the lookup finds them. - Just settle for identifiers with the subdomain like
@user@subdomain.domain.com
. (I eventually went for this this option.)
Just so that you mess things up and have to start from scratch like I did, here’s how you uninstall and reinstall Postgres on Ubuntu 🥲.
Setting Up a Host Server
With Oracle Cloud Infrastructure
My final setup is on an ARM-based OCI instance on their generous free tier offering, with the acknowledgement/expectation that this free tier may change in the future. To setup an account and create an instance, I follow this tutorial – admittedly including the script that, once in a while, checks if an instance is available in my home region. I’m lucky to have an instance created in about a week for my region.
Once the instance is created and a public IP address attached, I have no issues logging in with the ssh key. The default user is ubuntu
, but running sudo <command>
or switching to root (sudo su - root
) does not require a password – this is important because the super user permission is required to install Akkoma on the server.
OCI’s Ubuntu instances are firewall protected by both the OS’s iptables, and the VCN attached to the instance (we’ll see later), so don’t be surprised if a fresh instance doesn’t allow most ingress TCP connections.
With Vultr
I also get an instance with Vultr – they run year-round promos, allowing you to try out their instances for free for some initial periods of time. Akkoma’s resource consumption is minimal, so a humble $5/month instance with 1 vCPU, 1GB memory, and 1T bandwidth should be able to handle myself as the sole user of the app.
Once you have an account registered, select Cloud Compute -> Regular Performance -> 25GB SSD. Choose a location closest to you, and give the server a hostname. An SSH key pair can be generated and added from my Mac:
- Generate with
ssh-keygen -t ed25519 -C "email@example.com"
, and - add to ssh-agent with
ssh-add -K ~/.ssh/<name_of_private_key_file>
.
Also make sure to disable IPv6 and Auto Backups to avoid additional charges of $1/month.
Vultr’s Ubuntu instances are initially firewalled with ufw
– the Ubuntu OS firewall. Initially only port 22 are allowed:
root@server:~# ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
To enable port 80 and 443 for ingress connections, ufw allow 80/tcp
and ufw allow 43/tcp
, then reload with ufw reload
.
Setting Up DNS for the Subdomain
It’s good to start setting up the DNS now, since the records usually take a while to propagate because of delays with your DNS server, TTL, caches everywhere etc.
I’m trying to set up my Akkoma instance on a subdomain fedi.<domain>.com
, where <domain>.com
already hosts my blog on Gitlab Pages. So the subdomain fedi.<domain>.com
should point to my server. Vultr’s official DNS doc isn’t helpful on the subdomain issue, in that it directs you to use its own nameservers regardless of alternatives (OCI also has DNS servers available) – but in my case, I’m already using DNS at my domain registar for <domain>.com
. So I end up directly going to my domain registar, and adding my A
record for Hostname:akkoma, Type:A, value:<my_instance_ip>
. This is it!
Like all DNS configurations, this takes a while to take effect. After a couple of hours, I’m able to verify with nslookup fedi.<domain>.com
, which returns my instance’s IP.
Installing Akkoma (From Source)
On the OCI instance, I was following the OTP guide until the config generation step gave me:
$ su akkoma -s $SHELL -lc "./bin/pleroma_ctl instance gen --output /etc/akkoma/config.exs --output-psql /tmp/setup_db.psql"
/opt/akkoma/releases/3.5.0-0-gd9508474b/../../erts-13.1.2/bin/erl: 12: exec: /opt/akkoma/erts-13.1.2/bin/erlexec: Exec format error
This is when I realized Akkoma doesn’t support ARM builds yet at the time of writing – but unfortunately I’m on an ARM-based machine:
$ uname -m
aarch64
This means I’ll have to install from source! All of the following commands are derived from the official Akkoma documentation, on installing from source, for Arch Linux, and Alphine Linux, adapted for Ubuntu.
Installing Dependencies
- Switch to the root user:
sudo su - root
- Install the required deps:
apt install postgresql elixir git cmake file build-essential erlang
- Install the optional deps:
apt install imagemagick ffmpeg libimage-exiftool-perl
- Start the Postgres service:
systemctl start postgresql.service
The Akkoma Backend
- Create the akkoma user if not already (
less /etc/passwd
to check):I took this from the OTP install guide, so that the home directory isadduser --system --shell /bin/false --home /opt/akkoma akkoma
/opt/akkoma
instead. - Make the akkoma user the owner of
/opt/akkoma
, and clone the stable branch of akkoma code into it:mkdir -p /opt/akkoma chown -R akkoma /opt/akkoma su akkoma -s $SHELL -lc "git clone https://akkoma.dev/AkkomaGang/akkoma.git -b stable /opt/akkoma"
- Change into the directory:
cd /opt/akkoma
- Install akkoma dependencies – say yes when you’re asked to install
Hex
.su akkoma -s $SHELL -lc "mix deps.get"
- Generate configurations in
config/generated_config.exs
:su akkoma -s $SHELL -lc "MIX_ENV=prod mix pleroma.instance gen"
- As the offical doc explains, this step also compiles parts of akkoma, so it could take a bit while.
- Say yes when you’re asked to install
rebar3
. - It also interactively asks a few questions. Pay extra attention to the domain that the instance uses since it’s bad to change it later. Also I said no to storing the configuration in the database – I’ll enable it later. (Well, almost all the options can be changed later.) Additionally I used the OTP locations for uploads (
/var/lib/akkoma/uploads
) and static (/var/lib/akkoma/static
) instead of the default.
- Rename the config file to
/opt/akkoma/config/prod.secret.exs
:su akkoma -s $SHELL -lc "mv config/{generated_config.exs,prod.secret.exs}"
- Create the database:
su postgres -s $SHELL -lc "psql -f /opt/akkoma/config/setup_db.psql"
- Run the db migration – this compiles more files so again it takes a while.
su akkoma -s $SHELL -lc "MIX_ENV=prod mix ecto.migrate"
- Finally start the Akkoma backend:
From another terminal (ssh’ed into my server) I’m able to
su akkoma -s $SHELL -lc "MIX_ENV=prod mix phx.server"
curl http://localhost:4000/api/v1/instance
, and get back some json. Sweet!
A Quick Summary of Where Things Are So Far
- The config:
/opt/akkoma/config/prod.secret.exs
- The code:
/opt/akkoma
– this is also system userakkoma
’s home directory - The uploads directory:
/var/lib/akkoma/uploads
- The static directory (custom emojis, frontend bundle overrides, robots.txt, etc.):
/var/lib/akkoma/static
Moving on…
Reverse Proxy and TLS Handling
Any reverse proxy will do (the repo actually has a few other options in /opt/akkoma/installation
), but I’ll stick with nginx for now 😃
-
Stop nginx ot free up port 80:
systemctl stop nginx
And verify port 80 is clear with
netstat -ltpn
. -
Get a Let’s Encrypt certificate:
certbot certonly --standalone --preferred-challenges http -d fedi.<domain>.com
On the OCI ARM instance, this step the command initially failed for me on connection problems:
Certbot failed to authenticate some domains (authenticator: standalone). The Certificate Authority reported these problems: Domain: fedi.<domain>.com Type: connection Detail: <ip>: Fetching http://fedi.<domain>.com/.well-known/acme-challenge/9JJYxsrHYt-aD86w9Mlp0k4JZajbEGlL1eSSXHkG7c8: Timeout during connect (likely firewall problem)
An nmap scan (
nmap -Pn -p 22,80,443 --reason <ip>
from outside the server) also shows ports 80 and 443 as “filtered”:PORT STATE SERVICE REASON 22/tcp open ssh syn-ack 80/tcp filtered http no-response 443/tcp filtered https no-response
“Filtered” just means there’s a firewall blocking the port. Turns out two firewalls are blocking the connection – the host firewall and OCI’s Virtual Cloud Networks setup.
- I follow this article to enable 80 and 443 for the host firewall – essentially manipulate the iptable rules directly.
- On how to add the ingress rule to the VCN that my instance belongs to, credit to this article.
After the two steps, rerunning this command succeeds for me.
I also notice this line from stdout when I request the certificate:
This certificate expires on 2023-xx-xx. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background.
So it did, which means I don’t have to manually set up auto-renew. Neat!
-
Copying the nginx config and enabling it:
cp /opt/akkoma/installation/nginx/akkoma.nginx /etc/nginx/sites-available/akkoma.conf ln -s /etc/nginx/sites-available/akkoma.conf /etc/nginx/sites-enabled/akkoma.conf
-
nano /etc/nginx/sites-available/akkoma.conf
And replace all occurrences of
example.tld
tofedi.<domain>.com
. -
Verify the config with
nginx -t
-
Start nginx service, and optionally Akkoma backend in the foreground with
systemctl start nginx su akkoma -s $SHELL -lc "MIX_ENV=prod mix phx.server"
Pointing my browser at
https://fedi.<domain>.com
, I get:Welcome to Akkoma! If you're seeing this page, your server works! ...
with some more instructions and links to install a frontend. Yay!
-
Now to set up the Akkoma backend as a system service. Looking at the the service config file, the only thing I need to modify this the akkoma user’s home directory. So
nano /opt/akkoma/installation/akkoma.service
and change this line
Environment="HOME=/var/lib/akkoma"
to:Environment="HOME=/opt/akkoma"
-
Copy the service config file, start it and enable it on boot:
cp /opt/akkoma/installation/akkoma.service /etc/systemd/system/akkoma.service systemctl start akkoma systemctl enable akkoma systemctl restart nginx
Pointing the browser to
https://fedi.<domain>.com
again, I get the same instructions to install a frontend.
(Optional) Setting Up Custom Domain Identifiers
If you’re using a custom (sub)domain and want the usernames to be identified differently from the instance (sub)domain, this is when you want to set up two things:
Make sure to get it right now before your instance starts federating!
Installing A Frontend
- From what I heard,
pleroma-fe
is a light-weight minimalist frontend. I’ll use it to play around for now:Says it’s installed tocd /opt/akkoma su akkoma -s $SHELL -lc "MIX_ENV=prod mix pleroma.frontend install pleroma-fe --ref stable"
/var/lib/akkoma/static/frontends/pleroma-fe/stable
. - And now install
admin-fe
:su akkoma -s $SHELL -lc "MIX_ENV=prod mix pleroma.frontend install admin-fe --ref stable"
- Since we now have a frontend to do administration with, let’s not forget to activate in-database configuration – I initially opted out during the config generation step.
-
And set
nano config/prod.secret.exs
config :pleroma, configurable_from_database: true
(it’s one of the last lines on the very bottom). -
This also triggers some compiling.
su akkoma -s $SHELL -lc "MIX_ENV=prod mix pleroma.config migrate_to_db"
-
so that the change takes effect.
systemctl restart akkoma
-
Creating the admin user
su akkoma -s $SHELL -lc "MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress> --admin"
The command prints a URL to reset the password – copy and pasting it to the browser, and logging in – it works! Finally time to play around with some fun customizations 🎉.
Quick Validations
- Federation: I have another account on a Mastodon instance, and I try to have the two accounts follow each other and send direct messages – to see if they get each other semi-instantly. During my first attempt at the custom subdomain setup, I was able to uncover the federation issue this way.
- I notice that for the remote accounts I follow, my instance initially pulls posts from back a few months or even a year ago – but as my followees generate new contents, the new posts are up to date.