为什么要自建 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.socialhttps://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 上,你说的话是你,不用担心哪天账号没了、帖子没了、关注的人消失了。

如果你只是想找个替代品,用别人搭好实例就够了。但如果想真正掌控自己社交关系,自建是值得。

种下你的想法

在花园里留下一条评论,和这篇文章一起生长。

COMMENTS