Skip to content

fix: migrate to maintained nicholas-fedor/shoutrrr fork - #1359

Open
mvanhorn wants to merge 1 commit into
kubereboot:mainfrom
mvanhorn:fix/1024-teams-notifications-shoutrrr-fork
Open

fix: migrate to maintained nicholas-fedor/shoutrrr fork#1359
mvanhorn wants to merge 1 commit into
kubereboot:mainfrom
mvanhorn:fix/1024-teams-notifications-shoutrrr-fork

Conversation

@mvanhorn

Copy link
Copy Markdown

Summary

MS Teams notifications stopped working because the containrrr/shoutrrr project is unmaintained and its Teams service targets the retired Office 365 connector URLs. This migrates kured to the maintained nicholas-fedor/shoutrrr fork, whose Teams service supports the current Power Automate workflow URLs while keeping the same shoutrrr.Send API. Only the import path and module requirements change; behavior for the other notification services is unchanged.

Why this matters

Microsoft retired the Office 365 connector webhooks that the upstream shoutrrr Teams service generates, so every kured deployment notifying Teams through --notify-url is currently broken, which is what #1024 reports. The maintained fork is the path discussed in the issue thread; it tracks the current Teams webhook format without requiring kured to change how it passes --notify-url through to shoutrrr.

Testing

go build ./..., go vet, and go test ./cmd/... pass with the new module after go mod tidy. The commit is DCO signed off.

Fixes #1024

@dharsanb dharsanb added the community This items needs a discussion in a community meeting label Jun 10, 2026
@evrardjp

evrardjp commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Because it will impact the rest of the community and this has been requested multiple times, we should discuss this at the next community meeting.

We have a long hill to climb to get there, and I want everyone to be aware of this before continuing.

@mvanhorn

Copy link
Copy Markdown
Author

Makes sense, happy to hold here until the community meeting. If it would help the discussion, I can write up a short comparison of containrrr/shoutrrr vs the nicholas-fedor fork (maintenance activity, licensing, API differences), and I'll look into the FOSSA license flag on this branch in the meantime. Just let me know the outcome and I'll pick it back up.

@evrardjp

evrardjp commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Licensing is an issue, but not the only one.

The other one would be that we didn't review/audit the changes and we are not sure about the long term maintenance.

Alternatives are: forking our own/using an alternative tool for notifications/dropping the feature.

All of this should be discussed.

What you mentioned helps. Bring your arguments at the community meeting, please :) 🙏 (but don't hesitate to write those here too).

Thank you.

@dharsanb dharsanb added FEATURE-notifications decision This item waits for a decision of the core team labels Jun 11, 2026
@evrardjp

Copy link
Copy Markdown
Collaborator

I would love if you can go ahead with your plan of explaining the differences. For licensing, the problem is that we don't have a cncf exception for the github.com/eclipse/paho.golang (there was an exception for github.com/eclipse/paho.mqtt.golang ). So unless we fork it, i don't see how this could pan out, except if we do the long way of having an exception.

Tell me if I am wrong ofc.

@evrardjp

Copy link
Copy Markdown
Collaborator

@mvanhorn we are getting closer to next community meeting, will you be there at the next meeting? :)

It's on wednesday... https://www.cncf.io/calendar/

@evrardjp

evrardjp commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

We discussed this at last community meeting -- We don't have the bandwidth to solve that licensing + audit issue.
Happy to reconvene at next meeting. We need brainstorming!

@mvanhorn

Copy link
Copy Markdown
Author

Happy to carry some of that. If it helps the next meeting, I can prepare the license and provenance audit of the nicholas-fedor fork beforehand - diff against upstream shoutrrr, license continuity, release/signing practices - so the discussion starts from facts rather than unknowns. Anything else worth preparing?

@evrardjp evrardjp added the wontfix This was triaged and kured will not fix this. label Jul 28, 2026
@evrardjp

evrardjp commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

AFAIK, the problem comes from transitive dependencies. Paho and some MQTT library. the MQTT library had multiple variants, and the resolved one is NOT valid from LK/CNCF perspective (we are not granted an exception).

