Skip to content

Instantly share code, notes, and snippets.

@chris3000
Last active November 26, 2022 02:36
Show Gist options
  • Save chris3000/324d015072404737d37c0a8987dd9ccb to your computer and use it in GitHub Desktop.
Save chris3000/324d015072404737d37c0a8987dd9ccb to your computer and use it in GitHub Desktop.
Full, semi-automated setup of Mastodon. Tested with Digital Ocean
#!/bin/bash
# ***** THIS IS NOT A BASH FILE THAT YOU CAN JUST RUN *********
# It will take some hand holding, and will reboot in the middle. You could probably break it in two and it would work ok.
# Lightly modified from https://www.learnlinux.tv/build-your-own-mastodon-server-on-debian-step-by-step-server-build-guide/
# https://www.youtube.com/watch?v=2a9YrLsE45Y
# What you’ll need
# * A domain from a registrar [I'm using hover.com]
# * A VPS instance, 4GB RAM recommended, Debian 11 [I'm using Digital Ocean]
# * optional- create new ssh key:
# ssh-keygen -b 4096 -t rsa
# if you're on macOS, copy public key to clipboard and add to Digital Ocean
# cat id_rsa.pub | pbcopy
# * DNS A record pointing to VPS
# [go to hover.com, add Digital Ocean instance public IP address as A record]
# * An SMTP provider for outbound mail [I'm using sendgrid]
# boot up your machine and add firewall settings
# https://cloud.digitalocean.com/networking/firewalls
# Create Firewall -> add inbound rules for http, https, and ssh
# * Initial server setup
# * These commands aren’t specific to Mastodon, but will help us set up some common things that should be done on a fresh server build.
# login to your Digital Ocean machine once it's booted
# [localmachine] > ssh root@[ip address]
# Create a non-root user
# Create a user account to use while setting up the server.
adduser chris
# put whatever password you want.
# Enter for all defaults is fine
usermod -aG sudo chris
# move public ssh keys for easy and more secure ssh
mkdir /home/chris/.ssh
cp /root/.ssh/authorized_keys /home/chris/.ssh/authorized_keys
chown -R chris:chris /home/chris/.ssh
# Install all updates
#It’s always a good idea to install all updates on all fresh server deployments. To do so, first update the repository index to update the local cache with any packages that have been made available recently:
apt update
apt -y dist-upgrade
# go ahead and set up an env variable with your domain name.
DOMAIN=[your domain name]
#Set the hostname
#To set the hostname of your server, edit the /etc/hostname file:
echo $DOMAIN > /etc/hostname
# Next, edit /etc/hosts and set the name there too:
sed -i "s/127.0.0.1\tlocalhost/127.0.0.1\t$DOMAIN/" /etc/hosts
# [optional, but better for security] disable password login and only allow ssh keys
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/UsePAM yes/UsePAM no/' /etc/ssh/sshd_config
touch /etc/ssh/ssh_config.d/disable_password_login.conf
#OPTIONAL disable root login as well:
echo "PermitRootLogin no" >> /etc/ssh/ssh_config.d/disable_password_login.conf
#The first stage of setup is done, so it’s a good idea to reboot the server:
reboot
# Re-establish ssh as the new user you’ve created. Your domain name should work, if you'd rather use that than the ip address
# > ssh -i /path/to/sshkey root@domain-name
#or, if you'd prefer to avoid root from now on,
# > ssh -i /path/to/sshkey chris@domain-name
#Installing the required packages
#There’s going to be a handful of packages that will need to be installed from various categories. In this section, we’ll install all of the packages that we’ll end up needing through the rest of the tutorial.
#Install basic development packages
#First, we’ll install development packages from Debian’s default repositories:
sudo apt install -y build-essential bundler git libidn11-dev libjemalloc-dev libpq-dev nginx postgresql postgresql-contrib rbenv redis-server ruby ruby-dev imagemagick ffmpeg
#as of November 2022, Mastodon MUST use NodeJS 16.x
sudo curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
#Next, we’ll need to install yarn via npm:
sudo npm install --global yarn
#Database setup and configuration
#Set up PostgreSQL
sudo su postgres
psql -c "CREATE DATABASE mastodon_production;"
psql -c "CREATE USER mastodon;"
psql -c "ALTER USER mastodon createdb;"
psql -c "ALTER USER mastodon WITH ENCRYPTED PASSWORD 'secret-password';"
psql -c "ALTER DATABASE mastodon_production OWNER TO mastodon;"
exit
#Set up the mastodon system user
#We should create a dedicated user for mastodon. To do so, run the following command:
sudo adduser --group --system mastodon
#Download the Mastodon repository locally
#We can download the git repository for mastodon locally by running the following command:
git clone https://github.com/mastodon/mastodon.git
#Adjust permissions
#We should change the permissions such that the mastodon user and group owns the downloaded repository:
sudo chown -R mastodon:mastodon mastodon
#Create the app directory
#Move Mastodon’s files into the www directory
#Rather than serve Mastodon from our home directory (bad idea) we should move it into the /var/www directory instead:
sudo mv mastodon /var/www/
#Setting the Mastodon version to use
#Change into the directory where Mastodon’s files are now located:
cd /var/www/mastodon
#Adding the Mastodon directory to the safe list
#If we try to manage the repository now, it will fail. By default, repositories are now protected. To allow the mastodon user to manage mastodon files, we need to add the directory to the safe list (and do so as the mastodon user):
sudo -u mastodon git config --global --add safe.directory /var/www/mastodon
#Determining the latest version number of Mastodon
#We should specify the verison of Mastodon to use. First, visit the following URL:
# https://github.com/mastodon/mastodon/releases
#Make note of the version number marked “latest”. [as of November 21, it was v4.0.2]
#With the version number you noted in the previous step, check out that version of the code:
#Example- version has most likely changed
sudo -u mastodon git checkout v4.0.2
#Prepare Mastodon for installation
sudo gem install bundler
sudo -u mastodon bundle config deployment 'true'
sudo -u mastodon bundle config without 'development test'
sudo -u mastodon bundle install -j$(getconf _NPROCESSORS_ONLN)
#Set up Mastodon:
#The following command will run the setup script:
sudo -u mastodon RAILS_ENV=production bundle exec rake mastodon:setup
# Domain name: the DNS domain name you registered
# Do you want to enable single user mode? (y/N) -Probably you don't unless you are the only user
# Are you using Docker to run Mastodon? (Y/n) - Since we installed from source, the answer is no.
# PostgreSQL host: - default is correct
# PostgreSQL port: - default is correct
# Name of PostgreSQL database: (mastodon_production) - default is correct
# Name of PostgreSQL user: - default is correct
# Password of PostgreSQL user: - whatever you set it to when configing postgres
# Hopefully you seet this: Database configuration works! 🎆
# Redis host: (localhost) - default is fine
# Redis port: - default is fine
# Redis password: - none, just hit enter
# Hopefully you see this: Redis configuration works! 🎆
# Do you want to store uploaded files on the cloud? (y/N) - up to you. If you don't store them in the cloud then
# they will get saved to your local storage. Maybe this is ok?
# Keep in mind that these are the default options for cloud storage:
# DigitalOcean Spaces
# Amazon S3
# Wasabi
# Minio
# Google Cloud Storage
#I'm using Digital Ocean Spaces
# Provider DigitalOcean Spaces
# Answer questions about your Spaces bucket
# Do you want to access the uploaded files from your own domain? no
#set up mail
# Depending on your plans, you many need to authenticate your domain name with your smtp provider.
# The following setup is an example only. Your smtp provider may do things differently.
# Do you want to send e-mails from localhost? No
# SMTP server: smtp.sendgrid.net
# SMTP port: 587
# SMTP username: apikey
# SMTP password: [api key from sendgrid]
# SMTP authentication: plain
#SMTP OpenSSL verify mode: none
# Enable STARTTLS: auto
# E-mail address to send e-mails "from": Admin <admin@[YOUR DOMAIN NAME]>
# Send a test e-mail with this configuration right now? Yes
# Send test e-mail to: [one of your email addresses]
# This configuration will be written to .env.production
# Save configuration? Yes
# If the database already exists, this will erase its contents.
# Prepare the database now? (Y/n) Yes
# Compile the assets now? Yes
# ---- lots of compiling....
#Done!
#All done! You can now power on the Mastodon server 🐘
#### HOPEFULLY EVERYTHING WENT WELL!
# If you have issues, ensure that your server has at least 4gb RAM and a decent amount of disk space.
# If you get an error about a hash, then your Nodejs version may be too new.
# [OPTIONAL]
#Do you want to create an admin user straight away? Yes
#Username: admin, or whatever you want
#E-mail: admin@[DOMAIN NAME] or whatever you want
# You can login with the password: [random string of characters]
# You can change your password once you login.
#Install systemd units
# Copy the example mastodon startup scripts to the /etc/systemd/system directory:
sudo cp /var/www/mastodon/dist/mastodon*.service /etc/systemd/system
sudo sed -i 's/home\/mastodon\/live/var\/www\/mastodon/g' /etc/systemd/system/mastodon-*.service
sudo sed -i 's/home\/mastodon\/.rbenv\/shims/usr\/local\/bin/g' /etc/systemd/system/mastodon-*.service
sudo systemctl daemon-reload
sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
# Set up reverse proxy
sudo cp /var/www/mastodon/dist/nginx.conf /etc/nginx/conf.d/mastodon.conf
# Fix home path, and also the servername. Both in 80 and 443 sections
sudo sed -i 's/server_name example.com;/server_name [DOMAIN NAME];/g' /etc/nginx/conf.d/mastodon.conf
# Add the following near the commented-out certificate section:
sudo sed -i 's/# ssl_certificate_key.*/ssl_certificate_key \/etc\/ssl\/private\/ssl-cert-snakeoil.key;/g' /etc/nginx/conf.d/mastodon.conf
sudo sed -i 's/# ssl_certificate.*/ssl_certificate \/etc\/ssl\/certs\/ssl-cert-snakeoil.pem;/g' /etc/nginx/conf.d/mastodon.conf
sudo sed -i 's/root \/home\/mastodon\/live\/public;/root \/var\/www\/mastodon\/public;/g' /etc/nginx/conf.d/mastodon.conf
#Next, restart nginx so it takes advantage of the new settings:
sudo systemctl restart nginx
# Set up TLS certificate
sudo apt -y install snapd
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx
# Enter email address (used for urgent renewal and security notices)
# (Enter 'c' to cancel): [your email address]
# Please read the Terms of Service at
# https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
# agree in order to register with the ACME server. Do you agree?
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# (Y)es/(N)o: y
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Would you be willing, once your first certificate is successfully issued, to
# share your email address with the Electronic Frontier Foundation, a founding
# partner of the Let's Encrypt project and the non-profit organization that
# develops Certbot? We'd like to send you email about our work encrypting the web,
# EFF news, campaigns, and ways to support digital freedom.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# (Y)es/(N)o [either yes or no is fine]
#Which names would you like to activate HTTPS for?
#We recommend selecting either all domains, or all domains in a VirtualHost/server block.
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 1: [YOUR DOMAIN NAME]
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Select the appropriate numbers separated by commas and/or spaces, or leave input
# blank to select all options shown (Enter 'c' to cancel): [JUST HIT ENTER]
# HOPEFULLY YOU SEE THIS:
# Congratulations! You have successfully enabled HTTPS on https://[DOMAIN NAME]
# Add some default security tweaks
# Install unattended-upgrades
sudo apt install -y unattended-upgrades
# Edit /etc/apt/apt.conf.d/50unattended-upgrades
# Enable automatic reboot, automatic reboot time, and enable automatic reboot with users.
sudo sed -i 's/\/\/Unattended-Upgrade::Automatic-Reboot-WithUsers/Unattended-Upgrade::Automatic-Reboot-WithUsers/g' /etc/apt/apt.conf.d/50unattended-upgrades
sudo sed -i 's/\/\/Unattended-Upgrade::Automatic-Reboot-Time/Unattended-Upgrade::Automatic-Reboot-Time/g' /etc/apt/apt.conf.d/50unattended-upgrades
sudo sed -i 's/\/\/Unattended-Upgrade::Automatic-Reboot/Unattended-Upgrade::Automatic-Reboot/g' /etc/apt/apt.conf.d/50unattended-upgrades
sudo sed -i 's/Automatic-Reboot "false";/Automatic-Reboot "true";/g' /etc/apt/apt.conf.d/50unattended-upgrades
#Install Crowdsec
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
sudo apt install -y crowdsec
sudo apt install -y crowdsec-firewall-bouncer-iptables
# reboot
# DONE! ENJOY MASTODON!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment