As many of you reading this close to the date of publication, Twitter is in meltdown. Elon Musk has bought it, taking it into private ownership, and has been implementing his own brand of reform. Much has been written elsewhere, so I'll not go into details, but the trashing of the verified status system, sacking of , or resignations by, almost all senior staff, trust & privacy, moderators and developers, this has all caused chaos. As such, anybody with any sense has been looking for an alternative to Twitter.
This is where the fediverse, principally championed by Mastodon, has stepped up. A distributed, federated, collection of servers, all of which can talk to each other, not operated by any one individual or company, but each instance by their own users. Anybody can set up a server and join in. So I did. This is my tale..
I won't detail all the problems I had doing this. I'm merely going to indicate what worked. This is why you're here, after all!
I'm installing on a virtual server, that actually runs on a physical machine at home. This is behind a normal home broadband connection, with a Sophos UTM firewall between then. The ISP supplied router has the UTM as it's DMZ, so all incoming connections are passed directly to that. The UTM has reverse DNAT set up to forward ports 80 and 443 to a virtual machine which ruin Nginx Proxy Manager in a docker instance.
The domain name is handled by namecheap.com, and in their DNS, I set hostname "@" as "A+Dynamic DNS Record". The UTM supports their flavour of Dynamic DNS directly, so it is set to update this should my visible external IP change.
Mastodon was installed on a new VM freshly installed using Ubuntu 20.04 and updated with apt update && apt upgrade. (I tried first using the latest version, 22.04, but failed multiple times. YMMV but the docs say 20.04, so I went back to that and succeeded.) I followed this installation guide on the official github repository. This almost worked; almost at the end I got a complaint that Ruby 3.0.4 was required - the guide tells you to install 3.0.3, so I went back and reinstalled ruby, and then continued.
Do follow the directions to install nginx on your mastodon server, as its used to handle static content as well as passing things to and from the mastodon code., however DO NOT INSTALL CERTBOT/LetsEncrypt.
THIS is the /etc/nginx/sites-enabled/mastodon file I ended up using:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name irrelevant.me.uk 192.168.200.109 "";
keepalive_timeout 70;
sendfile on;
client_max_body_size 0;
root /home/mastodon/live/public;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
add_header Strict-Transport-Security "max-age=31536000";
location / {
try_files $uri @proxy;
}
location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri @proxy;
}
location @proxy {
proxy_set_header Host irrelevant.me.uk;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://localhost:3000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
location /api/v1/streaming {
proxy_set_header Host irrelevant.me.uk;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass http://localhost:4000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
error_page 500 501 502 503 504 /500.html;
}
In server name, I set the official name of the instance, the IP address, and, because all else failed, "" to make it accept anything.
The rest based on code in a github post I've now lost the link to, sorry! Note that there is no SSL in here any more.
Note also that I has to hard-code the hostname in the proxy set header Host directives. This means that whatever address you use in the URL to connect to the server, it passes the correct hostname through to mastodon. This was the critical bit that stopped me getting 403 errors on any access - it seems that mastodon is locked tight to the domain name you set when you install it.
Check you can connect locally via http://ip_of_your_server/ and get the front page!
In nginx proxy manager, I set nothing unusual. Set the domain name you want to serve, point it at http://ip_of_your_server:80, set Force SSL and allow NPM to deal with letsencrypt to get your SSL set up.
Your instance should be accessible at the domain name you have set up!
There are some things I want to tidy up. I've not tested the streaming part yet - I'm seeing 502 errors in the logs, but I'm not sure why yet, or what it is that's using it. Also, every line in the log seems to be coming from the ip of NPM, so there's more to set up here to identify the original IP. However, this is the first time I've used nginx, so it's all a bit of a learning curve. For now, I'm just glad I can actually read and post things!