Detailed step-by-step instruction for setting up Mastodon on cheap VPS (Hetzner behind Cloudflare) from scratch.
This instruction assumes that you want to run Mastodon on Hetzner cloud VM, using Hetzner storage box for media storage, without elasticsearch, behind Cloudflare, using let's encrypt certificate locally and only allowing requests over cloudflare
Without the loss of generality, the domain name is assumed to be social.penartur
.
It also assumes that Mastodon version is 2.4.4. You can probably install newer 2.4.x versions with this instruction; however, major upgrades may change docker layout, and you'll need to use updated docker-compose.yml.
You should have a registered domain with cloudflare enabled and email configured.
I've registered my domain with gandi.net, created two mailboxes in gandi control panel (admin@social.penartur and robot@social.penartur), added domain to cloudflare, and in gandi control panel updated domain nameservers to cloudflare-supplied ones.
You're better to do that in advance, since it takes time for changes to propagate through DNS, and it is easier to do the rest once everything is ready with domain and DNS.
-
Create new small (2EUR) Ubuntu-based Hetzner cloud VM with backups in Falkenstein (to get low latency connection to storage boxes, which are all located in Falkenstein).
-
In Cloudflare, on DNS tab, edit
@
(orsocial.penartur
) A record so that it points to your VM IP, with cloudflare protection (cloud icon) enabled (cloud should be yellow). -
Reset root password, open console (Chrome recommended; in FF and Edge, some key combinations such as Ctrl+Shift+F2 or Ctrl+K, do not work).
-
$ systemctl disable sshd
-
$ adduser YOURNAME
,$ adduser YOURNAME sudo
,$ exit
, login as YOURNAME. -
$ sudo apt-get update
,$ sudo apt-get dist-upgrade
. If you'll be prompted about grub config merge conflict, just "install the package maintainer's version". -
$ sudo reboot
,$ sudo apt-get update
,$ sudo apt autoremove
-
Create new Hetzner storage box. Log in via SCP (e.g. with WinSCP), create directory
mastodon
, create sub-directorymedia
-
In storage box settings, create new sub-account for
mastodon
directory. -
$ sudo ssh-keygen
-
$ sudo cat /root/.ssh/id_rsa.pub > storagebox_authorized_keys
-
$ ssh-keygen -e -f /root/.ssh/id_rsa.pub | grep -v "Comment:" >> storagebox_authorized_keys
-
$ sftp uXXXXXX-subY@uXXXXXX.your-storagebox.de
, enter password, execute:-
sftp> mkdir .ssh
-
sftp> chmod 700 .ssh
-
sftp> put storagebox_authorized_keys .ssh/authorized_keys
-
sftp> chmod 600 .ssh/authorized_keys
-
sftp> quit
-
-
Add storagebox to the root's list of known hosts and verify that sftp works with key authorization by doing
$ sudo sftp uXXXXXX-subY@uXXXXXX.your-storagebox.de
; it should not ask for password. -
$ sudo adduser mastodon
-
$ sudo apt-get install nginx sshfs certbot
,sudo systemctl stop nginx
,sudo systemctl disable nginx
-
$ sudo apt-get remove docker docker-engine docker.io
(just in case these were already installed) -
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
(just in case there weren't already installed) -
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
; verify with$ sudo apt-key fingerprint 0EBFCD88
-
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable
,sudo apt-get update
-
$ sudo apt-get install docker-ce
; verify withsudo docker run hello-world
-
$ sudo adduser mastodon docker
-
$ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
;sudo chmod +x /usr/local/bin/docker-compose
. NOTE that this command refers to the specific version of docker-compose; you should refer to the actual latest version. -
$ sudo mkdir /mastodon
-
Copy the required config files (see
samples
directory) to/mastodon/conf
directory. For example, copy them to storage box, and then:-
$ sudo sftp uXXXXXX-subY@uXXXXXX.your-storagebox.de
-
sftp> get mastodonconf/* /mastodon/conf
-
-
Open new TTY (e.g. with Ctrl+Alt+F2), log in as
mastodon
(or$ sudo su - mastodon
) -
$ mkdir /home/mastodon/docker-scratchpad
,cd /home/mastodon/docker-scratchpad
-
$ cp /mastodon/conf/docker-compose.yml .
,$ cp /mastodon/conf/.env.production .
-
$ script -f -c "docker-compose run --rm web bundle exec rake mastodon:setup" setup.log
-
Enter your domain name (e.g.
social.penartur
) -
Choose single/multi-user mode
-
Confirm that you're on Docker
-
Leave default postgresql and redis settings
-
Confirm that you don't want to store uploaded files on the cloud
-
Confirm that you don't want to send e-mails from localhost
-
SMTP server is
mail.gandi.net
, SMTP port is default (587), username isrobot@social.penartur
, password is your robot mailbox password, authentication is default (plain), verify mode is default (none), e-mail address isYour Mastodon Name <robot@social.penartur>
-
Agree to sending a test email; check that it has arrived (note that it may end up in a junk folder)
-
Confirm that you want to save configuration
-
Open new TTY (e.g. Ctrl+Shift+F3), log in as
mastodon
-
Make sure that
docker-scratchpad/setup.log
contains the configuration (e.g. by$ less docker-scratchpad/setup.log
). If it does not, return to TTY2, press some letters to forcescript
to flush its buffers, and switch to TTY3 again -
cp docker-scratchpad/setup.log docker-scratchpad/.env.production
,nano docker-scratchpad/.env.production
, remove redundant garbage (e.g. by Ctrl+K), leaving only config data (starting with# Generated with mastodon:setup
and ending beforeIt is also saved within this container
). Save it (Ctrl+O, Ctrl+X) -
Exit TTY3, return to TTY2
-
Confirm that you want to prepare database
-
Once database is prepared, switch to TTY1,
$ sudo chown -R 991:991 /mastodon/public
, switch back to TTY2 -
Confirm that you want to compile assets. Wait while assets compile (it should take around five minutes).
-
Once assets are compiled, switch to TTY1
-
$ sudo chmod 000 /mastodon/public/system
-
$ sudo nano /etc/fstab
, add new line:uXXXXXX-subY@uXXXXXX.your-storagebox.de:/media /mastodon/public/system fuse.sshfs delay_connect,_netdev,user,idmap=user,transform_symlinks,identityfile=/root/.ssh/id_rsa,allow_other,reconnect,uid=991,gid=991 0 0
, save and exit (Ctrl+O, Ctrl+X) -
$ sudo mount /mastodon/public/system
. Make sure everything is correct (including 991:991 ownership) by$ ls -la /mastodon/public/system
-
Return to TTY2
-
Confirm that you want to create an admin user, with username
admin
and emailadmin@social.penartur
-
Remember admin password
-
docker-compose up -d
-
mkdir /home/mastodon/live
,mkdir /home/mastodon/live/public
-
Exit TTY2, switch to TTY1
-
In Cloudflare, on Crypto tab, switch SSL to Flexible, disable "Always use HTTPS", disable "Authenticated origin pulls".
-
$ sudo systemctl stop nginx
-
$ sudo rm /etc/nginx/sites-enabled/default
-
Copy cloudflare client certificate to
/etc/nginx/certs/cloudflare.crt
-
Edit
penartur.social.conf
for your domain, renaming as appropriate, and put it to/etc/nginx/sites/available
-
$ cd /etc/nginx/sites-enabled
,$ sudo ln -s ../sites-available/social.penartur.conf
-
$ certbot certonly --standalone -d social.penartur
, enter your admin email address (admin@social.penartur) -
Check that everything is OK by
$ sudo nginx -t
-
In Cloudflare, on Crypto tab, switch SSL to Full (strict), enable "Always use HTTPS", enable "Authenticated origin pulls"
-
$ sudo systemctl start nginx
-
$ sudo certbot certonly --webroot -d social.penartur -w /home/mastodon/live/public
-
Create new script:
$ sudo nano /etc/cron.daily/letsencrypt-renew
:#!/usr/bin/env bash certbot renew systemctl reload nginx
-
Check that your mastodon instance (social.penartur) opens in browser
-
$ sudo reboot
(just to make sure it survives reboots correctly) -
Go to your mastodon instance, log in as admin, change password
-
Upload some media and make sure it went to storage box (media/media_attachments/files/...)
-
Follow someone from other instance, make sure that federation works
-
Set your VM to "protected mode" in hetzner cloud control panel, to make sure you don't accidentally delete it
-
Create a snapshot of your VM
-
Have some rest at last
If you experience shortage of CPU or RAM, you can always rescale your VM in hetzner control panel. Make sure to leave disk at its original volume (20GB) so that you'll be able to downscale later