So you want to start your own Fediverse server? This guide will walk you through it step-by-step, including the concrete details.
2021 UPDATE: I now recommend using Pleroma+Soapbox instead of Mastodon. This option is more flexible and easier to host. The article below teaches you how to install Mastodon, and the instructions still work if that's what you want to do. I'll update this article for Pleroma at some point.
This will take you 2–4 hours and cost you at least $15/mo. You can collect donations using PayPal or Patreon to help you cover the cost.
Technical experience is needed. If you don't have the experience, you should read Run Your Own Social instead and find someone with technical experience to read this article. You'll need someone able to use a terminal.
This article covers the doing. Shoot first and ask questions later.
I created spinster.xyz with MK Fain. It gained over 7000 users in its first month, and sustained attacks from the outside due to its controversial nature. User activity crashed the server and I had to scale it. This article will incorporate what I've learned.
Mastodon vs Pleroma vs Gab
- Mastodon is the most feature-rich option. I highly recommend it as the main choice.
- Pleroma is significantly more efficient than Mastodon. It's geared towards advanced users.
- There are also some Mastodon forks, such as glitch-soc, Gab Social, and Spinster. They have different goals and limited development resources.
For this guide, we'll be using Mastodon. Please don't overthink this. Running my own fork has taught me it's not for the faint of heart. Pleroma is great if your users are advanced, but this guide is intended for servers geared towards the average person.
Step 1: Domain name
Choose a domain name for your server. Ideally, choose something that's 2 syllables or less and resonates with your users.
I recommend using NameCheap to buy the domain name. You can search for available names there.
When naming Spinster, we tried a few different things.
- I created word clouds with data from Wikipedia and Reddit.
- We used Namelix to generate business names using artificial intelligence.
These activities got us thinking, but ultimately didn't lead us to the answer.
While scanning our bookshelf I saw The Spinster and Her Enemies by Sheila Jeffreys. It occurred to me that "Spinster" sounds like "Twitter," and that it could be used in a positive way like Jeffreys intended.
When I pitched the name Spinster, it was met with hesitation.
Go with your gut. Spend time on this, but once you have a name you like don't second-guess yourself or you'll stall.
Once you have a name idea, start searching on NameCheap.
.com is the best option, but in my opinion
.xyz is just as good and it's usually cheap too.
spinster.xyz cost us $1, so you should not feel pressure to spend a lot of money.
Step 1.1: Use Cloudflare
Cloudflare is a free service that will protect your site against DDoS attacks. It works by sitting between your domain name and server, absorbing malicious traffic.
Once you've purchased your domain name on NameCheap, create an account on Cloudflare and follow the instructions. You will need to go back to Namecheap and configure your DNS to point to Cloudflare.
On NameCheap, go into your domain settings and change the "Nameservers" dropdown to "Custom DNS," then enter the names provided by Cloudflare. More detailed instructions are here (although Cloudflare screenshots are outdated).
From now on, your domain will be configured through Cloudflare. You'll log into Cloudflare, not NameCheap, to manage subdomains and DNS records.
One last thing while you are here, go under the SSL/TLS tab and set encryption mode to Full. This will be needed later to prevent infinite redirects.
Step 1.2: Set up email
You will need an email provider to send confirmation emails, "I forgot my password" emails, and other notification emails to your users.
To do this, create an account with Postmark and follow the instructions to set it up with your domain name. You will need to:
- Create a server.
- Add a domain.
Under the "servers" tab, click "Create server" and follow the instructions.
You will also want to add a domain. In the screenshot below, choose the left option ("any email address") and follow the instructions.
Remember, you will need to configure this within Cloudflare. Go back into Cloudflare, then "DNS". Add a
TXT record and
CNAME record as instructed. I had to set the CNAME to "DNS only" by clicking the orange cloud icon before it worked.
You can verify everything is working once you have all green checkmarks.
Finally, you will need to take note of your credentials. Go into your server, then click "Default Transactional Stream," "Setup Instructions," and finally "SMTP."
Leave this tab open or copy the contents somewhere for later reference.
Step 2: Create the Mastodon server
Now we need to set up the public-facing server on the internet running Mastodon. We'll use DigitalOcean for this because it provides a 1-click installer for Mastodon.
After creating a DigitalOcean account, it's a good idea to create a team so multiple people can easily manage the server in the future.
Once in the team, you will want to create a new Droplet. Choose "Marketplace" then find the "Mastodon" option and select it.
Scroll down and choose the $10/mo option. Choosing a smaller size could prevent Mastodon's assets from compiling due to running out of RAM.
Use this configuration:
- Any datacenter region you want.
- Select "Private networking", "IPv6", and "Monitoring"
- Add your SSH key.
- For the hostname, enter your server's full domain name.
Finally, click "Create droplet" and wait. Once the droplet is ready, you will need to point Cloudflare to it.
Step 2.1: Point Cloudflare to your droplet
Copy the IPv4 address of the droplet, then return to Clouflare, go to "DNS," and delete any entries containing A, AAAA, and CNAME. Add a new A record, enter
@ as the name and paste your droplet's IP address in.
Find your droplet's IPv6 address by clicking into the droplet, then create a AAAA record in Cloudflare like before using the IPv6 address as the value.
Step 2.2: Media storage
When users upload pictures, they will need to be stored somewhere. You do not want them to be stored directly on the droplet. Apart from being a security risk, you will wake up one day to learn your server is offline due to storage running out. The solution is DigitalOcean Spaces.
The same way you created a droplet, create a space instead. Give it a unique name and use the default settings. You can put it in the same datacenter region as your droplet.
Media files will be hosted on a subdomain of your site, such as
media.mysite.com. To start this process, first go under "Settings" in your space and choose "Enable CDN." Click the dropdown, then "Add new subdomain certificate." Within the modal, click "Bring your own certificate." We'll generate one from Cloudflare.
Back on Cloudflare, go to SSL/TLS > Origin Server > Create Certificate. Click Next, then copy the certificate text back into DigitalOcean.
Once the CDN is enabled, you'll need to point
media.mysite.com to it. Back on Cloudflare, go under DNS again and create a
CNAME entry. Set the name to
media and the value to the endpoint from your DigitalOcean space.
Next we need to generate API keys for Mastodon to connect to your media server. You'll use the keys when configuring Mastodon in step 2.3.
In DigitalOcean, click Manage > API from the left sidebar. Scroll down to the Spaces access keys section and click Generate New Key. The name is for your personal reference.
Once created, save the values somewhere. The private key will disappear when you refresh the page. If you lose the private key, just delete it and create another key.
Step 2.3 Provision the server
From your terminal, run
ssh root@my-droplet-ip replacing the actual IP address of your droplet. Type "yes" to continue. You will be greeted with a screen containing further instructions.
At the prompt, enter your domain name and follow the instructions. Use these answers:
- Domain name: mysite.com
- Do you want to store user-uploaded files on the cloud? No (DigitalOcean Spaces is not supported through this prompt, so we'll configure it after)
- SMTP server: smtp.postmarkapp.com
- SMTP port: 587
- SMTP username: The username from step 1.2. It'll be in a format like
- SMTP password: The password is identical to the username on Postmark.
- SMTP authentication: plain
- SMTP OpenSSL verify mode: none
- E-mail address to send e-mails "from": Configure this how you want, eg
My Site <firstname.lastname@example.org>
- Send a test e-mail with this configuration right now? Yes
If all is well, an additional prompt will start up. Configure your admin account.
If this succeeded, you should be able to access the site from your browser now. If not, you may have an error like
Failed authorization procedure. mysite.com (http-01): urn:acme:error:unauthorized. In that case, something is wrong with your DNS. Try visiting your site in the browser and see if you can determine the issue.
Once the prompt is over, you'll still need to configure DigitalOcean Spaces for file uploads. Change to the Mastodon user with
su - mastodon in the terminal, then run
nano live/.env.production to edit the configuration file. At the bottom, add this configuration:
Replace the following values:
S3_BUCKET- find this in your DigitalOcean Space settings. It's the unique name you chose for the space.
nyc3with the region your Space is in.
AWS_ACCESS_KEY- this is the key you generated in step 2.2.
AWS_SECRET_ACCESS_KEY- the longer secret key from step 2.2.
S3_ALIAS_HOST- the domain name your media will be served at, as configured through Cloudflare in step 2.2.
Once done, press ctrl+X, Y, enter. Now reboot your server. Return to the root user by pressing ctrl+D, then type
Step 3: Updating the server
Both the base system and Mastodon version are outdated, so now is a good time to practice upgrading them. You'll have to do this periodically.
Shell into the droplet as the root user if you haven't already. Run this command to enable automatic updates:
<Yes> is highlighted then press enter. This will enable automatic security updates on the system, but won't update other packages.
Now lets update the base system packages. Run these commands in order:
apt update apt upgrade
This will update the package index on the system then upgrade all packages. You'll want to do this periodically. You will probably get an error about conflicts in the GRUB file the first time you run this - just choose "keep the package maintainer's version."
Next we can update Mastodon itself. This will actually affect your end users. Before upgrading Mastodon, it's crucial you always make a database backup before upgrading.
I'm not playing around here. I destroyed my first Mastodon instance by trying to upgrade it and the upgrade failed, corrupting the database. Don't be lazy, back up the database.
First become the Mastodon user with
su - mastodon. Now backup the database with this commmand:
pg_dump mastodon_production > db_latest.sql
Take a look at the Mastodon release notes and take note of the latest version. Read the upgrade notes - it's important.
Generally speaking, we'll upgrade Mastodon with these commands:
Finally, become the root user with ctrl+D the run
reboot. You should be running the latest Mastodon version now.
Step 4: Securing the firewall
Cloudflare will hide your droplet's IP address from end users, but other servers you federate will be able to see IP in their system logs. Your server is still vulnerable to a DDoS attack against the direct IP.
To get around this, use a firewall to block all traffic that doesn't come from Cloudflare. This means users will be forced to interact with your server by its domain name, not its IP address.
Shell into the server as the root user. First you'll have to remove the firewall provisioned by the Mastodon one-click image:
apt purge -y iptables-persistent rm /etc/iptables/rules.v4
Now we'll set up ufw instead. Enter these commands:
ufw default deny incoming ufw default allow outgoing ufw allow ssh ufw enable
This will prevent the droplet from being accessed except by SSH. Give it a shot - you shouldn't be able to access it anymore from your web browser.
To allow Cloudflare traffic, we'll need to allow all Cloudflare IP ranges (which they helpfully document). Paste the following into the terminal:
ufw allow from 126.96.36.199/20 to any port 80 ufw allow from 188.8.131.52/22 to any port 80 ufw allow from 184.108.40.206/22 to any port 80 ufw allow from 220.127.116.11/22 to any port 80 ufw allow from 18.104.22.168/18 to any port 80 ufw allow from 22.214.171.124/18 to any port 80 ufw allow from 126.96.36.199/20 to any port 80 ufw allow from 188.8.131.52/20 to any port 80 ufw allow from 184.108.40.206/22 to any port 80 ufw allow from 220.127.116.11/17 to any port 80 ufw allow from 18.104.22.168/15 to any port 80 ufw allow from 22.214.171.124/12 to any port 80 ufw allow from 126.96.36.199/13 to any port 80 ufw allow from 188.8.131.52/22 to any port 80 ufw allow from 2400:cb00::/32 to any port 80 ufw allow from 2606:4700::/32 to any port 80 ufw allow from 2803:f800::/32 to any port 80 ufw allow from 2405:b500::/32 to any port 80 ufw allow from 2405:8100::/32 to any port 80 ufw allow from 2a06:98c0::/29 to any port 80 ufw allow from 2c0f:f248::/32 to any port 80 ufw allow from 184.108.40.206/20 to any port 443 ufw allow from 220.127.116.11/22 to any port 443 ufw allow from 18.104.22.168/22 to any port 443 ufw allow from 22.214.171.124/22 to any port 443 ufw allow from 126.96.36.199/18 to any port 443 ufw allow from 188.8.131.52/18 to any port 443 ufw allow from 184.108.40.206/20 to any port 443 ufw allow from 220.127.116.11/20 to any port 443 ufw allow from 18.104.22.168/22 to any port 443 ufw allow from 22.214.171.124/17 to any port 443 ufw allow from 126.96.36.199/15 to any port 443 ufw allow from 188.8.131.52/12 to any port 443 ufw allow from 184.108.40.206/13 to any port 443 ufw allow from 220.127.116.11/22 to any port 443 ufw allow from 2400:cb00::/32 to any port 443 ufw allow from 2606:4700::/32 to any port 443 ufw allow from 2803:f800::/32 to any port 443 ufw allow from 2405:b500::/32 to any port 443 ufw allow from 2405:8100::/32 to any port 443 ufw allow from 2a06:98c0::/29 to any port 443 ufw allow from 2c0f:f248::/32 to any port 443 echo "Done"
Now refresh your browser. If it's working, all is well!
Step 5: Automated backups
You can pay DigitalOcean a small fee to back up your server once per week. I suggest paying it. However, if you're really serious about this site, you should set up your own automated backups.
In order to have independence from your server provider, it's important to store backups in your physical control. I recommend purchasing a Raspberry Pi and configuring it to make backups for you. A really simple backup script will look like this:
You could save this script as a file like
backup.sh then create a cron job with
crontab -e adding a line like:
0 * * * * /home/pi/backup.sh
This will make the backup script run every hour. You can plug the Raspberry Pi directly into your wireless router and forget about it.
Periodically you'll have to prune the backups, or you can just add python-rotate-backups to the end of your backup script.