{"id":28196331,"url":"https://github.com/nerves-networking/mdns_lite","last_synced_at":"2025-05-16T15:14:47.306Z","repository":{"id":37895988,"uuid":"271544799","full_name":"nerves-networking/mdns_lite","owner":"nerves-networking","description":"A simple, no frills mDNS implementation in Elixir","archived":false,"fork":false,"pushed_at":"2025-03-06T03:42:27.000Z","size":337,"stargazers_count":38,"open_issues_count":5,"forks_count":14,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-06T04:26:12.915Z","etag":null,"topics":["elixir","mdns","nerves"],"latest_commit_sha":null,"homepage":"","language":"Elixir","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/nerves-networking.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}},"created_at":"2020-06-11T12:49:10.000Z","updated_at":"2025-03-06T03:42:18.000Z","dependencies_parsed_at":"2023-12-29T23:22:57.828Z","dependency_job_id":"73aa3c9b-9bb1-4ee2-9aaa-bdbeb20cfbb0","html_url":"https://github.com/nerves-networking/mdns_lite","commit_stats":{"total_commits":237,"total_committers":15,"mean_commits":15.8,"dds":"0.43881856540084385","last_synced_commit":"d1257382acd554bde9300832b8ab1670ec6da664"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nerves-networking%2Fmdns_lite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nerves-networking%2Fmdns_lite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nerves-networking%2Fmdns_lite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nerves-networking%2Fmdns_lite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nerves-networking","download_url":"https://codeload.github.com/nerves-networking/mdns_lite/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254554026,"owners_count":22090420,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["elixir","mdns","nerves"],"created_at":"2025-05-16T15:14:46.466Z","updated_at":"2025-05-16T15:14:47.296Z","avatar_url":"https://github.com/nerves-networking.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MdnsLite\n\n[![Hex version](https://img.shields.io/hexpm/v/mdns_lite.svg \"Hex version\")](https://hex.pm/packages/mdns_lite)\n[![API docs](https://img.shields.io/hexpm/v/mdns_lite.svg?label=hexdocs \"API docs\")](https://hexdocs.pm/mdns_lite/MdnsLite.html)\n[![CircleCI](https://dl.circleci.com/status-badge/img/gh/nerves-networking/mdns_lite/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/nerves-networking/mdns_lite/tree/main)\n[![REUSE status](https://api.reuse.software/badge/github.com/nerves-networking/mdns_lite)](https://api.reuse.software/info/github.com/nerves-networking/mdns_lite)\n\nMdnsLite is a simple, limited, no frills implementation of an\n[mDNS](https://en.wikipedia.org/wiki/Multicast_DNS) (Multicast Domain Name\nSystem) client and server. It operates like DNS, but uses multicast instead of\nunicast so that any computer on a LAN can help resolve names. In particular, it\nresolves hostnames that end in `.local` and provides a way to advertise and\ndiscovery service.\n\nMdnsLite is intended for environments like on Nerves devices that do not already\nhave an `mDNS` service. If you're running on desktop Linux or on MacOS, you\nalready have `mDNS` support and do not need MdnsLite.\n\nFeatures of MdnsLite:\n\n* Advertise `\u003chostname\u003e.local` and aliases for ease of finding devices\n* Static (application config) and dynamic service registration\n* Support for multi-homed devices. For example, mDNS responses sent on a network\n  interface have the expected IP addresses for that interface.\n* DNS bridging so that Erlang's built-in DNS resolver can look up `.local` names\n  via mDNS.\n* Caching of results and advertisements seen on the network\n* Integration with\n  [VintageNet](https://github.com/nerves-networking/vintage_net) and Erlang's\n  `:inet` application for network interface monitoring\n* Easy inspection of mDNS record tables to help debug service discovery issues\n\nMdnsLite is included in [NervesPack](https://hex.pm/packages/nerves_pack) so you\nmight already have it!\n\n## Configuration\n\nA typical configuration in the `config.exs` file looks like:\n\n```elixir\nconfig :mdns_lite,\n  # Advertise `hostname.local` on the LAN\n  hosts: [:hostname],\n  # If instance_name is not defined it defaults to the first hostname\n  instance_name: \"Awesome Device\",\n  services: [\n    # Advertise an HTTP server running on port 80\n    %{\n      id: :web_service,\n      protocol: \"http\",\n      transport: \"tcp\",\n      port: 80,\n    },\n    # Advertise an SSH daemon on port 22\n    %{\n      id: :ssh_daemon,\n      protocol: \"ssh\",\n      transport: \"tcp\",\n      port: 22,\n    }\n  ]\n```\n\nThe `services` section lists the services that the host offers, such as\nproviding an HTTP server. Specifying a `protocol`, `transport` and `port` is\nusually the easiest way. The `protocol` and `transport` get combined to form the\nservice type that's actually advertised on the network. For example, a \"tcp\"\ntransport and \"ssh\" protocol will end up as `\"_ssh._tcp\"` in the advertisement.\nIf you need something custom, specify `:type` directly. Optional fields include\n`:id`, `:weight`, `:priority`, `:instance_name` and `:txt_payload`. An `:id` is\nneeded to remove the service advertisement at runtime. If not specified,\n`:instance_name` is inherited from the top-level config.  A `:txt_payload` is a\nlist of `\"\u003ckey\u003e=\u003cvalue\u003e\"` string that will be advertised in a TXT DNS record\ncorresponding to the service.\n\nSee [`MdnsLite.Options`](https://hexdocs.pm/mdns_lite/MdnsLite.Options.html) for\ninformation about all application environment options.\n\nIt's possible to change the advertised hostnames, instance names and services at\nruntime. For example, to change the list of advertised hostnames, run:\n\n```elixir\niex\u003e MdnsLite.set_hosts([:hostname, \"nerves\"])\n:ok\n```\n\nTo change the advertised instance name:\n\n```elixir\niex\u003e MdnsLite.set_instance_name(\"My Other Awesome Device\")\n:ok\n```\n\nHere's how to add and remove a service at runtime:\n\n```elixir\niex\u003e MdnsLite.add_mdns_service(%{\n    id: :my_web_server,\n    protocol: \"http\",\n    transport: \"tcp\",\n    port: 80,\n  })\n:ok\niex\u003e MdnsLite.remove_mdns_service(:my_web_server)\n:ok\n```\n\n## Client\n\n`MdnsLite.gethostbyname/1` uses mDNS to resolve hostnames. Here's an example:\n\n```elixir\niex\u003e MdnsLite.gethostbyname(\"my-laptop.local\")\n{:ok, {172, 31, 112, 98}}\n```\n\nIf you just want mDNS to \"just work\" with Erlang, you'll need to enable\nMdnsLite's DNS Bridge feature and configure Erlang's DNS resolver to use it. See\nthe DNS Bridge section for details.\n\nService discovery docs TBD...\n\n## DNS Bridge configuration\n\n`MdnsLite` can start a DNS server to respond to `.local` queries. This enables\ncode that has no knowledge of mDNS to resolve mDNS queries. For example,\nErlang/OTP's built-in DNS resolver doesn't know about mDNS. It's used to resolve\nhosts for Erlang distribution and pretty much any code using `:gen_tcp` and\n`:gen_udp`. `MdnsLite`'s DNS bridge feature makes `.local` hostname lookups work\nfor all of this. No code modifications required.\n\nNote that this feature is useful on Nerves devices. Erlang/OTP can use the\nsystem name resolver on desktop Linux and MacOS. The system name resolver should\nalready be hooked up to an mDNS resolver there.\n\nTo set this up, you'll need to enable the DNS bridge on `MdnsLite` and then set\nup the DNS resolver to use it first. Here are the options for the application\nenvironment:\n\n```elixir\nconfig :mdns_lite,\n  dns_bridge_enabled: true,\n  dns_bridge_ip: {127, 0, 0, 53},\n  dns_bridge_port: 53\n\nconfig :vintage_net,\n  additional_name_servers: [{127, 0, 0, 53}]\n```\n\nThe choice of running the DNS bridge on 127.0.0.53:53 is mostly arbitrary. This\nis the default.\n\n\u003e #### Info {: .info}\n\u003e\n\u003e If you're using a version of Erlang/OTP before 24.1, you'll be affected by\n\u003e [OTP #5092](https://github.com/erlang/otp/issues/5092). The workaround is to\n\u003e add the `dns_bridge_recursive: true` option to the `:mdns_lite` config.\n\n## Debugging\n\n`MdnsLite` maintains a table of records that it advertises and a cache per\nnetwork interface. The table of records that it advertises is based solely off\nits configuration. Review it by running:\n\n```elixir\niex\u003e MdnsLite.Info.dump_records\n\u003cinterface_ipv4\u003e.in-addr.arpa: type PTR, class IN, ttl 120, nerves-2e6d.local\n\u003cinterface_ipv6\u003e.ip6.arpa: type PTR, class IN, ttl 120, nerves-2e6d.local\n_epmd._tcp.local: type PTR, class IN, ttl 120, nerves-2e6d._epmd._tcp.local\n_services._dns-sd._udp.local: type PTR, class IN, ttl 120, _epmd._tcp.local\n_services._dns-sd._udp.local: type PTR, class IN, ttl 120, _sftp-ssh._tcp.local\n_services._dns-sd._udp.local: type PTR, class IN, ttl 120, _ssh._tcp.local\n_sftp-ssh._tcp.local: type PTR, class IN, ttl 120, nerves-2e6d._sftp-ssh._tcp.local\n_ssh._tcp.local: type PTR, class IN, ttl 120, nerves-2e6d._ssh._tcp.local\nnerves-2e6d._epmd._tcp.local: type SRV, class IN, ttl 120, priority 0, weight 0, port 4369, nerves-2e6d.local.\nnerves-2e6d._epmd._tcp.local: type TXT, class IN, ttl 120,\nnerves-2e6d._sftp-ssh._tcp.local: type SRV, class IN, ttl 120, priority 0, weight 0, port 22, nerves-2e6d.local.\nnerves-2e6d._sftp-ssh._tcp.local: type TXT, class IN, ttl 120,\nnerves-2e6d._ssh._tcp.local: type SRV, class IN, ttl 120, priority 0, weight 0, port 22, nerves-2e6d.local.\nnerves-2e6d._ssh._tcp.local: type TXT, class IN, ttl 120,\nnerves-2e6d.local: type A, class IN, ttl 120, addr \u003cinterface_ipv4\u003e\nnerves-2e6d.local: type AAAA, class IN, ttl 120, addr \u003cinterface_ipv6\u003e\n```\n\nNote that some addresses have not been filled in. They depend on which network\ninterface receives the query. The idea is that if a computer is looking for you\non the Ethernet interface, you should give records with that Ethernet's\ninterface rather than, say, the IP address of the WiFi interface.\n\n`MdnsLite`'s cache is filled with records that it sees advertised. It's\nbasically the same, but can be quite large depending on the mDNS activity on a\nlink. It looks like this:\n\n```elixir\niex\u003e MdnsLite.Info.dump_caches\nResponder: 172.31.112.97\n  ...\nResponder: 192.168.1.58\n  ...\n```\n\n## In memory\n\n[Peter Marks](https://github.com/pcmarks/) wrote and maintained the original\nversion of `mdns_lite`.\n\n## License\n\nCopyright (C) 2019-21 SmartRent\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnerves-networking%2Fmdns_lite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnerves-networking%2Fmdns_lite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnerves-networking%2Fmdns_lite/lists"}