What we can do is:

  • Ask people to fork, replace in go.mod, and build. It's super easy nowadays.
  • Migrate to a sidecar model where events are sent to kubernetes, and some notification can happen based on events.

I like the second idea far more, because it cleans up the code and do real separation of concerns. But it means two software to deploy. And I have to figure out if we can include both in the chart (I think we can).

@mvanhorn

mvanhorn commented Aug 1, 2026

Copy link
Copy Markdown
Author

I did the licensing dig I offered. Summary first: I think the blocker may be narrower than it looks, and there is a fourth option that needs no fork, no exception, and no sidecar.

The dependency path, from go mod why:

kured/cmd/kured
-> nicholas-fedor/shoutrrr
-> shoutrrr/pkg/router
-> shoutrrr/pkg/services/push/mqtt
-> eclipse/paho.golang/autopaho

So paho comes in only through the MQTT push service, which the router registers unconditionally.

On the license itself. paho.golang v0.23.0 is dual licensed, not EPL only. The module ships both epl-v20 and edl-v10, and its LICENSE says the material is available under the terms of both. The edl-v10 file is verbatim BSD-3-Clause (redistribution in source and binary forms, three conditions, no endorsement clause). A consumer can elect the EDL, which is on the CNCF allowlist.

The part I found most useful: paho.mqtt.golang, the one that does have an exception, is licensed identically. I diffed them.

edl-v10:            identical
LICENSE preamble:   identical

Same dual grant, same two license files. So as far as I can tell the two libraries are in the same licensing position, which means the existing exception is a direct precedent rather than a special case.

I also think I know why scanners flag it. paho's LICENSE inlines the full EPL-2.0 text, and says so explicitly in a comment in the file: it is "copied below in order to pass the pkg.go.dev license check". Scanners read the first license block and report EPL-2.0, missing the dual grant above it. That would explain the FOSSA flag on this branch without there being an actual EPL-only obligation.

I am not a lawyer and I am not asking anyone to take my reading as legal advice. But the identical-to-paho.mqtt.golang comparison seems like a concrete thing to put in front of CNCF legal, and it is a much smaller question than fork it or rearchitect notifications.

The fourth option. shoutrrr already has an opt-in build tag pattern:

pkg/router/servicemap_xmpp.go   //go:build xmpp
pkg/router/servicemap.go        no tag, imports mqtt directly

xmpp is behind a tag; mqtt is not. If mqtt moved to servicemap_mqtt.go behind //go:build mqtt, following their own existing pattern, paho leaves the default build graph entirely. That is a small upstream PR to nicholas-fedor/shoutrrr, it helps every downstream consumer with the same constraint, and it does not touch kured's architecture at all.

Ranking them as I see it:

  1. mqtt behind a build tag upstream. Smallest change, fixes it at the source.
  2. Confirm the EDL election with CNCF legal, using paho.mqtt.golang as precedent. No code change at all if it lands.
  3. Sidecar/events model. I agree it is the nicest design, but it is by far the most work and it is a separate conversation from unblocking this PR.
  4. Ask people to fork and replace in go.mod. Works, but pushes the problem to every operator.

Happy to open the upstream shoutrrr PR for option 1 if you think it is worth trying. I would rather not start it without a nod, since it only helps if kured would actually take that route.

@mvanhorn

mvanhorn commented Aug 2, 2026

Copy link
Copy Markdown
Author

Heads up on the red License Compliance check — I don't think it's something I can clear from this side.

FOSSA needs its token, and GitHub doesn't expose secrets to workflows triggered from a fork. Every other open PR right now (#1400-#1403) is dependabot's, running from a branch inside the repo, and they all pass; this is the only external one and it's the only red one.

For what it's worth the licence itself looks fine: containrrr/shoutrrr v0.8.0 and nicholas-fedor/shoutrrr v0.16.0 are both MIT, so the swap isn't introducing a new licence. Happy to be told otherwise if the FOSSA report says something more specific — I can't see it.

