From 6363aa713e7960ddfa57db21b7b32b2de545c9d9 Mon Sep 17 00:00:00 2001 From: drew Date: Thu, 28 May 2026 17:13:36 -0400 Subject: [PATCH] Logical bug fixes and add Jellyfin --- playbook.yml | 74 ++++--- roles/adguard/meta/main.yml | 4 - roles/adguard/tasks/main.yml | 61 ++---- roles/adguard/templates/AdGuardHome.yaml.j2 | 194 ------------------ roles/adguard/templates/adguard.container.j2 | 8 +- roles/caddy/meta/main.yml | 4 - roles/caddy/tasks/main.yml | 45 ++-- roles/caddy/templates/Caddyfile.j2 | 6 + roles/caddy/templates/caddy.container.j2 | 2 +- roles/cli_productivity/defaults/main.yml | 2 +- .../container_runtime/tasks/config-setup.yml | 14 ++ roles/container_runtime/tasks/directory.yml | 26 +++ roles/container_runtime/tasks/main.yml | 46 +++-- roles/container_runtime/tasks/systemd.yml | 31 +++ roles/coturn/meta/main.yml | 4 - roles/coturn/tasks/main.yml | 59 ++---- roles/coturn/templates/coturn.container.j2 | 2 +- roles/jellyfin/tasks/firewall.yml | 12 ++ roles/jellyfin/tasks/main.yml | 30 +++ .../jellyfin/templates/jellyfin.container.j2 | 21 ++ roles/matrix_synapse/meta/main.yml | 6 - roles/matrix_synapse/tasks/main.yml | 49 ++--- .../templates/synapse.container.j2 | 2 +- roles/nfs_client/tasks/main.yml | 93 +++------ roles/postgres/meta/main.yml | 4 - roles/postgres/tasks/main.yml | 59 ++---- .../postgres/templates/postgres.container.j2 | 2 +- roles/selinux_containers/tasks/labels.yml | 2 +- roles/selinux_containers/tasks/storage.yml | 17 -- roles/servarr/defaults/main.yml | 4 +- roles/servarr/meta/main.yml | 5 - roles/servarr/tasks/main.yml | 79 +++---- roles/storage_client/tasks/main.yml | 56 ++--- roles/tailscale/tasks/main.yml | 5 +- roles/trilium/tasks/main.yml | 48 ++--- roles/trilium/templates/trilium.container.j2 | 3 +- roles/vpn/tasks/main.yml | 44 ++-- roles/vpn/templates/gluetun.container.j2 | 4 +- roles/vpn_guard/tasks/main.yml | 28 +-- 39 files changed, 437 insertions(+), 718 deletions(-) delete mode 100644 roles/adguard/meta/main.yml delete mode 100644 roles/adguard/templates/AdGuardHome.yaml.j2 delete mode 100644 roles/caddy/meta/main.yml create mode 100644 roles/container_runtime/tasks/config-setup.yml create mode 100644 roles/container_runtime/tasks/directory.yml create mode 100644 roles/container_runtime/tasks/systemd.yml delete mode 100644 roles/coturn/meta/main.yml create mode 100644 roles/jellyfin/tasks/firewall.yml create mode 100644 roles/jellyfin/tasks/main.yml create mode 100644 roles/jellyfin/templates/jellyfin.container.j2 delete mode 100644 roles/matrix_synapse/meta/main.yml delete mode 100644 roles/postgres/meta/main.yml delete mode 100644 roles/selinux_containers/tasks/storage.yml delete mode 100644 roles/servarr/meta/main.yml diff --git a/playbook.yml b/playbook.yml index 2c2c2ac..2e97612 100644 --- a/playbook.yml +++ b/playbook.yml @@ -8,6 +8,9 @@ tags: firewall_base - role: cli_productivity tags: cli_productivity + - role: tailscale + tags: tailscale + when: tailscale_enabled | bool - name: Shared storage clients hosts: nfs_clients @@ -26,7 +29,7 @@ tags: nfs_server - name: Containers stack - hosts: services + hosts: nas:services become: true roles: - role: container_runtime @@ -34,13 +37,55 @@ - role: selinux_containers tags: selinux_containers +- name: VPN + hosts: vpn_hosts + become: true + roles: + - role: vpn + tags: vpn + +- name: Postgres stack + hosts: postgres_hosts + become: true + roles: + - role: postgres + tags: postgres + +- name: Matrix stack + hosts: matrix_hosts + become: true + roles: + - role: matrix_synapse + tags: matrix + when: matrix_enabled | bool + +- name: Coturn stack + hosts: coturn_hosts + become: true + roles: + - role: coturn + tags: coturn + - name: Media services hosts: media become: true roles: - # Jellyfin role will go here later. - # - role: jellyfin - # tags: jellyfin + - role: jellyfin + tags: jellyfin + +- name: Notes stack + hosts: notes_hosts + become: true + roles: + - role: trilium + tags: trilium + +- name: Servarr stack + hosts: servarr_hosts + become: true + roles: + - role: servarr + tags: servarr - name: DNS and reverse proxy hosts: services @@ -51,27 +96,6 @@ - role: caddy tags: caddy -- name: Servarr stack - hosts: servarr_hosts - become: true - roles: - - role: servarr - tags: servarr - -- name: Matrix stack - hosts: matrix_hosts - become: true - roles: - - role: matrix_synapse - tags: matrix - -- name: Notes stack - hosts: notes_hosts - become: true - roles: - - role: trilium - tags: trilium - - name: ML workloads hosts: ml_hosts become: true diff --git a/roles/adguard/meta/main.yml b/roles/adguard/meta/main.yml deleted file mode 100644 index cc7e2ed..0000000 --- a/roles/adguard/meta/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# adguard/meta/main.yml -dependencies: - - role: selinux_containers \ No newline at end of file diff --git a/roles/adguard/tasks/main.yml b/roles/adguard/tasks/main.yml index f0920dd..df86a73 100644 --- a/roles/adguard/tasks/main.yml +++ b/roles/adguard/tasks/main.yml @@ -1,59 +1,26 @@ --- #adguard/tasks/main.yml - import_tasks: firewall.yml - -- name: Create stack and config directories - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" - recurse: yes - loop: "{{ adguard_base_directories }}" - -- name: Directory SELinux requirement + +- name: Create adguard container directory ansible.builtin.set_fact: - selinux_container_paths: "{{ adguard_base_directories }}" + dir_list: "{{ adguard_base_directories }}" -- import_role: - name: selinux_containers - tasks_from: labels - -- name: Ensure container app config directories are owned by container UID - become: true - file: - path: "{{ adguard_dir }}/conf" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - recurse: true - -- name: Deploy AdGuard configuration template - template: - src: AdGuardHome.yaml.j2 - dest: "{{ stack_root }}/adguard/conf/AdGuardHome.yaml" - mode: '0600' - force: "{{ adguard_overwrite_config | default(false) | bool }}" +- name: Setup directory for adguard config + ansible.builtin.import_role: + name: container_runtime + tasks_from: config-setup - name: Deploy AdGuard Quadlet template: src: adguard.container.j2 dest: "{{ container_config_dir }}/adguard.container" -- name: Force systemd reload (blocking) - become: true - become_user: "{{ container_user }}" - command: systemctl --user daemon-reload +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "adguard" -- name: Wait for quadlet generation - pause: - seconds: 1 - -- name: Start and enable AdGuard service - become: true - become_user: "{{ container_user }}" - systemd: - name: adguard.service - scope: user - state: started \ No newline at end of file +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd \ No newline at end of file diff --git a/roles/adguard/templates/AdGuardHome.yaml.j2 b/roles/adguard/templates/AdGuardHome.yaml.j2 deleted file mode 100644 index 1ed8911..0000000 --- a/roles/adguard/templates/AdGuardHome.yaml.j2 +++ /dev/null @@ -1,194 +0,0 @@ -http: - pprof: - port: 6060 - enabled: false - doh: - routes: - - GET /dns-query - - POST /dns-query - - GET /dns-query/{ClientID} - - POST /dns-query/{ClientID} - insecure_enabled: false - address: 0.0.0.0:80 - session_ttl: 720h -users: - - name: "{{ adguard_admin_user }}" - password: "{{ adguard_admin_password_hash }}" -auth_attempts: 5 -block_auth_min: 15 -http_proxy: "" -language: "" -theme: auto -dns: - bind_hosts: - - 0.0.0.0 - port: 53 - anonymize_client_ip: false - ratelimit: 20 - ratelimit_subnet_len_ipv4: 24 - ratelimit_subnet_len_ipv6: 56 - ratelimit_whitelist: [] - refuse_any: true - upstream_dns: - - https://dns10.quad9.net/dns-query - upstream_dns_file: "" - bootstrap_dns: - - 9.9.9.10 - - 149.112.112.10 - - 2620:fe::10 - - 2620:fe::fe:10 - fallback_dns: [] - upstream_mode: load_balance - fastest_timeout: 1s - allowed_clients: [] - disallowed_clients: [] - blocked_hosts: - - version.bind - - id.server - - hostname.bind - trusted_proxies: - - 127.0.0.0/8 - - ::1/128 - cache_enabled: true - cache_size: 4194304 - cache_ttl_min: 0 - cache_ttl_max: 0 - cache_optimistic: false - cache_optimistic_answer_ttl: 30s - cache_optimistic_max_age: 12h - bogus_nxdomain: [] - aaaa_disabled: false - enable_dnssec: false - edns_client_subnet: - custom_ip: "" - enabled: false - use_custom: false - max_goroutines: 300 - handle_ddr: true - ipset: [] - ipset_file: "" - bootstrap_prefer_ipv6: false - upstream_timeout: 10s - private_networks: [] - use_private_ptr_resolvers: true - local_ptr_upstreams: [] - use_dns64: false - dns64_prefixes: [] - serve_http3: false - use_http3_upstreams: false - serve_plain_dns: true - hostsfile_enabled: true - pending_requests: - enabled: true -tls: - enabled: false - server_name: "" - force_https: false - port_https: 443 - port_dns_over_tls: 853 - port_dns_over_quic: 853 - port_dnscrypt: 0 - dnscrypt_config_file: "" - certificate_chain: "" - private_key: "" - certificate_path: "" - private_key_path: "" - strict_sni_check: false -querylog: - dir_path: "" - ignored: [] - interval: 2160h - size_memory: 1000 - enabled: true - ignored_enabled: false - file_enabled: true -statistics: - dir_path: "" - ignored: [] - interval: 24h - enabled: true - ignored_enabled: false -filters: - - enabled: true - url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt - name: AdGuard DNS filter - id: 1 - - enabled: false - url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt - name: AdAway Default Blocklist - id: 2 -whitelist_filters: [] -user_rules: [] -dhcp: - enabled: false - interface_name: "" - local_domain_name: lan - dhcpv4: - gateway_ip: "" - subnet_mask: "" - range_start: "" - range_end: "" - lease_duration: 86400 - icmp_timeout_msec: 1000 - options: [] - dhcpv6: - range_start: "" - lease_duration: 86400 - ra_slaac_only: false - ra_allow_slaac: false -filtering: - blocking_ipv4: "" - blocking_ipv6: "" - blocked_services: - schedule: - time_zone: UTC - ids: [] - protection_disabled_until: null - safe_search: - enabled: false - bing: true - duckduckgo: true - ecosia: true - google: true - pixabay: true - yandex: true - youtube: true - blocking_mode: default - parental_block_host: family-block.dns.adguard.com - safebrowsing_block_host: standard-block.dns.adguard.com - rewrites: [] - safe_fs_patterns: - - /opt/adguardhome/work/userfilters/* - safebrowsing_cache_size: 1048576 - safesearch_cache_size: 1048576 - parental_cache_size: 1048576 - cache_time: 30 - filters_update_interval: 24 - blocked_response_ttl: 10 - filtering_enabled: true - rewrites_enabled: true - parental_enabled: false - safebrowsing_enabled: false - protection_enabled: true -clients: - runtime_sources: - whois: true - arp: true - rdns: true - dhcp: true - hosts: true - persistent: [] -log: - enabled: true - file: "" - max_backups: 0 - max_size: 100 - max_age: 3 - compress: false - local_time: false - verbose: false -os: - group: "" - user: "" - rlimit_nofile: 0 -schema_version: 34 diff --git a/roles/adguard/templates/adguard.container.j2 b/roles/adguard/templates/adguard.container.j2 index 925864e..1ec3384 100644 --- a/roles/adguard/templates/adguard.container.j2 +++ b/roles/adguard/templates/adguard.container.j2 @@ -7,15 +7,15 @@ Requires=homelab-network.service [Container] Image=docker.io/adguard/adguardhome:latest ContainerName=adguard -Network=homelab.network +Network=homelab NetworkAlias=adguard Volume={{ adguard_dir }}/work:/opt/adguardhome/work Volume={{ adguard_dir }}/conf:/opt/adguardhome/conf -PublishPort=53:53/tcp -PublishPort=53:53/udp -PublishPort=3000:3000/tcp +PublishPort={{ adguard_bind_ip }}:{{ adguard_dns_port | default(53) }}:53/tcp +PublishPort={{ adguard_bind_ip }}:{{ adguard_dns_port | default(53) }}:53/udp +PublishPort={{ adguard_bind_ip }}:{{ adguard_web_port | default(3000) }}:3000/tcp [Service] Restart=always diff --git a/roles/caddy/meta/main.yml b/roles/caddy/meta/main.yml deleted file mode 100644 index 4b5b6cc..0000000 --- a/roles/caddy/meta/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# caddy/meta/main.yml -dependencies: - - role: selinux_containers \ No newline at end of file diff --git a/roles/caddy/tasks/main.yml b/roles/caddy/tasks/main.yml index 8e1aaa3..b7d4f8b 100644 --- a/roles/caddy/tasks/main.yml +++ b/roles/caddy/tasks/main.yml @@ -1,22 +1,13 @@ --- #caddy/tasks/main.yml -- name: Create stack and config directories - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" - recurse: yes - loop: "{{ caddy_base_directories }}" - -- name: Base SELinux requirement +- name: Create caddy container directory ansible.builtin.set_fact: - selinux_container_paths: "{{ caddy_base_directories }}" - -- import_role: - name: selinux_containers - tasks_from: labels + dir_list: "{{ caddy_base_directories }}" + +- name: Setup directory for caddy config + ansible.builtin.import_role: + name: container_runtime + tasks_from: config-setup - name: Ensure Caddyfile is deployed template: @@ -31,19 +22,11 @@ src: caddy.container.j2 dest: "{{ container_config_dir }}/caddy.container" -- name: Force systemd reload (blocking) - become: true - become_user: "{{ container_user }}" - command: systemctl --user daemon-reload +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "caddy" -- name: Wait for quadlet generation - pause: - seconds: 1 - -- name: Start service - become: true - become_user: "{{ container_user }}" - systemd: - name: caddy.service - scope: user - state: started \ No newline at end of file +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd \ No newline at end of file diff --git a/roles/caddy/templates/Caddyfile.j2 b/roles/caddy/templates/Caddyfile.j2 index 499fabf..e7b8b14 100644 --- a/roles/caddy/templates/Caddyfile.j2 +++ b/roles/caddy/templates/Caddyfile.j2 @@ -4,6 +4,12 @@ reverse_proxy {{ adguard_upstream }} } +# Jellyfin +{{ jellyfin_domain }} { + tls internal + reverse_proxy {{ jellyfin_upstream }} +} + # QBittorrent {{ qbittorrent_domain }} { tls internal diff --git a/roles/caddy/templates/caddy.container.j2 b/roles/caddy/templates/caddy.container.j2 index b9c899a..b252ea3 100644 --- a/roles/caddy/templates/caddy.container.j2 +++ b/roles/caddy/templates/caddy.container.j2 @@ -8,7 +8,7 @@ After=homelab-network.service [Container] Image=docker.io/caddy:latest ContainerName=caddy -Network=homelab.network +Network=homelab Volume={{ caddy_dir }}/Caddyfile:/etc/caddy/Caddyfile Volume={{ caddy_dir }}/data:/data diff --git a/roles/cli_productivity/defaults/main.yml b/roles/cli_productivity/defaults/main.yml index 7409836..a6c25cf 100644 --- a/roles/cli_productivity/defaults/main.yml +++ b/roles/cli_productivity/defaults/main.yml @@ -4,7 +4,7 @@ cli_user: "{{ container_user }}" cli_group: "{{ cli_user }}" cli_install_epel: true -cli_use_epel: "{{ cli_install_epel | bool and ansible_os_family == 'RedHat' and ansible_distribution != 'Fedora' }}" +cli_use_epel: "{{ cli_install_epel | bool and ansible_facts['os_family'] == 'RedHat' and ansible_facts['distribution'] != 'Fedora' }}" cli_set_fish_as_default_shell: true diff --git a/roles/container_runtime/tasks/config-setup.yml b/roles/container_runtime/tasks/config-setup.yml new file mode 100644 index 0000000..c6d2300 --- /dev/null +++ b/roles/container_runtime/tasks/config-setup.yml @@ -0,0 +1,14 @@ +--- +# container_runtime/tasks/config-setup.yml +- import_tasks: directory.yml + +- name: Directory SELinux requirement + ansible.builtin.set_fact: + selinux_container_paths: "{{ missing_dirs }}" + when: missing_dirs | length > 0 + +- name: Apply SELinux container labels + ansible.builtin.import_role: + name: selinux_containers + tasks_from: labels + when: missing_dirs | length > 0 \ No newline at end of file diff --git a/roles/container_runtime/tasks/directory.yml b/roles/container_runtime/tasks/directory.yml new file mode 100644 index 0000000..a6475d2 --- /dev/null +++ b/roles/container_runtime/tasks/directory.yml @@ -0,0 +1,26 @@ +- name: Check directories exist + ansible.builtin.stat: + path: "{{ item.path if item is mapping else item }}" + loop: "{{ dir_list }}" + register: dir_stats + +- name: Build list of missing directories + ansible.builtin.set_fact: + missing_dirs: >- + {{ + dir_stats.results + | rejectattr('stat.exists', 'equalto', true) + | map(attribute='item') + | list + }} + +- name: Ensure missing directories exist + become: true + ansible.builtin.file: + path: "{{ item.path if item is mapping else item }}" + state: directory + owner: "{{ container_user }}" + group: "{{ container_group }}" + mode: "{{ item.mode | default('0755') if item is mapping else '0755' }}" + loop: "{{ missing_dirs }}" + when: missing_dirs | length > 0 \ No newline at end of file diff --git a/roles/container_runtime/tasks/main.yml b/roles/container_runtime/tasks/main.yml index 501f086..5b682df 100644 --- a/roles/container_runtime/tasks/main.yml +++ b/roles/container_runtime/tasks/main.yml @@ -20,6 +20,24 @@ value: '53' state: present +- name: Check configuration directories exist + ansible.builtin.stat: + path: "{{ item }}" + loop: + - "{{ stack_root }}" + - "{{ container_config_dir }}" + register: config_dirs_stats + +- name: Build list of missing configuration directories + ansible.builtin.set_fact: + missing_config_dirs: >- + {{ + config_dirs_stats.results + | rejectattr('stat.exists') + | map(attribute='item') + | list + }} + - name: Create stack directories file: path: "{{ item }}" @@ -28,9 +46,9 @@ group: "{{ container_group }}" mode: "0755" recurse: yes - loop: - - "{{ stack_root }}" - - "{{ container_config_dir }}" + loop: "{{ missing_config_dirs }}" + when: missing_config_dirs | length > 0 + - name: Configure SELinux container policies ansible.builtin.import_tasks: ../selinux_containers/tasks/main.yml @@ -44,17 +62,11 @@ owner: "{{ container_user }}" group: "{{ container_group }}" -- name: Force systemd reload (blocking) - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - command: systemctl --user daemon-reload - -- name: Start homelab network - become: true - become_user: "{{ container_user }}" - systemd: - name: homelab-network.service - scope: user - state: started \ No newline at end of file +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "homelab-network" + +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd \ No newline at end of file diff --git a/roles/container_runtime/tasks/systemd.yml b/roles/container_runtime/tasks/systemd.yml new file mode 100644 index 0000000..89ef287 --- /dev/null +++ b/roles/container_runtime/tasks/systemd.yml @@ -0,0 +1,31 @@ +--- +# container_runtime/tasks/systemd.yml +- name: Build container service list + ansible.builtin.set_fact: + container_service_names: "{{ service_names | default([service_name]) }}" + +- name: Force systemd reload (blocking) + become: true + become_user: "{{ container_user }}" + environment: + XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" + command: systemctl --user daemon-reload + when: not ansible_check_mode + +- name: Wait for quadlet generation + pause: + seconds: 1 + when: not ansible_check_mode + +- name: Start and enable container services + become: true + become_user: "{{ container_user }}" + environment: + XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" + systemd: + name: "{{ item }}.service" + scope: user + state: started + enabled: true + loop: "{{ container_service_names }}" + when: not ansible_check_mode \ No newline at end of file diff --git a/roles/coturn/meta/main.yml b/roles/coturn/meta/main.yml deleted file mode 100644 index daa07a7..0000000 --- a/roles/coturn/meta/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# coturn/meta/main.yml -dependencies: - - role: selinux_containers \ No newline at end of file diff --git a/roles/coturn/tasks/main.yml b/roles/coturn/tasks/main.yml index 02ce3e0..fffcb22 100644 --- a/roles/coturn/tasks/main.yml +++ b/roles/coturn/tasks/main.yml @@ -2,32 +2,14 @@ # coturn/tasks/main.yml - import_tasks: firewall.yml -- name: Create stack and config directories - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" - recurse: yes - loop: "{{ coturn_base_directories }}" - -- name: Directory SELinux requirement +- name: Create coturn container directory ansible.builtin.set_fact: - selinux_container_paths: "{{ coturn_base_directories }}" + dir_list: "{{ coturn_base_directories }}" -- import_role: - name: selinux_containers - tasks_from: labels - -- name: Ensure container app config directories are owned by container UID - become: true - file: - path: "{{ coturn_dir }}/conf" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - recurse: true +- name: Setup directory for coturn config + ansible.builtin.import_role: + name: container_runtime + tasks_from: config-setup - name: Deploy Turnserver configuration template template: @@ -36,6 +18,8 @@ owner: "{{ container_user }}" group: "{{ container_group }}" mode: '0600' + force: "{{ coturn_overwrite_config | default(false) | bool }}" + when: not ansible_check_mode - name: Deploy Coturn Quadlet template: @@ -45,24 +29,11 @@ group: "{{ container_group }}" mode: '0644' -- name: Force systemd reload (blocking) - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - command: systemctl --user daemon-reload +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "coturn" -- name: Wait for quadlet generation - pause: - seconds: 1 - -- name: Start and enable Coturn service - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - systemd: - name: coturn.service - scope: user - state: started - enabled: true \ No newline at end of file +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd \ No newline at end of file diff --git a/roles/coturn/templates/coturn.container.j2 b/roles/coturn/templates/coturn.container.j2 index dfd09ce..12999ce 100644 --- a/roles/coturn/templates/coturn.container.j2 +++ b/roles/coturn/templates/coturn.container.j2 @@ -7,7 +7,7 @@ Requires=homelab-network.service ContainerName=coturn Image=docker.io/coturn/coturn:latest Volume={{ coturn_config_dir }}/turnserver.conf:/etc/coturn/turnserver.conf:Z -Network=homelab.network +Network=homelab PublishPort=3478:3478/tcp PublishPort=3478:3478/udp PublishPort=49152-49172:49152-49172/udp diff --git a/roles/jellyfin/tasks/firewall.yml b/roles/jellyfin/tasks/firewall.yml new file mode 100644 index 0000000..02fe898 --- /dev/null +++ b/roles/jellyfin/tasks/firewall.yml @@ -0,0 +1,12 @@ +--- +# jellyfin/tasks/firewall.yml + +- name: Open required Jellyfin firewall rules + become: true + ansible.posix.firewalld: + port: "{{ item.port | default(omit) }}" + service: "{{ item.service | default(omit) }}" + permanent: true + state: enabled + immediate: true + loop: "{{ jellyfin_firewall_rules }}" \ No newline at end of file diff --git a/roles/jellyfin/tasks/main.yml b/roles/jellyfin/tasks/main.yml new file mode 100644 index 0000000..442f774 --- /dev/null +++ b/roles/jellyfin/tasks/main.yml @@ -0,0 +1,30 @@ +--- +# jellyfin/tasks/main.yml + +- import_tasks: firewall.yml + +- name: Create jellyfin container directory + ansible.builtin.set_fact: + dir_list: "{{ jellyfin_base_directories }}" + +- name: Setup directory for jellyfin config + ansible.builtin.import_role: + name: container_runtime + tasks_from: config-setup + +- name: Deploy Jellyfin Quadlet + template: + src: jellyfin.container.j2 + dest: "{{ container_config_dir }}/jellyfin.container" + owner: "{{ container_user }}" + group: "{{ container_group }}" + mode: "0644" + +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "jellyfin" + +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd \ No newline at end of file diff --git a/roles/jellyfin/templates/jellyfin.container.j2 b/roles/jellyfin/templates/jellyfin.container.j2 new file mode 100644 index 0000000..ab121a8 --- /dev/null +++ b/roles/jellyfin/templates/jellyfin.container.j2 @@ -0,0 +1,21 @@ +[Unit] +Description=Jellyfin Media Server +Wants=network-online.target +After=network-online.target + +[Container] +ContainerName=jellyfin +Image=docker.io/jellyfin/jellyfin:10.11.7 +Network=host + +Volume={{ jellyfin_config_dir }}:/config:Z +Volume={{ jellyfin_cache_dir }}:/cache:Z +Volume={{ jellyfin_media_dir }}:/data:ro + +Environment=TZ={{ timezone }} + +[Service] +Restart=always + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/roles/matrix_synapse/meta/main.yml b/roles/matrix_synapse/meta/main.yml deleted file mode 100644 index eb2c7bd..0000000 --- a/roles/matrix_synapse/meta/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -# matrix_synapse/meta/main.yml -dependencies: - - role: tailscale - - role: postgres - - role: coturn \ No newline at end of file diff --git a/roles/matrix_synapse/tasks/main.yml b/roles/matrix_synapse/tasks/main.yml index 8704947..2afcfed 100644 --- a/roles/matrix_synapse/tasks/main.yml +++ b/roles/matrix_synapse/tasks/main.yml @@ -1,21 +1,13 @@ --- # matrix_synapse/tasks/main.yml -- name: Create stack and config directories - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" - loop: "{{ synapse_base_directories }}" - -- name: Directory SELinux requirement +- name: Create synapse container directory ansible.builtin.set_fact: - selinux_container_paths: "{{ synapse_base_directories }}" + dir_list: "{{ synapse_base_directories }}" -- import_role: - name: selinux_containers - tasks_from: labels +- name: Create directory for synapse config + ansible.builtin.import_role: + name: container_runtime + tasks_from: config-setup - name: Deploy homesever configuration template template: @@ -25,6 +17,7 @@ group: "{{ container_group }}" mode: '0600' force: "{{ matrix_overwrite_config | default(false) | bool }}" + when: not ansible_check_mode - name: Ensure Synapse signing key is deployed copy: @@ -34,6 +27,7 @@ group: "{{ container_group }}" mode: '0600' force: "{{ matrix_overwrite_signing_key | default(false) | bool }}" + when: not ansible_check_mode - name: Deploy Synapse Quadlet template: @@ -43,24 +37,11 @@ group: "{{ container_group }}" mode: '0644' -- name: Force systemd reload (blocking) - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - command: systemctl --user daemon-reload +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "synapse" -- name: Wait for quadlet generation - pause: - seconds: 1 - -- name: Start and enable Synapse service - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - systemd: - name: synapse.service - scope: user - state: started - enabled: true \ No newline at end of file +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd \ No newline at end of file diff --git a/roles/matrix_synapse/templates/synapse.container.j2 b/roles/matrix_synapse/templates/synapse.container.j2 index 8a96f2f..f0b9eec 100644 --- a/roles/matrix_synapse/templates/synapse.container.j2 +++ b/roles/matrix_synapse/templates/synapse.container.j2 @@ -7,7 +7,7 @@ Requires=postgres.service ContainerName=synapse Image=docker.io/matrixdotorg/synapse:latest Volume={{ synapse_config_dir }}:/data:Z -Network=homelab.network +Network=homelab # Expose the client-server API port PublishPort={{ tailscale_ip }}:8008:8008 UserNS=keep-id diff --git a/roles/nfs_client/tasks/main.yml b/roles/nfs_client/tasks/main.yml index 7f8034f..e123c51 100644 --- a/roles/nfs_client/tasks/main.yml +++ b/roles/nfs_client/tasks/main.yml @@ -1,70 +1,33 @@ --- # nfs_client/tasks/main.yml -- name: Configure dummy NAS storage for test environment - when: env == "test" - block: - - name: Create dummy NAS root for test environment - become: true - file: - path: "{{ nfs_mount_point }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" +- name: Install required NFS client packages + become: true + dnf: + name: nfs-utils + state: present - - name: Create dummy NAS storage tree for test environment - become: true - file: - path: "{{ nfs_mount_point }}/{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0775" - loop: "{{ storage_tree }}" +- name: Check whether NFS mount point is already mounted + become: true + ansible.builtin.command: findmnt --mountpoint "{{ nfs_mount_point }}" + register: nfs_mount_check + changed_when: false + failed_when: false - - name: Set SELinux context for dummy NAS storage in test environment - become: true - community.general.sefcontext: - target: "{{ nfs_mount_point }}(/.*)?" - setype: container_file_t - state: present +- name: Ensure local NFS mount point exists before mounting + become: true + file: + path: "{{ nfs_mount_point }}" + state: directory + owner: root + group: root + mode: "0755" + when: nfs_mount_check.rc != 0 - - name: Apply SELinux context for dummy NAS storage in test environment - become: true - command: restorecon -Rv "{{ nfs_mount_point }}" - changed_when: false - -- name: Configure NFS client for non-test environments - when: env != "test" - block: - - name: Install required NFS client packages - become: true - dnf: - name: nfs-utils - state: present - - - name: Check whether NFS mount point is already mounted - become: true - ansible.builtin.command: findmnt --mountpoint "{{ nfs_mount_point }}" - register: nfs_mount_check - changed_when: false - failed_when: false - - - name: Ensure local NFS mount point exists before mounting - become: true - file: - path: "{{ nfs_mount_point }}" - state: directory - owner: root - group: root - mode: "0755" - when: nfs_mount_check.rc != 0 - - - name: Ensure NFS mount is present in fstab and mounted - become: true - ansible.posix.mount: - path: "{{ nfs_mount_point }}" - src: "{{ nfs_server }}:{{ nfs_export }}" - fstype: "{{ nfs_fstype }}" - opts: "{{ nfs_options }}" - state: mounted \ No newline at end of file +- name: Ensure NFS mount is present in fstab and mounted + become: true + ansible.posix.mount: + path: "{{ nfs_mount_point }}" + src: "{{ nfs_server }}:{{ nfs_export }}" + fstype: "{{ nfs_fstype }}" + opts: "{{ nfs_options }}" + state: mounted \ No newline at end of file diff --git a/roles/postgres/meta/main.yml b/roles/postgres/meta/main.yml deleted file mode 100644 index 3572468..0000000 --- a/roles/postgres/meta/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# postgres/meta/main.yml -dependencies: - - role: selinux_containers \ No newline at end of file diff --git a/roles/postgres/tasks/main.yml b/roles/postgres/tasks/main.yml index 6566968..32d5f52 100644 --- a/roles/postgres/tasks/main.yml +++ b/roles/postgres/tasks/main.yml @@ -1,30 +1,13 @@ --- # postgres/tasks/main.yml -- name: Create stack and config directories - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" - loop: "{{ postgres_base_directories }}" - -- name: Directory SELinux requirement +- name: Create postgres container directory ansible.builtin.set_fact: - selinux_container_paths: "{{ postgres_base_directories }}" + dir_list: "{{ postgres_base_directories }}" -- import_role: - name: selinux_containers - tasks_from: labels - -- name: Ensure container app config directories are owned by container UID - become: true - file: - path: "{{ postgres_config_dir }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - recurse: true +- name: Setup directory for postgres config + ansible.builtin.import_role: + name: container_runtime + tasks_from: config-setup - name: Deploy Postgres Quadlet template: @@ -34,27 +17,14 @@ group: "{{ container_group }}" mode: "0600" -- name: Force systemd reload (blocking) - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - command: systemctl --user daemon-reload +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "postgres" -- name: Wait for quadlet generation - pause: - seconds: 1 - -- name: Start and enable Postgres service - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - systemd: - name: postgres.service - scope: user - state: started - enabled: true +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd - name: Wait for Postgres to be ready (Handling the double-start) become: true @@ -67,4 +37,5 @@ until: pg_check.rc == 0 retries: 20 delay: 5 - changed_when: false \ No newline at end of file + changed_when: false + when: not ansible_check_mode \ No newline at end of file diff --git a/roles/postgres/templates/postgres.container.j2 b/roles/postgres/templates/postgres.container.j2 index 3bee2dc..f5c6dc0 100644 --- a/roles/postgres/templates/postgres.container.j2 +++ b/roles/postgres/templates/postgres.container.j2 @@ -11,7 +11,7 @@ Environment=POSTGRES_PASSWORD={{ vault_matrix_postgres_password }} Environment=POSTGRES_DB=synapse Environment=POSTGRES_INITDB_ARGS="--lc-collate=C --lc-ctype=C --encoding=UTF8" Volume={{ postgres_data_dir }}:/var/lib/postgresql/data -Network=homelab.network +Network=homelab IP=10.89.0.54 [Install] diff --git a/roles/selinux_containers/tasks/labels.yml b/roles/selinux_containers/tasks/labels.yml index 5965f2f..14867c9 100644 --- a/roles/selinux_containers/tasks/labels.yml +++ b/roles/selinux_containers/tasks/labels.yml @@ -3,7 +3,7 @@ - name: Ensure SELinux context for container config paths become: true community.general.sefcontext: - target: "{{ item }}(/.*)?" + target: "{{ (item.path if item is mapping else item) }}(/.*)?" setype: container_file_t state: present loop: "{{ selinux_container_paths | default([]) }}" diff --git a/roles/selinux_containers/tasks/storage.yml b/roles/selinux_containers/tasks/storage.yml deleted file mode 100644 index 97136fb..0000000 --- a/roles/selinux_containers/tasks/storage.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -# selinux_containers/tasks/storage.yml -- name: Set SELinux context for storage mounts - become: true - community.general.sefcontext: - target: "{{ item }}(/.*)?" - setype: container_file_t - state: present - loop: "{{ storage_backends }}" - when: "'nas' in group_names" - -- name: Apply SELinux context (storage) - become: true - command: restorecon -R -F -v "{{ item }}" - loop: "{{ storage_backends }}" - changed_when: false - when: "'nas' in group_names" \ No newline at end of file diff --git a/roles/servarr/defaults/main.yml b/roles/servarr/defaults/main.yml index 07f8daf..8c8c829 100644 --- a/roles/servarr/defaults/main.yml +++ b/roles/servarr/defaults/main.yml @@ -6,4 +6,6 @@ servarr_firewall_rules: - port: 7878/tcp - port: 8191/tcp - port: 8989/tcp - - port: 9696/tcp \ No newline at end of file + - port: 9696/tcp + +vpn_guard_enabled: false \ No newline at end of file diff --git a/roles/servarr/meta/main.yml b/roles/servarr/meta/main.yml deleted file mode 100644 index d7468a9..0000000 --- a/roles/servarr/meta/main.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -# servarr/meta/main.yml -dependencies: - - role: selinux_containers - - role: vpn \ No newline at end of file diff --git a/roles/servarr/tasks/main.yml b/roles/servarr/tasks/main.yml index a211cf7..ecdfc27 100644 --- a/roles/servarr/tasks/main.yml +++ b/roles/servarr/tasks/main.yml @@ -1,31 +1,14 @@ #servarr/tasks/main.yml - import_tasks: firewall.yml -- name: Create stack and config directories - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" - recurse: yes - loop: "{{ servarr_base_directories }}" - -- name: Directory SELinux requirement +- name: Create servarr container directory ansible.builtin.set_fact: - selinux_container_paths: "{{ servarr_base_directories }}" + dir_list: "{{ servarr_base_directories }}" -- import_role: - name: selinux_containers - tasks_from: labels - -- name: Ensure systemd directory exists for rootless user - file: - path: "{{ container_config_dir }}" - state: directory - mode: '0755' - owner: "{{ container_user }}" - group: "{{ container_group }}" +- name: Setup directory for servarr config + ansible.builtin.import_role: + name: container_runtime + tasks_from: config-setup - name: Deploy Quadlet files template: @@ -34,33 +17,25 @@ loop: "{{ servarr_stack }}" register: quadlets_deployed -- name: Ensure app config directories are writable - become: true - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - recurse: true - loop: - - "{{ radarr_dir }}/config" - - "{{ sonarr_dir }}/config" - - "{{ qbittorrent_dir }}/config" - - "{{ prowlarr_dir }}/config" - - "{{ bazarr_dir }}/config" - -#- name: Force systemd reload (blocking) -# become: true -# become_user: "{{ container_user }}" -# command: systemctl --user daemon-reload - -- name: Force systemd reload (blocking) - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - command: systemctl --user daemon-reload - -- name: Validate VPN and start arr stack +- name: Validate VPN ansible.builtin.import_role: - name: vpn_guard \ No newline at end of file + name: vpn_guard + when: + - vpn_guard_enabled | bool + - not ansible_check_mode + +- name: Skip VPN guard validation in check mode + debug: + msg: "Skipping VPN guard validation during Ansible check mode." + when: + - vpn_guard_enabled | bool + - ansible_check_mode + +- name: Set fact for systemd + ansible.builtin.set_fact: + service_names: "{{ arr_suite }}" + +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd \ No newline at end of file diff --git a/roles/storage_client/tasks/main.yml b/roles/storage_client/tasks/main.yml index efd3614..8a9ea9c 100644 --- a/roles/storage_client/tasks/main.yml +++ b/roles/storage_client/tasks/main.yml @@ -1,43 +1,53 @@ ---- #storage_client/tasks/main.yml - name: Install required packages become: true - dnf: + ansible.builtin.dnf: name: "{{ item }}" state: present loop: "{{ base_storage_install_packages }}" + when: env == "prod" - name: Install mergerfs repo package become: true - dnf: + ansible.builtin.dnf: name: https://github.com/trapexit/mergerfs/releases/download/2.41.1/mergerfs-2.41.1-1.el10.x86_64.rpm disable_gpg_check: true state: present + when: env == "prod" -- name: Ensure source data directories exist - become: true - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" - loop: "{{ storage_backends }}" +- name: Set storage mount directory list + ansible.builtin.set_fact: + dir_list: "{{ storage_drives + mergerfs }}" + when: env == "prod" -- name: Create mergerfs mountpoint +- name: Ensure storage mount directories exist + ansible.builtin.import_role: + name: container_runtime + tasks_from: directory + when: env == "prod" + +- name: Mount filesystem by UUID become: true - file: - path: /mnt/nas01 - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" + ansible.posix.mount: + path: "{{ item.path }}" + src: "UUID={{ item.uuid }}" + fstype: "{{ item.fstype }}" + opts: "{{ item.opts }}" + dump: "{{ item.dump }}" + passno: "{{ item.passno }}" + state: mounted + loop: "{{ storage_drives }}" + when: env == "prod" - name: Mount mergerfs pool become: true ansible.posix.mount: - path: "{{ mergerfs_path }}" - src: "{{ drive_a_path }}/data:{{ drive_b_path }}/data" + path: "{{ item.path }}" + src: "{{ item.src_path }}" fstype: fuse.mergerfs - opts: defaults,allow_other,use_ino,category.create=mfs - state: mounted \ No newline at end of file + opts: "{{ item.opts }}" + dump: "{{ item.dump | default('0') }}" + passno: "{{ item.passno | default('0') }}" + state: mounted + loop: "{{ mergerfs }}" + when: env == "prod" \ No newline at end of file diff --git a/roles/tailscale/tasks/main.yml b/roles/tailscale/tasks/main.yml index b322e0f..b890ba1 100644 --- a/roles/tailscale/tasks/main.yml +++ b/roles/tailscale/tasks/main.yml @@ -20,6 +20,7 @@ name: tailscaled state: started enabled: true + when: not ansible_check_mode - name: Bring Tailscale up (without hijacking DNS) become: true @@ -33,4 +34,6 @@ changed_when: "'already authenticated' not in ts_up.stderr" failed_when: - ts_up.rc != 0 - - "'already authenticated' not in ts_up.stderr" \ No newline at end of file + - "'already authenticated' not in ts_up.stderr" + when: not ansible_check_mode + no_log: true \ No newline at end of file diff --git a/roles/trilium/tasks/main.yml b/roles/trilium/tasks/main.yml index f1e1b81..3ec2419 100644 --- a/roles/trilium/tasks/main.yml +++ b/roles/trilium/tasks/main.yml @@ -2,23 +2,14 @@ # trilium/tasks/main.yml - import_tasks: firewall.yml -- name: Create stack and config directories - file: - path: "{{ item }}" - state: directory - owner: "{{ container_user }}" - group: "{{ container_group }}" - mode: "0755" - recurse: yes - loop: "{{ trilium_base_directories }}" - -- name: Directory SELinux requirement +- name: Create trilium container directory ansible.builtin.set_fact: - selinux_container_paths: "{{ trilium_base_directories }}" + dir_list: "{{ trilium_base_directories }}" -- import_role: - name: selinux_containers - tasks_from: labels +- name: Setup directory for trilium config + ansible.builtin.import_role: + name: container_runtime + tasks_from: config-setup - name: Deploy Trilium Quadlet template: @@ -28,24 +19,11 @@ group: "{{ container_group }}" mode: "0644" -- name: Force systemd reload - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - command: systemctl --user daemon-reload +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "trilium" -- name: Wait for quadlet generation - pause: - seconds: 1 - -- name: Start and enable Trilium service - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - systemd: - name: trilium.service - scope: user - state: started - enabled: true \ No newline at end of file +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd \ No newline at end of file diff --git a/roles/trilium/templates/trilium.container.j2 b/roles/trilium/templates/trilium.container.j2 index 02af78f..fd3c0d5 100644 --- a/roles/trilium/templates/trilium.container.j2 +++ b/roles/trilium/templates/trilium.container.j2 @@ -7,9 +7,8 @@ Requires=homelab-network.service ContainerName=trilium Image=docker.io/triliumnext/notes:latest Volume={{ trilium_data_dir }}:/home/node/trilium-data:Z -Network=homelab.network +Network=homelab NetworkAlias=trilium -IP={{ trilium_ip }} Environment=TZ={{ timezone }} [Service] diff --git a/roles/vpn/tasks/main.yml b/roles/vpn/tasks/main.yml index 1406cd1..aee37ef 100644 --- a/roles/vpn/tasks/main.yml +++ b/roles/vpn/tasks/main.yml @@ -9,10 +9,11 @@ - name: Check whether xt_conntrack is available for running kernel become: true - command: modinfo xt_conntrack + ansible.builtin.command: modinfo xt_conntrack register: xt_conntrack_modinfo changed_when: false failed_when: false + check_mode: false - name: Reboot if kernel modules were installed but running kernel cannot find xt_conntrack become: true @@ -20,6 +21,8 @@ msg: "Rebooting to load kernel matching installed kernel-modules-extra for Gluetun firewall" reboot_timeout: 600 when: + - not ansible_check_mode + - kernel_modules_extra_install.changed - xt_conntrack_modinfo.rc != 0 - name: Load xt_conntrack for Gluetun firewall @@ -42,30 +45,21 @@ tasks_from: vpn - name: Deploy Quadlet files - template: + ansible.builtin.template: src: "gluetun.container.j2" dest: "{{ container_config_dir }}/gluetun.container" + owner: "{{ container_user }}" + group: "{{ container_group }}" + mode: "0644" -- name: Force systemd reload (blocking) - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - command: systemctl --user daemon-reload +- name: Set fact for systemd + ansible.builtin.set_fact: + service_name: "gluetun" -- name: Wait for quadlet generation - pause: - seconds: 1 - -- name: Start vpn - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - systemd: - name: gluetun.service - scope: user - state: started +- name: Execute systemd tasks + ansible.builtin.import_role: + name: container_runtime + tasks_from: systemd - name: Wait for Gluetun container to exist become: true @@ -76,7 +70,9 @@ delay: 2 until: gluetun_exists.rc == 0 changed_when: false + when: not ansible_check_mode -- name: Wait for Gluetun to stabilize - pause: - seconds: 5 \ No newline at end of file +- name: Skip Gluetun runtime validation in check mode + debug: + msg: "Skipping Gluetun container existence check during Ansible check mode." + when: ansible_check_mode \ No newline at end of file diff --git a/roles/vpn/templates/gluetun.container.j2 b/roles/vpn/templates/gluetun.container.j2 index 05a3035..739e737 100644 --- a/roles/vpn/templates/gluetun.container.j2 +++ b/roles/vpn/templates/gluetun.container.j2 @@ -7,7 +7,6 @@ Wants=network-online.target [Container] Image=docker.io/qmcgaw/gluetun:latest ContainerName=gluetun -UserNS=keep-id AddCapability=NET_ADMIN AddCapability=NET_RAW @@ -38,7 +37,8 @@ Environment=FIREWALL_ENABLED=on Environment=DNS_ENABLED=false Environment=FIREWALL_INPUT_PORTS=6767,7878,8080,8191,8989,9696 -Network=homelab:alias=gluetun +Network=homelab +NetworkAlias=gluetun [Install] WantedBy=default.target \ No newline at end of file diff --git a/roles/vpn_guard/tasks/main.yml b/roles/vpn_guard/tasks/main.yml index 568f3ea..8938153 100644 --- a/roles/vpn_guard/tasks/main.yml +++ b/roles/vpn_guard/tasks/main.yml @@ -4,6 +4,7 @@ command: curl -s https://ipinfo.io/ip register: host_ip changed_when: false + when: not ansible_check_mode - name: Get VPN public IP (via Gluetun) become: true @@ -11,30 +12,11 @@ command: podman exec gluetun wget -qO- https://ipinfo.io/ip register: vpn_ip changed_when: false + when: not ansible_check_mode - name: Fail if VPN is not active (kill switch check) fail: msg: "VPN is NOT active (host={{ host_ip.stdout }} vpn={{ vpn_ip.stdout }}). Aborting arr stack start." - when: host_ip.stdout == vpn_ip.stdout - -#- name: Start arr stack only after VPN validation -# become: true -# become_user: "{{ container_user }}" -# systemd: -# name: "{{ item }}.service" -# enabled: yes -# state: started -# scope: user -# loop: "{{ arr_suite }}" - -- name: Start arr stack only after VPN validation - become: true - become_user: "{{ container_user }}" - environment: - XDG_RUNTIME_DIR: "{{ container_runtime_dir }}" - systemd: - name: "{{ item }}.service" - enabled: yes - state: started - scope: user - loop: "{{ arr_suite }}" \ No newline at end of file + when: + - not ansible_check_mode + - host_ip.stdout == vpn_ip.stdout -- 2.40.1