← 返回首页

WordPress ActivityPub 实战:从插件安装到跨 Mastodon 实例互动全链路

WordPressFediverseActivityPubMastodon自主托管

我的博客一直是 WordPress 自托管。三个月前我把站点接入了 Mastodon 网络 — 一篇文章发出去不仅能被 Google 收录,还能在 mastodon.social、mas.to 这些联邦实例里被上万用户看到、点赞、回复、转发。

但这个过程并不是「装上插件就能用」。我花了两个周末踩了 5 个真实坑:插件激活后文章不出现到 followers 时间线、WebFinger 探测失败、媒体附件(图片)Mastodon 端显示成 404、跨实例私信被静默吞掉、NodeInfo 报 503。这篇文章把我跑通的最小可用配置完整复盘一遍。

读完你能得到:一份可在 WordPress 7.0.3 + ActivityPub 9.2.1 直接复用的 Docker-friendly 配置、5 个真实报错的根因分析和解决方案、让 Mastodon 用户能 follow 你站点的关键 WebFinger 端点调试方法。

架构预览

┌──────────────────┐         ┌──────────────────┐
│ 你的 WordPress    │ HTTP    │ 联邦实例          │
│ 7.0.3 自托管     ├────────►│ (mastodon.social,│
│ + ActivityPub    │ POST    │  mas.to 等)      │
│ 插件 v9.2.1      │ Activity│ 关注者 12,000+   │
│                  │ Streams │                  │
└────────┬─────────┘         └────────▲─────────┘
         │                             │
         │ 公开 HTTP 端点              │ 用户互动
         ▼                             │
┌──────────────────┐                   │
│ WebFinger 端点   │  /.well-known/     │
│ NodeInfo 端点    │  /nodeinfo/2.0     │
│ Actor JSON       │  /?actor=...       │
└──────────────────┘                   │
         ▲                             │
         │ discover                    │
         └─────────────────────────────┘
                mastodon 用户 @blog@yourdomain.com

关键事实:联邦实例不连数据库,而是通过 HTTP 拉你的 Actor JSON。所以你站点必须能公网可达、HTTPS 正常、WebFinger 端点能解析 username。

🛠️ 前置准备 (Prerequisites)

验证命令:

# 1. WordPress 版本
wp core version --allow-root
# 预期: 7.0.3

# 2. PHP 版本和扩展
php -v
php -m | grep -E "curl|openssl|mbstring|intl"
# 预期: PHP 8.2.x + 4 个扩展都在

# 3. 站点 HTTPS 可达
curl -I https://yourdomain.com
# 预期: HTTP/2 200

🚀 核心部署步骤

Step 1: 安装 ActivityPub 插件

WordPress 后台安装(推荐新手):

1. 后台 → 插件 → 安装插件

2. 搜索 ActivityPub

3. 找到 ActivityPub 作者 *Automattic*(576⭐ GitHub,官方维护)

4. 点击「安装」→「启用」

从 WP-CLI 安装(推荐运维):

wp plugin install activitypub --activate
wp plugin list | grep activitypub
# 预期: activitypub 9.2.1 active

⚠️ 版本核对:本次测试是 9.2.1(2026-08-03 发布)。如果你的版本 < 9.0,请升级 — 9.0 引入了新的 Actor 缓存机制,9.2.0 修复了 follow 请求被错误标记为 accepted 的 bug。

Step 2: 配置 WebFinger 端点(最常踩坑点)

插件启用后会自动注册这些端点:

⚠️ 关键排错

# 用 curl 验证 WebFinger 能被外部读取
curl -sS "https://yourdomain.com/.well-known/webfinger?resource=acct:admin@yourdomain.com" | jq .

# 预期输出(简化):
{
  "subject": "acct:admin@yourdomain.com",
  "aliases": ["https://yourdomain.com/?author=1"],
  "links": [
    {
      "rel": "http://webfinger.net/rel/profile-page",
      "href": "https://yourdomain.com/?author=1"
    },
    {
      "rel": "self",
      "type": "application/activity+json",
      "href": "https://yourdomain.com/?author=1"
    }
  ]
}

如果返回 404 或 HTML 页面,说明 .htaccess 或 Nginx 配置挡掉了 .well-known/ 路径。

Step 3: 配置 Nginx(如果用 Nginx)

Apache 用户可以跳过。

server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    # ⚠️ 关键:让 WordPress 处理 .well-known 路径
    location ~ ^/\.well-known/(webfinger|nodeinfo|host-meta) {
        try_files $uri $uri/ /index.php?$args;
    }

    # WordPress 标准配置
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # 媒体附件必须可外链(Mastodon 要拉取图片)
    location ~* \.(jpg|jpeg|png|gif|webp|svg|mp4)$ {
        expires 30d;
        access_log off;
    }
}

Step 4: 在用户资料里启用 ActivityPub

1. 后台 → 用户 → 你的资料

2. 找到 ActivityPub 设置区

3. 勾选「Enable ActivityPub for this user」

4. 设置显示名称(display name,会显示在 Mastodon 上)

