mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
In swarm mode `docker stack deploy` ignores the host IP of a short port mapping, so every `127.0.0.1:<port>:<port>` that container_ports renders for a `ports.local` entry is published by the ingress routing mesh on every node, via docker-proxy on 0.0.0.0 and [::] plus DNAT in nat PREROUTING. Databases, LDAP and application backends answered from outside the cluster. svc-swarm-node now loads an nftables table through svc-net-firewall. Its prerouting filter chain (priority mangle, ahead of Docker's dstnat) drops packets addressed to the node for any ingress-published port that no application declares under `ports.public`. Loopback, docker0, docker_gwbridge, the user bridges and the swarm nodes' own addresses stay admitted. Host-side provisioning over 127.0.0.1, containers that reach a host port through host-gateway, and node-to-node consumers such as the registry-cache mirror keep working. Both sets are read live on the manager (`docker service inspect` for `.Endpoint.Ports`, `docker node inspect` for `.Status.Addr`), so ephemeral ingress ports and nodes outside `--limit` are covered. The table is loaded on a node before it joins, reloaded on every node after the join, and reloaded after each stack deploy by the sys-svc-compose swarm handler. Refs #1089 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
46 lines
1.5 KiB
YAML
46 lines
1.5 KiB
YAML
---
|
|
DEPLOYMENT_MODE: "{{ 'swarm' if (groups['svc-swarm-node'] | default([]) | length) > 1 else 'compose' }}"
|
|
|
|
SWARM_CLUSTER_AVAILABLE: "{{ (groups['svc-swarm-node'] | default([]) | length) > 0 }}"
|
|
|
|
# Exception: a role default would be invisible to the by-path include in
|
|
# roles/svc-db-openldap/tasks/01_docker.yml, which reaches into
|
|
# roles/sys-svc-compose/tasks/utils/post_deploy.yml after the role has finished.
|
|
swarm_stack_converge_retries: 600
|
|
|
|
IS_STACK_HOST: >-
|
|
{{ DEPLOYMENT_MODE == 'compose'
|
|
or inventory_hostname in (groups['svc-swarm-manager'] | default([])) }}
|
|
|
|
IS_BACKUP_HOST: >-
|
|
{{ group_names | select('match', '^svc-bkp-') | list | length > 0 }}
|
|
|
|
STACK_HOST: >-
|
|
{{ (groups['svc-swarm-manager'] | default([]))[0] | default(inventory_hostname) }}
|
|
|
|
swarm_stack_fatal_grace: 180
|
|
|
|
SWARM_INGRESS_GUARDED: "{{ swarm_ingress_endpoints.stdout_lines | swarm_ingress_published | swarm_ingress_guarded(lookup('applications') | swarm_public_ports) }}"
|
|
|
|
SWARM_INGRESS_PEERS: "{{ swarm_ingress_nodes.stdout_lines | swarm_node_addresses }}"
|
|
|
|
swarm:
|
|
manager:
|
|
advertise_addr: >-
|
|
{{ lookup('mesh_address', STACK_HOST) if (WIREGUARD_ENABLED | bool) else '' }}
|
|
network:
|
|
encryption: true
|
|
registry:
|
|
host: "{{ (groups['svc-swarm-manager'] | default([]))[0] | default('') }}"
|
|
port: 5000
|
|
|
|
SWARM_REGISTRY_PREFIX: >-
|
|
{{
|
|
(swarm.registry.host ~ ':' ~ swarm.registry.port ~ '/')
|
|
if (
|
|
DEPLOYMENT_MODE == 'swarm'
|
|
and (swarm.registry.host | length > 0)
|
|
)
|
|
else ''
|
|
}}
|