为什么要自建 Mastodon
Twitter 改名叫 X 之后,算法越改越离谱,付费蓝V横行,言论边界越来越模糊。很多人迁移到了 Mastodon,但大多数人是加入别人实例。
问题是:别人的实例,规则是别人定,哪天实例管理员跑路了、历史帖子全没了这种事并不少见。
所以,如果你在乎数据主权、自主权和长期稳定,自己搭一个实例是最好选择。
Mastodon 是什么
Mastodon 是一个去中心化社交网络软件,运行在 ActivityPub 协议上—这也是 W3C 制定的去中心化社交标准之一。
它的结构和邮件很像:
- 你注册在
mastodon.example.com,我叫you@example.org - 我能看到你帖子,你能看我
- 你可以关注我,不用迁移账号,不用重新开始
- 不同实例之间可以自由通信,这就是「联邦宇宙」(FediVerse)
每个 Mastodon 实例是独立,有自己规则、主题和管理员。你选实例就是在选社区。
官方客户端 vs 自托管
Mastodon 有官方托管服务(mastodon.social),免费注册,但功能和自由度受限。
自托管优势:
- 数据完全归你,备份、迁移自己说了算
- 可以定制实例规则和审核政策
- 可以安装非官方插件
- 适合小圈子私密社交
劣势:
- 需要维护,有技术门槛
- 如果实例只有你一个人,社交面会窄一些
- 需要处理实例其他大实例屏蔽问题
环境要求
- 一台 Linux 服务器(Ubuntu 22.04 或 Debian 12)
- 至少 2GB 内存(建议 4GB)
- 至少 20GB 存储空间(帖子、媒体文件会持续增长)
- 域名
- Docker 和 Docker Compose
安装 Docker
如果服务器上没有 Docker,先装一下:
apt update && apt install -y docker.io docker-compose
systemctl enable --now docker
下载官方配置
Mastodon 官方提供了 Docker 部署脚本,最省事办法是用这个:
apt install -y git
git clone https://github.com/mastodon/mastodon.git
cd mastodon
git checkout v4.3.0 # 建议锁定一个稳定版本
生产环境不要用 latest 分支,版本号太飘。
配置环境变量
Mastodon 的配置通过 .env 文件管理。官方给了一个模板:
cp .env.production.sample .env
然后编辑 .env,以下几个字段必须改:
域名
LOCAL_DOMAIN=mastodon.example.com
WEB_DOMAIN=mastodon.example.com
PostgreSQL 密码
DB_PASS=这里写一个强密码
Redis 密码
REDIS_PASSWORD=这里也写一个强密码
SMTP 邮件配置(重要)
Mastodon 需要邮件服务发送验证邮件、密码重置等。没有邮件,注册用户收不到确认码,实例就是废。
用 Mailgun、AWS SES 或者自建 SMTP 都行。这里以 Mailgun 为例:
SMTP_SERVER=smtp.mailgun.org
SMTP_PORT=587
SMTP_LOGIN=postmaster@yourdomain.mailgun.org
SMTP_PASSWORD=your-mailgun-api-key
SMTP_FROM_ADDRESS=notifications@mastodon.example.com
申请 Mailgun 账号后,把 API Key 填进 SMTP_PASSWORD,发送域名配好,测试一下能通。
生成密钥
Mastodon 需要几个密钥来保证安全:
docker compose run --rm web bundle exec rake secret
执行一次,复制输出字符串,填入 SECRET_KEY_BASE。
再执行一次,填入 OTP_SECRET。
再执行一次,填入 VAPID_PRIVATE_KEY。
然后生成公钥:
docker compose run --rm web bundle exec rake mastodon:webpush:generate_vapid_key
会输出公钥和私钥,私钥填 VAPID_PRIVATE_KEY,公钥填 VAPID_PUBLIC_KEY。
修改 docker-compose.yml
官方 docker-compose 模板适合单机使用,一般不用大改。但有两个地方可以优化:
调整媒体文件存储策略
Mastodon 会把图片、视频、音频都存在本地。如果流量大,磁盘空间会快速增长。可以用对象存储( S3 兼容)来缓解:
# 在 .env 中添加
S3_ENABLED=true
S3_BUCKET=mastodon-media
S3_REGION=us-east-1
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
S3_HOSTNAME=s3.us-east-1.amazonaws.com
国内可以用 Cloudflare R2 或腾讯云 COS,协议兼容 S3。
限制资源使用
如果不希望媒体处理进程把服务器资源吃满,可以限制并发数:
SIDEKIQ_CONCURRENCY=10
4G 内存的服务器,10 个并发基本够了。
初始化数据库
配置完成后,运行数据库迁移:
docker compose run --rm web bundle exec rails db:migrate
预编译资源文件(CSS、JS):
docker compose run --rm web bundle exec rails assets:precompile
配置 Nginx 反向代理
Mastodon 自带 Puma 作为 Web 服务器,但不建议直接暴露到公网。前面加一层 Nginx 更安全、更稳定。
upstream mastodon {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name mastodon.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name mastodon.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
keepalive_timeout 70;
client_max_body_size 100m;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
location / {
proxy_pass http://mastodon;
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_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
}
location /api/v1/streaming {
proxy_pass http://mastodon;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
注意 /api/v1/streaming 这段是给实时推送(Timeline 实时更新)用的,必须加 Upgrade 头,否则刷不出新帖子。
申请 SSL 证书:
apt install -y certbot
certbot certonly --nginx -d mastodon.example.com
启动服务
docker compose up -d
检查各个容器状态:
docker compose ps
三个核心容器应该都是 Up 状态:
mastodon-web— 主应用mastodon-sidekiq— 后台任务队列(处理发嘟、邮件推送等)mastodon-streaming— 实时推送服务
创建管理员账号
docker compose run --rm web bin/tootctl accounts create admin \
--email admin@example.com \
--role Owner
然后设置密码:
docker compose run --rm web bin/tootctl accounts modify admin \
--set-password 你的新密码
登录后台管理界面:https://mastodon.example.com/admin
加入联邦宇宙
实例搭好了,怎么让别人来关注你?
几个常用入口:
https://joinmastodon.org/communities— 实例列表,可以在上面找到感兴趣社区https://fediverse.party/— 联邦宇宙探索工具- 加入实例目录,让你的实例其他人发现
申请加入 Federation 目录(instance directory)可以让更多人发现你实例。登录 https://instances.social 或 https://mastodon.instance.garden/ 提交申请。
日常维护
媒体文件清理
Mastodon 会缓存其他实例图片和视频,时间长了会占用大量空间。定期清理:
# 删除 7 天前的远程媒体缓存
docker compose run --rm web bin/tootctl media remove --days-older-than 7
# 删除未使用的头像和横幅
docker compose run --rm web bin/tootctl media remove-orphans
# 查看当前媒体占用
docker compose run --rm web bin/tootctl media usage
建议用 cron 每周跑一次清理。
更新 Mastodon
cd ~/mastodon
git fetch
git checkout 4.3.1 # 切到新版本
docker compose pull
docker compose run --rm web bundle exec rails db:migrate
docker compose run --rm web bundle exec rails assets:precompile
docker compose up -d
Mastodon 更新比较频繁,每次大版本升级看 Release Note,有 breaking change 要单独处理。
备份
备份三样东西就够了:
- PostgreSQL 数据:
docker compose exec postgres pg_dump -U postgres postgres > backup.sql .env文件(包含所有密钥)public/system/目录(用户上传媒体文件)
建议每天自动备份一次,保留 7 天的历史。
关于实例屏蔽
Mastodon 实例之间可以互相屏蔽(Block)。如果你实例一些主流实例屏蔽了,你发的嘟文他们看不到。
解决方法是:换一个好名声域名,或者加入一个已经在大实例白名单里实例作为联合托管。很多小实例选择托管在大实例子域名下,就是这个原因。
写在
自己搭 Mastodon 实例这几年,我最大感受是:互联网本来就不应该是这个样子。
几个人控制着全球几十亿人信息流,可以随意封号、删帖、改算法,这种集中化是不健康。去中心化一种对互联网原教旨回归—信息应该自由流动,数据应该属于用户。
Mastodon 不是完美。它没有 Twitter 当年的那种网络效应,用户体验在某些细节上也比不上商业产品。但至少,在 Mastodon 上,你说的话是你,不用担心哪天账号没了、帖子没了、关注的人消失了。
如果你只是想找个替代品,用别人搭好实例就够了。但如果想真正掌控自己社交关系,自建是值得。
种下你的想法
在花园里留下一条评论,和这篇文章一起生长。