The branch is rebased on current main and the rest of CI is green.

@mvanhorn

mvanhorn commented Aug 2, 2026

Copy link
Copy Markdown
Author

The License Compliance failure here is real and I don't think I can fix it from this PR, so flagging what's behind it.

FOSSA passes on the other open PRs and fails only on this one, because nicholas-fedor/shoutrrr v0.16.0 requires github.com/eclipse/paho.golang v0.23.0 for its MQTT service. containrrr/shoutrrr v0.8.0 did not. paho.golang is Eclipse Public License 2.0 / Eclipse Distribution License 1.0, and GitHub reports it as NOASSERTION, which is what trips the policy.

Go modules have no optional dependencies, so paho.golang lands in the module graph whether or not kured ever calls the MQTT sender. There's no build tag or import pruning that removes it while staying on this fork.

So it's a call for you rather than a code change: either EPL-2.0 gets a FOSSA policy exception, or kured stays on the unmaintained containrrr fork, or we find a maintained fork that doesn't carry MQTT. Happy to chase the third if you want, but I didn't want to keep pushing at a red check whose cause is a licensing policy question.

@mvanhorn

mvanhorn commented Aug 8, 2026

Copy link
Copy Markdown
Author

Provenance half of the audit I promised, to go with the licensing notes above.

Fork continuity: nicholas-fedor/shoutrrr was forked 2025-02-24 from containrrr/shoutrrr at 3c77fd5 (upstream HEAD at the time) and the git history is a clean continuation, no rebase or squash discontinuity. The compare view shows the fork 1250 ahead / 11 behind, and all 11 missing upstream commits postdate the fork. One inherited quirk: upstream's own v0.8.0 tag commit is not an ancestor of upstream main, which is an upstream tagging artifact, not fork history rewriting.

Releases: built in public GitHub Actions with GoReleaser. Assets ship per-artifact SBOMs, a checksums.txt with a cosign keyless signature, and GitHub build provenance. Verified live on v0.17.0: gh attestation verify shoutrrr_linux_amd64_0.17.0.tar.gz -R nicholas-fedor/shoutrrr passes, and the certificate ties the artifact to the tagged workflow run. Docker images are cosign-signed. Tags are annotated but not GPG-signed.

Hygiene: OpenSSF Scorecard 7.8 as of this week (Maintained 10, CI-Tests 10, SAST 10, Token-Permissions 10; weak spots Branch-Protection 3, Code-Review 0, Fuzzing 0). Workflows are SHA-pinned with hardened runners, Renovate is active, SECURITY.md exists (its version table is stale).

Maintenance and adoption: effectively a solo maintainer (~95 percent of human commits over the last 12 months, 7 human contributors total), 26 releases in the last year. The same person maintains the de facto watchtower successor fork while containrrr/watchtower sits archived. Downstream go.mod adopters already include evcc, DNSControl, beszel, keel, scrutiny, autobrr, and homebox.

Net: provenance is clean and verifiable per release, and supply-chain practice is above average for a project this size. The real structural risk is bus factor: one maintainer, no external code review. kured pins by version and can verify attestations per release, which mitigates but does not remove that. The 0.9 to 0.17 minor-version cadence also implies more API churn than the frozen upstream v0.8.

@evrardjp

evrardjp commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

The License Compliance failure here is real and I don't think I can fix it from this PR, so flagging what's behind it.

FOSSA passes on the other open PRs and fails only on this one, because nicholas-fedor/shoutrrr v0.16.0 requires github.com/eclipse/paho.golang v0.23.0 for its MQTT service. containrrr/shoutrrr v0.8.0 did not. paho.golang is Eclipse Public License 2.0 / Eclipse Distribution License 1.0, and GitHub reports it as NOASSERTION, which is what trips the policy.

Go modules have no optional dependencies, so paho.golang lands in the module graph whether or not kured ever calls the MQTT sender. There's no build tag or import pruning that removes it while staying on this fork.

