{"id":44042465,"url":"https://github.com/ikornaselur/notiflux","last_synced_at":"2026-02-07T21:14:48.431Z","repository":{"id":229308397,"uuid":"775171263","full_name":"ikornaselur/notiflux","owner":"ikornaselur","description":"notiflux - subscribe over WebSockets, publish over REST","archived":false,"fork":false,"pushed_at":"2024-10-07T18:40:10.000Z","size":182,"stargazers_count":5,"open_issues_count":10,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-11T13:28:02.872Z","etag":null,"topics":["jwt","pubsub","rust","websocket"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ikornaselur.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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}},"created_at":"2024-03-20T22:20:34.000Z","updated_at":"2025-03-21T08:47:59.000Z","dependencies_parsed_at":"2024-05-03T09:09:22.145Z","dependency_job_id":"9cd635c8-a7ab-4b9e-9f1c-72cf52e5d1e6","html_url":"https://github.com/ikornaselur/notiflux","commit_stats":null,"previous_names":["ikornaselur/notiflux"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ikornaselur/notiflux","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikornaselur%2Fnotiflux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikornaselur%2Fnotiflux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikornaselur%2Fnotiflux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikornaselur%2Fnotiflux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ikornaselur","download_url":"https://codeload.github.com/ikornaselur/notiflux/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikornaselur%2Fnotiflux/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29208226,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T20:33:12.493Z","status":"ssl_error","status_checked_at":"2026-02-07T20:30:47.381Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["jwt","pubsub","rust","websocket"],"created_at":"2026-02-07T21:14:47.674Z","updated_at":"2026-02-07T21:14:48.422Z","avatar_url":"https://github.com/ikornaselur.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# notiflux\n\nnotiflux is a pub/sub server where clients subscribe over a WebSocket and\nmessages are broadcast over a POST request\n\n## How does it work?\n\nClient connect via WebSocket and subscribe to topics. A publishing source\nwill make POST requests to the broadcast endpoint, with a message and a topic,\nwhich will then publish the message to all connected clients.\n\n### Usage\n\n#### Subscribing to topics\n\nClients connect over WebSocket and subscribe to the topics, which can be any\nstring. The idea is that they could subscribe to something like\n`campaign:\u003ccampaign_id\u003e` for notifications about a specific campaign, or even\njust `campaigns` for all campaign updates.\n\nThis is by calling the subscribe command with the topic and a token (see next\nsection for token info)\n\n```\n/subscribe \u003ctopic\u003e \u003ctoken\u003e\n```\n\nclients can then unsubscribe with\n\n```\n/unsubscribe \u003ctopic\u003e  # From one topic\n/unsubscribe-all      # From all topics\n```\n\n#### Broadcasting messages\n\nTo make a broadcast to a topic, a POST request must be made to `/broadcast`,\nwhich includes the topic, message and token\n\n```bash\ncurl \\\n    -XPOST \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\"topic\": \"\u003ctopic\u003e\", \"message\": \"\u003cmessage\u003e\", \"token\": \"\u003ctoken\u003e\"}' \\\n    localhost:8080/broadcast\n```\n\n### Auth token\n\nNotiflux uses an EC256 public/private key pair JWT for authentication. Notiflux\nis deployed with the public key, while the broadcaster has the private key as a\nsecret.\n\nWhen clients connect, they need to provide a JWT with the topics and scope,\nsigned by the private key. This token should be provided be the broadcasting\nsource.\n\nTo make a broadcast, the broadcaster makes a POST request with a JWT as well,\nusing the broadcast scope.\n\n### JWT structure\n\nThe JWT token needs to have the following payload:\n\n```js\n{\n    \"sub\": \"notiflux\",               // Can be any value\n    \"exp\": 123,                      // Expiry just needs to be valid for the broadcast\n                                     // or subscribe event, so just few seconds is enough\n    \"topics\": [\"topic\"],             // The topics to validate against\n    \"scope\": \"subscribe|broadcast\",  // Needs to be either 'subscribe' for clients\n                                     // or 'broadcast' for broadcaster\n}\n```\n\nNote that the topics can be a list of just one topic or multiple topics, which\nmeans the same JWT can be used to subscribe or broadcast to multiple topics.\n\nSee ./scripts folder for examples in Python\n\n## Deployment\n\nnotiflux is published as a docker container as ghcr.io/ikornaselur/notiflux:latest\n\nThe configuration is done through environment variables:\n\n* `HOST`: Defaults to 127.0.0.1\n* `PORT`: Defaults to 8080\n* `JWT_PUBLIC_KEY_B64`: Required, the base64 encoded public key\n\nGenerating a private key can be done with\n\n```bash\nopenssl ecparam -genkey -name prime256v1 -out es256_private.pem\n```\n\nand then the public key\n\n```bash\nopenssl ec -in es256_private.pem -pubout -out es256_public.pem\n```\n\nwhich can be base64 encoded with\n\n```bash\ncat es256_public.pem | base64\n```\n\nthen running with docker is as simple as\n\n```bash\ndocker run \\\n    -e JWT_PUBLIC_KEY_B64=... \\\n    -e HOST=0.0.0.0 \\\n    -p 127.0.0.1:8080:8080 \\\n    ghcr.io/ikornaselur/notiflux:latest\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikornaselur%2Fnotiflux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fikornaselur%2Fnotiflux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikornaselur%2Fnotiflux/lists"}