如何在 Debian 12 上安装 Mastodon 社交网络
Mastodon 是一个免费、去中心化、开源的社交网络。它是作为 Twitter 的替代品而创建的。就像 Twitter 一样,人们可以互相关注、发布消息、图像和视频。但与 Twitter 不同的是,它的内容没有中央存储或权威机构。
相反,Mastodon 在数千个不同的服务器上运行,每个服务器都由社区的不同成员运行。在一台服务器上注册的用户可以轻松连接到另一网络上的用户,并跨实例相互关注。
任何人都可以安装他们的 Mastodon 服务器实例。本教程将教您如何使用 Docker 在 Debian 12 的服务器上设置 Mastodon 实例。 Docker 通过包含容器中所需的所有包和服务,使安装 Mastodon 变得容易。
先决条件
运行 Debian 12 且至少具有 2 个 CPU 核心和 2GB 内存的服务器。您将需要根据要求升级服务器。
具有 sudo 权限的非 root 用户。
指向您的服务器的完全限定域名 (FQDN)。出于我们的目的,我们将使用 mastodon.example.com
作为域名。
Mastodon 向用户发送电子邮件通知。我们建议您使用第 3 方事务性邮件服务,例如 Mailgun、SendGrid、Amazon SES 或 Sparkpost。本指南中的说明将使用 Amazon SES。
确保一切都已更新。
$ sudo apt update
安装基本实用程序包。其中一些可能已经安装。
$ sudo apt install curl wget nano software-properties-common dirmngr apt-transport-https ca-certificates lsb-release debian-archive-keyring gnupg2 ufw unzip -y
第 1 步 - 配置防火墙
第一步是配置防火墙。 Debian 默认带有 ufw(简单防火墙)。
检查防火墙是否正在运行。
$ sudo ufw status
您应该得到以下输出。
Status: inactive
允许 SSH 端口,以便防火墙在启用它时不会中断当前连接。
$ sudo ufw allow OpenSSH
还允许 HTTP 和 HTTPS 端口。
$ sudo ufw allow http
$ sudo ufw allow https
启用防火墙
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
再次检查防火墙的状态。
$ sudo ufw status
您应该看到类似的输出。
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
443 ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)
第 2 步 - 安装 Docker 和 Docker Compose
Debian 12 附带旧版本的 Docker。要安装最新版本,首先导入 Docker GPG 密钥。
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
创建 Docker 存储库文件。
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
更新系统存储库列表。
$ sudo apt update
安装最新版本的 Docker。
$ sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
验证它是否正在运行。
$ sudo systemctl status docker
? docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; preset: enabled)
Active: active (running) since Mon 2024-01-01 09:00:14 UTC; 17s ago
TriggeredBy: ? docker.socket
Docs: https://docs.docker.com
Main PID: 1839 (dockerd)
Tasks: 9
Memory: 27.6M
CPU: 598ms
CGroup: /system.slice/docker.service
??1839 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
默认情况下,Docker 需要 root 权限。如果您想避免每次运行 docker
命令时都使用 sudo
,请将您的用户名添加到 docker
组中。
$ sudo usermod -aG docker $(whoami)
您需要注销服务器并以同一用户身份重新登录才能启用此更改或使用以下命令。
$ su - ${USER}
确认您的用户已添加到 Docker 组。
$ groups
navjot sudo users docker
第 3 步 - 准备安装
Elasticsearch 的 mmap 计数的默认限制非常低。运行以下命令检查默认值。
$ sudo sysctl vm.max_map_count
您将得到以下输出。
vm.max_map_count = 65530
使用以下命令增加该值。
$ echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/90-max_map_count.conf
vm.max_map_count=262144
$ sudo sysctl --load /etc/sysctl.d/90-max_map_count.conf
vm.max_map_count=262144
第 4 步 - 安装 Mastodon
创建目录并设置所有权
为 Mastodon 和相关服务创建目录。
$ sudo mkdir -p /opt/mastodon/database/{postgresql,pgbackups,redis,elasticsearch}
$ sudo mkdir -p /opt/mastodon/web/{public,system}
$ sudo mkdir -p /opt/mastodon/branding
为 Elasticsearch、Web 和备份目录设置正确的所有权。
$ sudo chown 991:991 /opt/mastodon/web/{public,system}
$ sudo chown 1000 /opt/mastodon/database/elasticsearch
$ sudo chown 70:70 /opt/mastodon/database/pgbackups
切换到 Mastodon 目录。
$ cd /opt/mastodon
创建环境和docker compose文件
为应用程序和数据库创建环境文件。
$ sudo touch application.env database.env
创建并打开 Docker compose 文件进行编辑。
$ sudo nano docker-compose.yml
将以下代码粘贴到其中。
services:
postgresql:
image: postgres:16-alpine
env_file: database.env
restart: always
shm_size: 512mb
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'postgres']
volumes:
- postgresql:/var/lib/postgresql/data
- pgbackups:/backups
networks:
- internal_network
redis:
image: redis:7-alpine
restart: always
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
volumes:
- redis:/data
networks:
- internal_network
redis-volatile:
image: redis:7-alpine
restart: always
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
networks:
- internal_network
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.16
restart: always
env_file: database.env
environment:
- cluster.name=elasticsearch-mastodon
- discovery.type=single-node
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- ingest.geoip.downloader.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m -Des.enforce.bootstrap.checks=true"
- xpack.license.self_generated.type=basic
- xpack.watcher.enabled=false
- xpack.graph.enabled=false
- xpack.ml.enabled=false
- thread_pool.write.queue_size=1000
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
healthcheck:
test: ["CMD-SHELL", "nc -z elasticsearch 9200"]
volumes:
- elasticsearch:/usr/share/elasticsearch/data
networks:
- internal_network
ports:
- '127.0.0.1:9200:9200'
website:
image: tootsuite/mastodon:v4.2.3
env_file:
- application.env
- database.env
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
restart: always
depends_on:
- postgresql
- redis
- redis-volatile
- elasticsearch
ports:
- '127.0.0.1:3000:3000'
networks:
- internal_network
- external_network
healthcheck:
test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
volumes:
- uploads:/mastodon/public/system
shell:
image: tootsuite/mastodon:v4.2.3
env_file:
- application.env
- database.env
command: /bin/bash
restart: "no"
networks:
- internal_network
- external_network
volumes:
- uploads:/mastodon/public/system
- static:/static
streaming:
image: tootsuite/mastodon:v4.2.3
env_file:
- application.env
- database.env
command: node ./streaming
restart: always
depends_on:
- postgresql
- redis
- redis-volatile
- elasticsearch
ports:
- '127.0.0.1:4000:4000'
networks:
- internal_network
- external_network
healthcheck:
test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']
sidekiq:
image: tootsuite/mastodon:v4.2.3
env_file:
- application.env
- database.env
command: bundle exec sidekiq
restart: always
depends_on:
- postgresql
- redis
- redis-volatile
- website
networks:
- internal_network
- external_network
healthcheck:
test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]
volumes:
- uploads:/mastodon/public/system
networks:
external_network:
internal_network:
internal: true
volumes:
postgresql:
driver_opts:
type: none
device: /opt/mastodon/database/postgresql
o: bind
pgbackups:
driver_opts:
type: none
device: /opt/mastodon/database/pgbackups
o: bind
redis:
driver_opts:
type: none
device: /opt/mastodon/database/redis
o: bind
elasticsearch:
driver_opts:
type: none
device: /opt/mastodon/database/elasticsearch
o: bind
uploads:
driver_opts:
type: none
device: /opt/mastodon/web/system
o: bind
static:
driver_opts:
type: none
device: /opt/mastodon/web/public
o: bind
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
在撰写本教程时,Mastodon 的最新可用版本是 v4.2.3。检查 Mastodon GitHub Releases 页面并适当调整 Docker compose 文件中的版本。我们还使用最新版本的 PostgreSQL 和 Redis。您可以根据您的要求调整它们。我们目前使用的是 Elasticsearch 7.17.16。
创建应用程序机密
下一步是创建应用程序机密值。
通过运行以下命令两次来生成 SECRET_KEY_BASE
和 OTP_SECRET
值。第一次将需要一些时间,因为它会拉取图像。
$ docker compose run --rm shell bundle exec rake secret
349623c049e3b856f6848638146e459857862b908ed387bbef372a30d9bd7c604fc4de5338addc86bd369a99d38ef59bacfa28e02a1750f7094ea6ede05457b8
您还可以使用 openssl
实用程序来实现相同的目的。
$ openssl rand -hex 64
ae01cf7d4dfae0182461a1345f1f2bf159658a27339ffafe7d356bef9ee8d4fa015ab2e72a608f236bd8e3f9b2af2dcb1d55ee5c8e43646959112c7da5582f4b
使用以下命令生成 VAPID_PRIVATE_KEY
和 VAPID_PUBLIC_KEY
值。
$ docker compose run --rm shell bundle exec rake mastodon:webpush:generate_vapid_key
您将得到类似的输出。
VAPID_PRIVATE_KEY=u2qsCs5JdmdmMLnUuU0sgmFGvZedteJz-lFB_xF4_ac=
VAPID_PUBLIC_KEY=BJXjE2hIXvFpo6dnHqyf1i-2PcP-cBoL95UCmhhxwlAgtFw_vnrYp4GBneR7_cmI9LZUYjHFh-TBAPSb9WTqH9A=
使用 openssl
实用程序生成 PostgreSQL 和 Elasticsearch 密码。
$ openssl rand -hex 15
dd0bd7a95960623ed8e084a1fb7d5c
$ openssl rand -hex 15
0fb52834c991b5e296c647166185bc
乳齿象环境文件
打开 application.env
文件进行编辑。
$ sudo nano application.env
将以下行粘贴到其中。
# environment
RAILS_ENV=production
NODE_ENV=production
# domain
LOCAL_DOMAIN=mastodon.example.com
# redirect to the first profile
SINGLE_USER_MODE=false
# 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=email-smtp.us-west-2.amazonaws.com
SMTP_PORT=587
SMTP_LOGIN=AKIA3FIG4NVFB343PZEI
SMTP_PASSWORD=AZX01WiA6JGbeZ2pwVXnyC9DhEa2nKcmXSu/zbLp
[email
# secrets
SECRET_KEY_BASE=349623c049e3b856f6848638146e459857862b908ed387bbef372a30d9bd7c604fc4de5338addc86bd369a99d38ef59bacfa28e02a1750f7094ea6ede05457b8
OTP_SECRET=ae01cf7d4dfae0182461a1345f1f2bf159658a27339ffafe7d356bef9ee8d4fa015ab2e72a608f236bd8e3f9b2af2dcb1d55ee5c8e43646959112c7da5582f4b
# Changing VAPID keys will break push notifications
VAPID_PRIVATE_KEY=oNe_4BEL7Tpc3iV8eMtLegfLwrzA7ifitGJ2YOg3dUM=
VAPID_PUBLIC_KEY=BKBgmB90vIrJg6Ifq3cCHixalyPghJDkui9vm1wscxvAfNNoAQL0KinoxRTLDp0UFlGK_ahUG2n4W2n4x9AUAWM=
# IP and session retention
# -----------------------
# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml
# to be less than daily if you lower IP_RETENTION_PERIOD below two days (172800).
# -----------------------
IP_RETENTION_PERIOD=2592000
SESSION_RETENTION_PERIOD=2592000
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
我们已启用 Amazon SES 邮件服务。如果不需要,可以删除该部分。默认情况下,Mastodon 保留 IP 地址 1 年,但我们已将其更改为 30 天(2592000 秒)。您可以根据您的要求更改它。确保保存超过 2 天,否则,您将需要进行更多修改,这超出了我们教程的范围。
打开database.env
文件进行编辑。
$ sudo nano database.env
将以下行粘贴到其中。
# postgresql configuration
POSTGRES_USER=mastodon
POSTGRES_DB=mastodon
POSTGRES_PASSWORD=0fb52834c991b5e296c647166185bc
PGPASSWORD=0fb52834c991b5e296c647166185bc
PGPORT=5432
PGHOST=postgresql
PGUSER=mastodon
# pgbouncer configuration
#POOL_MODE=transaction
#ADMIN_USERS=postgres,mastodon
#DATABASE_URL="postgres://mastodon:0fb52834c991b5e296c647166185bc@postgresql:5432/mastodon"
# elasticsearch
ELASTIC_PASSWORD=dd0bd7a95960623ed8e084a1fb7d5c
# mastodon database configuration
#DB_HOST=pgbouncer
DB_HOST=postgresql
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=0fb52834c991b5e296c647166185bc
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=dd0bd7a95960623ed8e084a1fb7d5c
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
准备乳齿象
准备好静态文件以供 Nginx 提供服务。这一步需要一些时间,因为 Docker 会第一次拉取所有镜像。
$ docker compose run --rm shell bash -c "cp -r /opt/mastodon/public/* /static/"
调出数据层。
$ docker compose up -d postgresql redis redis-volatile
检查容器的状态。
$ watch docker compose ps
等待运行(健康)
,然后按Ctrl + C
并使用以下命令初始化数据库。
$ docker compose run --rm shell bundle exec rake db:setup
如果您收到有关数据库 mastodon
已存在的错误,请运行以下命令。
$ docker compose run --rm shell bundle exec rake db:migrate
第 5 步 - 安装 Nginx
Debian 12 附带旧版本的 Nginx。要安装最新版本,您需要下载官方 Nginx 存储库。
导入 Nginx 的签名密钥。
$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
添加 Nginx 主线版本的存储库。
$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
更新系统存储库。
$ sudo apt update
安装 Nginx。
$ sudo apt install nginx
验证安装。在 Debian 系统上,您需要 sudo 来运行以下命令。
$ sudo nginx -v
nginx version: nginx/1.25.3
启动 Nginx 服务器。
$ sudo systemctl start nginx
检查服务器的状态。
$ sudo systemctl status nginx
? nginx.service - nginx - high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2024-01-01 10:17:38 UTC; 4s ago
Docs: https://nginx.org/en/docs/
Process: 8972 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
Main PID: 8973 (nginx)
Tasks: 3 (limit: 4637)
Memory: 2.9M
CPU: 17ms
CGroup: /system.slice/nginx.service
??8973 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
??8974 "nginx: worker process"
??8975 "nginx: worker process"
Jan 01 10:17:38 mastodon systemd[1]: Starting nginx.service - nginx - high performance web server...
Jan 01 10:17:38 mastodon systemd[1]: Started nginx.service - nginx - high performance web server.
第 6 步 - 安装 SSL
我们需要安装 Certbot 来生成 SSL 证书。您可以使用 Debian 的存储库安装 Certbot,也可以使用 Snapd 工具获取最新版本。我们将使用 Snapd 版本。
Debian 12 并未安装 Snapd。安装 Snapd 软件包。
$ sudo apt install snapd
运行以下命令以确保您的 Snapd 版本是最新的。确保您的 Snapd 版本是最新的。
$ sudo snap install core
$ sudo snap refresh core
安装证书机器人。
$ sudo snap install --classic certbot
使用以下命令通过创建指向 /usr/bin
目录的符号链接来确保 Certbot 命令运行。
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
验证安装。
$ certbot --version
certbot 2.8.0
运行以下命令生成 SSL 证书。
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email -d mastodon.example.com
上述命令会将证书下载到服务器上的 /etc/letsencrypt/live/mastodon.example.com
目录中。
生成 Diffie-Hellman 组证书。
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
检查 Certbot 续订调度程序服务。
$ systemctl list-timers
您会发现 snap.certbot.renew.service
是计划运行的服务之一。
NEXT LEFT LAST PASSED UNIT ACTIVATES
-----------------------------------------------------------------------------------------------------------------------------------------
Mon 2024-01-01 20:03:52 UTC 9h left Mon 2023-12-11 21:56:24 UTC 2 weeks 6 days ago apt-daily.timer apt-daily.service
Mon 2024-01-01 21:06:00 UTC 10h left - - snap.certbot.renew.timersnap.certbot.renew.service
Tue 2024-01-02 00:00:00 UTC 13h left - - dpkg-db-backup.timer dpkg-db-backup.service
对该过程进行一次演练,以检查 SSL 续订是否正常工作。
$ sudo certbot renew --dry-run
如果没有看到任何错误,则一切都已准备就绪。您的证书将自动更新。
第 7 步 - 配置 Nginx
打开文件 /etc/nginx/nginx.conf
进行编辑。
$ sudo nano /etc/nginx/nginx.conf
在 include /etc/nginx/conf.d/*.conf;
行之前添加以下行。
server_names_hash_bucket_size 64;
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
创建并打开文件 /etc/nginx/conf.d/mastodon.conf
进行编辑。
$ sudo nano /etc/nginx/conf.d/mastodon.conf
将以下代码粘贴到其中。
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 default_server;
server_name mastodon.example.com;
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl;
server_name mastodon.example.com;
access_log /var/log/nginx/mastodon.access.log;
error_log /var/log/nginx/mastodon.error.log;
http2 on; # Enable HTTP/2 - works only on Nginx 1.25.1+
ssl_certificate /etc/letsencrypt/live/mastodon.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mastodon.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/mastodon.example.com/chain.pem;
ssl_session_timeout 1d;
# Enable TLS versions (TLSv1.3 is required upcoming HTTP/3 QUIC).
ssl_protocols TLSv1.2 TLSv1.3;
# Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to
# prevent replay attacks.
#
# @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
ssl_early_data on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
keepalive_timeout 70;
sendfile on;
client_max_body_size 80m;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
add_header X-Early-Data $tls1_3_early_data;
root /opt/mastodon/web/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;
}
# This block is useful for debugging TLS v1.3. Please feel free to remove this
# and use the `$ssl_early_data` variable exposed by NGINX directly should you
# wish to do so.
map $ssl_early_data $tls1_3_early_data {
"~." $ssl_early_data;
default "";
}
完成后,按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
验证 Nginx 配置文件语法。
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新启动 Nginx 服务器。
$ sudo systemctl restart nginx
第 8 步 - 启动 Mastodon
Tootctl CLI 工具
Tootctl CLI 工具用于在 Mastodon 上执行管理任务。我们需要使其能够在主机 shell 上访问。
创建文件 /usr/local/bin/tootctl
并打开它进行编辑。
$ sudo nano /usr/local/bin/tootctl
将以下代码粘贴到其中。
#!/bin/bash
docker compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl "$@"
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
授予文件可执行权限。
$ sudo chmod +x /usr/local/bin/tootctl
乳齿象服务文件
您可以使用 Docker compose 命令启动 Mastodon 容器,但通过 systemd 单元文件更容易。
创建并打开 Mastodon 服务文件进行编辑。
$ sudo nano /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
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
重新加载系统守护进程以启动服务文件。
$ sudo systemctl daemon-reload
启用并启动 Mastodon 服务。
$ sudo systemctl enable --now mastodon.service
检查 Docker 容器的状态。
$ watch docker compose -f /opt/mastodon/docker-compose.yml ps
一旦容器的状态更改为正在运行(正常)
,请按Ctrl + C退出屏幕。
为 Mastodon 创建管理员用户并记下提供的密码。
$ tootctl accounts create navjot --email [email --confirmed --role Owner
OK
New password: 1338afbe1b4e06e823b6625da80cb537
如果要关闭用户注册,请使用以下命令。
$ tootctl settings registrations close
要再次打开注册,请发出以下命令。
$ tootctl settings registrations open
初始化搜索
在创建和填充 Elasticsearch 索引之前,您需要发出嘟嘟声。发出嘟嘟声后,发出以下命令。
$ tootctl search deploy
您可能会收到以下错误。
/opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/progress.rb:76:in `total=': You can't set the item's total value to less than the current progress. (ProgressBar::InvalidProgressError)
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/base.rb:178:in `block in update_progress'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/output.rb:43:in `with_refresh'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/base.rb:177:in `update_progress'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/ruby-progressbar-1.11.0/lib/ruby-progressbar/base.rb:101:in `total='
from /opt/mastodon/lib/mastodon/search_cli.rb:67:in `deploy'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/invocation.rb:116:in `invoke'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor.rb:243:in `block in subcommand'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
from /opt/mastodon/vendor/bundle/ruby/3.0.0/gems/thor-1.2.1/lib/thor/base.rb:485:in `start'
from /opt/mastodon/bin/tootctl:8:in `<main>'
在这种情况下,进入网站容器 shell。
$ docker exec -it mastodon-website-1 /bin/bash
运行以下命令。
$ sed -E '/progress.total = /d' -i lib/mastodon/search_cli.rb
退出容器外壳。
$ exit
再次运行 Elasticsearch 部署命令。有时该命令可能稍后才起作用。这是 Mastodon 持续存在的问题,因此目前还没有明确的解决方案。
$ tootctl search deploy
Done! 1/?? |-=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=| ETA: ??:??:?? (0 docs/s)
Indexed 1 records, de-indexed 0
额外的帮手服务
让我们创建另一个服务来删除下载的媒体文件。
创建并打开 Mastodon 媒体删除服务进行编辑。
$ sudo nano /etc/systemd/system/mastodon-media-remove.service
将以下代码粘贴到其中。
[Unit]
Description=Mastodon - media remove service
Wants=mastodon-media-remove.timer
[Service]
Type=oneshot
StandardError=null
StandardOutput=null
WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl media remove
[Install]
WantedBy=multi-user.target
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
如果您想安排媒体删除,可以为其设置计时器服务。
$ sudo nano /etc/systemd/system/mastodon-media-remove.timer
粘贴以下代码。
[Unit]
Description=Schedule a media remove every week
[Timer]
Persistent=true
OnCalendar=Sat *-*-* 00:00:00
Unit=mastodon-media-remove.service
[Install]
WantedBy=timers.target
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
您可以设置另一个服务来删除使用 OpenGraph 标签生成的丰富预览卡。
$ sudo nano /etc/systemd/system/mastodon-preview_cards-remove.service
粘贴以下代码。
[Unit]
Description=Mastodon - preview cards remove service
Wants=mastodon-preview_cards-remove.timer
[Service]
Type=oneshot
StandardError=null
StandardOutput=null
WorkingDirectory=/opt/mastodon
ExecStart=/usr/bin/docker compose -f /opt/mastodon/docker-compose.yml run --rm shell tootctl preview_cards remove
[Install]
WantedBy=multi-user.target
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
设置相应的定时服务。
$ sudo nano /etc/systemd/system/mastodon-preview_cards-remove.timer
粘贴以下代码。
[Unit]
Description=Schedule a preview cards remove every week
[Timer]
Persistent=true
OnCalendar=Sat *-*-* 00:00:00
Unit=mastodon-preview_cards-remove.service
[Install]
WantedBy=timers.target
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
重新加载系统守护进程。
$ sudo systemctl daemon-reload
启用并启动计时器。
$ sudo systemctl enable --now mastodon-preview_cards-remove.timer
$ sudo systemctl enable --now mastodon-media-remove.timer
列出所有计时器以检查 Mastodon 服务的时间表。
$ systemctl list-timers
.....
Sat 2024-01-06 00:00:00 UTC 4 days left - - mastodon-media-remove.timer mastodon-media-remove.service
Sat 2024-01-06 00:00:00 UTC 4 days left - - mastodon-preview_cards-remove.timer mastodon-preview_cards-remove.service
访问乳齿象
访问 URL https://mastodon.example.com
来访问您的实例,您将看到类似的页面。
在上面的屏幕截图中,您可以看到有 0 个用户。这是因为我们还没有登录。即使您创建了管理员帐户,它也不会在第一次运行时显示在主页上。为此,请登录您的实例,您将进入以下页面。
单击右侧边栏中的首选项选项以访问设置。从那里,单击左侧菜单中的管理选项以访问 Mastodon 的管理面板。
单击左侧边栏中的服务器设置选项。
在这里,填写您的联系人用户名和企业电子邮件,这些信息现在将反映在您服务器的主页上。还可以填写各种其他信息,包括服务器描述、徽标和服务器规则,以自定义您的 Mastodon 实例。
第 9 步 - 乳齿象维护
要查看 Mastodon 实例的性能和日志,请访问 https://mastodon.example.com/sidekiq/
。
您可以在此处查看与 Mastodon 实例相关的各种进程和计划任务的列表。您还可以在死亡或重试部分下检查失败的任务。它还会告诉您实例的内存使用情况。
您可以从 https://mastodon.example.com/pghero/
检查实例数据库的运行状况。
您可以执行数据库维护、运行 SQL 查询以及删除未使用的索引。要启用查询统计,请点击上面页面上的启用按钮,您将得到以下信息。
切换到root用户。
$ sudo -i su
切换到 /opt/mastodon/database/postgresql
目录。
$ cd /opt/mastodon/database/postgresql
打开 postgresql.conf 文件。
$ nano postgresql.conf
找到行 #shared_preload_libraries='' # (change require restart)
并将其替换为以下内容。
shared_preload_libraries = 'pg_stat_statements'
在文件末尾添加以下行。
pg_stat_statements.track = all
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
重新启动 Mastodon 容器。
$ systemctl restart mastodon.service
退出根 shell。
$ exit
如果你检查数据库健康页面,你可以看到现在是否有任何缓慢的查询。
注意:您还可以从首选项菜单启动 PgHero 和 Sidekiq URL。
如果您的站点由于某种原因无法加载,您可以检查 Docker 生成的日志。
$ docker logs <container-name>
第10步 - 备份乳齿象
我们将使用名为 Restic 的第三方工具来备份 Mastodon。使用 Restic 进行备份的第一步是将所有文件和目录添加到存储库列表中。
创建并打开存储库列表文件进行编辑。
$ sudo nano /opt/mastodon/backup-files
将以下行粘贴到其中。
/etc/nginx
/etc/letsencrypt
/etc/systemd/system
/root
/opt/mastodon/database/pgbackups
/opt/mastodon/*.env
/opt/mastodon/docker-compose.yml
/opt/mastodon/branding
/opt/mastodon/database/redis
/opt/mastodon/web/system
/opt/mastodon/backup-files
/opt/mastodon/mastodon-backup
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
安装 Restic。
$ sudo apt install restic
创建备份存储库并创建初始备份。我们正在将数据备份到 S3 服务。
$ restic -r s3:https://$SERVER:$PORT/mybucket init
$ restic -r s3:https://$SERVER:$PORT/mybucket backup $(cat /opt/mastodon/backup-files) --exclude /opt/mastodon/database/postgresql
创建 Mastodon 备份服务计时器并打开它进行编辑。
$ sudo nano /etc/systemd/system/mastodon-backup.timer
将以下代码粘贴到其中。
[Unit]
Description=Schedule a mastodon backup every hour
[Timer]
Persistent=true
OnCalendar=*:00:00
Unit=mastodon-backup.service
[Install]
WantedBy=timers.target
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
创建 Mastodon 备份服务文件并打开它进行编辑。
$ sudo nano /etc/systemd/system/mastodon-backup.service
将以下代码粘贴到其中。
[Unit]
Description=Mastodon - backup service
# Without this, they can run at the same time and race to docker compose,
# double-creating networks and failing due to ambiguous network definition
# requiring `docker network prune` and restarting
After=mastodon.service
[Service]
Type=oneshot
StandardError=file:/var/log/mastodon-backup.err
StandardOutput=file:/var/log/mastodon-backup.log
WorkingDirectory=/opt/mastodon
ExecStart=/bin/bash /opt/mastodon/mastodon-backup
[Install]
WantedBy=multi-user.target
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
接下来,创建并打开 /opt/mastodon/mastodon-backup
文件进行编辑。这包含实际的备份命令。
$ sudo nano /opt/mastodon/mastodon-backup
将以下代码粘贴到其中。
#!/bin/bash
set -e
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
SERVER=
PORT=
RESTIC_PASSWORD_FILE=/root/restic-pasword
docker compose -f /opt/mastodon/docker-compose.yml run --rm postgresql sh -c "pg_dump -Fp mastodon | gzip > /backups/dump.sql.gz"
restic -r s3:https://$SERVER:$PORT/mybucket --cache-dir=/root backup $(cat /opt/mastodon/backup-files) --exclude /opt/mastodon/database/postgresql
restic -r s3:https://$SERVER:$PORT/mybucket --cache-dir=/root forget --prune --keep-hourly 24 --keep-daily 7 --keep-monthly 3
按 Ctrl + X 并在出现提示时输入 Y 来保存文件。
为备份脚本授予可执行权限。
$ sudo chmod +x /opt/mastodon/mastodon-backup
重新加载服务守护进程并启动备份服务和计时器。
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now mastodon-backup.service
$ sudo systemctl enable --now mastodon-backup.timer
使用以下命令确认每小时备份正在进行并可访问。
$ restic -r s3:https://$SERVER:$PORT/mybucket snapshots
$ restic -r s3:https://$SERVER:$PORT/mybucket mount /mnt
第 11 步 - 升级 Mastodon
升级 Mastodon 需要几个步骤。首先,切换到目录。
$ cd /opt/mastodon
拉取 Mastodon 的最新容器镜像。
$ docker compose pull
如果需要,可以对 docker-compose.yml 进行任何更改。
执行所有数据库迁移。
$ docker compose run --rm shell bundle exec rake db:migrate
更新静态文件的副本。
$ docker compose run --rm shell bash -c "cp -r /opt/mastodon/public/* /static/"
重新启动 Mastodon 容器。
$ sudo systemctl restart mastodon.service
上述说明是通用更新说明。请务必检查 Mastodon 的 GitHub 发布页面,查找版本之间的任何特定更新任务和命令,以确保一切顺利进行。
结论
关于在 Debian 12 服务器上使用 Docker 安装 Mastodon 社交网络的教程到此结束。如果您有任何疑问,请在下面的评论中发表。