Skip to content

macula-io/macula-mdns

 
 

Repository files navigation

Macula mDNS

Hex.pm Hex Docs

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.

Attribution

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

Overview

mDNS is an implementation of the Multicast DNS discovery protocol written in Erlang/OTP. It enables two or more Erlang nodes to:

Installation

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.

Quick Start

Automatic Node Discovery

By default, mDNS advertises a service of type _erlang._tcp. You can view registered services using standard tools:

Linux (Avahi):

avahi-browse _erlang._tcp

macOS:

dns-sd -B _erlang._tcp

Automatic Mesh Formation

mDNS can automatically form an Erlang/OTP mesh network when MDNS_CAN_MESH is enabled.

On dev001.local:

MDNS_CAN_MESH=true rebar3 shell

On dev002.local:

MDNS_CAN_MESH=true rebar3 shell

After 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']

Configuration

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)

Environment-Based Isolation

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 shell

Subscribing to Advertisements

mDNS 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}.

Advertisement Map Structure

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

Integration with Macula

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.

Architecture

┌─────────────────────────────────────────────────────┐
│                    mdns_sup                         │
│                  (supervisor)                       │
└────────────────┬────────────────────────────────────┘
                 │
     ┌───────────┴───────────┐
     │                       │
┌────▼─────────────┐  ┌──────▼────────────┐
│ mdns_advertise_  │  │ mdns_discover_    │
│ sup (supervisor) │  │ sup (supervisor)  │
└────────┬─────────┘  └────────┬──────────┘
         │                     │
    ┌────▼────┐           ┌────▼────┐
    │ mdns_   │           │ mdns_   │
    │advertise│           │discover │
    │ (worker)│           │ (worker)│
    └─────────┘           └─────────┘

Dependencies

  • gproc - Extended process registry with pub/sub
  • macula_envy - Environment configuration

Requirements

  • 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

Troubleshooting

No nodes discovered

  1. Check multicast: Ensure multicast is enabled on your network
  2. Check firewall: Allow UDP 5353 inbound and outbound
  3. Check environment: Nodes must share the same MDNS_ENVIRONMENT
  4. Check cookie: Nodes must share the same Erlang cookie for meshing

Verify mDNS traffic

# Linux - capture mDNS packets
sudo tcpdump -i any port 5353

# Verify service is advertised
avahi-browse -a

License

Apache-2.0

Links

About

Multicast DNS in Erlang/OTP

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Erlang 88.0%
  • Shell 8.9%
  • Makefile 3.1%