Personal Mastodon instance guide (a minimal Mastodon on EC2) https://gist.github.com/AndrewKvalheim/a91c4a4624d341fe2faba28520ed2169
Installing Mastodon (official guide) https://docs.joinmastodon.org/admin/install/
Setup swap since we only have 1gb ram and the gp2 ssd is not charged for iops https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-18-04
Tuning Mastodon https://github.com/felx/mastodon-documentation/blob/master/Running-Mastodon/Tuning.md
tootctl https://docs.joinmastodon.org/admin/tootctl/
This guide uses comments.yourdomain.org as the subdomain you own and on which you want to install your Mastodon instance. You can also use a main domain (e.g. yourdomain.org) if you don't have any other plans for that domain.
This guide also assumes:
- you'll be sending outgoing emails via SES from the main domain (e.g. yourdomain.org)
- you can receive incoming email for your initial admin user: e.g. admin@yourdomain.org
- you have your own DNS provider, like route 53, cloudflare, gandi, etc.
create iam role: service-comments-yourdomain-org
with an ec2 trust relationship
create ec2 security group: comments-yourdomain-org-1
allow all inbound from admin ip
allow all inbound from anywhere to ports 443 and 80
create ses smtp iam user: ses-smtp-user.yourdomain.org
write down the smtp username, password, and smtp endpoint (like email-smtp.us-east-1.amazonaws.com)
create ses domain identity for yourdomain.org
easy dkim
key length: RSA_2048_BIT
Publish DNS records to Route53: disabled # perhaps enable if you use route53?
DKIM signatures: enabled # default
tag: (whatever you want)
add the 3 dkim cnames over on your dns provider, amazon verfies them pretty quickly
Ubuntu Server 18.04 LTS (HVM), SSD Volume Type, 64-bit (x86)
t3a.micro (- ECUs, 2 vCPUs, 2.2 GHz, -, 1 GiB memory, EBS only)
on demand hourly rate: $0.0094 => $6.768 for 30 days
iam role: service-comments-yourdomain-org
Enable termination protection: yes
Credit specification: Unlimited
8gb general purpose ssd (gp2) volume (magnetic is half as expensive but worry about perf)
$0.10/GB-month -> $0.80/mo
Delete on Termination: no
tag: (whatever you want)
security group: comments-yourdomain-org-1
keypair: (create one or use existing, you'll need the keypair .pem file to ssh into the box below)
let's assume it launches with ip 123.123.123.123 and hostname ec2-123-123-123-123.compute-1.amazonaws.com
once running, use your dns provider to add comments.yourdomain.org as an A record pointing to the ec2 ip or CNAME record pointing to the ec2 hostname
ssh -i ~/path/to/ec2-keypair.pem ubuntu@ec2-123-123-123-123.compute-1.amazonaws.com
# initial os setup, create swap file
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo sysctl vm.swappiness=10
sudo vi /etc/sysctl.conf # add to the bottom: vm.swappiness=10
sudo sysctl vm.vfs_cache_pressure=200
sudo vi /etc/sysctl.conf # add to the bottom: vm.vfs_cache_pressure=200
sudo vi /etc/default/grub.d/50-cloudimg-settings.cfg # Append zswap.enabled=1 to GRUB_CMDLINE_LINUX_DEFAULT
sudo update-grub
sudo apt update
sudo apt upgrade
sudo reboot
# mastodon setup
sudo -i
curl -sL https://deb.nodesource.com/setup_12.x | bash -
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt install -y \
imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file git-core \
g++ libprotobuf-dev protobuf-compiler pkg-config nodejs gcc autoconf \
bison build-essential libssl-dev libyaml-dev libreadline6-dev \
zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev \
nginx redis-server redis-tools postgresql postgresql-contrib \
certbot python3-certbot-nginx yarn libidn11-dev libicu-dev libjemalloc-dev
adduser --disabled-login mastodon
su - mastodon
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec bash
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 2.7.2 # takes a while
rbenv global 2.7.2
gem install bundler --no-document
exit # back to root
sudo vi /etc/postgresql/10/main/postgresql.conf # uncomment and set effective_cache_size = 512MB
# db data is in here: /var/lib/postgresql/10/main
systemctl restart postgresql
sudo -u postgres psql
CREATE USER mastodon CREATEDB;
\q
su - mastodon # switch to mastodon user
git clone https://github.com/tootsuite/mastodon.git live && cd live
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1) # was v3.4.6 on 2022-02-06
bundle config deployment 'true'
bundle config without 'development test'
bundle install -j$(getconf _NPROCESSORS_ONLN) # takes a while
yarn install --pure-lockfile
RAILS_ENV=production bundle exec rake mastodon:setup
domain name: comments.yourdomain.org
enable single user mode: no # we may want to create a few posting users
using docker: no
postgres host: # default
postgres port: # default
postgres db: mastodon_production # default
postgres user: mastodon #default
postgress pass: # default
redis options: # defaults
store uploads in the cloud: no # maybe later
emails from localhost: no
smtp server: (amazon ses smtp server from above)
smtp port: 587 # default
smtp username: (amazon ses smtp username from above)
smtp password: (amazon ses smtp password from above)
smtp auth: plain # default
smtp openssl verify mode: none # default
email from: Notifications <notifications@yourdomain.org>
send test: yes # confirm email received
save config: yes
prepare database now: yes
compile assets now: yes
create admin user: yes
username: admin # default
email: admin@yourdomain.org # note the generated password: (hex string)
exit # back to root
cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon
ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon
sudo vi /etc/nginx/sites-available/mastodon # replace example.com with yourdomain.org
systemctl reload nginx
certbot --nginx -d comments.yourdomain.org
email: admin@yourdomain.org
choose option 1, may create a new "default" site you'll have to remove below
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/mastodon
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/comments.yourdomain.org/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/comments.yourdomain.org/privkey.pem
Your cert will expire on yyyy-mm-dd. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
# if it created/modified the "default" site, remove it and add to mastodon manually
rm /etc/nginx/sites-available/default
rm /etc/nginx/sites-enabled/default
sudo vi /etc/nginx/sites-available/mastodon
ssl_certificate /etc/letsencrypt/live/comments.yourdomain.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/comments.yourdomain.org/privkey.pem;
# else if it modified the "mastodon" site automatically, you're good
systemctl reload nginx # now seeing the elephant!
cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/
sudo vi /etc/systemd/system/mastodon-sidekiq.service # change 25 to 5 in line: ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25
sudo vi /etc/systemd/system/mastodon-streaming.service # ensure line exists: Environment="STREAMING_CLUSTER_NUM=1"
sudo vi /etc/systemd/system/mastodon-web.service # append these lines to the end:
Environment="MAX_THREADS=2"
Environment="WEB_CONCURRENCY=1"
systemctl daemon-reload
systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
sudo reboot
# setup tootctl
sudo -i
su - mastodon
vi ~/.bashrc # append these lines to the end:
export PATH="$HOME/live/bin:$PATH"
export RAILS_ENV=production
exit
su - mastodon
# close registrations, disable signup form on the homepage
tootctl settings registrations close
# done!
-----
# to restart services:
(as root)
systemctl restart mastodon-sidekiq
systemctl reload mastodon-web
systemctl restart mastodon-streaming
How those 8 gigs on the EBS volume are used at various stages:
df -h
Filesystem Size Used Avail Use%
/dev/nvme0n1p1 7.7G 1.2G 6.6G 16% / # after launch
/dev/nvme0n1p1 7.7G 2.6G 5.2G 34% / # after swap setup + upgrade
/dev/nvme0n1p1 7.7G 3.4G 4.4G 44% / # after package installs
/dev/nvme0n1p1 7.7G 4.9G 2.9G 64% / # after all setup