professional geek ramblings
est. 2003

My Journey to Setting up a Local Development Mastodon Instance

Mastodon Development Instance

I’ve been looking for a way to update my skills in web development recently while searching for a new job. I’ve been working in the IT industry for over 20 years now, mostly in the .NET sphere. I noticed that I was turning down a few really interesting opportunities because of my lack of accomplishments with specific modern front end frameworks, including React.js and Angular. I have a few projects that I’ve worked on in the past that I could use to demonstrate my skills, but I wanted to do something more.

I wanted to build something from scratch, and I wanted to do it in a way that I could share with others. I also wanted to do it in a way that I could use to demonstrate my skills to potential employers.

So I decided to build a local development instance of Mastodon; a free, open-source social network. I’ve been using Mastodon for a few months now, and I really like it. It currently feels like 2008-2010 Twitter, when it was still fun and interesting.

And not run by Elon Musk.

It was not an easy task, but I learned a lot along the way. I’m going to share my journey with you, and hopefully you’ll find it useful.

Base Environment : OS X

I decided to use my MacBook instead of my Windows box or the Ubuntu Linux that I installed on a Mac Mini. I might change my mind later. I’m not sure yet. This was more of a proof of concept: can I even get all of the moving parts to work together? I’m not sure if I’ll actually use this instance for anything other than testing and development.

Guest Environment : VirtualBox

I’m using VirtualBox as the virtualization provider for Vagrant with the Ubuntu 18.04 LTS box, which is a 64-bit version of Bionic Beaver.

Host Environment : Vagrant

I wanted to build this on my Mac, but I also wanted to be able to easily destroy and rebuild the environment if I needed to. So I decided to use Vagrant.

Vagrant is a tool for building and managing virtual machine environments in a single workflow. It allows you to define a virtual machine configuration in a single file, and then spin up the virtual machine with a single command.

I used homebrew to install it:

    brew cask install vagrant

I then created a new directory for my project, and created a new Vagrantfile in it:

    mkdir vagrant
    cd vagrant
    vagrant init

I then edited the Vagrantfile to use the Ubuntu 18.04 LTS box:

    Vagrant.configure("2") do |config|
        config.vm.box = "ubuntu/bionic64"

I customized the Vagrantfile a little more using the Vagrantfile for Mastodon as a reference.

I started the virtual machine:

    vagrant up

I then SSH’d into it:

    vagrant ssh

Installing Mastodon from Source

I decided to install Mastodon from source, instead of using the Docker image. I wanted to learn more about the underlying technologies, and I wanted to be able to customize the installation. Also, I wanted to be able to use the latest version of Mastodon, instead of the version that was available in the Docker image. To accomplish this, I needed to install Ruby, Rails, and PostgreSQL.

I started with the Mastodon Installation Guide. It took me a few tries to get it right, but I was able to get it working in the end.

Probably the most difficult challenge was getting certbot to issue a certificate for my domain. I was able to get it working, but I had to use the --manual option, and I had to manually create the DNS records for the challenge. I’m not sure if there is a better way to do this, but it worked for me. I found a pretty decent guide at esc.sh that got me most of the way there. (see above)

webpacker woes

Well now I have a working Mastodon instance, but webpacker is refusing to spin up, claiming that a service is already running on the port provided in the config file. This is my first time even looking at webpacker, having most of my experience in ASP.NET MVC. So I looked at the config/webpacker.yml file, and I noticed that the port was set to 3035. I looked at the nginx config file, and I noticed that the port was set to 3000. These aren’t the same ports, what gives? This is usually the part of a blog post where I would say something like “I spent hours trying to figure this out, but I finally figured it out.” And I did. But I’m not going to bore you with how. This is already one of the longest blog posts I’ve ever written.

I tried several different approaches and ended up having to restart the webpacker service a few times. Eventually it started working. I didn’t take note of what was the winning magic incantation, but after a couple of restarts I have a working mastodon instance.

It lives!


I don’t fully understand how all of the pieces fit together yet, but I’m getting there. I’m going to continue to work on this project, and I’ll update if I come across anything interesting.

It felt good to hack on something that gave me that feeling of accomplishment that I used to get when I was a young developer. If you’ve read this far, you’re a champ. Thanks fam.