Zero-configuration networking for Erlang/OTP applications using Multicast DNS.
This is a rebar3-compatible fork of shortishly/mdns, maintained by macula-io for use in the Macula HTTP/3 mesh platform.
This library was originally created by Peter Morgan (shortishly).
Peter Morgan's implementation provides an elegant, production-ready mDNS solution that enables automatic node discovery and mesh formation in local networks. All credit for the design, protocol implementation, and core functionality goes to Peter Morgan. This fork adds rebar3/hex.pm packaging support while preserving the original functionality.
Original Repository: github.com/shortishly/mdns
mDNS is an implementation of the Multicast DNS discovery protocol written in Erlang/OTP. It enables two or more Erlang nodes to:
- Self-discover other nodes on the local network
- Automatically form a mesh network
- Register and discover services using DNS-Based Service Discovery (RFC 6763)
Add macula_mdns to your rebar.config dependencies:
{deps, [
{macula_mdns, "0.1.0"}
]}.Note: The hex package is named macula_mdns, but the OTP application is mdns for compatibility with the original API.
By default, mDNS advertises a service of type _erlang._tcp. You can view registered services using standard tools:
Linux (Avahi):
avahi-browse _erlang._tcpmacOS:
dns-sd -B _erlang._tcpmDNS can automatically form an Erlang/OTP mesh network when MDNS_CAN_MESH is enabled.
On dev001.local:
MDNS_CAN_MESH=true rebar3 shellOn dev002.local:
MDNS_CAN_MESH=true rebar3 shellAfter a short period, both machines will have automatically formed a mesh:
(mdns@dev001.local)1> nodes().
['mdns@dev002.local'](mdns@dev002.local)1> nodes().
['mdns@dev001.local']mDNS can be configured via environment variables or application environment:
| Application Config | Environment Variable | Default | Description |
|---|---|---|---|
can_advertise |
MDNS_CAN_ADVERTISE |
true |
Advertise this node's services |
can_discover |
MDNS_CAN_DISCOVER |
true |
Discover other nodes |
can_mesh |
MDNS_CAN_MESH |
false |
Auto-form Erlang cluster |
environment |
MDNS_ENVIRONMENT |
dev |
Environment tag (nodes must match to mesh) |
multicast_address |
MDNS_MULTICAST_ADDRESS |
224.0.0.251 |
mDNS multicast address |
udp_port |
MDNS_UDP_PORT |
5353 |
mDNS UDP port |
domain |
MDNS_DOMAIN |
.local |
mDNS domain |
service |
MDNS_SERVICE |
_erlang._tcp |
Service type to advertise |
ttl |
MDNS_TTL |
120 |
DNS record TTL (seconds) |
Only nodes that share the same environment value can be automatically meshed together. This allows multiple development environments on the same network:
# Team A's development cluster
MDNS_ENVIRONMENT=team_a MDNS_CAN_MESH=true rebar3 shell
# Team B's development cluster (won't mesh with Team A)
MDNS_ENVIRONMENT=team_b MDNS_CAN_MESH=true rebar3 shellmDNS uses gproc's pub/sub pattern. Applications can subscribe to mDNS advertisements:
%% Subscribe to advertisement events
mdns:subscribe(advertisement).
%% In your gen_server handle_info/2:
handle_info({gproc_ps_event, advertisement, Info}, State) ->
#{host := Host,
node := Node,
port := Port,
env := Env} = Info,
%% Handle the discovered node...
{noreply, State}.| Key | Type | Description |
|---|---|---|
host |
binary() |
Hostname of the advertised node |
node |
atom() |
Node name of the advertised node |
port |
integer() |
Distribution protocol port |
env |
binary() |
Environment of this node |
In the Macula HTTP/3 mesh platform, mDNS provides optional local network discovery. When available, Macula uses mDNS to discover seed nodes on the local network, reducing the need for static seed configuration.
%% Macula checks for mDNS availability
case whereis(mdns_advertise_sup) of
undefined ->
%% mDNS not available, use DHT discovery
ok;
_Pid ->
%% Subscribe to local node advertisements
mdns:subscribe(advertisement)
end.See Macula mDNS Setup Guide for integration details.
┌─────────────────────────────────────────────────────┐
│ mdns_sup │
│ (supervisor) │
└────────────────┬────────────────────────────────────┘
│
┌───────────┴───────────┐
│ │
┌────▼─────────────┐ ┌──────▼────────────┐
│ mdns_advertise_ │ │ mdns_discover_ │
│ sup (supervisor) │ │ sup (supervisor) │
└────────┬─────────┘ └────────┬──────────┘
│ │
┌────▼────┐ ┌────▼────┐
│ mdns_ │ │ mdns_ │
│advertise│ │discover │
│ (worker)│ │ (worker)│
└─────────┘ └─────────┘
- gproc - Extended process registry with pub/sub
- macula_envy - Environment configuration
- Network: Multicast must be enabled on your network
- Firewall: UDP port 5353 must be open for mDNS traffic
- Same subnet: Nodes must be on the same local network segment
- Check multicast: Ensure multicast is enabled on your network
- Check firewall: Allow UDP 5353 inbound and outbound
- Check environment: Nodes must share the same
MDNS_ENVIRONMENT - Check cookie: Nodes must share the same Erlang cookie for meshing
# Linux - capture mDNS packets
sudo tcpdump -i any port 5353
# Verify service is advertised
avahi-browse -aApache-2.0
- Original Repository - Peter Morgan's original implementation
- Macula Platform - HTTP/3 mesh networking platform
- mDNS RFC - Protocol specification
- DNS-SD RFC 6763 - Service discovery specification
- Hex.pm Package
- Documentation