Ticketing and On-call
FreeSDN raises alerts. These three turn them into work.
| Plugin | What it does | Default floor |
|---|---|---|
jira-tickets |
Opens a Jira issue, closes it when the alert clears | high |
servicenow-incidents |
Creates a ServiceNow incident, resolves it when the alert clears | high |
pagerduty-incidents |
Triggers a PagerDuty incident, resolves it when the alert clears | critical |
All three subscribe to alert.fired and alert.resolved, and all three default to
dry_run: true so the first thing you see is the tickets they would have opened.
Why these are plugins and not integrations
Section titled “Why these are plugins and not integrations”The Integrations page offers a webhook: a URL, a set of event types, and an HMAC secret. That is everything it has. There is no auth field, no custom headers and no payload templating, which is fine for anything that accepts an arbitrary JSON body - a generic endpoint, an n8n webhook trigger, a Make.com scenario - and structurally impossible for a vendor API that needs its own credentials.
There is nowhere to put a Jira token, so the request cannot even authenticate, never mind send the issue shape Jira expects. Integrations still lists all three types, now marked Needs a plugin and pointing here.
Deduplication is the feature
Section titled “Deduplication is the feature”An alert rule that flaps publishes alert.fired every time it trips. One ticket per
firing gives you forty identical tickets by morning, and the reliable outcome of that is
somebody switching the integration off - after which nobody gets any tickets at all.
- Jira and ServiceNow remember the alert id against the issue they opened. A repeat firing comments on the existing issue instead of filing a new one.
- PagerDuty gets it for free: it deduplicates server-side on
dedup_key, and the FreeSDN alert id is that key. So that plugin keeps no state at all, rather than a second source of truth that can drift out of step with theirs.
Setting each one up
Section titled “Setting each one up”Plugins → Jira Tickets → Settings.
| Setting | Notes |
|---|---|
jira_url |
https://your-org.atlassian.net, no trailing path |
jira_email |
The account the token belongs to. Jira Cloud uses Basic auth with email + token, not the token alone |
jira_api_token |
From id.atlassian.net → Security. Stored encrypted |
project_key |
The prefix in NET-123, not the project name |
issue_type |
Case-sensitive, and must exist in that project |
resolve_transition |
Matched case-insensitively against the transitions your workflow offers |
Saving checks two things: that the credentials work, and that the project is readable. Connecting with a token that cannot see the project files nothing, and finding that out from the first real alert is what this check exists to prevent.
Jira Cloud’s v3 API refuses a plain string for description - it wants Atlassian
Document Format, and the failure is a 400 that does not say so. The plugin handles that.
ServiceNow
Section titled “ServiceNow”Plugins → ServiceNow Incidents → Settings.
Give the integration user itil plus write on the incident table and nothing more. A
personal admin account is the usual shortcut here and the usual regret.
ServiceNow has no severity. It models urgency and impact separately and derives
priority from a matrix every instance tunes, so urgency_map is yours to set rather
than ours to guess:
critical=1,high=2,medium=2,low=3,info=3impact is a single fixed value because FreeSDN knows how bad the alert is, not how
much of your business it affects.
An unknown close_code is refused by ServiceNow rather than defaulted. When that
happens the incident is left open with a work note explaining why - an incident that
silently stayed open is worse than one that says what stopped it closing.
PagerDuty
Section titled “PagerDuty”Plugins → PagerDuty Incidents → Settings. You need the Integration Routing Key from the service you want paged (Service → Integrations → Events API v2). It is 32 characters, and it is a credential: anyone holding it can page your on-call.
The floor defaults to critical rather than high, because this one wakes people up
and the cost of a page nobody needed is measured in trust.
Set events_url to https://events.eu.pagerduty.com/v2/enqueue for the EU region.
Going live
Section titled “Going live”Every one starts in dry_run. Watch the log, confirm the tickets it reports are the
ones you want, then turn it off:
Plugins -> <the plugin> -> Settings -> dry_run -> off -> Save settingsThe severity floor is the other dial worth turning before you go live. A ticket queue that fills with informational noise stops being read, which costs more than the tickets it saves.
Writing your own
Section titled “Writing your own”The pattern is on_event plus a severity floor plus a dedup key, and all three are
readable end to end in registry/plugins/. One trap worth knowing if you copy from
them:
except Exception as exc: return False, f"{exc.__class__.__name__}: {exc}" # NOT type(exc).__name__type is not in the plugin sandbox’s builtin allowlist. Calling it raises NameError
from inside the except block, which replaces the real error with a confusing one - and
in a settings validator it blanks the warning entirely, so an unreachable host reports
nothing at all. See the SDK reference.
All product names, logos, and brands are property of their respective owners. FreeSDN is an independent project and is not affiliated with or endorsed by the vendors it integrates with. See Trademarks.