惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
S
SegmentFault 最新的问题
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog
博客园 - 聂微东
小众软件
小众软件
J
Java Code Geeks
MyScale Blog
MyScale Blog
人人都是产品经理
人人都是产品经理
量子位
GbyAI
GbyAI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Apple Machine Learning Research
Apple Machine Learning Research
有赞技术团队
有赞技术团队
月光博客
月光博客
B
Blog RSS Feed
D
DataBreaches.Net
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cyberwarzone
Cyberwarzone
I
Intezer
The Register - Security
The Register - Security
博客园 - 【当耐特】
博客园 - 司徒正美
L
Lohrmann on Cybersecurity
U
Unit 42
N
News and Events Feed by Topic
S
Security Affairs
V
Visual Studio Blog
Y
Y Combinator Blog
Security Latest
Security Latest
Know Your Adversary
Know Your Adversary
Google DeepMind News
Google DeepMind News
大猫的无限游戏
大猫的无限游戏
S
Schneier on Security
P
Privacy International News Feed
TaoSecurity Blog
TaoSecurity Blog
Spread Privacy
Spread Privacy
G
Google Developers Blog
NISL@THU
NISL@THU
Project Zero
Project Zero
P
Palo Alto Networks Blog
Help Net Security
Help Net Security
宝玉的分享
宝玉的分享
Stack Overflow Blog
Stack Overflow Blog
S
Security @ Cisco Blogs
G
GRAHAM CLULEY
www.infosecurity-magazine.com
www.infosecurity-magazine.com

atpX

自建 S3 兼容对象存储服务 Garage 听风的歌 偶尔是深夜就好了 新玩具 AirPods Pro 3 公交车上的时间 从 WHOIS 到 RDAP 通过 WireGuard 访问 NFS 共享文件 自建音乐串流服务探索 我停止了探索 Fediverse 互联网背景噪音 我的数字生活降级 小城与确定性的墙 一只特立独行的猪 Fediverse 与社交 承认的勇气 mediaX - 轻量书影音记录管理工具 我的博客写作流程 网站新增 Misc 页面 擅长对线的鲍勃 在 Chroot 环境下使用 Rsync 同步 再见 JavaScript 当我玩博客时我在玩什么 为什么我的博客没有友链页面 小熊猫与大熊猫 (HDR 照片测试) 是时候为网站开启 HTTP/3 支持了吗 使用 AdGuard Home 搭建自用 DoH 服务 谈谈读书与消遣 2023 年终总结 西安两日游 从 AirPods「升级」到 EarPods 聊聊 iPhone 15 Pro 使用感受 能否将 TOTP 二次验证存放在密码管理器里 认识史蒂夫·乔布斯 与“锤哥”克里斯·海姆斯沃斯一起养生 逃离爆炸的信息 你想活出怎样的人生 重温《龙珠》动画 为什么关闭评论 从域名注册商到 DNS 服务,找到自己的组合 如何提高用户网页阅读体验 从 Typecho 迁移到 Hugo 个人博客的最终归宿是静态网站吗 我选择了放弃 jQuery 关于我的小破站折腾速度优化这件事 记一次家庭网络折腾 贴一些 SmokePing 记录 我的域名邮箱选择 不存在的语录 Typecho 评论验证插件 CaptchaPlus 谈谈写字这件事 新的网站 Logo 探索 曲线解决 Typecho 图片占位抖动问题 自建 vaultwarden / bitwarden_rs 密码管理器 使用 Plausible 自建网站流量统计分析工具 如何优雅地徒手剥开火腿肠 简单的集中隔离生活记录 新玩具 M2 MacBook Air 使用 acme.sh 申请 Google 公共证书 Docker 搭建去中心化的微博客平台 Misskey 搭建 Lsky Pro 兰空图床 折腾树莓派系统的一天 我的吉卜力之旅 使用 Uptime Kuma 自建服务器/网站在线率监控 Spartan Host Review - Best Hosting & Service Support Debian 下 Nginx 配合 Fail2Ban 减少恶意扫描和攻击 升级 Typecho 到最新开发版本 v1.2.0 Linux rm 命令详解 Debian 系统安装 Docker 教程 BandwagonHost - Reliable Blog and Business VPS Hosting 使用 Isso 为 Hugo/Hexo 等静态网站添加评论功能 推荐 5 款免费开源的网站流量分析统计工具 搭建 Shynet 网站流量统计分析工具 聊聊 DDoS 攻击那些事 Hugo 使用 Fancybox 实现图片灯箱/放大功能 从 Debian 10 升级到 Debian 11 教程 使用 Umami 自建网站流量统计分析工具 Linux 一次执行多个命令的 3 种方式 Typecho 修改永久链接后旧链接 301 跳转到新链接 从不同需求推荐几家稳定可靠的 VPS 服务商 Build EchoIP service with Docker 浅谈一下这些年折腾过的 VPS 单线复用解决一根网线同时 IPTV 和宽带问题 不完全吃灰的树莓派 开发一个自己的 Telegram Bot 使用 Nginx 实现 TCP 四层反向代理 画画真难 我读村上春树 使用 acme.sh 自动签发和更新证书 卡拉马佐夫式悲剧 安装 File Browser 轻量网盘工具 新玩具树莓派到手 Linux 定时自动备份数据到 OneDrive/Google Drive 记一次服务器崩溃 使用 rsync 同步文件 短信的消失 幻灭的艺术家 新玩具戴尔 S2721DGF 开箱 蝴蝶 用 Docker 整合 SeafilePro 搭建私人云盘 搭建自己的 kms 服务器
Docker 搭建去中心化的微博客平台 Mastodon
ATP · 2023-10-20 · via atpX
mastodon

