--- - name: Assert layout and hostnames ansible.builtin.assert: that: - multica_layout in ['single', 'split'] - caddy_tls_mode in ['acme_http', 'cloudflare_dns', 'internal'] - multica_layout == 'split' or (multica_domain | length) > 0 - multica_layout == 'single' or ((multica_app_domain | length) > 0 and (multica_api_domain | length) > 0) fail_msg: >- Set multica_domain (layout=single) or multica_app_domain + multica_api_domain (layout=split), and use a valid caddy_tls_mode. - name: Assert required secrets are provided ansible.builtin.assert: that: - (multica_jwt_secret | length) >= 32 - (multica_postgres_password | length) >= 16 - (multica_vcs_secret_key | length) >= 16 - caddy_tls_mode != 'cloudflare_dns' or (caddy_cloudflare_api_token | length) > 0 fail_msg: >- Missing secrets. Define vault_multica_jwt_secret (>=32 chars), vault_multica_postgres_password (>=16), vault_multica_vcs_secret_key (>=16) and, for cloudflare_dns, vault_cloudflare_api_token. Generate with: openssl rand -hex 32 quiet: true - name: Check Docker Compose v2 is available ansible.builtin.command: docker compose version register: _multica_compose_ver changed_when: false - name: Ensure git is installed ansible.builtin.package: name: git state: present # ── Port checks (skipped when our own stack already holds the ports) ── - name: Look for an existing Multica deployment ansible.builtin.stat: path: "{{ multica_install_dir }}/{{ _multica_compose_file }}" register: _multica_compose_stat - name: List running Multica containers ansible.builtin.command: cmd: "docker compose -p {{ multica_compose_project }} -f {{ _multica_compose_file }} ps -q" chdir: "{{ multica_install_dir }}" register: _multica_ps changed_when: false when: _multica_compose_stat.stat.exists - name: Check for a running Caddy container ansible.builtin.command: "docker ps -q --filter name=^{{ caddy_container_name }}$" register: _caddy_ps changed_when: false - name: Ensure Multica ports are free on first deploy when: not (_multica_compose_stat.stat.exists and ((_multica_ps.stdout | default('')) | length) > 0) block: - name: Wait for 3000/8080 to be unused ansible.builtin.wait_for: host: 127.0.0.1 port: "{{ item }}" state: stopped timeout: 3 loop: - "{{ _multica_frontend_port }}" - "{{ _multica_backend_port }}" rescue: - name: Fail with hint ansible.builtin.fail: msg: "Port 3000 or 8080 is already in use on the target host and Multica is not running. Free it before deploying." - name: Ensure Caddy ports are free on first deploy when: (_caddy_ps.stdout | length) == 0 block: - name: Wait for Caddy HTTP/HTTPS ports to be unused ansible.builtin.wait_for: host: 127.0.0.1 port: "{{ item }}" state: stopped timeout: 3 loop: "{{ [caddy_http_port, caddy_https_port] | map('int') | list }}" rescue: - name: Fail with hint ansible.builtin.fail: msg: >- Port {{ caddy_http_port }} or {{ caddy_https_port }} is already in use on the target host (another reverse proxy such as nginx?). Set caddy_http_port / caddy_https_port to free ports, or deploy Caddy on a different host.