{"id":51547731,"url":"https://github.com/zone-eu/haraka-plugin-gelf","last_synced_at":"2026-07-09T20:00:53.390Z","repository":{"id":355556389,"uuid":"1222322941","full_name":"zone-eu/haraka-plugin-gelf","owner":"zone-eu","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-16T09:28:12.000Z","size":89,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-16T11:18:24.093Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"eupl-1.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zone-eu.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-27T08:52:36.000Z","updated_at":"2026-06-16T09:28:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zone-eu/haraka-plugin-gelf","commit_stats":null,"previous_names":["zone-eu/haraka-plugin-gelf"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/zone-eu/haraka-plugin-gelf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zone-eu%2Fharaka-plugin-gelf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zone-eu%2Fharaka-plugin-gelf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zone-eu%2Fharaka-plugin-gelf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zone-eu%2Fharaka-plugin-gelf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zone-eu","download_url":"https://codeload.github.com/zone-eu/haraka-plugin-gelf/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zone-eu%2Fharaka-plugin-gelf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35311289,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-09T02:00:07.329Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-09T20:00:52.442Z","updated_at":"2026-07-09T20:00:53.373Z","avatar_url":"https://github.com/zone-eu.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# haraka-plugin-gelf\n\nA [Haraka](https://haraka.github.io/) plugin that forwards log messages to a [Graylog](https://graylog.org/) server via GELF UDP.\n\n## Features\n\n- Forwards all Haraka log messages to Graylog in GELF format\n- UDP transport with automatic IPv4/IPv6 detection\n- Chunked UDP support for large messages (GELF chunking spec)\n- Optional gzip compression\n- Per-plugin configuration with independent URL, fields, and routing\n- Configurable custom GELF fields with variable interpolation\n- Exposes a `loggelf` API on `server.notes` for other plugins to send structured GELF messages directly\n\n## AI Usage Disclaimer\n\nThis project makes limited use of generative AI tools during development:\n\n- Generative AI was used for brainstorming, test generation, documentation and code review assistance\n- All production code was written, reviewed, and validated by a human\n- Final design decisions and implementations are human-driven\n- Any defects or limitations in the code are the responsibility of the human authors\n\n## Installation\n\n```\nnpm install haraka-plugin-gelf\n```\n\nAdd to `config/plugins`:\n\n```\ngelf\n```\n\n## Configuration\n\nCreate `config/gelf.yaml`. A minimal configuration:\n\n```yaml\nurl: 'udp://graylog.example.com:12201'\n```\n\nFull configuration with all options:\n\n```yaml\n# Enable/disable GELF logging\nenabled: true\n\n# Enable/disable Haraka log hook\n#   true  - all Haraka log messages are forwarded to Graylog\n#   false - only messages sent via the server.notes.loggelf API are forwarded\nlog_hook_enabled: false\n\n# Minimum level of log messages to forward to graylog from log hook\n# 0 - emerg, 1 - alert, 2 - crit, 3 - error, 4 - warn, 5 - notice, 6 - info, 7 - debug\nlog_hook_level: 4\n\n# GELF UDP endpoint. Supports udp://, udp4://, udp6:// schemes\nurl: 'udp://graylog.example.com:12201'\n\n# Compress messages with gzip\ncompress: true\n\n# Maximum UDP packet/chunk size in bytes (64–65475)\n# 1420 suits standard Ethernet MTU; 8192 suits jumbo frames\nmax_chunk_size: 1420\n\n# Override the hostname reported in GELF messages (defaults to os.hostname())\n# hostname: mail.example.com\n\n# If true, no further log plugins will be called after this one\nlast: false\n\n# Custom fields added to every GELF message (see Custom Fields below)\nfields:\n  logger: '${logger}'\n  connection: '${connection_uuid}'\n  transaction: '${transaction_uuid}'\n\n# Per-plugin overrides (see Per-plugin Configuration below)\n# plugins:\n#   rspamd:\n#     url: 'udp4://rspamd-graylog.example.com:12201'\n#     fields:\n#       component: 'rspamd'\n```\n\n## URL scheme\n\nThe `url` setting controls both the transport endpoint and the preferred address family:\n\n| Scheme    | Behaviour                                                            |\n|-----------|----------------------------------------------------------------------|\n| `udp://`  | Dual-stack; uses system address family preference (IPv4 or IPv6)     |\n| `udp4://` | Forces IPv4                                                          |\n| `udp6://` | Forces IPv6 only                                                     |\n\nWhen a hostname resolves to multiple addresses, DNS round-robin provides basic load distribution.\n\n## Custom Fields\n\nThe `fields` section lets you add fixed or dynamic fields to every GELF message. Field values are strings and support variable interpolation using `${variable}` syntax.\n\nThe following variables are available:\n\n| Variable           | Value                                          |\n|--------------------|------------------------------------------------|\n| `${logger}`        | Name of the plugin that emitted the log entry  |\n| `${connection_uuid}` | Haraka connection UUID                       |\n| `${transaction_uuid}` | Haraka transaction UUID (includes `.N` suffix) |\n\nIf a variable is not available in context (e.g. `${transaction_uuid}` outside of a transaction), the field is omitted from the message entirely.\n\nExample:\n\n```yaml\nfields:\n  logger: '${logger}'\n  connection: '${connection_uuid}'\n  transaction: '${transaction_uuid}'\n  environment: 'production'\n  facility: 'smtp'\n```\n\nTo explicitly suppress a field that would be inherited from the main config in a per-plugin override, set it to `null`:\n\n```yaml\nplugins:\n  rspamd:\n    fields:\n      transaction: null   # omit transaction field for rspamd messages\n      component: 'rspamd'\n```\n\n## Per-plugin Configuration\n\nAny top-level setting can be overridden per Haraka plugin under the `plugins` key. Plugin names match `plugin.name` in Haraka (e.g. `karma`, `dkim`, `rcpt_to.in_host_list`).\n\nPer-plugin `fields` are merged with (not replaced by) the top-level `fields`.\n\n```yaml\nplugins:\n  karma:\n    url: 'udp://karma-graylog.example.com:12201'\n    last: true\n    fields:\n      component: 'karma'\n\n  rspamd:\n    enabled: false\n\n  wildduck:\n    log_hook_enabled: true\n    url: 'udp4://wildduck-graylog.example.com:12201'\n    fields:\n      component: 'mx'\n      transaction: null\n      queue_id: '${transaction_uuid}'\n```\n\n## API for other plugins\n\nWhen loaded, the plugin exposes `server.notes.loggelf` for structured GELF logging from other plugins.\n\n### `message(callerPlugin, msg)`\n\nSend a raw GELF message object. Returns `cfg.last` (boolean) — when `true`, no further log plugins will be called.\n\n```javascript\nexports.hook_queue = function (next, connection) {\n    connection.server.notes.loggelf?.message(this, {\n        short_message: 'Mail queued',\n        level: 6, // INFO\n        _recipient: connection.transaction.rcpt_to.toString(),\n        _sender: connection.transaction.mail_from.toString(),\n    });\n\n    next(OK);\n};\n```\n\n### `log(callerPlugin, connection, level, shortMessage, additionalFields)`\n\nSend a structured log message. Automatically formats `short_message` as `[transaction_uuid] [plugin_name] message` to match Haraka's log format, and populates `connection_uuid` and `transaction_uuid` template variables from the connection object.\n\n```javascript\ngelf?.log(this, connection, 6, 'Mail queued', { _queue: 'outbound' });\n```\n\n### Convenience log methods\n\nAll accept `(callerPlugin, connection, shortMessage, additionalFields)`. `connection` may be `null`.\n\n```javascript\nconst gelf = connection.server.notes.loggelf;\n\ngelf?.emergency(this, connection, 'System failure');\ngelf?.alert(this, connection, 'Disk almost full');\ngelf?.critical(this, connection, 'Database unreachable');\ngelf?.error(this, connection, 'Delivery failed', { _recipient: 'user@example.com' });\ngelf?.warning(this, connection, 'Rate limit approached');\ngelf?.notice(this, connection, 'New connection');\ngelf?.info(this, connection, 'Message accepted');\ngelf?.debug(this, connection, 'Processing step', { _detail: 'some value' });\n```\n\n### Additional fields in `msg`\n\nFields in `msg` beyond the standard GELF fields are included as additional fields, automatically prefixed with `_` if not already. Reserved GELF field names (`host`, `version`, `short_message`, `full_message`, `timestamp`, `level`, `facility`, `file`, `line`, `id`) are never duplicated as additional fields.\n\n| Type      | Behaviour                    |\n|-----------|------------------------------|\n| `string`  | Passed as-is                 |\n| `number`  | Passed as-is                 |\n| `boolean` | Converted to `\"true\"`/`\"false\"` |\n| `Date`    | Converted to ISO 8601 string |\n| Other     | JSON round-tripped           |\n\n## GELF message format\n\nMessages are sent as GELF 1.1 JSON over UDP. Supported standard fields:\n\n| Field           | Source                                         |\n|-----------------|------------------------------------------------|\n| `version`       | Always `\"1.1\"`                                 |\n| `host`          | `msg.host`, `hostname` config, or `os.hostname()` |\n| `short_message` | Required                                       |\n| `full_message`  | Optional                                       |\n| `timestamp`     | `msg.timestamp` (Date or number) or `Date.now()` |\n| `level`         | Syslog severity (0–7), defaults to INFO (6)    |\n| `facility`      | Optional                                       |\n| `file`          | Optional                                       |\n| `line`          | Optional integer                               |\n\n## Log levels\n\n| Level     | Value |\n|-----------|-------|\n| emergency | 0     |\n| alert     | 1     |\n| critical  | 2     |\n| error     | 3     |\n| warning   | 4     |\n| notice    | 5     |\n| info      | 6     |\n| debug     | 7     |\n\nHaraka log levels `DATA` and `PROTOCOL` are mapped to `DEBUG` (7).\n\n## License\n\nEUPL-1.1+\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzone-eu%2Fharaka-plugin-gelf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzone-eu%2Fharaka-plugin-gelf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzone-eu%2Fharaka-plugin-gelf/lists"}