自从老马被迫收购 Twitter 后,操作不断,改名 X 后更是在成为微信的路上一去不复返,虽然我只是偶尔上 Twitter 看看猫猫狗狗的萌图,但感觉老马迟早不给免费用户玩。于是未雨绸缪,搭建一个自己用。以前分享过使用 Docker 搭建去中心化的微博客平台 Misskey,这次又探索了一些类似平台,如 SoapboxMinds 以及基于 Misskey 的 firefish 等,迫于兼容性和文档考虑,最后还是准备使用 Mastodon

虽然网上有很多详细的教程,但大多是很早以前的了。我在搭建时可以说是充满曲折,这里也记录下来,希望对遇到了同样问题的朋友有帮助。

* 演示安装环境为 Debian 12,使用 root 用户,采用预编译的官方 Docker 镜像通过 Docker Compose 部署。

准备工作

Docker 和 Docker Compose 的安装与基础使用可以参考文章 Debian 系统安装 Docker 教程,不建议在中国大陆的服务器上部署 Mastodon。

在合适的路径下创建目录:

mkdir -p /home/mastodon && cd /home/mastodon

修改 docker-compose.yml 配置文件

wget https://raw.githubusercontent.com/mastodon/mastodon/main/docker-compose.yml
vim docker-compose.yml

注释掉所有镜像(web, streaming, sidekiq)的编译命令 build: .,并修改你想要的镜像版本,如 image: ghcr.io/mastodon/mastodon:v4.2.1,如果你想要最新版本则设置为 image: ghcr.io/mastodon/mastodon:latest。如果你需要全文搜索功能,则将 es 服务整块取消注释。

修改 .env.production 配置文件

这里有手动和交互式向导两种方式配置环境。但如果直接使用自带向导配置可能会在最后一步设置管理员账户的时候弹出一个 Redis 连接的错误:

ERROR -- : RedisCacheStore: read_entry failed, returned nil: Redis::CannotConnectError: Error connecting to Redis on localhost:6379 (Errno::ECONNREFUSED)

失败几次后发现可能的原因是在向导配置时没有写入参数导致找不到 Redis Host。有两个办法解决,先手动设置 REDIS_HOST 后再通过交互式命令配置,或者先不要设置管理员账户,之后用 tootctl 工具创建,这里我选择前者。

获取并修改 .env.production 配置文件:

wget https://raw.githubusercontent.com/mastodon/mastodon/main/.env.production.sample -O .env.production
vim .env.production

提前修改部分参数,如果在生产环境中,这里建议修改 DB_USER 设置一个 Mastodon 数据库专用用户(例如 mastodon)并设置 DB_PASS 密码,下例为了方便使用 Postgres 数据库的默认账户 postgres 进行演示:

# Federation
# ----------
# This identifies your server and cannot be changed safely later
# ----------
LOCAL_DOMAIN=<你的域名>

# Redis
# -----
REDIS_HOST=mastodon-redis-1
REDIS_PORT=6379
REDIS_URL=redis://@mastodon-redis-1:6379

# PostgreSQL
# ----------
DB_HOST=mastodon-db-1
DB_USER=postgres
DB_NAME=mastodon_production
DB_PASS=
DB_PORT=5432

...

配置 Mastodon

运行配置命令:

docker compose run --rm web bundle exec rake mastodon:setup

第一次拉取镜像时可能要花些时间(下载 1G+),耐心等待。这里注意在配置时数据库和 Redis 的相关参数和前面文件中的保持一致。

Mastodon 向导安装配置界面
Mastodon 向导安装配置界面。

最后一步完成后记下输出的管理员密码。并将上方打印的 .env.production 相应参数手动覆盖到文件中,主要是 SECRET_KEY_BASE, OTP_SECRET, VAPID_PRIVATE_KEY, VAPID_PUBLIC_KEY 这几个,完整的参数列表和作用请查阅文档

启动 Mastodon

修改 public 目录权限:

chown -R 991:991 public

启动 Mastodon 服务:

docker compose up -d

配置 Nginx

参照官方模版,修改文件中的域名和 root 路径,并将所有的 try_files $uri =404; 替换为 try_files $uri @proxy;

如果你幸运的话此时可以正常打开网站使用了。

但我到这里折腾了一个通宵也没成功,打开网站一片空白,所有静态资源无限报 net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK) 错误,以前在其它程序也遇到过,当时参考 Stack Overflow 上一篇帖子关闭 proxy_max_temp_file_size 缓存限制就好了。