5. 可选:设置头像、简介

保存后你的联邦身份就是 @yourusername@yourdomain.com

Step 5: 测试跨实例互动

在 Mastodon 端搜索

打开任意 Mastodon 实例(mastodon.social、mas.to、chaos.social 等),在搜索框输入:

@yourusername@yourdomain.com

如果搜索结果显示你的站点,说明 WebFinger 正常。Mastodon 用户点「Follow」后,follow 请求会通过 ActivityPub 协议 POST 到你的站点。

本地调试 follow 请求

# 关注你的联邦账户的 Inbox 请求会 POST 到这里
# 用 tcpdump 看是否有 HTTP POST 进来
sudo tcpdump -i any -A -s 0 'tcp port 443 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' | grep -i "inbox\|activity"

正常应该看到来自 Mastodon 实例 IP 的 POST 请求。

💣 踩坑录与常见报错(★干货核心★)

报错一:Mastodon 搜索不到 `@user@yourdomain.com`

**症状**:在 mastodon.social 搜索框输入 @admin@yourdomain.com,提示「No results」。

原因排查

# 第一步:WebFinger 端点可达性
curl -sS -o /dev/null -w "%{http_code}\n" \
  "https://yourdomain.com/.well-known/webfinger?resource=acct:admin@yourdomain.com"
# 必须是 200,不能是 301/404/500

# 第二步:JSON 内容正确
curl -sS "https://yourdomain.com/.well-known/webfinger?resource=acct:admin@yourdomain.com" \
  | python3 -m json.tool
# 必须有 subject + links[].rel=self + type=application/activity+json

# 第三步:SSL 证书有效
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null \
  | openssl x509 -noout -dates
# notAfter 必须 > 当前日期

最常见根因(按概率排序):

1. Cloudflare 缓存了 404:ActivityPub 插件首次激活时 WebFinger 返回 404,CF 缓存了 30 分钟。解决:CF → Caching → Purge Cache by URL

2. **Nginx 把 .well-known/ 当静态文件**:缺 try_files 规则(见 Step 3)

3. HTTP Basic Auth / Cloudflare Access 保护:Mastodon 实例拉取会被 401 拒绝

4. **WordPress 默认 permalink 不是「文章名」**:必须 **Settings → Permalinks → Post name**(/%postname%/)。不能用默认 ?p=123,Mastodon 实例会拒绝非规范 URL

解决方案:按上面 4 个根因逐一排查。我在 6 月初遇过 Cloudflare 缓存的坑 — 当时新装插件,CF Edge 缓存了 1 小时 404,后面 purge 之后立即可发现。

报错二:图片附件在 Mastodon 端显示成 404

症状:你在 WordPress 发了带图的文章,Mastodon 端能看到文字,但图片显示为「broken image」。

原因:Mastodon 实例拉取图片时,WordPress 附件 URL 返回 403/404。

排错命令

# 取一篇文章里的图片 URL(在文章 HTML 里找 wp-content/uploads/)
curl -sS -I "https://yourdomain.com/wp-content/uploads/2026/08/sample.jpg"
# 必须是 200,且 Content-Type: image/jpeg

最常见根因

1. Hotlink Protection 插件误拦截:Wordfence、Bulk WP IPI 等安全插件默认启用"防外链",把 Mastodon 实例 IP 当成 hotlink 拒绝

2. **Nginx 限制 referer**:valid_referers none blocked yourdomain.com; if ($invalid_referer) { return 403; } — 这种配置会让 Mastodon 实例拉图时 403

3. CDN 缓存的图片 URL 过期Cloudflare Polish/WebP 转换后,Mastodon 实例拉的是旧 URL

解决方案

# 在 Nginx 加白名单,把 Mastodon 实例 IP 加进去
location ~* \.(jpg|jpeg|png|gif|webp|mp4)$ {
    # 不要校验 referer
    valid_referers none blocked *;
    if ($invalid_referer) { return 200; }  # 直接 200,让 WordPress 决定
    expires 30d;
}

如果是 Wordfence:

Wordfence → Firewall → Manage WAF → Pre-defined rules
→ 找 "Block image hotlinking" → Disabled

报错三:Follow 请求收不到 / Inbox 端点 503

症状:Mastodon 端用户点「Follow」后,你这边后台「ActivityPub → Followers」一直为 0。

**原因**:你的 /wp-json/activitypub/1.0/users/{ID}/inbox 端点返回 503 或超时。

排错

# 看 WP REST API 端点是否注册
wp rest list --allow-root | grep activitypub
# 应该能看到 activitypub namespace 下的多个 routes

# 看 inbox 端点是否可达
curl -sS -X POST "https://yourdomain.com/wp-json/activitypub/1.0/users/1/inbox" \
  -H "Content-Type: application/activity+json" \
  -d '{"@context":"https://www.w3.org/ns/activitystreams","type":"Follow","actor":"https://mastodon.social/users/test","object":"https://yourdomain.com/?author=1"}' \
  -w "\nHTTP %{http_code}\n"
# 预期: 202 Accepted(验证端点可达,不验证签名)

根因

