relayd

command module
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

README



GitHub Tag GitHub License GitHub Issues or Pull Requests

Relayd

relayd is a lightweight, "set and forget" external DNS synchronization agent for Docker. It seamlessly updates DNS records (A, AAAA, and TXT ownership records) across various providers based on your Docker container labels.

Features

  • Docker Native: Automatically extracts hostnames from relayd.hosts and Traefik .rule labels.
  • Dual-Stack Support: Synchronizes both A (IPv4) and AAAA (IPv6) records simultaneously.
  • Safe Ownership: Uses specific TXT records to track ownership, guaranteeing it will never overwrite or delete domains it doesn't own.
  • Multi-Provider: Sync your public domains to Cloudflare, while simultaneously syncing your internal/local domains to Pi-hole, UniFi, or PowerDNS.

Usage

Simply run the container and mount the docker socket:

Docker Compose

In standard Docker, relayd automatically discovers the primary local IP using the OS routing table. Use network_mode: host to give relayd direct access to the host's network interfaces so it can discover the host's actual LAN IP:

services:
  relayd:
    image: ghcr.io/mizuchilabs/relayd:latest
    network_mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - RELAYD_PROVIDER_CLOUDFLARE_TYPE=cloudflare
      - RELAYD_PROVIDER_CLOUDFLARE_TOKEN=your-api-token
      - RELAYD_PROVIDER_CLOUDFLARE_ZONES=example.com
Docker Swarm

relayd has native Docker Swarm support. Because Swarm's ingress routing mesh automatically routes traffic received on any node to the correct container, you only need to publish one IP address for your services.

You should run exactly one instance of relayd on a manager node. It will automatically detect all swarm services with the relayd.enable=true label across the entire cluster and publish its own node's IP.

services:
  relayd:
    image: ghcr.io/mizuchilabs/relayd:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    environment:
      - RELAYD_PROVIDER_CLOUDFLARE_TYPE=cloudflare
      - RELAYD_PROVIDER_CLOUDFLARE_TOKEN=your-api-token
      - RELAYD_PROVIDER_CLOUDFLARE_ZONES=example.com

Note: Without host networking or manual overrides, relayd will discover its internal container IP. If you are using local-scoped providers and need the actual Host IP, you can configure the RELAYD_LOCAL_OVERRIDE_IPV4 and RELAYD_LOCAL_OVERRIDE_IPV6 environment variables manually. For public-scoped providers (the default), relayd uses external services to resolve the public IP automatically, so network mode does not matter.

Adding domains to your containers

You can configure DNS targets by adding the relayd.enable and relayd.hosts label to any container:

services:
  whoami:
    image: traefik/whoami
    labels:
      - relayd.enable=true
      - relayd.hosts=whoami.example.com,test.example.com
      # If you are using Traefik, you can also add the following and remove the `relayd.hosts` label:
      - traefik.enable=true
      - traefik.http.routers.whoami.rule=Host(`whoami.example.com`)
      # To restrict which DNS providers or scopes a container uses use the `relayd.providers` label:
      - relayd.providers=local # or cloudflare, pihole, unifi, powerdns

Architecture & Edge Cases

To prevent disaster, relayd uses a Safe Ownership model. Whenever it creates an A or AAAA record, it creates a companion TXT record (e.g., relayd.yoursubdomain="managed-by=relayd-yourhostname"). relayd will never delete or modify a DNS record unless it sees its exact matching TXT record.

Multiple Instances (Split-Brain)

If you run relayd on two entirely separate Docker hosts (Host A and Host B) that point to the same DNS Zone, they will natively ignore each other's records if their hostnames don't match and force mode is enabled. Otherwise if force mode is disabled and these instances point to the same DNS Zone, they will constantly overwrite each other's records! Be careful when using it with Pi-hole since it doesn't support TXT records.

Using with tether & tetherd (Centralized Traefik)

If you are using relayd in combination with tether and tetherd to proxy Traefik configurations to a central hub, you may encounter a DNS routing issue.

By default, an agent running relayd will publish its own local IP for its containers. However, since all traffic must flow through your central Traefik instance, DNS queries will point to the agent instead of the central router, causing resolution to fail.

To fix this, you need to explicitly tell relayd on the agent machines to broadcast the central Traefik server's IP instead of their own. You can do this using the IP override environment variables:

services:
  relayd:
    image: ghcr.io/mizuchilabs/relayd:latest
    environment:
      # Override the detected IP with the IP of your central Traefik instance
      - RELAYD_LOCAL_OVERRIDE_IPV4=192.168.1.10

Configuration

Relayd can be configured entirely via environment variables.

Global Options
Variable Default Description
RELAYD_INTERVAL 5m Background sync interval (e.g. 5m, 1h).
RELAYD_INSTANCE hostname Instance name (e.g. my-nas, test-server).
RELAYD_IP_FAMILY ipv4 IP family to synchronize (ipv4, ipv6, dual).
RELAYD_LOCAL_OVERRIDE_IPV4 auto Hardcode the local IPv4 address instead of auto-discovering.
RELAYD_LOCAL_OVERRIDE_IPV6 auto Hardcode the local IPv6 address instead of auto-discovering.
RELAYD_PUBLIC_OVERRIDE_IPV4 auto Hardcode the public IPv4 address instead of auto-discovering.
RELAYD_PUBLIC_OVERRIDE_IPV6 auto Hardcode the public IPv6 address instead of auto-discovering.
Configuring Providers

Providers are automatically discovered by scanning your environment variables for any variable ending in _TYPE with the RELAYD_PROVIDER_ prefix. You can name your providers anything you like (e.g., CF, LOCAL, MYDNS).

For detailed configuration examples per provider, see the docs/providers directory:

License

Apache 2.0 License - see LICENSE for details

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
config
Package config handles the parsing and structuring of configuration options for relayd.
Package config handles the parsing and structuring of configuration options for relayd.
discovery
Package discovery is responsible for locating services and extracting their desired hostnames.
Package discovery is responsible for locating services and extracting their desired hostnames.
dns
Package dns provides an abstracted interface over various DNS providers using libdns.
Package dns provides an abstracted interface over various DNS providers using libdns.
dns/pihole
Package pihole provides a client for the Pi-hole API.
Package pihole provides a client for the Pi-hole API.
dns/unifi
Package unifi provides a client for the UniFi API.
Package unifi provides a client for the UniFi API.
engine
Package engine orchestrates the discovery, target IP resolution, and DNS reconciliation loops.
Package engine orchestrates the discovery, target IP resolution, and DNS reconciliation loops.
reconcile
Package reconcile compares desired DNS states with actual provider states and applies the necessary changes.
Package reconcile compares desired DNS states with actual provider states and applies the necessary changes.
targets
Package targets handles the resolution of target IP addresses for local and public interfaces.
Package targets handles the resolution of target IP addresses for local and public interfaces.
util
Package util provides common utility functions for string manipulation and environment variables.
Package util provides common utility functions for string manipulation and environment variables.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL