From 52b4606ab50766581568b8bdfc823f51b288741e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Aug 2026 12:14:32 +0000 Subject: [PATCH] Add optional per-service companion doc files to write_readme Any services/.md next to services/.sh gets appended to the generated ~/docker//README.md automatically, with no changes needed to the calling install_() function. Keeps install-time-invariant walkthroughs (third-party UI linking steps, multi-account setup) out of the compose/README heredocs, which should stay focused on values chosen during install. Add services/traccar.md as the reference example: documents the per-user Connections-tab linking needed for ntfy notifications to reach non-admin accounts, and why TEST CHANNELS can return success without actually sending anything (Traccar's SMS notificator silently no-ops when the logged-in user's Phone field is empty). --- CLAUDE.md | 12 ++++++++++++ lib/common.sh | 17 +++++++++++++++++ services/traccar.md | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 services/traccar.md diff --git a/CLAUDE.md b/CLAUDE.md index 44804a7..fea2c45 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -304,6 +304,18 @@ Writes `$DIR/README.md` (creates the directory if needed). No-ops in DRY_RUN. Every Docker service should call this so `~/docker//README.md` is self-documenting on the deployed box. +**Companion doc files.** If `services/.md` exists next to +`services/.sh`, `write_readme` appends its contents automatically — +no per-service code needed to opt in, just add the file. It's outside +`setup.sh`'s `services/*.sh` glob so it never registers or runs on its own; +it's purely markdown that gets tacked onto the generated README. Use it for +walkthroughs that don't depend on anything chosen at install time (linking +steps in a third-party UI, multi-account setup, troubleshooting notes) — +content like that bloats the heredoc without adding anything install-specific. +Keep the heredoc for content that *does* depend on install-time values (the +actual port chosen, generated credentials, etc.); use `services/.md` +for everything else. See `services/traccar.md` for the reference example. + ## Categories | Group | Purpose | diff --git a/lib/common.sh b/lib/common.sh index 349af3f..b8b8209 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -472,6 +472,13 @@ prompt_reinstall_mode() { # # Title # ... # MD +# +# If services/.md exists next to the calling services/.sh, its +# contents are appended automatically. That file is optional and untouched by +# setup.sh's services/*.sh glob (doesn't register, doesn't run) — it's just a +# place for install-time-invariant walkthroughs (multi-step UI instructions, +# third-party linking, etc.) that would otherwise bloat the heredoc above with +# content that doesn't depend on any variable chosen during install. write_readme() { local dir="$1" if [ "$DRY_RUN" = true ]; then @@ -481,6 +488,16 @@ write_readme() { fi mkdir -p "$dir" cat > "$dir/README.md" + + local caller_script="${BASH_SOURCE[1]:-}" + if [ -n "$caller_script" ]; then + local companion_doc="${caller_script%.sh}.md" + if [ -f "$companion_doc" ]; then + printf '\n' >> "$dir/README.md" + cat "$companion_doc" >> "$dir/README.md" + fi + fi + chown "$ACTUAL_USER:$ACTUAL_USER" "$dir/README.md" 2>/dev/null || true } diff --git a/services/traccar.md b/services/traccar.md new file mode 100644 index 0000000..5d1e39d --- /dev/null +++ b/services/traccar.md @@ -0,0 +1,39 @@ +## Getting ntfy notifications to actually fire (multi-user setup) + +If `.env` has `SMS_HTTP_URL` set (the ntfy setup above), a Traccar user still +needs two separate things configured on their own account before they'll +receive anything — this trips people up because both are per-user, not +global, and neither is optional: + +1. **Their own Phone field set to their ntfy topic.** + Settings → Users → click the user → Phone field → their topic name. + Different users can share one topic or each get their own, depending on + whether you want them to see the same alerts or separate ones. + +2. **The notification rule linked to that user.** + Creating a notification (e.g. "Geofence exited" with the SMS channel + checked) does not automatically apply to every user — it has to be + attached. Go to **Settings → Users → click the user → Connections tab**, + and select which Devices, Geofences, Notifications, and Users are linked + to that account. A user only gets alerts for notifications, devices, and + geofences actually selected there. + +Both steps are required per account. There's no way to configure this once +for everyone — a non-admin user who can't see a device/geofence/notification +in their own Connections list won't get notified about it, even if the admin +configured everything else correctly. + +### Why "TEST CHANNELS" can return success with nothing arriving + +The `TEST CHANNELS` button only ever tests the **currently logged-in +session's user** — there's no way for an admin to test "as" another account. +Worse, it can report success (HTTP 204) even when nothing was sent: Traccar's +SMS notificator silently no-ops (no error, no log line) if that user's Phone +field is empty, since `HttpSmsClient` — which is what actually calls out to +ntfy and would throw on failure — never gets invoked in that case. A 204 +from this button only proves the request loop completed, not that ntfy was +reached. + +To verify a specific account actually works, log in **as that account** and +click the button there, or just trigger a real matching event (e.g. cross a +linked geofence) and watch for the notification.