[25.04][mDNS][Guide] Making all apps easy access with .local domains

Truenas SCALE .local domains

I made this guid for myself, but I could be useful for others.
This guide describes how to configure TrueNAS 25.04 to broadcast .local domains for apps using Traefik and mdns-publish-cname app in Container (experimental in 25.04)

Preconfigure TrueNAS network bridge

By default Containers and VMs can’t see each other if used physical iface. To fix this TrueNAS should be configured to use bridged interface and acquire address on bridge itself.

Short instruction:

  • stop all apps, containers and VMs and unassign physical interfaces from it
  • remove dhcp or static addresses from physical interface at Network configuration
  • create a bridge interface and add a physical interface to it
  • Either configure static ip/alias or enable DHCP on Bridge
  • Test configuration and if everything ok → Save changes
  • Add new bridge interface as physical interface on app containers and VMs formerly used phy iface

Truenas docs how to configure bridge so containers and VMs can see TrueNAS

https://www.truenas.com/docs/scale/25.04/scaletutorials/network/containernasbridge/

Configure Container lightweight linux to broadcast mDNS

Install Alpine linux to Container

  • On Containers tab press Create Container
  • set name and chose Alpine edge linux image
  • uncheck Use default network settings network on Network section and choose bridged interface (not sure Bridged NICs or Macvlan NICs, guess first)
  • Create container

As container created login to it using web shell, here you can change root user password to use ssh or continue through web shell

Configure ssh (optional)

  • change root password with passwd command

  • install openssh apk add openssh

  • allow root login editing /etc/ssh/sshd_config with vi or install micro/nano and change PermitRootLogin yes

  • restart sshd rc-service sshd restart

    Now you should be able to login to container with ssh and root

Install avahi-daemon and tools

  • install avahi daemon apk add avahi

  • install avahi tools apk add avahi-tools

  • enable avahi-daemon rc-update add avahi-daemon

  • start avahi-daemon rc-service avahi-daemon start

    now you should able to see your container domain in network as .local

Install usefull toolls (optional)

You can install handy editor with syntax highlighting micro apk add micro or nano apk add nano \nAlso useful tools it bat apk install bat like cat but with syntax highlight and lnav log viewer.

Install mdns-publish-cname

This is a python app so you need install python first and its binary dependencies:

  • apk add python3
  • apk add py3-pip
  • apk add gcc
  • apk add python3-dev
  • apk add dbus-dev dbus-glib-dev
  • apk add git

Then you can run pip install --break-system-packages mdns-publisher to install app systemwide and run hash -r to update paths.\nYou now able to test if everything working running command mdns-publish-cname paperless.local you should able to ping this domain from you device in network.\n\nThen we need to create init script so it will start automatically, use micro /etc/init.d/mdns-publish-cname to create and open edit file or touch and vi and place script to it:

#!/sbin/openrc-run

name="mdns-publish-cname"
description="Publish CNAME records via mDNS"
command="/usr/bin/mdns-publish-cname"
command_args=" paperless.local netdata.local plex.local radarr.local sonarr.local flood.local outline.local "
pidfile="/run/${RC_SVCNAME}.pid"
command_background="yes"
output_log="/var/log/${RC_SVCNAME}.log"
error_log="/var/log/${RC_SVCNAME}.log"

depend() {
    need net avahi-daemon
    after avahi-daemon
}

start_pre() {
    if [ ! -x "${command}" ]; then
        eerror "Command ${command} not found or not executable"
        return 1
    fi
    
    # Clean up any stale PID file
    if [ -f "${pidfile}" ]; then
        rm -f "${pidfile}"
    fi
}

start() {
    ebegin "Starting ${name}"
    
    start-stop-daemon --start \
        --background \
        --make-pidfile \
        --pidfile "${pidfile}" \
        --stdout "${output_log}" \
        --stderr "${error_log}" \
        --exec "${command}" \
        -- ${command_args}
    
    eend $?
}

stop() {
    ebegin "Stopping ${name}"
    
    start-stop-daemon --stop \
        --pidfile "${pidfile}" \
        --retry 10
    
    eend $?
}

status() {
    if [ -f "${pidfile}" ]; then
        read pid < "${pidfile}"
        if kill -0 "${pid}" 2>/dev/null; then
            einfo "status: started (pid ${pid})"
            return 0
        else
            einfo "status: crashed"
            return 1
        fi
    else
        einfo "status: stopped"
        return 3
    fi
}

In command_args= you should place domains you want to publish/broadcast

Then make script executable by chmod +x /etc/init.d/mdns-publish-cname.

Add to autorun and start:

  • rc-update add mdns-publish-cname
  • rc-service mdns-publish-cname start

Configure Traefik to reverse proxy to apps

  • Install Traefik apk add traefik
  • edit Traefik config: micro /etc/traefik/traefik.yaml like this:
global:
  checkNewVersion: false
  sendAnonymousUsage: false

log:
  level: DEBUG
  filePath: /var/log/traefik/traefik.log

accessLog:
  filePath: /var/log/traefik/access.log

entryPoints:
  http:
    address: ':80'
  https:
    address: ':443'
  traefik:
    address: ':8080'

api:
  insecure: true
  dashboard: true

ping: {}

#certificatesResolvers:
#  sample:
#    acme:
#      email: ''
#      storage: traefik/acme/account
#      dnsChallenge:
#        provider: cloudflare
#        delayBeforeCheck: 10

providers:
  file:
    directory: /etc/traefik/dynamic
    watch: true

I set log level to DEBUG for now, you may need to change to INFO after ensure that everything works.
Also made :8080 port allowed from external to see Traefik dashboard\nAnd configured providers to look for configs at dynamic dir like nginx site-enable approach. Then we need to configure those site. I will show only one so you can copy change for every app.

  • create configuration for you app (paperless in my case): micro /etc/traefik/dynamic/paperless.yaml :
http:
  routers:
    paperless:
      rule: "Host(`paperless.local`)"
      entryPoints:
        - http
      service: paperless_svc
  services:
    paperless_svc:
      loadBalancer:
        servers:
          - url: "http://192.168.88.22:30070"

where paperless and paperless_svc is variables, should be uniq for every site, paperless.local is domain we listen and published with mdns service at url: actual url to app in truenas, you should use IP address instead of truenas.local:30070 as local mdns resolver not used. At this stage make sense to set IP addresses to static in router DHCP settings.

  • add traefik service and run rc-update add traefik rc-service traefik start you can see traefik log at /var/log/traefik.log with cat or lnav to see that everything works smoothly. Next when will add new sites configs to dynamic directory or change it will reload config on-the-fly (watch: true).

Now you should be able to access your configured apps by their local domains like paperless.local, plex.local etc