server {
  ...
  ...
  gzip off;
  proxy_max_temp_file_size 0;
  location / {
    proxy_pass http://127.0.0.1:3000/;
    ...

然而这里却没有起作用,网上也搜不到相关的错误。几经放弃,最后又复盘了下,能建立链接但是资源请求失败,肯定是反代那里出了问题,终于在尝试取消反代缓存后居然成功进入了网站界面。

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;

    tcp_nodelay on;
}

接着又经过无数次探索和尝试,最后发现万恶之源在 proxy_cache_path 上面。根据 Nginx 文档的说法:

The directory for temporary files is set based on the use_temp_path parameter (1.7.10). If this parameter is omitted or set to the value on, the directory set by the proxy_temp_path directive for the given location will be used. If the value is set to off, temporary files will be put directly in the cache directory.

临时文件的目录默认为 on,Nginx 会先把要缓存的文件放到临时存储区,如果为 off,则会将缓存文件直接写入指定的 cache 文件中,而不使用 temp_path 指定的临时存储路径。

可能就是这里读取缓存文件时出现了玄学问题导致我一直没成功,在尝试添加 use_temp_path=off 后终于完美运行。

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g use_temp_path=off;
Mastodon 安装完成后的关于页面
Mastodon 安装完成后的实例关于页面(搭配 mastodon-bird-ui 主题)。

运维管理操作

这里记录一些常用的使用 Docker 部署的 Mastodon 服务器运维管理操作。

使用 tootctl 管理

管理 Mastodon 推荐通过内置的 tootctl 命令进行,Docker 部署的 Mastodon 最直接的方式可以使用 docker exec 命令管理:

docker exec mastodon-web-1 tootctl <command>

例如通过使用 tootctl 创建一个 id 为 newuser 的普通用户:

docker exec mastodon-web-1 tootctl accounts create \
  newuser \
  --email newusr@example.com \
  --confirmed

如果是一些需要交互的设置,可以进入容器后再在执行命令:

docker exec -it mastodon-web-1 /bin/bash

此时,你可以配合 crontab 执行定时任务来自动化管理,例如每天凌晨 3 点定时清理本地缓存的其它实例媒体文件:

0 3 * * * docker exec mastodon-web-1 tootctl media remove --days=7
0 3 * * * docker exec mastodon-web-1 tootctl media remove-orphans
0 3 * * * docker exec mastodon-web-1 tootctl statuses remove --days=90
0 3 * * * docker exec mastodon-web-1 tootctl preview_cards remove --days=180

其中:

  • tootctl media remove :清除缓存超过指定天数的外站媒体附件
  • tootctl media remove-orphans :移除不属于任何媒体附件的文件
  • tootctl statuses remove :从数据库中删除超过指定天数未被引用的嘟文
  • tootctl preview_cards remove : 移除超过指定天数的本地预览卡片缩略图

迁移服务器

如果旧服务器正常运行的话,最简单的方法是直接迁移 Docker 容器。这里主要结合官方文档,给出旧服务器忘记续费/rm -rf/爆炸后,只有备份文件的情况下的恢复示例 为了验证流程有效性,我直接把数据库删了 QAQ

你平时可以通过下面的命令导出数据库文件,和 .env.production 文件以及媒体文件(public/system)一起使用 rsync 或者 rclone 定时自动备份到安全的地方。

docker exec mastodon-db-1 pg_dump -U postgres -Fc mastodon_production > /path/to/db-backup.dump
  1. 恢复数据库

在新服务器上将数据库备份文件、docker-compose.yml.env.production 文件复制到你的项目路径下。注意不能和部署新实例时一样运行向导配置。

进入你的项目路径,启动数据库容器:

docker compose up -d db

使用 docker ps 找到该容器 id,拷入数据库文件之后进入容器创建一个新的空白(UTF8/en_US.utf8)数据库:

docker cp ./db-backup.dump <container id>:/tmp/db-backup.dump
docker exec -it <container id> /bin/bash
su - postgres
createdb -T template0 mastodon_production

* 如果你此前使用了其它账户管理数据库,这里还需要新建相应的数据库用户,假设该用户为 mastodon,密码和 .env.production 中一致:

psql
CREATE USER mastodon WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE mastodon_production TO mastodon;
\q

导入数据库,注意修改 -U--role 参数相应的用户名:

pg_restore -U mastodon -n public --no-owner --role=mastodon \
  -d mastodon_production /tmp/db-backup.dump

最后退出并停止容器。

  1. 导入媒体文件

直接将备份的 /public/system/ 目录上传到项目路径下并修改权限即可:

chown 991:991 -R ./public

如果你没有备份外站用户的缓存(例如头像、头图等),之后会出现 404,可以刷新所有用户缓存:

docker compose run --rm web bin/tootctl accounts refresh --all

媒体附件同理可以通过 tootctl media refresh 刷新。

  1. 重建主页时间流
docker compose run --rm web bin/tootctl feeds build

等待完成后就可以启动 Mastodon 服务了:

docker compose up -d

如果你准备开放实例供他人注册使用的话,需要配置和优化的地方还有很多,连接中继、云端存储、定时备份、性能优化等等,我这里由于服务器性能限制,暂时不打算开放注册,就不再研究了。