{"id":50381938,"url":"https://github.com/benoitc/mycelium","last_synced_at":"2026-05-30T12:30:37.844Z","repository":{"id":355480734,"uuid":"1228160052","full_name":"benoitc/mycelium","owner":"benoitc","description":"HyParView P2P membership over upstream quic_dist with multi-hop circuits","archived":false,"fork":false,"pushed_at":"2026-05-24T05:58:02.000Z","size":1255,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-24T07:20:31.509Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benoitc.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":"SECURITY-AUDIT-PREP.md","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-05-03T17:12:06.000Z","updated_at":"2026-05-24T05:58:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/benoitc/mycelium","commit_stats":null,"previous_names":["benoitc/mycelium"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/benoitc/mycelium","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitc%2Fmycelium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitc%2Fmycelium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitc%2Fmycelium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitc%2Fmycelium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benoitc","download_url":"https://codeload.github.com/benoitc/mycelium/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benoitc%2Fmycelium/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33692997,"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-05-30T02:00:06.278Z","response_time":92,"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-05-30T12:30:37.316Z","updated_at":"2026-05-30T12:30:37.831Z","avatar_url":"https://github.com/benoitc.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mycelium\n\nMycelium is an Erlang/OTP library for peer-to-peer clusters.\n\nIt keeps the Erlang programming model: `Pid ! Msg`, `gen_server`,\n`rpc`, links, monitors, and the usual supervision habits. It changes\nwhat happens underneath:\n\n- distribution runs over QUIC, not TCP;\n- nodes authenticate with Ed25519;\n- membership is bounded with HyParView, not full mesh;\n- services are discovered through a CRDT registry;\n- EPMD is not required.\n\nThe result is a cluster where each node keeps a small number of gossip\nconnections, while any process can still talk to any process in the\ncluster.\n\n## Why Erlang developers may care\n\nStandard Erlang distribution is simple and good. It becomes harder to\noperate when the cluster grows, when every node must connect to every\nother node, when EPMD is not welcome, or when nodes move between\nnetwork paths.\n\nMycelium keeps your application code close to normal OTP code. You\nstill register processes, call servers, monitor pids, and send\nmessages. The library takes care of the cluster shape, peer identity,\nservice discovery, and the QUIC dist carrier.\n\n## The cluster shape\n\nRead this graph from node A. The green nodes are the active view:\nthe small set of peers node A uses for gossip and membership\nmaintenance. The grey nodes are known peers kept in the passive view.\nThey are not connected now, but they are warm spares when the topology\nchanges.\n\n![HyParView active view: a node connects to a small set of gossip peers, with additional known peers held in a passive cache.](docs/diagrams/active-view.png)\n\nThe important point: the active view is not the cluster. It is not\nthe list of nodes your application may talk to. It is only the\nmaintenance topology.\n\nApplication traffic is different. If code on node A sends to a pid on\nnode E, OTP can open a dist channel on demand. Mycelium authenticates\nthat channel, then the normal Erlang message is delivered.\n\n![Sending a message to a pid on a node that is not in the local active view: OTP opens a QUIC dist channel on demand, runs Ed25519 auth, then delivers the message.](docs/diagrams/message-passing.png)\n\nOnce you hold the pid, Mycelium is no longer on the application data\npath. You use Erlang.\n\n## Project status\n\nMycelium is experimental and pre-1.0. APIs may change between minor\nreleases until a `1.0` tag.\n\nThe cryptographic and transport layers, Ed25519 dist auth and the\nQUIC carrier, have unit and multi-node test coverage. They have not\nbeen independently audited. Do not use Mycelium where a transport\ncompromise would be costly without doing your own review first.\n\nBug reports and PRs are welcome. Security reports go through\n[SECURITY.md](SECURITY.md).\n\n## Five-minute start\n\nAdd Mycelium to `rebar.config`:\n\n```erlang\n{deps, [\n    {mycelium, \"0.1.0\"}\n]}.\n```\n\nUse Mycelium as the Erlang distribution carrier:\n\n```text\n-proto_dist mycelium\n-epmd_module mycelium_epmd\n-start_epmd false\n```\n\nStart the application and join a seed:\n\n```erlang\napplication:ensure_all_started(mycelium).\nok = mycelium:join('seed@192.168.1.10').\n```\n\nRegister the current process as a service:\n\n```erlang\nok = mycelium:register_service(worker_pool, #{shard =\u003e 1}).\n```\n\nFind it from another node:\n\n```erlang\n{ok, _Node, Worker} = mycelium:whereis_service(worker_pool),\nWorker ! {work, \u003c\u003c\"payload\"\u003e\u003e}.\n```\n\nThat send is a standard Erlang send. `whereis_service/1` returns\n`{ok, Pid}` for a local service and `{ok, Node, Pid}` for a remote\none. If the target node is not already connected, the dist channel is\nopened on demand over QUIC.\n\n## Configuration\n\nA small development config:\n\n```erlang\n{mycelium, [\n    {active_size, 5},\n    {passive_size, 30},\n    {listen_port, 9100},\n    {contact_nodes, ['seed@192.168.1.10']},\n    {auth_enabled, true},\n    {auth_trust_mode, tofu}\n]}.\n```\n\nThe defaults are intentionally narrow:\n\n- `active_size` bounds the number of gossip peers.\n- `passive_size` bounds the known-but-disconnected peer cache.\n- `listen_port` is the UDP port for QUIC distribution.\n- `contact_nodes` gives the node a first place to join.\n- `auth_trust_mode` is `tofu` or `strict`.\n\nFor production notes, see [run in production](docs/how-to/run-in-production.md).\n\n## What is included\n\n- **QUIC distribution**. `-proto_dist mycelium` plugs into Erlang's\n  alternative distribution layer. No stock EPMD daemon is required.\n- **HyParView membership**. Each node keeps a bounded active view\n  instead of a full mesh.\n- **Service registry**. Processes can be registered by name and found\n  from any node through a CRDT-backed registry.\n- **Replicated state**. `mycelium_map` is a gossiped, last-write-wins\n  key-value map for cluster-wide config, flags, and routing tables;\n  the `mycelium_replica` behaviour underneath is public for custom\n  merge.\n- **Plumtree broadcast**. Registry changes and gossip move through an\n  efficient epidemic broadcast tree.\n- **Ed25519 peer identity**. Nodes prove their identity after the QUIC\n  TLS handshake and before application traffic flows.\n- **Tagged QUIC streams**. Applications can open tagged streams for\n  large or byte-oriented transfers.\n- **Operational tools**. Helpers exist for one-shot RPC, TLS material,\n  key rotation, metrics, migration, and test clusters.\n\n## Documentation\n\nThe docs are organised into five sections. Each section has a hub\npage that lists its children; the hub pages are linked below.\n\n### Overview\n\nRead this first if mycelium is new to you.\n\n- [What is mycelium?](docs/overview/what-is-mycelium.md) — the\n  project in one page, with the architecture diagram and the\n  load-bearing ideas.\n- [Benefits and trade-offs](docs/overview/benefits.md) — why pick\n  mycelium, and what you give up.\n- [Introduction](docs/overview/introduction.md) — the long\n  narrative through every layer.\n- [Getting started](docs/overview/getting-started.md) — boot two\n  nodes and send a real message.\n\n### Core concepts\n\nHow each subsystem works, explained one page at a time.\n\n- [Cluster membership](docs/concepts/cluster-membership.md) —\n  HyParView's bounded active and passive views.\n- [Service registry](docs/concepts/service-registry.md) — OR-Map\n  CRDT, eventual consistency, the registration lifecycle.\n- [Gossip broadcast](docs/concepts/gossip-broadcast.md) — Plumtree\n  push-lazy-push trees, self-healing graft/prune.\n- [Dist channel](docs/concepts/dist-channel.md) —\n  `-proto_dist mycelium` over QUIC, the discovery chain, the\n  idle GC.\n- [Authentication](docs/concepts/authentication.md) — Ed25519\n  mutual challenge-response, trust modes.\n- [Streams](docs/concepts/streams.md) — tagged user-stream\n  multiplex over the same QUIC connection.\n- [Connection migration](docs/concepts/connection-migration.md) —\n  RFC 9000 §9 path rebind.\n- [Hybrid logical clocks](docs/concepts/hybrid-logical-clocks.md) —\n  the timestamps the CRDT uses.\n\n### Tutorials\n\nEnd-to-end walkthroughs.\n\n- [Hello, cluster](docs/tutorials/hello-cluster.md) — the\n  smallest two-node walkthrough.\n- [Distributed chat](docs/tutorials/distributed-chat.md) — a\n  small application that uses the service registry and service\n  events.\n\n### How-to guides\n\nTask-focused recipes for operating a cluster.\n\n- [Run in production](docs/how-to/run-in-production.md) — sizing,\n  network surface, secrets, shutdown.\n- [Configure authentication](docs/how-to/configure-authentication.md)\n  — TOFU and strict modes, provisioning, rotation.\n- [Observe a cluster](docs/how-to/observe-cluster.md) — metrics\n  catalogue and exporter wiring.\n- [Troubleshoot](docs/how-to/troubleshoot.md) — symptom-cause-fix\n  tables.\n- [Migrate connections](docs/how-to/migrate-connections.md) — a\n  watchdog recipe for path migration.\n- [Route through a relay](docs/how-to/route-through-relay.md) —\n  wiring an external tunnel or proxy adapter.\n- [Run the tests](docs/how-to/run-tests.md) — EUnit, Common Test,\n  docker, and soak suites.\n\n### Reference\n\nAuthoritative material when you know what you are looking for.\n\n- [API overview](docs/reference/api-overview.md) — every public\n  function in `mycelium.erl`, grouped by subsystem.\n- [Configuration](docs/reference/configuration.md) — every key\n  under `{mycelium, [...]}` in sys.config.\n- [Architecture](docs/reference/architecture.md) — the full\n  supervision tree and protocol-level details.\n- [Comparison with Partisan](docs/reference/comparison-with-partisan.md)\n  — side-by-side, when to pick which library.\n- [Feature stability](docs/features.md) — public API tiers and\n  coverage.\n\n## Example application\n\nA small distributed chat app lives under\n[`examples/chat`](examples/chat/README.md).\n\n```bash\ncd examples/chat\n./scripts/run-demo.sh seed\n./scripts/run-demo.sh node 1\n```\n\nThe demo starts Erlang nodes with `-proto_dist mycelium`, generates\nlocal TLS and Ed25519 material on first boot, and uses the service\nregistry to find chat rooms across the cluster.\n\n## Testing\n\nRun the local suites:\n\n```bash\nrebar3 eunit\nrebar3 ct\n```\n\nThe Docker scripts under `docker/scripts/` exercise multi-node\nclusters. See [run the tests](docs/how-to/run-tests.md) for the\nfull command list.\n\n## API reference\n\nGenerate HTML documentation:\n\n```bash\nrebar3 ex_doc\n```\n\n## Versioning\n\nMycelium is still in `0.x`.\n\n- Minor bumps, `0.x` to `0.y`, may change documented public APIs.\n- Patch bumps, `0.x.y` to `0.x.y+1`, are non-breaking.\n- `1.0` will come after an external audit of the dist auth and\n  transport layers, and after public user feedback on a `0.x` release.\n\nPublic API stability tiers are tracked in [docs/features.md](docs/features.md).\nAnything not listed there is internal.\n\n## License\n\nApache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitc%2Fmycelium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenoitc%2Fmycelium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitc%2Fmycelium/lists"}