The Joys of Self-Hosting
To the surprise of probably nobody, I am not a huge fan of corporations, especially when it comes to the internet. For decades I have been self-hosting - first on my own dsl line, then by renting one in a small server farm. This allowed me to own my email, webpages, network file storage and many other things.
Mastodon
I am also not a huge fan of social networks, with twitter being probably the only one I really *use* (as in: I am there from time to time). Recent advancements on the matter (i.e. the acquisition of the platform by a certain billionaire) made me look for an alternative - and that is how I rediscovered Mastodon. To a little surprise, the technology has matured in the past years, so I decided to host my own instance of it and become part of the *fediverse*. And no, I do not really care if anyone follows me or reads my content. I write things mostly for myself to remember them when needed ;)
The setup
At the moment of installation the server was running Ubuntu 24.04 and Apache 2. I have to say that the official setup guide was of great help and it was pretty straightforward to follow it. Most of the steps worked, with some notable exceptions.
Mastodon
I used the latest version of Mastodon available at the time, so 4.3.1. System user has its home directory not in /home/mastodon
, but elsewhere. The home directory is readable by various user groups, most notably www-data
.
Ruby 3
Sadly, there is no default package for the latest version of Ruby on Ubuntu, so some magic with rbenv
was needed. Remember to update $PATH
to include the .rbenv
version first, otherwise all gems install nicely, but out of a sudden there is an error of a non-existing class, pointing still to version 2.7.
Node 18
I decided to use a newer version of Node - 23.2 instead of the suggested LTS 18. That failed spectacularly - while I was able to get everything up, Mastodon just ended up showing an empty main page, with files failing to load. To my surprise, some pages were showing (like account settings), but the web app was unusable.
So I had to install the recommended Node 18 instead of the newest version, and it just worked.
My previous installation used also Node 18, but for an older version of Mastodon (4.0.2, which recommended Node 16). That broke yarn
, as it uses openssl
3 instead of 2. To allow it to work an extra parameter must be provided when running the setup: RAILS_ENV=production NODE_OPTIONS=--openssl-legacy-provider bundle exec rake mastodon:setup
(only if precompiling assets is needed).
Postgres
Despite creating a database user, its database and making the user the owner of it, the install script still required the user to have createdb
rights.
Also, the database password is written in plain text in the .env file. Please make sure nobody can access that file and that the password is not used anywhere else. As soon as the setup was done I also updated the postgres user with nocreatedb
, just in case.
Paths
As I mentioned before, my instance is installed in a directory different from /home/mastodon
. This means that all the paths in systemd
configuration were incorrect and required adjusting.
Apache 2 configuration
The setup deals with proxying ngix
. Here are the relevant bits for Apache:
<Directory "/path/to/mastodon/public"> Options Indexes MultiViews FollowSymLinks AllowOverride None Require all granted </Directory>
<LocationMatch "^/(assets|avatars|emoji|headers|packs|sounds|system)> Header always set Cache-Control "public, max-age=31536000, immutable" Require all granted </LocationMatch>
<IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" Header always set Referrer-Policy "strict-origin-when-cross-origin" </IfModule>
SSLProxyEngine On SSLEngine on SSLProtocol -all +TLSv1.2 SSLHonorCipherOrder on SSLCipherSuite EECDH+AESGCM:AES256+EECDH:AES128+EECDH
Protocols h2 h2c http/1.1 ProxyPreserveHost On RequestHeader set X-Forwarded-Proto "https" ProxyPass /api/v1/streaming/ ws://localhost:4000/ ProxyPassReverse /api/v1/streaming/ ws://localhost:4000/ ProxyPass / http://localhost:3000/ ProxyPassReverse / http://localhost:3000/
ErrorDocument 500 /500.html ErrorDocument 501 /500.html ErrorDocument 502 /500.html ErrorDocument 503 /500.html ErrorDocument 504 /500.html
This seems to be working fine. Of course the site is behind a Let's Encrypt certificate.
Rails issues
Once everything was up and running I was constantly getting 404 Not Found
from Apache. Checking directly with Rails by wget http://localhost:port/intent.css
I noticed that the real code was actually 403 Forbidden
. That is how I found out that Rails blocks all hosts by default and a magic line needs to be added to configuration: config.hosts << 'localhost'
.
That solved 403
, it was now showing 404
from both web servers - and that was caused by Rails not serving static files. To solve that, I simply modified the setting to config.public_file_server.enabled = true
.
Conclusion
Setting up Mastodon was an interesting experience, relatively easy to follow, but with a few twists on the way. However, it seems to be working - feel free to follow me on my own Mastodon server.