Flux Notification Controller: commit status, Telegram, and Mattermost
Published: 2026-03-01
Flux ships with a Notification Controller that turns reconciliation events into webhooks. Two primitives: Provider (where to send) and Alert (what to send and when). This covers commit status badges in GitLab, Telegram via generic webhook, and organizing notifications per environment.
Providers
GitLab commit status
Sets a pipeline status on the commit that triggered a Flux reconcile. Engineers see a green/red badge directly in the GitLab MR:
yamlapiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: gitlab-status
namespace: flux-system
spec:
type: gitlab
address: https://gitlab.example.com
secretRef:
name: gitlab-token
---
apiVersion: v1
kind: Secret
metadata:
name: gitlab-token
namespace: flux-system
stringData:
token: "${GITLAB_TOKEN}"
The token needs api scope on the account that owns the repo. Store it in Vault and use External Secrets Operator to create the Secret.
Telegram via generic webhook
Flux doesn't have a native Telegram provider, but generic sends a JSON POST to any URL. Combine it with abot:
yamlapiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: telegram
namespace: flux-system
spec:
type: generic
address: http://abot.observability.svc.cluster.local:9444/flux
abot needs a /flux endpoint that accepts Flux's event JSON and reformats it into Telegram HTML. Alternatively, use the telegram provider type with a bot token directly if you don't need proxy support:
yamlspec:
type: telegram
address: https://t.me/bot_token
channel: "-100123456789"
secretRef:
name: telegram-bot-token
Mattermost
yamlapiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: mattermost
namespace: flux-system
spec:
type: mattermost
address: https://chat.example.com/hooks/infra-flux-hook
Alerts
An Alert selects which objects to watch, filters by event severity, and routes to a Provider.
Notify on HelmRelease failures
yamlapiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: helmrelease-failures
namespace: flux-system
spec:
summary: "HelmRelease failed in dev"
providerRef:
name: telegram
eventSeverity: error
eventSources:
- kind: HelmRelease
namespace: dev
name: "*"
name: "*" matches all HelmRelease objects in the dev namespace. eventSeverity: error means only failed reconciles trigger a notification — successful ones are silent.
Notify on any Kustomization change
yamlapiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: kustomization-applied
namespace: flux-system
spec:
summary: "Kustomization applied"
providerRef:
name: gitlab-status
eventSeverity: info
eventSources:
- kind: Kustomization
namespace: "*"
name: "*"
This creates a GitLab commit status for every Kustomization reconcile — success or failure. Engineers see which cluster layer applied successfully from the MR view.
Notify on image updates
yamlapiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: image-update
namespace: flux-system
spec:
summary: "Image auto-update"
providerRef:
name: telegram
eventSeverity: info
eventSources:
- kind: ImageUpdateAutomation
namespace: "*"
name: "*"
Notifies when Flux automatically bumps an image tag after a new CI build.
Event payload
The generic provider sends:
json{
"involvedObject": {
"kind": "HelmRelease",
"name": "elasticsearch",
"namespace": "dev"
},
"severity": "error",
"reason": "UpgradeFailed",
"message": "Helm upgrade failed: rendered manifests contain a resource...",
"timestamp": "2026-03-01T12:34:56Z"
}
The message field has the full Flux error — the same text you'd see in flux get helmreleases.
Structuring Alerts per cluster
All Alerts live in spoke/notifications/ and are applied by the spoke Kustomization. Each environment has its own Alerts pointing to its own namespace:
spoke/
notifications/
provider-telegram.yaml
provider-gitlab.yaml
alert-helmrelease-errors.yaml
alert-kustomization-status.yaml
This way, a failure in dev only fires the dev channel, not the production channel.
Debugging
bash# Check notification controller logs
kubectl logs -n flux-system deploy/notification-controller -f
# Check Provider health
kubectl get provider -n flux-system
# Check Alert status
kubectl describe alert helmrelease-failures -n flux-system
# Force a test event (trigger reconcile on a HelmRelease)
flux reconcile helmrelease my-app -n dev
If notifications aren't arriving, check:
kubectl get provider -n flux-system— should beReady- Controller logs for HTTP errors when posting to the webhook URL
- The Alert's
eventSeverity— ensure it matches the event type you expect