AWS Services used:
- EC2
- S3
- Cloudfront
- Route 53
- ACM
- IAM
Notes:
- Most of the shell commands require
sudo
- Unless using Elastic IP, public IPv4 address changes on EC2 instance restarts, update new IP address to domain records
https://docs.joinmastodon.org/user/run-your-own
- Route 53 hosted zone
- EC2 instance
- S3 bucket
https://docs.joinmastodon.org/admin/prerequisites
EC2 instance
- AMI Ubuntu Server 20.04 arm64
- Recommended memory at least 2GB
t4g.small
- Create key pair for SSH access
- Network settings/security groups:
- Inbound: SSH, HTTP, HTTPS, IPv6
- Outbound: all traffic
- Storage: 8GB gp3
Route 53 hosted zone, point domain and www to instance.
Create root (blank record name) and www A records with ec2 instance’s Public IPv4 address as values.
https://docs.joinmastodon.org/admin/install
Step install postgresql
: skip and follow this guide instead https://www.postgresql.org/download/linux/ubuntu
- Run the script and continue
Step rbenv install
Ruby, the installation may crash if machine memory is too low (crashed on t4g.nano
, .5 GiB
)
- Stop instance and change to higher instance type (see note)
Step mastodon:setup
full steps here https://github.com/mastodon/mastodon/blob/v3.5.3/lib/tasks/mastodon.rake
- Domain name: example.com
- Single user blog: yes if personal use only
- Docker: no
- PostgreSQL/Redis: no input, leave all default
- Store uploaded files to cloud: yes + S3, leave all default, update values later
- Access the uploaded files from your own domain: yes,
files.example.com
- Send a test e-mail with this configuration right now: no
- Save configuration/Prepare database/Compile assets: yes
Step setup nginx
and acquire SSL certificate (domain A records are required for certbot)
- Get SSL certificate before setup nginx
certbot certonly --standalone -d example.com
Setup systemd
services and visit the domain in browser.
If this error appears This page is not correct / We're sorry, but something went wrong on our end.
- SSH and run at root user
sudo journalctl -u mastodon-web
, ifmastodon-web
service stopped after application preloading that means system memory is insufficient to run the application (t4g.micro
,1 GiB
)bundle[2066]: [2066] * Preloading application systemd[1]: mastodon-web.service: Main process exited, code=killed, status=9/KILL
- Stop instance and change to higher instance type (see note)
Create S3 bucket and turn off Block all public access
in Permissions.
AWS IAM
- Add user
- Select AWS credential type
Access key - Programmatic access
- At Permissions step, attach
AmazonS3FullAccess
policy to user - Continue until the last step
Create user
, store user credentials (access and secret keys) in a safe place
SSH to project repository, open .env.production
and update these variables:
S3_BUCKET
=name of the bucket created aboveS3_REGION
=find in bucket Properties, e.g.us-east-1
S3_HOSTNAME
=use region id above and follow this formats3-us-east-1.amazonaws.com
AWS_ACCESS_KEY_ID
=access key from IAM user aboveAWS_SECRET_ACCESS_KEY
=secret key from IAM user above
Try uploading files, at this step we can find the items in the S3 bucket but they are not public until deployed via a CloudFront distribution.
Go to Route 53 hosted zone and point sub-domain to instance like we did in step 2. Prepare machine.
Open /etc/nginx/sites-available/mastodon
and add new server for the sub-domain:
server {
server_name files.example.com
}
Run sudo certbot -d files.example.com
to generate ssl certificate, then open newly created keys in editor
/etc/letsencrypt/live/files.example.com/fullchain.pem
/etc/letsencrypt/live/files.example.com/privkey.pem
Sub-domain entry above can be deleted after SSL generation.
Go to AWS ACM and import certificate, there are 3 fields:
- Certificate body: look into
fullchain.pem
, there are 3 certificates, copy the first one-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----
- Certificate private key:
privkey.pem
- Certificate chain: the remains of
fullchain.pem
Create distribution with S3 bucket above
- At Default cache behaviour, redirect HTTP to HTTPS
- At Settings, add the sub-domain (
files.example.com
) to Alternate domain name (CNAME) and select corresponding SSL certificate imported previously in ACM - Finish creating distribution
Update the sub-domain record in hosted zone
- Record type A
- Turn Alias on
- Route traffic to CloudFront distribution and choose the distribution created above
- Save the record
Complete configuration and enjoy.
Additional configuration, redirect www to non-www https://www.vultr.com/docs/nginx-redirects-for-non-www-sub-domains-to-www/