Init mastodon.pub.solar
This commit is contained in:
parent
fbf5a80b6d
commit
0d1fef2a16
2
mastodon/.gitignore
vendored
Normal file
2
mastodon/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.sql
|
||||
.env.production
|
58
mastodon/README.md
Normal file
58
mastodon/README.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
# pub.solar mastodon
|
||||
https://mastodon.pub.solar
|
||||
|
||||
### Upgrading
|
||||
This section assumes you edited `docker-compose.yml` and bumped the mastodon docker
|
||||
image version tag
|
||||
```
|
||||
# check current trailing number of mastodon containers
|
||||
# current_container_index
|
||||
docker ps | grep -E "sidekiq|streaming|web"
|
||||
|
||||
# make a DB backup and copy it to your local machine
|
||||
docker exec -it matrix-postgres bash
|
||||
|
||||
# in shell in matrix-postgres container:
|
||||
pg_dump -U mastodon -d mastodon_production -W -f /root/mastodon_db_backup-$(date +%F).sql
|
||||
exit
|
||||
|
||||
# copy backup to local machine
|
||||
docker cp matrix-postgres:/root/mastodon_db_backup-$(date +%F).sql .
|
||||
|
||||
# download new mastodon docker images
|
||||
docker-compose --project-name blue-mastodon pull
|
||||
|
||||
# run pre-update migrations
|
||||
docker-compose run \
|
||||
--rm \
|
||||
-e SKIP_POST_DEPLOYMENT_MIGRATIONS=true \
|
||||
web \
|
||||
rails db:migrate
|
||||
|
||||
# create new containers with new mastodon version
|
||||
docker-compose --project-name blue-mastodon up \
|
||||
--detach \
|
||||
--scale web=2 \
|
||||
--scale streaming=2 \
|
||||
--scale sidekiq=2 \
|
||||
--no-recreate
|
||||
|
||||
# stop containers with old mastodon version
|
||||
docker stop \
|
||||
blue-mastodon_web_($current_container_index - 1) \
|
||||
blue-mastodon_streaming_($current_container_index - 1) \
|
||||
blue-mastodon_sidekiq_($current_container_index - 1)
|
||||
|
||||
# run post-deployment migrations
|
||||
docker-compose run --rm web rails db:migrate
|
||||
|
||||
# clean up containers with old mastodon version
|
||||
docker rm \
|
||||
blue-mastodon_web_($current_container_index - 1) \
|
||||
blue-mastodon_streaming_($current_container_index - 1) \
|
||||
blue-mastodon_sidekiq_($current_container_index - 1)
|
||||
```
|
||||
|
||||
Todos:
|
||||
- implement automatic backups, they are only done manually during upgrades at the moment
|
||||
- switch proxy from nginx-dehydrated to caddy - done
|
0
mastodon/backups/.gitkeep
Normal file
0
mastodon/backups/.gitkeep
Normal file
184
mastodon/docker-compose.yml
Normal file
184
mastodon/docker-compose.yml
Normal file
|
@ -0,0 +1,184 @@
|
|||
version: "2.4"
|
||||
|
||||
services:
|
||||
|
||||
# we're using matrix-postgres as DB
|
||||
#db:
|
||||
# restart: always
|
||||
# image: postgres:14-alpine
|
||||
# shm_size: 256mb
|
||||
# networks:
|
||||
# - mastodon-fabric
|
||||
|
||||
# Experimentally replaced by caddy
|
||||
#nginx:
|
||||
# image: hub.greenbaum.cloud/nginx-dehydrated:1.19-alpine
|
||||
# mem_limit: 256m
|
||||
# restart: always
|
||||
# environment:
|
||||
# - LETSENCRYPT_DOMAIN=mastodon.pub.solar
|
||||
# - UPSTREAM_NAME=mastodon
|
||||
# - UPSTREAM_CNS_BASE_DOMAIN=svc.e5756d08-36fd-424b-f8bc-acdb92ca7b82.cgn-1.int.greenbaum.zone
|
||||
# - UPSTREAM_PORT=3000
|
||||
# network_mode: mastodon-fabric
|
||||
# ports:
|
||||
# - 80
|
||||
# - 443
|
||||
# labels:
|
||||
# - triton.cns.services=mastodon-proxy
|
||||
|
||||
caddy:
|
||||
image: caddy:2.5.1
|
||||
mem_limit: 256m
|
||||
restart: always
|
||||
environment:
|
||||
- SITE_DOMAIN=mastodon.pub.solar
|
||||
- UPSTREAM_APP_DOMAIN=mastodon-web.svc.e5756d08-36fd-424b-f8bc-acdb92ca7b82.cgn-1.int.greenbaum.zone
|
||||
- UPSTREAM_STREAMING_DOMAIN=mastodon-streaming.svc.e5756d08-36fd-424b-f8bc-acdb92ca7b82.cgn-1.int.greenbaum.zone
|
||||
- UPSTREAM_APP_PORT=3000
|
||||
- UPSTREAM_STREAMING_PORT=4000
|
||||
network_mode: mastodon-fabric
|
||||
ports:
|
||||
- 80
|
||||
- 443
|
||||
labels:
|
||||
- triton.cns.services=mastodon-proxy
|
||||
entrypoint: /bin/sh
|
||||
command: >-
|
||||
-c 'echo "
|
||||
{
|
||||
email admins@pub.solar
|
||||
}
|
||||
|
||||
$$SITE_DOMAIN {
|
||||
@streaming {
|
||||
path /api/v1/streaming/*
|
||||
}
|
||||
@cache_control {
|
||||
path_regexp ^/(emoji|packs|/system/accounts/avatars|/system/media_attachments/files)
|
||||
}
|
||||
log {
|
||||
output stderr
|
||||
}
|
||||
handle /.well-known/keybase.txt {
|
||||
root * /srv
|
||||
file_server
|
||||
}
|
||||
reverse_proxy @streaming {
|
||||
to http://$$UPSTREAM_STREAMING_DOMAIN:$$UPSTREAM_STREAMING_PORT
|
||||
}
|
||||
reverse_proxy {
|
||||
to http://$$UPSTREAM_APP_DOMAIN:$$UPSTREAM_APP_PORT
|
||||
}
|
||||
handle_errors {
|
||||
rewrite 500.html
|
||||
}
|
||||
|
||||
encode zstd gzip
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000"
|
||||
}
|
||||
header /sw.js Cache-Control "public, max-age=0"
|
||||
header @cache_control Cache-Control "public, max-age=31536000, immutable"
|
||||
}
|
||||
|
||||
files.pub.solar {
|
||||
handle {
|
||||
rewrite * /s/jw24ad6l4a6zxsnd32cmf5hp5nsq/pub-solar-mastodon{uri}?download
|
||||
reverse_proxy {
|
||||
# backends / upstreams
|
||||
to https://link.tardigradeshare.io
|
||||
|
||||
# header manipulation
|
||||
# proxy to an HTTPS endpoint
|
||||
header_up Host {upstream_hostport}
|
||||
# copied from mastodon docs for nginx with s3 for files
|
||||
header_up Connection ""
|
||||
header_up Authorization ""
|
||||
# remove these header from the backends response
|
||||
header_down -content-disposition
|
||||
header_down -Set-Cookie
|
||||
header_down -Access-Control-Allow-Origin
|
||||
header_down -Access-Control-Allow-Methods
|
||||
header_down -Access-Control-Allow-Headers
|
||||
header_down -x-amz-id-2
|
||||
header_down -x-amz-request-id
|
||||
header_down -x-amz-meta-server-side-encryption
|
||||
header_down -x-amz-server-side-encryption
|
||||
header_down -x-amz-bucket-region
|
||||
header_down -x-amzn-requestid
|
||||
# add these header to the backends response
|
||||
# cache client side for 7 days
|
||||
header_down Cache-Control "public, max-age=604800"
|
||||
}
|
||||
}
|
||||
handle_errors {
|
||||
rewrite 500.html
|
||||
}
|
||||
}
|
||||
" | caddy run --adapter caddyfile --config -'
|
||||
|
||||
|
||||
# using SmartOS native zone mastodon-redis, lx-brand redis crashes regularly,
|
||||
# upstream bug: https://github.com/redis/redis/issues/8861
|
||||
# redis:
|
||||
# image: redis:6.2-alpine
|
||||
# mem_limit: 512m
|
||||
# restart: always
|
||||
# network_mode: mastodon-fabric
|
||||
# labels:
|
||||
# - triton.cns.services=mastodon-redis
|
||||
|
||||
web:
|
||||
image: tootsuite/mastodon:v3.5.3
|
||||
mem_limit: 1g
|
||||
restart: always
|
||||
env_file: .env.production
|
||||
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
|
||||
network_mode: mastodon-fabric
|
||||
# see redis service comment
|
||||
#depends_on:
|
||||
# - redis
|
||||
labels:
|
||||
- triton.cns.services=mastodon-web
|
||||
|
||||
streaming:
|
||||
image: tootsuite/mastodon:v3.5.3
|
||||
mem_limit: 1g
|
||||
restart: always
|
||||
env_file: .env.production
|
||||
command: node ./streaming
|
||||
network_mode: mastodon-fabric
|
||||
# see redis service comment
|
||||
#depends_on:
|
||||
# - redis
|
||||
labels:
|
||||
- triton.cns.services=mastodon-streaming
|
||||
|
||||
sidekiq:
|
||||
image: tootsuite/mastodon:v3.5.3
|
||||
mem_limit: 1g
|
||||
restart: always
|
||||
env_file: .env.production
|
||||
command: bundle exec sidekiq
|
||||
network_mode: mastodon-fabric
|
||||
labels:
|
||||
- triton.cns.services=mastodon-sidekiq
|
||||
|
||||
elasticsearch:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
|
||||
mem_limit: 512m
|
||||
restart: always
|
||||
environment:
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
- "cluster.name=es-mastodon"
|
||||
- "discovery.type=single-node"
|
||||
- "bootstrap.memory_lock=true"
|
||||
network_mode: mastodon-fabric
|
||||
labels:
|
||||
- triton.cns.services=mastodon-elasticsearch
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
56
mastodon/keybase/teutat3s-keybase-verification.txt
Normal file
56
mastodon/keybase/teutat3s-keybase-verification.txt
Normal file
|
@ -0,0 +1,56 @@
|
|||
==================================================================
|
||||
https://keybase.io/teutat3s
|
||||
--------------------------------------------------------------------
|
||||
|
||||
I hereby claim:
|
||||
|
||||
* I am an admin of https://mastodon.pub.solar
|
||||
* I am teutat3s (https://keybase.io/teutat3s) on keybase.
|
||||
* I have a public key ASCk3wTzXKHXwHUoTzp0MOjVgNx3qrRAx21X_rjzqTZJFQo
|
||||
|
||||
To do so, I am signing this object:
|
||||
|
||||
{
|
||||
"body": {
|
||||
"key": {
|
||||
"eldest_kid": "0120a4df04f35ca1d7c075284f3a7430e8d580dc77aab440c76d57feb8f3a93649150a",
|
||||
"host": "keybase.io",
|
||||
"kid": "0120a4df04f35ca1d7c075284f3a7430e8d580dc77aab440c76d57feb8f3a93649150a",
|
||||
"uid": "5d555cc40616a706ec189ddd24b35019",
|
||||
"username": "teutat3s"
|
||||
},
|
||||
"merkle_root": {
|
||||
"ctime": 1618093923,
|
||||
"hash": "0aa5f6178ad671eda21e4e198202f4ab7f4fefff87760df4da17c78fdaf299ecdf0ae6d8858389123fe360416a4a9471bb4de5cdade3a068bed6a1bf377e76de",
|
||||
"hash_meta": "883b0d6b47df62fc1566dd8671aac8a34bb93fa7e2d41e8e38bec4f5e19b3721",
|
||||
"seqno": 19597808
|
||||
},
|
||||
"service": {
|
||||
"entropy": "gopmQPbYzUUJHhnB0+YaTF45",
|
||||
"hostname": "mastodon.pub.solar",
|
||||
"protocol": "https:"
|
||||
},
|
||||
"type": "web_service_binding",
|
||||
"version": 2
|
||||
},
|
||||
"client": {
|
||||
"name": "keybase.io go client",
|
||||
"version": "5.6.1"
|
||||
},
|
||||
"ctime": 1618093946,
|
||||
"expire_in": 504576000,
|
||||
"prev": "ecc6e3707d269e8fd62ea94d1ee7330fd15206ae3e6d14946c2f2a4b8f12c535",
|
||||
"seqno": 28,
|
||||
"tag": "signature"
|
||||
}
|
||||
|
||||
which yields the signature:
|
||||
|
||||
hKRib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEgpN8E81yh18B1KE86dDDo1YDcd6q0QMdtV/6486k2SRUKp3BheWxvYWTESpcCHMQg7MbjcH0mno/WLqlNHuczD9FSBq4+bRSUbC8qS48SxTXEIJd2HskvMapYSjPnoSSaFz9MJALBipX25kyi5bMvU+yUAgHCo3NpZ8RA+CMgOYpqqk/K0x7tgsH810Qvjxvs8FJbdCQ3SwAiFZ9v323TzWnFxuq1qbl5fAvQq6RInKYpPNALxD0c42miAahzaWdfdHlwZSCkaGFzaIKkdHlwZQildmFsdWXEIOyhPREWh9nbN6VTbOXs1YJofwkachECGbSqLa/aoyuWo3RhZ80CAqd2ZXJzaW9uAQ==
|
||||
|
||||
And finally, I am proving ownership of this host by posting or
|
||||
appending to this document.
|
||||
|
||||
View my publicly-auditable identity here: https://keybase.io/teutat3s
|
||||
|
||||
==================================================================
|
117
mastodon/nginx/nginx-default.conf.template
Normal file
117
mastodon/nginx/nginx-default.conf.template
Normal file
|
@ -0,0 +1,117 @@
|
|||
upstream ${UPSTREAM_NAME} {
|
||||
server mastodon-web.${UPSTREAM_CNS_BASE_DOMAIN}:${UPSTREAM_PORT};
|
||||
}
|
||||
|
||||
upstream streaming {
|
||||
server mastodon-streaming.${UPSTREAM_CNS_BASE_DOMAIN}:4000 fail_timeout=0;
|
||||
}
|
||||
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g;
|
||||
|
||||
# generated 2021-02-28, Mozilla Guideline v5.6, nginx 1.19, OpenSSL 1.1.1d, modern configuration
|
||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.19&config=modern&openssl=1.1.1d&guideline=5.6
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
|
||||
ssl_certificate /data/dehydrated/certs/${LETSENCRYPT_DOMAIN}/fullchain.pem;
|
||||
ssl_certificate_key /data/dehydrated/certs/${LETSENCRYPT_DOMAIN}/privkey.pem;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
|
||||
ssl_session_tickets off;
|
||||
|
||||
# modern configuration
|
||||
ssl_protocols TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
|
||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||
|
||||
# OCSP stapling
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
# verify chain of trust of OCSP response using Root CA and Intermediate certs
|
||||
ssl_trusted_certificate /data/dehydrated/certs/${LETSENCRYPT_DOMAIN}/fullchain.pem;
|
||||
|
||||
# replace with the IP address of your resolver
|
||||
resolver 85.88.23.13 85.88.23.14 85.88.1.92;
|
||||
|
||||
keepalive_timeout 70;
|
||||
sendfile on;
|
||||
client_max_body_size 80m;
|
||||
|
||||
location /.well-known/keybase.txt {
|
||||
root /var/www/html;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri @proxy;
|
||||
}
|
||||
|
||||
location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
try_files $uri @proxy;
|
||||
}
|
||||
|
||||
location /sw.js {
|
||||
add_header Cache-Control "public, max-age=0";
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
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://${UPSTREAM_NAME};
|
||||
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";
|
||||
|
||||
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;
|
||||
}
|
77
mastodon/nginx/nginx-files.conf
Normal file
77
mastodon/nginx/nginx-files.conf
Normal file
|
@ -0,0 +1,77 @@
|
|||
server {
|
||||
listen 443 ssl http2;
|
||||
|
||||
server_name files.pub.solar;
|
||||
|
||||
ssl_certificate /data/dehydrated/certs/files.pub.solar/fullchain.pem;
|
||||
ssl_certificate_key /data/dehydrated/certs/files.pub.solar/privkey.pem;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
|
||||
ssl_session_tickets off;
|
||||
|
||||
# modern configuration
|
||||
ssl_protocols TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
|
||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||
|
||||
# OCSP stapling
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
# verify chain of trust of OCSP response using Root CA and Intermediate certs
|
||||
ssl_trusted_certificate /data/dehydrated/certs/files.pub.solar/fullchain.pem;
|
||||
|
||||
root /var/www/files;
|
||||
|
||||
keepalive_timeout 30;
|
||||
|
||||
location = / {
|
||||
index index.html;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri @s3;
|
||||
}
|
||||
|
||||
set $s3_backend 'https://link.tardigradeshare.io/s/jw24ad6l4a6zxsnd32cmf5hp5nsq/pub-solar-mastodon';
|
||||
|
||||
location @s3 {
|
||||
limit_except GET {
|
||||
deny all;
|
||||
}
|
||||
|
||||
resolver 85.88.23.13 85.88.23.14 85.88.1.92;
|
||||
|
||||
|
||||
proxy_set_header Host link.tardigradeshare.io;
|
||||
proxy_set_header Connection '';
|
||||
proxy_set_header Authorization '';
|
||||
proxy_hide_header content-disposition;
|
||||
proxy_hide_header Set-Cookie;
|
||||
proxy_hide_header 'Access-Control-Allow-Origin';
|
||||
proxy_hide_header 'Access-Control-Allow-Methods';
|
||||
proxy_hide_header 'Access-Control-Allow-Headers';
|
||||
proxy_hide_header x-amz-id-2;
|
||||
proxy_hide_header x-amz-request-id;
|
||||
proxy_hide_header x-amz-meta-server-side-encryption;
|
||||
proxy_hide_header x-amz-server-side-encryption;
|
||||
proxy_hide_header x-amz-bucket-region;
|
||||
proxy_hide_header x-amzn-requestid;
|
||||
proxy_ignore_headers Set-Cookie;
|
||||
proxy_pass $s3_backend$uri?download;
|
||||
proxy_intercept_errors off;
|
||||
|
||||
proxy_cache CACHE;
|
||||
proxy_cache_valid 200 48h;
|
||||
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
|
||||
proxy_cache_lock on;
|
||||
|
||||
expires 1y;
|
||||
add_header Cache-Control public;
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
add_header Content-Disposition 'inline';
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue