Reserve fixed IPs on the lava network so Caddy can always start

lava was created by hand without an ip_range, so any container could be
given Caddy's fixed IP (172.20.0.5). After a reboot the containers race
for the low addresses and Caddy often fails with "Address already in use".

- The docker role now creates lava as 172.20.0.0/16 with dynamic
  addresses limited to 172.20.128.0/17, so 172.20.0.x is free for fixed
  IPs, and warns if the network still has the old layout.
- Gitea gets fixed IP 172.20.0.6 once the network has the reserved range,
  since its ufw-docker SSH rule points at its IP.
- ufw-docker allow rules for Caddy (80, 443) and Gitea SSH are managed by
  the playbook and follow IP changes.
- migrate-lava-network.yml recreates the existing network once: it takes
  down every compose project on lava (volumes kept), recreates the
  network, and brings them back up, Caddy first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Phil
2026-10-29 21:04:22 -06:00
co-authored by Claude Opus 5.5
parent c0145dd5a2
commit e569a56417
7 changed files with 201 additions and 3 deletions
+40
View File
@@ -56,6 +56,46 @@
state: restarted
when: ufw_docker_check.rc != 0
- name: Look up the shared docker network
community.docker.docker_network_info:
name: "{{ docker.network_name }}"
register: lava_net
tags: always
# True once the network has the reserved range. Fixed IPs other than Caddy's
# are only applied then, since today's dynamic containers may hold them.
- name: Record whether the shared network has the reserved range
ansible.builtin.set_fact:
lava_reserved: >-
{{ lava_net.exists and
(lava_net.network.IPAM.Config | map(attribute='IPRange', default='') | first) == docker.ip_range }}
tags: always
- name: Create the shared docker network
community.docker.docker_network:
name: "{{ docker.network_name }}"
driver: bridge
ipam_config:
- subnet: "{{ docker.subnet }}"
gateway: "{{ docker.gateway }}"
iprange: "{{ docker.ip_range }}"
when: not lava_net.exists
register: lava_created
- name: Mark a freshly created network as reserved
ansible.builtin.set_fact:
lava_reserved: true
when: lava_created is changed
# Docker can't change a network's address range in place; recreating it
# needs every container detached first. See migrate-lava-network.yml.
- name: Warn if the shared network has the old address layout
ansible.builtin.debug:
msg: >-
{{ docker.network_name }} has no reserved range (wanted {{ docker.ip_range }}),
so other containers can take Caddy's fixed IP. Run migrate-lava-network.yml.
when: lava_net.exists and not (lava_reserved | bool)
- name: make directories
ansible.builtin.file:
path: "{{ item }}"