--- - name: Configure the server and install required software hosts: vpn-host gather_facts: false become: true vars_files: - config.cfg tasks: - block: - name: Wait until the cloud-init completed wait_for: path: /var/lib/cloud/data/result.json delay: 10 # Conservative 10 second initial delay timeout: 480 # Reduce from 600 to 480 seconds (8 minutes) sleep: 10 # Check every 10 seconds (less aggressive) state: present become: false when: cloudinit - block: - name: Ensure the config directory exists file: dest: configs/{{ IP_subject_alt_name }} state: directory mode: "0700" - name: Dump the ssh config copy: dest: configs/{{ IP_subject_alt_name }}/ssh_config mode: "0600" content: | Host {{ IP_subject_alt_name }} {{ algo_server_name }} HostName {{ IP_subject_alt_name }} User {{ ansible_ssh_user }} Port {{ ansible_ssh_port }} IdentitiesOnly yes IdentityFile {{ SSH_keys.private | realpath }} KeepAlive yes ServerAliveInterval 30 when: inventory_hostname != 'localhost' become: false delegate_to: localhost - import_role: name: common tags: common # Configure VPN services (parallel when performance_parallel_services enabled) - block: - name: Start DNS service configuration import_role: name: dns async: 300 poll: 0 register: dns_job when: algo_dns_adblocking or dns_encryption tags: dns - name: Start WireGuard service configuration import_role: name: wireguard async: 300 poll: 0 register: wireguard_job when: wireguard_enabled tags: wireguard - name: Start StrongSwan service configuration import_role: name: strongswan async: 300 poll: 0 register: strongswan_job when: ipsec_enabled tags: ipsec - name: Start SSH tunneling service configuration import_role: name: ssh_tunneling async: 300 poll: 0 register: ssh_tunneling_job when: algo_ssh_tunneling tags: ssh_tunneling - name: Wait for DNS service configuration to complete async_status: jid: "{{ dns_job.ansible_job_id }}" register: dns_result until: dns_result.finished retries: 60 delay: 5 when: dns_job.ansible_job_id is defined tags: dns - name: Wait for WireGuard service configuration to complete async_status: jid: "{{ wireguard_job.ansible_job_id }}" register: wireguard_result until: wireguard_result.finished retries: 60 delay: 5 when: wireguard_job.ansible_job_id is defined tags: wireguard - name: Wait for StrongSwan service configuration to complete async_status: jid: "{{ strongswan_job.ansible_job_id }}" register: strongswan_result until: strongswan_result.finished retries: 60 delay: 5 when: strongswan_job.ansible_job_id is defined tags: ipsec - name: Wait for SSH tunneling service configuration to complete async_status: jid: "{{ ssh_tunneling_job.ansible_job_id }}" register: ssh_tunneling_result until: ssh_tunneling_result.finished retries: 60 delay: 5 when: ssh_tunneling_job.ansible_job_id is defined tags: ssh_tunneling - name: Display VPN service completion status debug: msg: | VPN Service Status Summary (Parallel Mode): DNS: {{ 'COMPLETED' if (dns_result.rc | default(-1)) == 0 else 'FAILED' if dns_result.rc is defined else 'SKIPPED' }} WireGuard: {{ 'COMPLETED' if (wireguard_result.rc | default(-1)) == 0 else 'FAILED' if wireguard_result.rc is defined else 'SKIPPED' }} StrongSwan: {{ 'COMPLETED' if (strongswan_result.rc | default(-1)) == 0 else 'FAILED' if strongswan_result.rc is defined else 'SKIPPED' }} SSH Tunneling: >- {{ 'COMPLETED' if (ssh_tunneling_result.rc | default(-1)) == 0 else 'FAILED' if ssh_tunneling_result.rc is defined else 'SKIPPED' }} tags: vpn_services - name: Check for any VPN service failures fail: msg: | One or more VPN services failed to configure properly. Please check the detailed error messages above. when: > (dns_result.rc is defined and dns_result.rc != 0) or (wireguard_result.rc is defined and wireguard_result.rc != 0) or (strongswan_result.rc is defined and strongswan_result.rc != 0) or (ssh_tunneling_result.rc is defined and ssh_tunneling_result.rc != 0) tags: vpn_services when: performance_parallel_services | default(true) # Sequential service configuration (fallback) - import_role: name: dns when: - not (performance_parallel_services | default(true)) - algo_dns_adblocking or dns_encryption tags: dns - import_role: name: wireguard when: - not (performance_parallel_services | default(true)) - wireguard_enabled tags: wireguard - import_role: name: strongswan when: - not (performance_parallel_services | default(true)) - ipsec_enabled tags: ipsec - import_role: name: ssh_tunneling when: - not (performance_parallel_services | default(true)) - algo_ssh_tunneling tags: ssh_tunneling - import_role: name: privacy when: privacy_enhancements_enabled | default(true) tags: privacy - block: - name: Dump the configuration copy: dest: configs/{{ IP_subject_alt_name }}/.config.yml mode: '0644' content: | server: {{ 'localhost' if inventory_hostname == 'localhost' else inventory_hostname }} server_user: {{ ansible_ssh_user }} ansible_ssh_port: "{{ ansible_ssh_port | default(22) }}" {% if algo_provider != "local" %} ansible_ssh_private_key_file: {{ SSH_keys.private }} {% endif %} algo_provider: {{ algo_provider }} algo_server_name: {{ algo_server_name }} algo_ondemand_cellular: {{ algo_ondemand_cellular }} algo_ondemand_wifi: {{ algo_ondemand_wifi }} algo_ondemand_wifi_exclude: {{ algo_ondemand_wifi_exclude }} algo_dns_adblocking: {{ algo_dns_adblocking }} algo_ssh_tunneling: {{ algo_ssh_tunneling }} algo_store_pki: {{ algo_store_pki }} IP_subject_alt_name: {{ IP_subject_alt_name }} ipsec_enabled: {{ ipsec_enabled }} wireguard_enabled: {{ wireguard_enabled }} {% if tests | default(false) | bool %} ca_password: '{{ CA_password }}' p12_password: '{{ p12_export_password }}' {% endif %} become: false delegate_to: localhost - name: Create a symlink if deploying to localhost file: src: "{{ IP_subject_alt_name }}" dest: configs/localhost state: link force: true when: inventory_hostname == 'localhost' - name: Import tmpfs tasks import_tasks: playbooks/tmpfs/umount.yml become: false delegate_to: localhost vars: facts: "{{ hostvars['localhost'] }}" when: - pki_in_tmpfs - not algo_store_pki - debug: msg: - "{{ congrats.common.split('\n') }}" - " {{ congrats.p12_pass if algo_ssh_tunneling or ipsec_enabled else '' }}" - " {{ congrats.ca_key_pass if algo_store_pki and ipsec_enabled else '' }}" - " {{ congrats.ssh_access if algo_provider != 'local' else ''}}" tags: always rescue: - include_tasks: playbooks/rescue.yml