cd ~{,/zhs/}

Run Mastodon Server on Arch Linux VPS

Meta Info

I’m using Docker to run Mastodon now, this article is reserved only for reference.


Short story: open-source self-hosted Twitter. So why not Twitter? Well Mastodon should be more private and under my own control.

VPS Requirement

I’m using one-year free trial of AWS, there are Arch Linux AMIs according to ArchWiki, which people can directly launch EC2 instances.

Basically a VPS that one can install Arch Linux on it is enough; Hardware resource requirement depends on user amount, in my case, a free trial VPS should be enough.

Add DNS Record

Go to my DNS service website then add an A record with public IP of VPS to my domain.

Add Swap Space

Swap - ArchWiki

My VPS has only 1G memory, so a swapfile is considered necessery.

# pacman --sync systemd-swap
# sed --in-place 's/swapfc_enabled=0/swapfc_enabled=1/' /etc/systemd/swap.conf
# systemctl enable systemd-swap
# reboot

Install Packages Needed

# pacman --sync nano sudo tmux yay nginx certbot-nginx

I don’t know how to use vi so nano is needed.

For package yay, one can install it after adding Arch Linux CN repository.

Create a Privileged User

An AUR package is not allowed to install with root user, so I have to run useradd -m -G wheel liolok && passwd liolok to create a user of administration group, then run nano /etc/sudoers and uncomment the line %wheel ALL=(ALL) ALL.

Install AUR Package

# su - liolok
$ tmux
$ yay --sync mastodon

Nodejs stuff will take quite a long time even without output. After installation, press Ctrl + D twice to return to root user.

PostgreSQL and Redis

# systemctl enable --now postgresql redis

I ran into a trouble that the service of PostgreSQL failed to start, so look into it:

 root   systemctl status postgresql                                                                                                                                                    1 
 postgresql.service - PostgreSQL database server
     Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; vendor preset: disabled)
     Active: failed (Result: exit-code) since Sun 2019-12-08 16:37:37 UTC; 20s ago
    Process: 150840 ExecStartPre=/usr/bin/postgresql-check-db-dir ${PGROOT}/data (code=exited, status=1/FAILURE)

Dec 08 16:37:37 ip-172-31-21-37 systemd[1]: Starting PostgreSQL database server...
Dec 08 16:37:37 ip-172-31-21-37 postgres[150840]: "/var/lib/postgres/data" is missing or empty. Use a command like
Dec 08 16:37:37 ip-172-31-21-37 postgres[150840]:   su - postgres -c "initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'"
Dec 08 16:37:37 ip-172-31-21-37 postgres[150840]: with relevant options, to initialize the database cluster.
Dec 08 16:37:37 ip-172-31-21-37 systemd[1]: postgresql.service: Control process exited, code=exited, status=1/FAILURE
Dec 08 16:37:37 ip-172-31-21-37 systemd[1]: postgresql.service: Failed with result 'exit-code'.
Dec 08 16:37:37 ip-172-31-21-37 systemd[1]: Failed to start PostgreSQL database server.

It seems not a big deal, just follow the instruction to initialize the database cluster and then start service.

# su - postgres --command "initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'"
# systemctl start postgres

Then create the Mastodon PostgreSQL user and grant it the ability to create databases:

# su - postgres --shell /bin/sh --command "createuser -d mastodon"


Copy Mastodon’s default nginx configuration:

# cd /etc/nginx/
# mkdir sites-available sites-enabled
# cp --verbose /var/lib/mastodon/dist/nginx.conf sites-available/mastodon
# ln --symbolic --verbose sites-available/mastodon sites-enabled/mastodon

Replace with my own domain, fix mastodon path:

# sed --in-place=".default" /etc/nginx/sites-available/mastodon \
--expression 's/example\.com/zone\.liolok\.com/' \
--expression 's/home\/mastodon\/live/var\/lib\/mastodon/'

Generate certificate:

# certbot --nginx --domains

This command reports that certificate and chain are saved, but haven’t been installed to nginx configuration.

It’s ok, do the next steps:

Then run systemctl enable --now nginx.

Final Setup

# tmux
# su - mastodon --shell /bin/sh --command "cd '/var/lib/mastodon'; RAILS_ENV=production bundle exec rails mastodon:setup"

In this step, there will be a command line interface that seems kind of user friendly.

First content to input is my own domain; then comes stuff about postgresql and redis, leave them default; then comes E-mail part: this confused me for a lot of time, at last I used my previous configured Yandex domain mail:

Then the database and pre-compile work, latter would take longer. Finally I config the admin account information, and get the default password generated.

Up to now, everything is ready. Start the mastodon services, and the website becomes available.

# systemctl enable --now