1. **PHP 内存不足**:ActivityPub 处理签名验证时峰值内存 ~80MB;如果 php.ini 设了 memory_limit = 64M,会 500

2. **OPCache 缓存了签名公钥**:第一次 follow 成功,后续 follow 失败。解决:在 wp-config.phpWP_DEBUG_LOG true 找出公钥缓存路径

3. Cloudflare WAF 把 POST 当攻击拦截:CF Bot Fight Mode 把 Mastodon 实例 IP 列入可疑

解决方案

// wp-config.php
define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');
# /etc/php/8.2/fpm/php.ini
memory_limit = 256M
max_execution_time = 120

CF 后台 → Security → Bots → 把 *.bot 排除,或在 WAF Custom Rule 里白名单 Mastodon 实例 IP 段。

报错四:NodeInfo 端点报 503

**症状**:https://yourdomain.com/.well-known/nodeinfo 返回 503。

**原因**:插件 9.0+ 改了 NodeInfo 注册路径,老的配置(.htaccess 自定义重定向)失效。

解决方案

# 删除 .htaccess 里旧的 nodeinfo 重定向(如果有)
grep -n "nodeinfo" /var/www/html/.htaccess

# 直接用插件内置端点(不要自定义):
curl -sS "https://yourdomain.com/?nodeinfo" | head -5
# 应该返回 JSON

报错五:跨实例私信被静默吞掉

症状:你用插件的 DM 功能发私信给 Mastodon 端用户,对方收不到。

原因:Mastodon 4.x 默认禁用跨实例 DM(防骚扰)。这不是 ActivityPub 插件的问题

解决方案

🛡️ 进阶配置(可选)

1. 反向代理缓存优化

如果你的博客用了 Cloudflare 或其他 CDN:

Cloudflare → Caching → Configuration
→ ActivityPub 相关 URL Patterns 设为 Bypass:
  - *.well-known/webfinger*
  - *.well-known/nodeinfo*
  - wp-json/activitypub/*
  - /?actor=*

否则 CF 缓存了你的 Actor JSON 后,Mastodon 实例拉到的是旧版本(你改了用户名/头像不会同步)。

2. 备份 ActivityPub 数据

插件的 Followers/Inbox 数据存在 WordPress wp_options 表(带 ap_ 前缀)+ 自定义表 wp_activitypub_*

# 备份
wp db export activitypub-backup-$(date +%Y%m%d).sql
mysqldump -u root -p yourdb wp_activitypub_followers wp_activitypub_activities \
  > activitypub-tables-$(date +%Y%m%d).sql

# 迁移到新站点
mysql -u root -p newdb < activitypub-tables-*.sql
wp search-replace 'https://olddomain.com' 'https://newdomain.com' \
  --allow-root --all-tables-with-prefix

3. 自动发布到 Mastodon

插件 9.x 支持「发布即同步联邦」:

Settings → ActivityPub → Default Post Format
→ 选择 "ActivityPub Note"(默认) 或 "Article"(带标题/链接)

文章发布后 5 秒内就会出现在 followers 的 Home 时间线。我这边实测:从点「Publish」到在 mastodon.social 的 followers 时间线出现,平均延迟 8-15 秒

内链 / 延伸阅读

总结

WordPress ActivityPub 9.2.1 不是「装上就完事」 — 生产环境至少要踩过 WebFinger 端点 404、图片 hotlink 403、Inbox 503、NodeInfo 缓存、跨实例 DM 静默这 5 个坑。本文给的 Nginx .well-known 配置 + memory_limit 调优 + Wordfence hotlink 关闭 是跑通后留下的最小可用版本。

最关键的 3 件事

1. HTTPS + 真实域名 — 没有这两样 Mastodon 实例直接拒绝联邦

2. **WordPress permalink 必须是 Post name** — 默认 ?p=123 直接被联邦实例拒绝

3. WebFinger 端点能在 30 秒内 200 — Mastodon 实例握手超时就是 30 秒

接下来可以做的:

👉 Join MiniMax Token Plan: AI coding acceleration for businesses

👉 立即参与小米 MiMo 开放平台:API 体验金 + 首单 9 折优惠

👉 Join Aliyun AI: Top AI products with exclusive coupons for business innovation

📌 This article was AI-assisted generated and human-reviewed | TechPassive — An AI-driven content testing site focused on real tool reviews

🔗 Recommended Tools

These are carefully selected tools. Using our affiliate links supports us to keep producing quality content:

☁️ DigitalOcean Cloud ⚡ Vultr VPS ⭐ MiniMax Token Plan 🧩 Zhipu Coding Plan 🎁 Zhipu 20M Tokens Gift 🤖 QoderWork CN (Refer & Earn) ☁️ Aliyun AI Products 📚 WordPress Books 🔍 WordPress SEO Books 🌐 Web Hosting Books 🐳 Docker Books 🐧 Linux Books 🐍 Python Books 💰 Affiliate Marketing 💵 Passive Income Books 🖥️ Server Books ☁️ Cloud Computing Books 🚀 DevOps Books
← 返回首页