5 min read

Mastodon migrations

I have been running my own Mastodon instance since early this year, just for myself, and I've been broadly happy with it. I run it on a pretty low powered VPS but given I'm the only one using it, it's fine.

Part of the interest in mastodon for me was the ability to actually own and manage your own data. There are absolutely downsides to that, it costs me money and I have to maintain it. But I enjoy it, it has been good.

However, I made a bit of a mistake when setting my initial instance up. I set it up on the subdomain 'md.qassim.uk'. That's fine in itself, but I didn't go through the effort at the beginning to then configure what Mastodon calls the LOCAL_DOMAIN to be qassim.uk. So my username on Mastodon thus far has been qassim@md.qassim.uk.

Okay, not the end of the world. But it did bug me. Unfortunately, due to the way the federation processes happen, once you've set up your instance and your instance has begun interacting with the fediverse then it becomes highly inadvisable to try and change that domain. In fact, it doesn't really work at all. If you change it, you break a lot of things that don't really resolve themselves.

A new instance

FWIW, this isn't going to be a step-by-step tutorial - just a high level explanation of a few of the changes I made. If you're trying to follow this, I'm going to assume you know enough to fill in the blanks.

The only way for me to fix this issue was to fire up a new mastodon instance, on a new subdomain (mastodon.qassim.uk), set that one up properly so that:

LOCAL_DOMAIN = qassim.uk
WEB_DOMAIN = mastodon.qassim.uk

Before getting started on firing up the new instance, the key component to making this work is a webfinger redirect from qassim.uk to mastodon.qassim.uk, so that when the ActivityPub protocol sees the username qassim@qassim.uk and makes a request against it, it gets redirected to mastodon.qassim.uk.

This required a simple bit of nginx config on the server hosting qassim.uk

	location /.well-known/webfinger {
  	   add_header Access-Control-Allow-Origin '*';
           return 301 https://mastodon.qassim.uk$request_uri;

After this, I set up Mastodon by using the DigitalOcean Mastodon '1 Click App' - so it basically configures a working instance for you out of the box, with you having to provide some config on initial startup via a wizard.

My modifications are as simple as:

  • Host media cache in s3 (fronted by cloudfront)
  • Setup email

Then I do some standard modifications for security/maintainability that I do on my Linux servers.

However, the aforementioned start-up wizard does not offer an option or take into consideration running your mastodon instance on a different domain than the domain you wish your user to be federated as. My solution was a bit of a hacky-back-and-forth.


I have since raised a pull request on the mastodon packer repository to add the option in to support WEB_DOMAIN in the setup wizard. See here: https://github.com/mastodon/packer/pull/10

If it doesn't get approved or merged, then I'll leave my fork up in case anyone else would like to use it. You'll just need to build the image yourself and deploy from the snapshot it creates in your account (see the README).

You can use my changes above instead of following the hacky approach below if you prefer.

When first ssh'ing onto the VPS after creating the droplet, it throws you straight into a first-boot wizard, I exited out of the wizard and modified:


Which is the login script that executes the first boot wizard. I changed all instances of LOCAL_DOMAIN to WEB_DOMAIN, as where this script uses the LOCAL_DOMAIN are for things like generating the nginx config, getting the SSL cert, generally everything to do with running the web interface for mastodon on your desired subdomain.

My modifications looked like this:


set -e

echo "Booting Mastodon's first-time setup wizard..."

su - mastodon -c "cd /home/mastodon/live && RAILS_ENV=production bundle exec rake digitalocean:setup"
export "$(grep '^WEB_DOMAIN=' /home/mastodon/live/.env.production | xargs)"

echo "Launching Let's Encrypt utility to obtain SSL certificate..."
systemctl stop nginx
certbot certonly --standalone --agree-tos -d $WEB_DOMAIN
cp /home/mastodon/live/dist/nginx.conf /etc/nginx/conf.d/mastodon.conf
sed -i -- "s/example.com/$WEB_DOMAIN/g" /etc/nginx/conf.d/mastodon.conf
sed -i -- "s/  # ssl_certificate/  ssl_certificate/" /etc/nginx/conf.d/mastodon.conf
rm -f /etc/nginx/conf.d/default.conf
nginx -t

systemctl start nginx
systemctl enable mastodon-web
systemctl start mastodon-web
systemctl enable mastodon-streaming
systemctl start mastodon-streaming
systemctl enable mastodon-sidekiq
systemctl start mastodon-sidekiq
cp -f /etc/skel/.bashrc /root/.bashrc
rm /home/mastodon/live/lib/tasks/digital_ocean.rake

set +e


echo "Setup is complete! Login at https://$WEB_DOMAIN"

So I logged back out and logged back in again, I completed the wizard and then the script errored out on line 8:

export "$(grep '^WEB_DOMAIN=' /home/mastodon/live/.env.production | xargs)"

Because as I mentioned earlier, the wizard has no concept of WEB_DOMAIN, so it didn't write one to the env file it's trying to read from.

So I modified /home/mastodon/live/.env.production, adding WEB_DOMAIN=mastodon.qassim.uk. I then modified /opt/mastodon/steup.sh again to comment out line 7:

#su - mastodon -c "cd /home/mastodon/live && RAILS_ENV=production bundle exec rake digitalocean:setup"

So that this part of the wizard didn't run again and overwrite my modifications to the envar file. It had completed successfully the first time, it created me a user and I noted the password.

The rest of the wizard then completed without issue. It generated the nginx and TLS config, it updated mastodon to the latest versions without issue, and then I was free to start using my instance.

A bit of a faff, but it worked in the end.


So here's the awkward part, not technically - just it feels like a bit of a weakness in the whole Mastodon/ActivityPub architecture/protocol. Moving between instances.

I just followed the standard process detailed here:

Moving or leaving accounts
Take your information and do what you want with it.

It worked as described. It brought my followers over, I could easily recreate my profile, and bring over who I follow, and that's as far as the migration goes.

It does not bring your posts over, for valid technical reasons. There are hacky work arounds out there, but they don't sound great and I'm not too bothered about losing my post history at this point.

As of writing this, a few hours later, both my old and new mastodon instances are still up. I'll give it maybe a day or so more to settle, then shut off the old instance.

My new mastodon username is:

My instance is hosted at: https://mastodon.qassim.uk/@qassim

I exported my post archive from my old profile and generated a static HTML page from the JSON it provides, just in case I want to refer back to those old posts at any point. I've embedded it below.