Table of Contents
A budget Mastodon installation that still strives to be productionised and fault-tolerant.
You'll need terraform installed.
Sign up for a Digital Ocean account. Create a personal access token
I used [Mailgun][mailgun], but any provider will work. You'll need the server, port, login, and password.
You'll need a domain with DNS you control.
There needs to be a private key, unencrypted, at ~/.ssh/id_rsa and a corresponding public key at ~/.ssh/id_rsa.pub
- install all required Terraform modules:
terraform init terraform/- Fill out your details into
terraform.tfvarsin the root of the repository:
digital_ocean_token = "< digital ocean token>"
mastodon_domain = "mycool.example"
letsencrypt_email = "<your email address, needed by letsencrypt>"
smtp_login = "<smtp login>"
smtp_password = "<smtp password>"
- Then, create a terraform plan to create the floating IP:
terraform plan -target digitalocean_floating_ip.ip -out tf.plan terraform/- If everything looks good, go ahead and and execute the plan:
terraform apply tf.plan-
That should give you a stable IP address. create an A record on your domain pointing to that IP.
-
Let terraform plan out the rest of the infrastrucutre:
terraform plan -out tf.plan terraform/
- Apply the changes:
terraform apply tf.plan
- Wait 5-10 minutes for all the infrastructure to come up. Don't let your computer go to sleep.
Updating the salt files won't trigger a replacemet on its own. Instead, you can taint the droplet to trigger a replace:
terraform taint digitalocean_droplet.mastodon terraform/
Then plan and apply infrastructure changes as usual.
The script provinions the Droplet to work with masterless saltstack, but it can also use a local master.
- Set up a master locally.
- SSH into the droplet:
ssh -R 4505:localhost:4505 -R 4506:localhost:4506 Eroot@<floating ip>the -R commands open remote ports to the local machine, so the droplet doesn't need to access
- On the droplet, edit
/etc/salt/minionto point at at the localhost for master:
# Set the location of the salt master server. If the master server cannot be
# resolved, then the minion will fail to start.
master: localhost- Restart the salt minion daemon:
systemctl restart salt-minion- On the local host, accept the minion's key:
salt-key -a mastodon
- Edit
/etc/salt/masterto point at the appropriate directories:
pillar_roots:
base:
- /home/<user>/do_mastodon/salt/pillar
file_roots:
base:
- /home/<user>/do_mastodon/salt- Apply the salt state:
salt mastodon state.applyYou can do this as much as you want, to update the Mastodon instance without the downtime incurred by destroy-and-replace.
If you already have existing infrastructure you'd like to use with Terraform, you can import it. The most important resources to add are the static IP and the volume:
terraform import -config=terraform digitalocean_volume.do_volume $(curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer <your api token>" "https://api.digitalocean.com/v2/volumes?region=nyc1" | jq -r '.volumes[0].id')
terraform import -config=terraform digitalocean_floating_ip.ip $(curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer <your api token>" "https://api.digitalocean.com/v2/floating_ips?region=nyc1" | jq -r '.floating_ips[0].ip')