Files
computer-playbook/roles/svc-dns-unbound/meta/services.yml
kevinveenbirkenbachandClaude Opus 5 b036f60039 refactor(container_ports): express the remaining published ports through the lookup
The list form could publish a host:container pair and nothing else, so thirteen blocks stayed hand-written: the ones needing a protocol suffix, a port range, the swarm long syntax with mode host, or a container-port-only publish. Each of those duplicated numbers the role already declares in meta/services.yml, which is the drift the lookup exists to remove.

The lookup keeps the list form unchanged for its 93 existing call sites and gains a dict form: transport emits one item per protocol, container 'same' serves the services that cannot remap (STUN/TURN, media relays), mode 'host' emits the long block an edge role needs in swarm so the client address survives the hop, publish 'ephemeral' emits the container port alone, and key names the block for Discourse's launcher file, whose expose: list is what becomes docker run -p there. A declared {start, end} mapping renders as start-end on both sides, so a relay range needs no term of its own.

svc-prx-openresty had no ports block at all and bound 80 and 443 as literals in its template, while torrc.j2 carried a third literal 80 for the hidden service. None of the three referenced the others. openresty now declares the ports, the compose template reads them, and the onion's port 80 comes from ports.onion.http through TOR_ONION_EXTRA_PORTS.

Three blocks stay raw, each with the reason it cannot route through one call: keycloak's sso_proxy maps a published port owned by the consuming role to a container port owned by web-app-keycloak, and matrix's ansible flavor takes element on 8080 and federation on 8048 from the upstream playbook rather than from this repo's ports.internal.

The enforcing lint scanned only files with compose in the name and only double-quoted list items, so nine of the thirteen blocks were invisible to it. It now reads every role template that can carry a ports block, catches unquoted items, protocol suffixes, ranges, flow style and the long syntax, and tracks the block by the indentation of its key: keying on the next line closed the block on anything shaped like a key, which target, published, protocol and mode all are. Under expose: only a real mapping counts, because there the single-segment form documents a container port and publishes nothing.

Verified by rendering all 110 container_ports call sites through the real templar, the real lookup and the real merged applications view.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 14:55:25 +02:00

37 lines
910 B
YAML

---
unbound:
modes:
compose:
enabled: true
swarm:
enabled: true
# nocheck: default-placement-manager engine on-disk state (trust anchors / root hints), node-local in swarm
placement: manager
enabled: true
shared: true
bond: 1
image: ghcr.io/mailu/unbound
name: unbound
version: "2024.06"
min_storage: 283MB
backup:
disabled: true
cpus: "0.5"
mem_reservation: "128m"
mem_limit: "512m"
pids_limit: 256
ports:
internal:
unbound: 53
local:
unbound: 53
onion:
# nocheck: onion-flag a recursive resolver published on the onion is an open resolver, and the containers it serves reach it on the role network
unbound: false
lifecycle: beta
# nocheck: dynamic-flag - the resolver state volume is backup-disabled rebuildable cache, the backup consumer stays permanently off
container_backup:
enabled: false
shared: true