From 7c566cda50933251fa071e68b0314012734f97db Mon Sep 17 00:00:00 2001 From: MajorLinux Date: Sun, 10 May 2026 00:05:18 -0400 Subject: [PATCH] Add: diagnosing Castopod posts that don't appear on Mastodon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Walks the four-step diagnostic chain (post created → activity delivered → follower exists → notification semantics) for the common confusion where a Castopod admin's auto-broadcast "doesn't show up" on a Mastodon account they expected. Most cases are not federation bugs but the difference between favouriting/boosting (no follow required) and following + the fact that Mastodon notifications fire only for mentions/follows/favs/ boosts/etc., not for new posts from people you follow. Documents the bell icon and `@`-mention escape hatches. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../castopod-broadcast-not-on-mastodon.md | 154 ++++++++++++++++++ SUMMARY.md | 3 +- index.md | 10 +- 3 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 05-troubleshooting/security/castopod-broadcast-not-on-mastodon.md diff --git a/05-troubleshooting/security/castopod-broadcast-not-on-mastodon.md b/05-troubleshooting/security/castopod-broadcast-not-on-mastodon.md new file mode 100644 index 0000000..c62a81f --- /dev/null +++ b/05-troubleshooting/security/castopod-broadcast-not-on-mastodon.md @@ -0,0 +1,154 @@ +--- +title: "Castopod Posts Don't Appear on Mastodon — Diagnosing the Federation Path" +domain: troubleshooting +category: security +tags: [castopod, mastodon, fediverse, activitypub, federation, notifications] +status: published +created: 2026-05-10 +updated: 2026-05-10 +--- + +# Castopod Posts Don't Appear on Mastodon — Diagnosing the Federation Path + +## 🛑 Problem + +You publish a podcast episode (or a standalone post) on Castopod. The Castopod admin shows it went out fine. But on the Mastodon account that you *expected* to see it from — your own personal account, an account that follows your podcast, a colleague's — the post never shows up. Or it shows up in the home timeline but the notification bell never rings. + +Three different failure modes hide behind "I didn't get the post." This article walks the diagnostic chain that distinguishes them. + +--- + +## 🔬 The four checks, in order + +Run these in sequence. The first one that fails tells you what's actually wrong. + +### Check 1 — Did Castopod create the post? + +On the Castopod host: + +```sh +mysql -u $CP_DB_USER -p$CP_DB_PASS $CP_DB_NAME --binary-as-hex -e " + SELECT HEX(id), actor_id, LEFT(message,80), episode_id, published_at, created_at + FROM cp_fediverse_posts + ORDER BY created_at DESC LIMIT 5 +" +``` + +If your post isn't here at all, Castopod didn't generate it. That's a Castopod-side bug — check `writable/logs/log-.log`, verify the per-minute task scheduler is firing (`php spark tasks:list` should show `Last Run` for `fediverse-broadcast`), and confirm the cron exists: + +```sh +sudo crontab -u www-data -l | grep tasks:run +# expect: * * * * * php /var/www/html/castopod/spark tasks:run >> /dev/null 2>&1 +``` + +### Check 2 — Did Castopod queue and deliver the activity? + +```sh +mysql -u $CP_DB_USER -p$CP_DB_PASS $CP_DB_NAME --binary-as-hex -e " + SELECT HEX(id), actor_id, type, status, scheduled_at, created_at + FROM cp_fediverse_activities + WHERE type='Create' + ORDER BY created_at DESC LIMIT 10 +" +``` + +The `status` column tells you everything: + +| Status | Meaning | +|---|---| +| `queued` | Sitting in the queue, broadcast task hasn't run yet (or is bogged down) | +| `processing` | In-flight | +| `delivered` | All follower inboxes returned 2xx | +| `failed` | One or more inbox POSTs returned non-2xx, gave up after retries | + +If `status='delivered'`, Castopod has done its job — and yet someone says they didn't see the post. Move to Check 3. + +### Check 3 — Are they actually a follower? + +The single most common cause of "I didn't see it." Federation only delivers `Create` activities to **followers** (and to anyone explicitly mentioned). Interacting with a post (favourite, boost) does NOT establish a follow relationship. + +On the Castopod host: + +```sh +mysql -u $CP_DB_USER -p$CP_DB_PASS $CP_DB_NAME -e " + SELECT a.username, a.domain, f.created_at + FROM cp_fediverse_follows f + JOIN cp_fediverse_actors a ON a.id = f.actor_id + ORDER BY f.created_at DESC +" +``` + +`cp_fediverse_follows.actor_id` is the **follower** (remote actor); `target_actor_id` is your local podcast actor. If the user's `username@domain` isn't in this list, they don't follow your podcast, and the Create activity was never sent to their inbox. + +Cross-check from the Mastodon side (if you control both): + +```sh +sudo -u postgres psql mastodon_production -t -A -c " + SELECT a.username, a.domain + FROM follows f + JOIN accounts a ON a.id = f.target_account_id + WHERE f.account_id = + AND a.domain = '' +" +``` + +Empty result on both sides = they're not following. **Resolution: have them search `@yourpodcast@yourdomain.tld` in their Mastodon and click Follow.** + +A subtler corner of this check: `accounts WHERE domain=''` returning 0 rows on the Mastodon side means Mastodon has never even webfingered your podcast actor. The user may have *thought* they followed at some point, but it never went through (e.g., they typed the handle wrong, or the follow request errored). + +### Check 4 — Is "didn't see it" a notification problem, not a delivery problem? + +Even after a successful follow, the post lands in the **home timeline** by default. Mastodon **notifications** (the bell icon, the unread badge) fire for a specific list of activity types — and "new post from someone I follow" isn't one of them. Notifications fire for: + +- Mentions (`@you` in the post body) +- Follows (someone follows you) +- Favourites of your posts +- Boosts of your posts +- Polls ending +- Status edits (post you favourited was edited) +- Admin alerts + +So even with delivery working perfectly and the follow in place, "I didn't get a notification on my account" is the expected state for a regular podcast post. Three ways to make notifications happen: + +1. **Bell icon on the followed profile.** Mastodon UI: open the followed account's profile → click the bell. Enables per-account post notifications. Now every new post from that account raises a notification. +2. **`@`-mention in the post.** Have Castopod include `@you@yourdomain.tld` in the post text. Mention activities always raise notifications regardless of follow/bell state. (You may not control the post text on someone else's Castopod, but you control your own.) +3. **Cross-post via a different actor.** If you also run a Mastodon account for the show, post manually from there and `@`-mention the audience accounts you want to page. + +--- + +## 🧪 Worked example + +A real case: someone running a podcast on Castopod 2.0.0-next.4 expected a new episode's auto-post to appear on their personal Mastodon. It didn't. + +- Check 1 → post present in `cp_fediverse_posts`, episode_id correct ✓ +- Check 2 → matching `cp_fediverse_activities` row, `type='Create'`, `status='delivered'` ✓ +- Check 3 → 8 followers in `cp_fediverse_follows`, none from the personal Mastodon's domain ✗ + +Outcome: the user wasn't following their own podcast. They had been favouriting and boosting its posts (which doesn't require following), and assumed those interactions implied a follow. Resolution: search-and-follow from the personal Mastodon. After the follow propagated, future broadcasts arrived as expected. + +The post itself never raised a notification (only landed in home timeline). They later enabled the bell icon on the podcast profile and started getting notified on new episodes. + +--- + +## 🧭 When this isn't the answer + +If Check 3 shows the person IS a follower but they still didn't receive the post: + +- **Check their inbox** if you have access: Mastodon nginx access log: + ```sh + sudo grep '' /var/log/nginx/access.log | grep inbox + ``` + Expect a `POST /users//inbox HTTP/2.0 202` from the Castopod IP shortly after `published_at`. No POST = Castopod didn't deliver despite claiming `status='delivered'` (rare; check Castopod's HTTP signing config and any outbound firewall on the Castopod host). + +- **Check Sidekiq** on Mastodon for `ActivityPub::ProcessingWorker` failures around the activity timestamp. + +- **Check domain blocks**: `SELECT * FROM domain_blocks WHERE domain = ''` on Mastodon. A silenced or suspended domain on either end would explain everything. + +--- + +## 📚 References + +- ActivityPub spec — [Delivery semantics](https://www.w3.org/TR/activitypub/#delivery): `Create` activities go to actors in `to`/`cc`/`bcc`/`audience`; for public posts that resolves to the actor's followers collection. +- Mastodon notification types: `app/models/notification.rb` — `TYPES` constant +- Castopod fediverse module: `modules/Fediverse/Commands/Broadcast.php` (the per-minute task) and `modules/Fediverse/Models/ActivityModel.php` (queue model) +- Related: [Castopod: Stale Federated Avatar URLs After Remote Profile Updates](castopod-stale-federated-avatar.md) — sister article, also Castopod fediverse module diff --git a/SUMMARY.md b/SUMMARY.md index dd96751..80881c9 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,6 +1,6 @@ --- created: 2026-04-02T16:03 -updated: 2026-05-08T01:08 +updated: 2026-05-10T00:10 --- * [Home](index.md) * [Linux & Sysadmin](01-linux/index.md) @@ -77,6 +77,7 @@ updated: 2026-05-08T01:08 * [Custom Fail2ban Jail: Apache Directory Scanning](05-troubleshooting/security/apache-dirscan-fail2ban-jail.md) * [Tuning Netdata `web_log_1m_successful` for Redirect-Heavy WordPress Sites](05-troubleshooting/security/netdata-web-log-successful-redirect-heavy-tuning.md) * [Castopod: Stale Federated Avatar URLs After Remote Profile Updates](05-troubleshooting/security/castopod-stale-federated-avatar.md) + * [Castopod Posts Don't Appear on Mastodon — Diagnosing the Federation Path](05-troubleshooting/security/castopod-broadcast-not-on-mastodon.md) * [Nextcloud AIO Unhealthy 20h After Nightly Update](05-troubleshooting/docker/nextcloud-aio-unhealthy-20h-stuck.md) * [n8n Behind Reverse Proxy: X-Forwarded-For Trust Fix](05-troubleshooting/docker/n8n-proxy-trust-x-forwarded-for.md) * [Docker & Caddy Recovery After Reboot (Fedora + SELinux)](05-troubleshooting/docker-caddy-selinux-post-reboot-recovery.md) diff --git a/index.md b/index.md index 8747c10..d10b82a 100644 --- a/index.md +++ b/index.md @@ -1,13 +1,13 @@ --- created: 2026-04-06T09:52 -updated: 2026-05-08T01:08 +updated: 2026-05-10T00:10 --- # MajorLinux Tech Wiki — Index > A growing reference of Linux, self-hosting, open source, streaming, and troubleshooting guides. Written by MajorLinux. Used by MajorTwin. > -> **Last updated:** 2026-05-08 -> **Article count:** 108 +> **Last updated:** 2026-05-10 +> **Article count:** 109 ## Domains @@ -17,7 +17,7 @@ updated: 2026-05-08T01:08 | 🏠 Self-Hosting & Homelab | `02-selfhosting/` | 39 | | 🔓 Open Source Tools | `03-opensource/` | 10 | | 🎙️ Streaming & Podcasting | `04-streaming/` | 2 | -| 🔧 General Troubleshooting | `05-troubleshooting/` | 45 | +| 🔧 General Troubleshooting | `05-troubleshooting/` | 46 | --- @@ -202,6 +202,7 @@ updated: 2026-05-08T01:08 - [Custom Fail2ban Jail: Apache Directory Scanning & Junk Methods](05-troubleshooting/security/apache-dirscan-fail2ban-jail.md) - [Tuning Netdata `web_log_1m_successful` for Redirect-Heavy WordPress Sites](05-troubleshooting/security/netdata-web-log-successful-redirect-heavy-tuning.md) - [Castopod: Stale Federated Avatar URLs After Remote Profile Updates](05-troubleshooting/security/castopod-stale-federated-avatar.md) +- [Castopod Posts Don't Appear on Mastodon — Diagnosing the Federation Path](05-troubleshooting/security/castopod-broadcast-not-on-mastodon.md) ### Storage - [mdadm RAID Recovery After USB Hub Disconnect](05-troubleshooting/storage/mdadm-usb-hub-disconnect-recovery.md) @@ -216,6 +217,7 @@ updated: 2026-05-08T01:08 | Date | Article | Domain | |---|---|---| +| 2026-05-10 | [Castopod Posts Don't Appear on Mastodon — Diagnosing the Federation Path](05-troubleshooting/security/castopod-broadcast-not-on-mastodon.md) | Troubleshooting | | 2026-05-08 | [Castopod: Stale Federated Avatar URLs After Remote Profile Updates](05-troubleshooting/security/castopod-stale-federated-avatar.md) | Troubleshooting | | 2026-05-08 | [Tuning Netdata `web_log_1m_successful` for Redirect-Heavy WordPress Sites](05-troubleshooting/security/netdata-web-log-successful-redirect-heavy-tuning.md) | Troubleshooting | | 2026-05-07 | [Mastodon — The `--prune-profiles` Trap and How to Recover](02-selfhosting/services/mastodon-prune-profiles-trap.md) | Self-Hosting |