# DDNS for Route53

- [DDNS for Route53](#ddns-for-route53)
  - [Quickly Update DDNS Records](#quickly-update-ddns-records)
  - [Install a New DDNS Service](#install-a-new-ddns-service)
    - [Ansible 3D Server Records](#ansible-3d-server-records)
    - [Ansible Unifi External Records](#ansible-unifi-external-records)
    - [Ansible Hostname reeselink records](#ansible-hostname-reeselink-records)
  - [Development](#development)
    - [Testing](#testing)
    - [Building Container Image](#building-container-image)

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](/active/aws_iam/aws_iam.md) and [aws_cli](/active/aws_cli/aws_cli.md)

## Quickly Update DDNS Records

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

```bash
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:

```yaml
aws:
    access_key_id: key_here
    secret_access_key: secret_here
```

`secrets/records.yaml` example:

```yaml
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:

```bash
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](/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

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

### Ansible Unifi External Records

```bash
ansible-playbook \
-i ansible/inventory.yaml \
-l unifi-external \
active/podman_ddns/install_ddns.yaml \
-e "@active/podman_ddns/secrets/unifi_external_record.yaml"
```

### Ansible Hostname reeselink records

```bash
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

```bash
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

```bash
# 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
```
