140 lines
3.7 KiB
Markdown
140 lines
3.7 KiB
Markdown
# Dynu DNS Read-Only Inventory
|
|
|
|
This repository includes a **read-only** Dynu DNS inventory workflow for `lan.ddnsgeek.com`.
|
|
|
|
> This integration is intentionally read-only. No Dynu mutations are permitted in this repo at this stage.
|
|
|
|
## Scope
|
|
|
|
- Fetch live DNS/domain data from Dynu using **GET requests only**.
|
|
- Correlate Dynu hostnames with Traefik `Host(...)` rules found in compose files.
|
|
- Generate local inventory artifacts for documentation.
|
|
|
|
## Safety Guard Rails
|
|
|
|
- Scripts fail unless `DYNU_READ_ONLY=true`.
|
|
- No Dynu write methods (`POST`, `PUT`, `PATCH`, `DELETE`) are implemented.
|
|
- No Terraform Dynu provider/resources/modules are introduced.
|
|
- No Ansible Dynu mutation tasks are introduced.
|
|
- API secrets are read from environment variables and are never logged.
|
|
|
|
## Correlation logic
|
|
|
|
`scripts/dynu/correlate_dynu_with_traefik.py` uses compose files as the source of truth and parses them as YAML.
|
|
|
|
It supports both common label formats:
|
|
|
|
- list style:
|
|
|
|
```yaml
|
|
labels:
|
|
- "traefik.http.routers.app.rule=Host(`app.lan.ddnsgeek.com`)"
|
|
```
|
|
|
|
- map style:
|
|
|
|
```yaml
|
|
labels:
|
|
traefik.http.routers.app.rule: "Host(`app.lan.ddnsgeek.com`)"
|
|
```
|
|
|
|
The parser extracts hostnames from router rules such as:
|
|
|
|
- `Host(`a`)`
|
|
- `Host("a")`
|
|
- `Host('a')`
|
|
- multi-host rules (comma-delimited)
|
|
- combined expressions such as `Host(...) && PathPrefix(...)`
|
|
|
|
## Route metadata in inventory
|
|
|
|
Each discovered hostname mapping includes:
|
|
|
|
- fqdn
|
|
- compose service name
|
|
- compose file path
|
|
- stack area (`apps`, `monitoring`, `core`)
|
|
- router label key(s)
|
|
- raw router rule
|
|
- `uses_tls`
|
|
- `tls_options`
|
|
- `middlewares`
|
|
- `uses_mtls`
|
|
- `uses_authelia`
|
|
|
|
mTLS is metadata only and **never blocks mapping**.
|
|
|
|
## Validation model
|
|
|
|
The generated JSON/Markdown include a top-level `validation` section with:
|
|
|
|
- `allowed_unmapped_hostnames`
|
|
- `unexpected_unmapped_hostnames`
|
|
- `duplicate_hostnames`
|
|
- `ambiguous_hostnames`
|
|
- `validation_ok`
|
|
|
|
Current policy:
|
|
|
|
- `edge.lan.ddnsgeek.com` is the only allowed unmapped DNS hostname.
|
|
- every other `*.lan.ddnsgeek.com` DNS hostname should map to a compose/Traefik-discovered service.
|
|
|
|
Optional strict mode:
|
|
|
|
- Set `DYNU_ENFORCE_VALIDATION=true` to make the correlate script exit non-zero when unexpected unmapped hostnames exist.
|
|
|
|
## Required Environment Variables
|
|
|
|
- `DYNU_API_KEY` (required for fetch)
|
|
- `DYNU_BASE_URL` (optional, defaults to `https://api.dynu.com`)
|
|
- `DYNU_READ_ONLY` (**must** be `true`)
|
|
|
|
Recommended local secrets file (not committed): `secrets/dynu.env`
|
|
|
|
```bash
|
|
DYNU_API_KEY=replace-with-real-api-key
|
|
DYNU_READ_ONLY=true
|
|
DYNU_BASE_URL=https://api.dynu.com
|
|
```
|
|
|
|
Notes:
|
|
|
|
- Keep values unquoted unless required by your shell.
|
|
- `scripts/dynu/build_dns_inventory.sh` will auto-load `secrets/dynu.env` when present.
|
|
|
|
## Commands
|
|
|
|
Run directly:
|
|
|
|
```bash
|
|
DYNU_READ_ONLY=true DYNU_API_KEY=... python3 scripts/dynu/fetch_dynu_dns.py
|
|
DYNU_READ_ONLY=true python3 scripts/dynu/correlate_dynu_with_traefik.py
|
|
```
|
|
|
|
Or run the wrapper:
|
|
|
|
```bash
|
|
scripts/dynu/build_dns_inventory.sh
|
|
```
|
|
|
|
## Artifacts
|
|
|
|
- `data/dns/dynu_live.json` (generated, untracked by default due to repo `data/` ignore)
|
|
- `data/dns/dynu_traefik_inventory.json` (generated, untracked by default)
|
|
- `docs/generated/dns-inventory.md` (generated documentation artifact)
|
|
|
|
Because `data/` is gitignored in this repository, JSON outputs are intentionally local-only unless ignore behavior changes in the future.
|
|
|
|
## Ansible Wrapper (Read-Only)
|
|
|
|
A syntax-safe wrapper playbook is provided at:
|
|
|
|
- `infrastructure/ansible/playbooks/dns-inventory.yml`
|
|
|
|
It only executes the local read-only scripts and does not call write-capable Dynu APIs.
|
|
|
|
## Not Managed Yet
|
|
|
|
Dynu DNS records are **not** managed by Terraform or Ansible in this repository at this stage.
|
|
No configuration in this repository sends Dynu mutation requests.
|