mastodon-docker-stack/install.sh

341 lines
9.1 KiB
Bash

#!/bin/bash
## CHANGE
DOMAIN=REPLACE.to.your.domain
USER=setYOURuser
EMAIL=your@user.email
## UPDATE SYSTEM
apt update
apt upgrade
## setup repo
apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release -y
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install nginx docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-compose -y
## increase mapareas
echo "vm.max_map_count=262144" | tee /etc/sysctl.d/90-max_map_count.conf
systemctl --load /etc/sysctl.d/90-max_map_count.conf
## DOCKER
# apt install docker.io docker-compose
#
echo Create Folders
mkdir -p/opt/mastodon/
mkdir -p /opt/mastodon/database/{postgresql,redis,elasticsearch}
mkdir -p /opt/mastodon/web/{public,system}
echo Set Permissions
chown 991:991 /opt/mastodon/web/{public,system}
chown 1000 /opt/mastodon/database/elasticsearch
echo Change into folder
cd /opt/mastodon
echo Download docker compose
wget https://git.dev-c.at/Theenoro/mastodon-docker-stack/raw/branch/main/docker-compose.yml
echo Create ENV Files
touch /opt/mastodon/application.env
touch /opt/mastodon/database.env
echo Generate Keys and Secrets
docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake secret
SECRET_KEY_BASE=$(docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake secret)
OTP_SECRET=$(docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake secret)
docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake mastodon:webpush:generate_vapid_key > /tmp/tmpFileCode
VAPID_PRIVATE_KEY=$(awk '/VAPID_PRIVATE_KEY=([A-z0-9=]*)/{gsub("VAPID_PRIVATE_KEY=","",$0);print $0}' /tmp/tmpFileCode)
VAPID_PUBLIC_KEY=$(awk '/VAPID_PUBLIC_KEY=([A-z0-9=]*)/{gsub("VAPID_PUBLIC_KEY=","",$0);print $0}' /tmp/tmpFileCode)
rm /tmp/tmpFileCode
echo Fill application.env
cat << EOF | tee /opt/mastodon/application.env
# environment
RAILS_ENV=production
NODE_ENV=production
# domain
LOCAL_DOMAIN=$DOMAIN
# redirect to the first profile
SINGLE_USER_MODE=true
# do not serve static files
RAILS_SERVE_STATIC_FILES=false
# concurrency
WEB_CONCURRENCY=2
MAX_THREADS=5
# pgbouncer
#PREPARED_STATEMENTS=false
# locale
DEFAULT_LOCALE=en
# email, not used
SMTP_SERVER=localhost
SMTP_PORT=587
SMTP_FROM_ADDRESS=notifications@example.org
#SMTP_SERVER=smtp.example.com
#SMTP_PORT=465
#SMTP_LOGIN=mastodon@example.com
#SMTP_PASSWORD=long_password
#SMTP_AUTH_METHOD=plain
#SMTP_SSL=true
#SMTP_ENABLE_STARTTLS_AUTO=true
#SMTP_OPENSSL_VERIFY_MODE=none
#SMTP_FROM_ADDRESS=mastodon@example.com
#SMTP_DELIVERY_METHOD=smtp
#SMTP_DOMAIN=localhost
# secrets
SECRET_KEY_BASE=$SECRET_KEY_BASE
OTP_SECRET=$OTP_SECRET
VAPID_PRIVATE_KEY=$VAPID_PRIVATE_KEY
VAPID_PUBLIC_KEY=$VAPID_PUBLIC_KEY
EOF
POSTGRES_PASSWORD=$(docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake secret)
ELASTIC_PASSWORD=$(docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake secret)
DB_PASS=$(docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake secret)
cat << EOF | tee /opt/mastodon/database.env
# postgresql configuration
POSTGRES_USER=mastodon
POSTGRES_DB=mastodon_production
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
# pgbouncer configuration
#POOL_MODE=transaction
#ADMIN_USERS=postgres,mastodon
#DATABASE_URL="postgres://mastodon:O6lOD6nF2LbhhJs1e7QL@postgresql:5432/mastodon_production"
# elasticsearch
ES_JAVA_OPTS=-Xms512m -Xmx512m
ELASTIC_PASSWORD=$ELASTIC_PASSWORD
# mastodon database configuration
#DB_HOST=pgbouncer
DB_HOST=postgresql
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=$DB_PASS
DB_PORT=5432
REDIS_HOST=redis
REDIS_PORT=6379
CACHE_REDIS_HOST=redis-volatile
CACHE_REDIS_PORT=6379
ES_ENABLED=true
ES_HOST=elasticsearch
ES_PORT=9200
ES_USER=elastic
ES_PASS=$ELASTIC_PASSWORD
EOF
chmod 777 /opt/mastodon/web/public
docker volume create --opt type=none --opt device=/opt/mastodon/web/public --opt o=bind temporary_static
docker run --rm -v "temporary_static:/static" tootsuite/mastodon:v3.5.1 bash -c "cp -r /opt/mastodon/public/* /static/"
chmod 744 /opt/mastodon/web/public
mkdir -p /etc/nginx/ssl/
openssl req -subj "/commonName=$DOMAIN/" -x509 -nodes -days 730 -newkey rsa:2048 -keyout /etc/nginx/ssl/$DOMAIN.key -out /etc/nginx/ssl/$DOMAIN.crt
echo Fill application.env
cat << 'EOF' | tee /etc/nginx/sites-available/mastodon
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream backend {
server 127.0.0.1:3000 fail_timeout=0;
}
upstream streaming {
server 127.0.0.1:4000 fail_timeout=0;
}
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g;
server {
listen 80;
server_name REPLACEDOMAIN;
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
server_name REPLACEDOMAIN;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/ssl/REPLACEDOMAIN.crt;
ssl_certificate_key /etc/nginx/ssl/REPLACEDOMAIN.key;
keepalive_timeout 70;
sendfile on;
client_max_body_size 80m;
root /opt/mastodon/public;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;
add_header Strict-Transport-Security "max-age=31536000" always;
location / {
try_files $uri @proxy;
}
location ~ ^/(system/accounts/avatars|system/media_attachments/files) {
add_header Cache-Control "public, max-age=31536000, immutable";
add_header Strict-Transport-Security "max-age=31536000" always;
root /opt/mastodon/;
try_files $uri @proxy;
}
location ~ ^/(emoji|packs) {
add_header Cache-Control "public, max-age=31536000, immutable";
add_header Strict-Transport-Security "max-age=31536000" always;
try_files $uri @proxy;
}
location /sw.js {
add_header Cache-Control "public, max-age=0";
add_header Strict-Transport-Security "max-age=31536000" always;
try_files $uri @proxy;
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://backend;
proxy_buffering on;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_cache CACHE;
proxy_cache_valid 200 7d;
proxy_cache_valid 410 24h;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cached $upstream_cache_status;
add_header Strict-Transport-Security "max-age=31536000" always;
tcp_nodelay on;
}
location /api/v1/streaming {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
proxy_pass http://streaming;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
error_page 500 501 502 503 504 /500.html;
}
EOF
sed -i "s/REPLACEDOMAIN/$DOMAIN/" /etc/nginx/sites-available/mastodon
ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/
systemctl restart nginx
docker-compose -f /opt/mastodon/docker-compose.yml pull
cat << EOF | tee /etc/systemd/system/mastodon.service
[Unit]
Description=Mastodon service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker-compose -f /opt/mastodon/docker-compose.yml up -d
ExecStop=/usr/bin/docker-compose -f /opt/mastodon/docker-compose.yml down
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
docker-compose -f /opt/mastodon/docker-compose.yml up -d postgresql redis redis-volatile
docker-compose -f /opt/mastodon/docker-compose.yml ps
docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake db:setup
docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bundle exec rake db:migrate
systemctl enable --now mastodon.service
docker-compose -f /opt/mastodon/docker-compose.yml ps
docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bin/tootctl accounts create $USER --email $EMAIL --confirmed --role admin >> ./output.log
docker-compose -f /opt/mastodon/docker-compose.yml run --rm shell bin/tootctl settings registrations close
cat ./output.log