So it's a call for you rather than a code change: either EPL-2.0 gets a FOSSA policy exception, or kured stays on the unmaintained containrrr fork, or we find a maintained fork that doesn't carry MQTT. Happy to chase the third if you want, but I didn't want to keep pushing at a red check whose cause is a licensing policy question.

This matches my findings.
I could be writing an exception in fossa for this project, but this does not the good way to solve it: we would still be linking the projects and that would require approval from cncf/lf legal. I would rather avoid that route.

There is a 4th option: extract notifications.

Which summarises the options as this:

  • get cncf license exception
  • find a suitable alternative fork (audited/license compliant/...)
  • stay as is (request our users to replace the include and rebuild, probably provide them instructions).
  • reimplement our own notifications without such deps.
  • extract notifications as events and add a notify on events system in the helm chart.

For me the best solution going forward (for the long run) is the extraction, but I am happy to discuss it in the next community meeting or on slack call with the interested parties.

@evrardjp

evrardjp commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Provenance half of the audit I promised, to go with the licensing notes above.

Fork continuity: nicholas-fedor/shoutrrr was forked 2025-02-24 from containrrr/shoutrrr at 3c77fd5 (upstream HEAD at the time) and the git history is a clean continuation, no rebase or squash discontinuity. The compare view shows the fork 1250 ahead / 11 behind, and all 11 missing upstream commits postdate the fork. One inherited quirk: upstream's own v0.8.0 tag commit is not an ancestor of upstream main, which is an upstream tagging artifact, not fork history rewriting.

Releases: built in public GitHub Actions with GoReleaser. Assets ship per-artifact SBOMs, a checksums.txt with a cosign keyless signature, and GitHub build provenance. Verified live on v0.17.0: gh attestation verify shoutrrr_linux_amd64_0.17.0.tar.gz -R nicholas-fedor/shoutrrr passes, and the certificate ties the artifact to the tagged workflow run. Docker images are cosign-signed. Tags are annotated but not GPG-signed.

Hygiene: OpenSSF Scorecard 7.8 as of this week (Maintained 10, CI-Tests 10, SAST 10, Token-Permissions 10; weak spots Branch-Protection 3, Code-Review 0, Fuzzing 0). Workflows are SHA-pinned with hardened runners, Renovate is active, SECURITY.md exists (its version table is stale).

Maintenance and adoption: effectively a solo maintainer (~95 percent of human commits over the last 12 months, 7 human contributors total), 26 releases in the last year. The same person maintains the de facto watchtower successor fork while containrrr/watchtower sits archived. Downstream go.mod adopters already include evcc, DNSControl, beszel, keel, scrutiny, autobrr, and homebox.

Net: provenance is clean and verifiable per release, and supply-chain practice is above average for a project this size. The real structural risk is bus factor: one maintainer, no external code review. kured pins by version and can verify attestations per release, which mitigates but does not remove that. The 0.9 to 0.17 minor-version cadence also implies more API churn than the frozen upstream v0.8.

Very good work!

Is there any chance we can have this without the attached license :D

Did you try contacting the author by any chance ?

@evrardjp

evrardjp commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Really thanks a lot for the work.

Fixes broken MS Teams notifications. The containrrr/shoutrrr project is
unmaintained and its Teams service targets retired Office 365 connector
URLs; the maintained fork supports the current Power Automate workflow
URLs while keeping the same API.

Fixes kubereboot#1024

Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
@mvanhorn
mvanhorn force-pushed the fix/1024-teams-notifications-shoutrrr-fork branch from e559869 to 3544a1c Compare August 21, 2026 10:27
@mvanhorn

Copy link
Copy Markdown
Author

Rebased onto current main. The conflict was go.mod: main had moved prometheus/client_golang to v1.24.1 and prometheus/common to v0.70.1, so I kept those and re-ran go mod tidy on top of the shoutrrr change. go build ./... and go test ./cmd/kured/... pass locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community This items needs a discussion in a community meeting decision This item waits for a decision of the core team FEATURE-notifications wontfix This was triaged and kured will not fix this.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MS Teams notifications are currently broken with new message format

3 participants