This tutorial is for users of Debian GNU/Linux who want to set up a mastodon instance. This particular instance runs in a VM (4-core / 16GB RAM / 1TB) for which the underlying host OS setup and hardware is outlined here: VM Server. I used Mastodon's official docs and also relied fairly heavily on Linux Babe's tutorial whose use cases are often similar to my own. Alright, first install postgres SQL:
echo "deb [signed-by=/etc/apt/keyrings/postgresql.asc] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list sudo mkdir -p /etc/apt/keyrings/ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /etc/apt/keyrings/postgresql.asc sudo apt update sudo apt install -y postgresql postgresql-contrib
Once it is installed, create a database for mastodon:
sudo -u postgres -i psql <CREATE DATABASE mastodon;> <CREATE USER mastodon;> <ALTER USER mastodon WITH ENCRYPTED PASSWORD 'your_preferred_password';> <ALTER USER mastodon createdb;> <ALTER DATABASE mastodon OWNER TO mastodon;> \q
Once the database is created, we need to install ruby/gems, which is the platform mastodon uses along with nginx to serve content on the web. This includes creating a mastodon user to perform gem/rake operations. Also, the install method clones a git repo and builds the instance from source.
sudo apt install ruby ruby-dev sudo adduser mastodon --system --group --disabled-login sudo apt install git git clone https://github.com/tootsuite/mastodon.git sudo mv mastodon/ /var/www/ sudo chown mastodon:mastodon /var/www/mastodon/ -R cd /var/www/mastodon/ sudo -u mastodon git checkout v3.5.3 sudo gem install bundler curl -sL https://deb.nodesource.com/setup_16.x | sudo bash - sudo apt install nodejs echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - sudo apt update sudo apt -y install yarn
That's the ruby/gem toolchain there, and now install dependencies and libraries required for compiling the project from source:
sudo apt install redis-server optipng pngquant jhead jpegoptim gifsicle nodejs imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file g++ libprotobuf-dev protobuf-compiler pkg-config gcc autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev libidn11-dev libicu-dev libjemalloc-dev
After installing the package dependencies, I created an A record for GNU/Linux Social and then set up a postfix send-only MTA. I also created a PTR record for my domain, an SPF record, and a dmarc record. I have a separate tutorial on how to setup spf records, so view that if you need help. Typically, you need to contact your ISP or datacenter for help with your PTR records; my provider,Brown Rice Internet ,provides a web panel where I can add them myself. To setup postfix, do the following:
sudo apt install postfix mailutils <Internet Site> <gnulinux.social> sudo nano /etc/postfix/main.cf <inet_interfaces = loopback-only> <myhostname=gnulinux.social> systemctl restart postfix
Now that our Mail Transfer Agent is setup, we can switch over to building the ruby/gem bundle. To do that, we first use the mastodon user to perform a ruby bundle configuration prior to building from source. After those three configurations are complete, we run the ruby install script with an environment variable required for the compiling.
sudo -u mastodon bundle config deployment 'true' sudo -u mastodon bundle config without 'development test' sudo -u mastodon bundle install -j$(getconf _NPROCESSORS_ONLN) sudo -u mastodon RAILS_ENV=production bundle exec rake mastodon:setup
Next, we want to use the systemd units that Mastodon provides and change the example web root directory to our production web root directory. You can do this with sed like Linux Babe did, or just edit the files manually is fine too. Once you finish, reload all systemd units and start the three required services.
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
Now that the back end ruby/gem environment is working and operational, you need to setup an nginx reverse proxy that will forward port 80/443 requests to that. To do this, install nginx and use the Mastodon suggested server blocks and edit appropriately in both the 80 and 443 blocks. Note, since the Mastodon template has a 443 block, we must temporarily use the self-signed cert/keys so that the service can start without error. Optionally, you could use cert-only with ACME, but I have trouble with that myself.
sudo apt install nginx sudo cp /var/www/mastodon/dist/nginx.conf /etc/nginx/conf.d/mastodon.conf sudo nano /etc/nginx/conf.d/mastodon.conf <server_name gnulinux.social;> <root /var/www/mastodon/public;> <ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;> <ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;> sudo mkdir -p /var/nginx/cache/ systemctl restart nginx
Now that nginx is all set up with self-signed certs and the service is running, we can easily set up Let's Encrypt. Personally, Linux Babe's ACME command failed for me, so I ran my own trusted command that I've used for years and it worked right away.
sudo apt install certbot python3-certbot-nginx sudo certbot --authenticator standalone --installer apache -d gnulinux.social --pre-hook "systemctl stop nginx" --post-hook "systemctl start nginx"
Make sure to set up a cronjob for the cert to automatically renew:
30 2 * * 1 /usr/bin/certbot renew >> /var/log/le-renew.log
Also, I have four scripts that I run on this instance to keep nginx, postgres, and fail2ban running. I also have a separate script that dumps the entire database daily with a time stamp. If you need help setting up fail2ban, use this tutorial. Here are the scripts currently in use:
Also, there's no point in setting this up unless you have regular backups! In my case, since this is a VM, I just use the same script as I use for all my other instances. That script powers down the VM, and copies a sparse file, then tarballs it. After restarting the VM, my backup workstation pulls down the tarballs (also sparse) on a set schedule, keeping approximately 90 days of restore points. The backup script I use is found here and, of course, this runs on the host OS (not the Mastodon VM instance):
Lastly, I also have a hot-spare in case my co-located hardware fails. Swing on by:
— oemb1905 2022/11/23 20:47