Files
homelab/active/podman_ddns/ddns.md
ducoterra 5184c84d50
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 33s
overhauls of most service docs
2025-07-22 18:29:07 -04:00

3.8 KiB

DDNS for Route53

This service will automatically keep ipv4 and ipv6 records updated in AWS Route53.

NOTE: This requires the aws cli to be installed on each node with credentials that can modify records in route53. See aws_iam and aws_cli

Quickly Update DDNS Records

In the event of a record change you can quickly trigger the ddns services with

systemctl start --all ddns*.service

Install a New DDNS Service

You need two files:

  1. secrets/vars.yaml (with aws credentials)
  2. secrets/records.yaml (with AWS records)

secrets/vars.yaml example:

aws:
    access_key_id: key_here
    secret_access_key: secret_here

secrets/records.yaml example:

records:
  - record: some.domain.com
    hosted_zone_id: ABC123456789
  - record: someother.domain.com
    hosted_zone_id: ABC123456789

Then you'll need to pick a server responsible for keeping those records updated. Whichever host you run the service on will also be the host which provides the public IP. Choose the host accordingly if it will be updating a public IP on behalf of another server, as the IPv6 address will not be correct.

Now you can install the DDNS service with something like:

ansible-playbook \
# specify your inventory
-i ansible/inventory.yaml \
# -l limits to a particular host
-l 3dserver \
active/podman_ddns/install_ddns.yaml \
# -e brings in our secrets/records.yaml
-e "@active/podman_ddns/secrets/records.yaml"

See ansible playbook install_ddns.yaml

It's recommended that you have multiple secret foobar-records.yaml files for multiple servers. If you have a podman server, it'll have its own podman-records.yaml. If you have a docker server, it'll have its own docker-records.yaml. Etc. etc.

Ansible 3D Server Records

ansible-playbook \
-i ansible/inventory.yaml \
-l 3dserver \
active/podman_ddns/install_ddns.yaml \
-e "@active/podman_ddns/secrets/3dserver_records.yaml"

Ansible Podman Record

ansible-playbook \
-i ansible/inventory.yaml \
-l podman \
active/podman_ddns/install_ddns.yaml \
-e "@active/podman_ddns/secrets/podman_records.yaml"

Ansible Unifi External Records

ansible-playbook \
-i ansible/inventory.yaml \
-l unifi-external \
active/podman_ddns/install_ddns.yaml \
-e "@active/podman_ddns/secrets/unifi_external_record.yaml"
export PLAYBOOK_PATH=active/podman_ddns
ansible-playbook \
-i ansible/inventory.yaml \
${PLAYBOOK_PATH}/install_ddns.yaml \
-e "@${PLAYBOOK_PATH}/secrets/hostname_reeselink_record.yaml"

Development

Testing

export ROUTE53_RECORD=test-ddns.reeseapps.com
export HOSTED_ZONE_ID=$(cat secrets/secret_vars.yaml | yq -r '.reeseapps_zone_id')
uv run update.py

Building Container Image

# Build
podman build -t gitea.reeseapps.com/services/ddns:latest -f ./Containerfile
podman push gitea.reeseapps.com/services/ddns:latest

# Run
export ROUTE53_RECORD=test-ddns.reeseapps.com
export HOSTED_ZONE_ID=$(cat secrets/secret_vars.yaml | yq -r '.reeseapps_zone_id')
podman run \
-e ROUTE53_RECORD=$ROUTE53_RECORD \
-e HOSTED_ZONE_ID=$HOSTED_ZONE_ID \
-e AWS_PROFILE=prod \
-v $HOME/.aws:/root/.aws:Z \
-it --rm \
gitea.reeseapps.com/services/ddns:latest