mirror of
https://github.com/jakejarvis/mastodon-utils.git
synced 2025-04-26 02:15:22 -04:00
304 lines
10 KiB
Bash
Executable File
304 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# exit when any step fails
|
|
set -euo pipefail
|
|
|
|
# :)
|
|
MY_NAME_IS_JAKE_JARVIS="false"
|
|
|
|
# can't say you weren't warned
|
|
if [ "$MY_NAME_IS_JAKE_JARVIS" != "pinky promise" ]; then
|
|
echo "🚨 LISTEN UP!!!! YOU PROBABLY WANT THIS SCRIPT INSTEAD:"
|
|
echo "https://github.com/jakejarvis/mastodon-installer/blob/main/install.sh"
|
|
exit 69
|
|
fi
|
|
|
|
# initialize paths (and silence warnings about things not existing yet because that's why we're running the installer.)
|
|
# shellcheck disable=SC1091
|
|
. "$(dirname "${BASH_SOURCE[0]}")"/../init.sh >/dev/null
|
|
|
|
# check for existing installation
|
|
if [ -d "$APP_ROOT" ]; then
|
|
echo "⚠️ $APP_ROOT already exists. Are you sure Mastodon isn't already installed?"
|
|
exit 255
|
|
fi
|
|
|
|
# ask for required info up-front
|
|
read -rp "Server FQDN? " MASTODON_DOMAIN
|
|
read -rp "Public domain? (the second part of usernames, usually the same as FQDN) " MASTODON_USERNAME_DOMAIN
|
|
read -rp "Admin username? " MASTODON_ADMIN_USERNAME
|
|
read -rp "Admin email? " MASTODON_ADMIN_EMAIL
|
|
|
|
# leave our mark
|
|
INSTALLER_WUZ_HERE="# Generated by mastodon-installer @ $(date)"
|
|
|
|
# set FQDN (especially necessary for sendmail)
|
|
echo -e "\n$INSTALLER_WUZ_HERE
|
|
127.0.0.1 localhost $MASTODON_DOMAIN
|
|
::1 localhost $MASTODON_DOMAIN" | sudo tee -a /etc/hosts >/dev/null
|
|
sudo hostnamectl set-hostname "$MASTODON_DOMAIN"
|
|
|
|
# create non-root user named MASTODON_USER (unless it already exists)
|
|
if ! id -u "$MASTODON_USER" >/dev/null 2>&1; then
|
|
sudo adduser --gecos "" --home "$MASTODON_ROOT" --disabled-login "$MASTODON_USER" || :
|
|
echo "[ -s \"$UTILS_ROOT/init.sh\" ] && \. \"$UTILS_ROOT/init.sh\" >/dev/null 2>&1" | sudo tee -a "$MASTODON_ROOT/.bashrc" >/dev/null
|
|
sudo chown -R "$MASTODON_USER":"$MASTODON_USER" "$MASTODON_ROOT"
|
|
fi
|
|
|
|
# install latest ubuntu updates & basic prerequisites
|
|
sudo apt-get update
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
|
curl \
|
|
wget \
|
|
gnupg \
|
|
apt-transport-https \
|
|
lsb-release \
|
|
ca-certificates \
|
|
tzdata
|
|
|
|
# add official postgresql apt repository
|
|
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /usr/share/keyrings/postgresql-archive-keyring.gpg
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/postgresql.list >/dev/null
|
|
|
|
# add official redis apt repository
|
|
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list >/dev/null
|
|
|
|
# add official nginx apt repository
|
|
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/ubuntu/ $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null
|
|
|
|
# install prerequisites:
|
|
# https://docs.joinmastodon.org/admin/install/#system-packages
|
|
sudo apt-get update
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
|
autoconf \
|
|
bison \
|
|
build-essential \
|
|
ffmpeg \
|
|
file \
|
|
g++ \
|
|
gcc \
|
|
git \
|
|
imagemagick \
|
|
libaugeas-dev \
|
|
libffi-dev \
|
|
libgdbm-dev \
|
|
libicu-dev \
|
|
libidn11-dev \
|
|
libjemalloc-dev \
|
|
libncurses-dev \
|
|
libpq-dev \
|
|
libprotobuf-dev \
|
|
libreadline-dev \
|
|
libssl-dev \
|
|
libxml2-dev \
|
|
libxslt1-dev \
|
|
libyaml-dev \
|
|
nginx \
|
|
pkg-config \
|
|
postgresql \
|
|
postgresql-contrib \
|
|
protobuf-compiler \
|
|
python3 \
|
|
python3-psycopg2 \
|
|
python3-venv \
|
|
redis-server \
|
|
redis-tools \
|
|
shared-mime-info \
|
|
zlib1g-dev
|
|
|
|
# install rbenv & ruby-build
|
|
# https://github.com/rbenv/rbenv#basic-git-checkout
|
|
# https://github.com/rbenv/ruby-build#clone-as-rbenv-plugin-using-git
|
|
as_mastodon git clone https://github.com/rbenv/rbenv.git "$RBENV_ROOT"
|
|
as_mastodon git clone https://github.com/rbenv/ruby-build.git "$RBENV_ROOT/plugins/ruby-build"
|
|
|
|
# install nvm
|
|
# https://github.com/nvm-sh/nvm#manual-install
|
|
as_mastodon git clone https://github.com/nvm-sh/nvm.git "$NVM_DIR"
|
|
|
|
# clone vanilla Mastodon & checkout latest version:
|
|
as_mastodon git clone https://github.com/mastodon/mastodon.git "$APP_ROOT" && cd "$APP_ROOT"
|
|
as_mastodon git config --global --add safe.directory "$APP_ROOT"
|
|
as_mastodon git checkout "$(as_mastodon git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)"
|
|
# uncomment (and keep above lines) to install glitch-soc fork:
|
|
# as_mastodon git remote add glitch-soc https://github.com/glitch-soc/mastodon
|
|
# as_mastodon git fetch --all
|
|
# as_mastodon git checkout glitch-soc/main
|
|
|
|
# apply customizations
|
|
. "$UTILS_ROOT"/scripts/customize.sh
|
|
|
|
# install ruby
|
|
as_mastodon RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install --skip-existing
|
|
as_mastodon rbenv global "$(as_mastodon cat "$APP_ROOT"/.ruby-version)"
|
|
|
|
# install node & yarn
|
|
as_mastodon nvm install
|
|
as_mastodon nvm use
|
|
as_mastodon npm install --global yarn
|
|
|
|
# install npm and gem dependencies
|
|
as_mastodon gem install bundler --no-document
|
|
as_mastodon bundle config deployment "true"
|
|
as_mastodon bundle config without "development test"
|
|
as_mastodon bundle install --jobs "$(getconf _NPROCESSORS_ONLN)"
|
|
as_mastodon yarn install --pure-lockfile
|
|
|
|
# set up database w/ random alphanumeric password
|
|
DB_PASSWORD=$(
|
|
tr </dev/urandom -dc A-Za-z0-9 | head -c32
|
|
echo
|
|
)
|
|
echo "CREATE USER $MASTODON_USER WITH PASSWORD '$DB_PASSWORD' CREATEDB" | sudo -u postgres psql -f -
|
|
|
|
# populate .env.production config
|
|
echo "$INSTALLER_WUZ_HERE
|
|
|
|
LOCAL_DOMAIN=$MASTODON_USERNAME_DOMAIN
|
|
WEB_DOMAIN=$MASTODON_DOMAIN
|
|
SINGLE_USER_MODE=false
|
|
|
|
WEB_CONCURRENCY=3
|
|
MAX_THREADS=10
|
|
STREAMING_CLUSTER_NUM=1
|
|
RAILS_LOG_LEVEL=warn
|
|
|
|
DB_HOST=localhost
|
|
DB_USER=$MASTODON_USER
|
|
DB_NAME=mastodon_production
|
|
DB_PASS=$DB_PASSWORD
|
|
# without pgbouncer:
|
|
DB_PORT=5432
|
|
# with pgbouncer: https://github.com/jakejarvis/mastodon-utils/wiki/Postgres-&-PgBouncer#pgbouncer
|
|
# DB_PORT=6432
|
|
# PREPARED_STATEMENTS=false
|
|
|
|
REDIS_HOST=localhost
|
|
REDIS_PORT=6379
|
|
|
|
# get SES credentials: https://us-east-1.console.aws.amazon.com/ses/home?region=us-east-1#/smtp
|
|
# ...or use SendGrid, MailGun, AWS SES, etc...
|
|
# SMTP_SERVER=email-smtp.us-east-1.amazonaws.com
|
|
# SMTP_PORT=587
|
|
# SMTP_FROM_ADDRESS=\"Mastodon <noreply@$MASTODON_DOMAIN>\"
|
|
# SMTP_LOGIN=XXXXXXXX
|
|
# SMTP_PASSWORD=XXXXXXXX
|
|
|
|
# uses linode, not brand name S3: https://cloud.linode.com/object-storage/buckets/create
|
|
# AWS_ACCESS_KEY_ID=XXXXXXXX
|
|
# AWS_SECRET_ACCESS_KEY=XXXXXXXX
|
|
# S3_ENABLED=true
|
|
# S3_BUCKET=my-bucket
|
|
# S3_PROTOCOL=https
|
|
# S3_HOSTNAME=us-east-1.linodeobjects.com
|
|
# S3_ENDPOINT=https://us-east-1.linodeobjects.com
|
|
# S3_ALIAS_HOST=my-bucket.us-east-1.linodeobjects.com
|
|
|
|
# https://github.com/jakejarvis/mastodon-utils/wiki/ElasticSearch
|
|
# ES_ENABLED=true
|
|
# ES_HOST=localhost
|
|
# ES_PORT=9200
|
|
# optional, not enabled by default:
|
|
# ES_USER=
|
|
# ES_PASS=
|
|
|
|
# https://github.com/jakejarvis/mastodon-utils/wiki/Prometheus-&-Grafana
|
|
# STATSD_ADDR=localhost:9125
|
|
|
|
IP_RETENTION_PERIOD=31556952
|
|
SESSION_RETENTION_PERIOD=31556952
|
|
|
|
SECRET_KEY_BASE=$(as_mastodon RAILS_ENV=production bundle exec rake secret)
|
|
OTP_SECRET=$(as_mastodon RAILS_ENV=production bundle exec rake secret)
|
|
$(as_mastodon RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key)" | as_mastodon tee "$APP_ROOT/.env.production" >/dev/null
|
|
|
|
# manually setup db
|
|
as_mastodon RAILS_ENV=production SAFETY_ASSURED=1 bundle exec rails db:setup
|
|
|
|
# precompile assets
|
|
as_mastodon RAILS_ENV=production bundle exec rails assets:precompile
|
|
|
|
# install latest certbot
|
|
# https://certbot.eff.org/instructions?ws=nginx&os=pip
|
|
sudo python3 -m venv /opt/certbot/
|
|
sudo /opt/certbot/bin/pip install --upgrade pip
|
|
sudo /opt/certbot/bin/pip install certbot certbot-nginx
|
|
sudo ln -s /opt/certbot/bin/certbot /usr/local/bin/certbot
|
|
|
|
# ensure nginx hasn't started itself
|
|
sudo systemctl stop nginx
|
|
|
|
# order an ssl certificate from LE
|
|
sudo certbot certonly \
|
|
--non-interactive \
|
|
--agree-tos \
|
|
--no-eff-email \
|
|
--domains "$MASTODON_DOMAIN" \
|
|
--email "$MASTODON_ADMIN_EMAIL" \
|
|
--standalone
|
|
|
|
# configure nginx: copies conf files from this repo to /etc/nginx
|
|
sudo mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
|
|
sudo cp "$UTILS_ROOT"/etc/nginx/nginx.conf /etc/nginx/nginx.conf
|
|
sudo sed -i /etc/nginx/nginx.conf -e "s|user nginx;|user $MASTODON_USER;|g"
|
|
sudo mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled /etc/nginx/snippets
|
|
sudo cp -f "$UTILS_ROOT"/etc/nginx/sites-available/*.conf /etc/nginx/sites-available/
|
|
sudo sed \
|
|
-i /etc/nginx/sites-available/mastodon.conf \
|
|
-e "s|mastodon.example.com|$MASTODON_DOMAIN|g" \
|
|
-e "s|/home/mastodon/live|$APP_ROOT|g"
|
|
sudo ln -sf /etc/nginx/sites-available/mastodon.conf /etc/nginx/sites-enabled/mastodon.conf
|
|
# sudo ln -sf /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/default.conf
|
|
sudo cp -f "$UTILS_ROOT"/etc/nginx/snippets/*.conf /etc/nginx/snippets/
|
|
sudo cp -f "$UTILS_ROOT"/etc/nginx/modules/*.so /usr/lib/nginx/modules/
|
|
sudo nginx -t
|
|
|
|
# configure mastodon systemd services
|
|
sudo cp "$UTILS_ROOT"/etc/systemd/system/mastodon-*.service /etc/systemd/system/
|
|
|
|
# fix hard-coded paths and usernames in systemd files
|
|
# (they already match the defaults from init.sh, so it's likely nothing will change)
|
|
sudo sed \
|
|
-i /etc/systemd/system/mastodon-*.service \
|
|
-e "s|/home/mastodon/live|$APP_ROOT|g" \
|
|
-e "s|/home/mastodon|$MASTODON_ROOT|g" \
|
|
-e "s|User=mastodon|User=$MASTODON_USER|g"
|
|
|
|
# start everything up!
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
|
|
sudo systemctl start nginx
|
|
|
|
# wait a bit to be safe
|
|
sleep 5
|
|
|
|
# create admin account
|
|
tootctl accounts create \
|
|
"$MASTODON_ADMIN_USERNAME" \
|
|
--email "$MASTODON_ADMIN_EMAIL" \
|
|
--role Owner \
|
|
--confirmed
|
|
|
|
# create directory for cron logdrain
|
|
as_mastodon mkdir -p "$LOGS_ROOT"
|
|
as_mastodon touch "$LOGS_ROOT"/cron.log
|
|
|
|
# set cleanup & backup tasks to run weekly
|
|
# https://docs.joinmastodon.org/admin/setup/#cleanup
|
|
(
|
|
sudo crontab -l
|
|
echo -e "\n$INSTALLER_WUZ_HERE
|
|
@weekly bash -c \"$UTILS_ROOT/scripts/weekly_cleanup.sh >> $LOGS_ROOT/cron.log 2>&1\"
|
|
@weekly bash -c \"$UTILS_ROOT/scripts/backup.sh >> $LOGS_ROOT/cron.log 2>&1\"
|
|
|
|
# automatically renew Let's Encrypt certificates
|
|
# https://certbot.eff.org/instructions?ws=nginx&os=pip
|
|
0 0,12 * * * root /opt/certbot/bin/python -c \"import random; import time; time.sleep(random.random() * 3600)\" && certbot renew -q
|
|
"
|
|
) | sudo crontab -
|
|
|
|
echo "🎉 done! don't forget to fill in .env.production with optional credentials"
|
|
echo "https://$MASTODON_DOMAIN/auth/sign_in"
|