diff --git a/CLAUDE.md b/CLAUDE.md index fd69e61..dbf883e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -112,6 +112,9 @@ Many services depend on Authentik for SSO. When deploying new services, consider - Network connectivity requirements within Docker stack - Hairpinning fixes for internal service-to-service communication +### Shared Docker Network (`lava`) +Created by the docker role as `{{ docker.subnet }}` with `ip_range: {{ docker.ip_range }}`. Docker only hands out dynamic addresses from that range, so `172.20.0.x` is reserved for fixed IPs: Caddy (`docker.hairpin_ip`, .5) and Gitea (`docker.gitea_ip`, .6). Both need fixed IPs because ufw-docker firewall rules point at container IPs. A network without the range (the 2024 original) is migrated once with `migrate-lava-network.yml`. + ### Hairpinning Resolution Services inside Docker containers cannot reach external domains that resolve to the same server. Fix by adding `extra_hosts` mappings: diff --git a/group_vars/all/infrastructure.yml b/group_vars/all/infrastructure.yml index 2c1a647..8b01935 100644 --- a/group_vars/all/infrastructure.yml +++ b/group_vars/all/infrastructure.yml @@ -4,7 +4,13 @@ docker: network_name: "lava" stacks_path: "/opt/stacks" - hairpin_ip: "172.20.0.5" + hairpin_ip: "172.20.0.5" # Caddy's fixed IP + # Shared network layout. Docker only hands out addresses from ip_range, + # so 172.20.0.x is kept free for fixed IPs and can't be taken by others. + subnet: "172.20.0.0/16" + gateway: "172.20.0.1" + ip_range: "172.20.128.0/17" + gitea_ip: "172.20.0.6" # fixed so the ufw-docker SSH rule stays valid # SMTP configuration smtp: diff --git a/migrate-lava-network.yml b/migrate-lava-network.yml new file mode 100644 index 0000000..660225d --- /dev/null +++ b/migrate-lava-network.yml @@ -0,0 +1,129 @@ +--- +# One-off: recreate the shared docker network with a reserved address range. +# +# Why: lava was created without an ip_range, so any container can be given +# Caddy's fixed IP (172.20.0.5) and Caddy then fails with "Address already +# in use". Docker can't change a network's range in place, so every stack on +# it is taken down, the network is recreated, and the stacks come back up. +# Volumes (all data) are kept. Expect a few minutes of downtime for everything. +# +# Run: ansible-playbook migrate-lava-network.yml -i hosts.yml --vault-password-file vault_pass +# Then: ansible-playbook site.yml -i hosts.yml --vault-password-file vault_pass +# (gives gitea its fixed IP and fixes its firewall rule) +# +# The list of stacks is saved to /root/lava-migration-