/
/
/
Ansible role that provisions my storage server.
1---
2# Storage Services Validation and Health Checks
3
4- name: Check Docker daemon status
5 systemd:
6 name: docker
7 state: started
8 check_mode: no
9
10- name: Verify storage network exists
11 community.docker.docker_network_info:
12 name: "{{ storage_docker_network }}"
13 register: storage_network_info
14
15- name: Verify arr network exists
16 community.docker.docker_network_info:
17 name: "{{ arr_docker_network }}"
18 register: arr_network_info
19
20- name: Display network status
21 debug:
22 msg: |
23 Storage network {{ storage_docker_network }} is available: {{ storage_network_info.exists }}
24 Arr network {{ arr_docker_network }} is available: {{ arr_network_info.exists }}
25 when: storage_network_info.exists or arr_network_info.exists
26
27- name: Check service directories exist
28 stat:
29 path: "{{ item.path }}"
30 register: service_dir_check
31 changed_when: false
32 loop:
33 - { name: "Jellyfin", path: "{{ jellyfin_data_dir }}", enabled: "{{ jellyfin_enabled }}" }
34 - { name: "Arr Stack", path: "{{ arr_config_dir }}", enabled: "{{ arr_stack_enabled }}" }
35 - { name: "Music Assistant", path: "{{ music_assistant_config_dir }}", enabled: "{{ music_assistant_enabled }}" }
36 - { name: "Calibre Stack", path: "{{ calibre_config_dir }}", enabled: "{{ calibre_enabled }}" }
37 - { name: "Restic Server", path: "{{ restic_backup_config_dir }}", enabled: "{{ restic_backup_server_enabled }}" }
38 when: item.enabled
39
40- name: Collect container status for enabled services
41 command: docker compose ps --format json
42 args:
43 chdir: "{{ item.item.path }}"
44 register: container_status
45 changed_when: false
46 ignore_errors: true
47 loop: "{{ service_dir_check.results }}"
48 when:
49 - item.item.enabled
50 - item.stat.exists
51
52- name: Verify service health endpoints
53 uri:
54 url: "{{ item.url }}"
55 method: GET
56 status_code: "{{ item.status_code | default(200) }}"
57 validate_certs: no
58 register: service_health
59 changed_when: false
60 ignore_errors: true
61 loop:
62 - { name: "Jellyfin", url: "http://localhost:{{ jellyfin_host_port }}/health", enabled: "{{ jellyfin_enabled }}" }
63 - { name: "Sonarr", url: "http://localhost:{{ sonarr_host_port }}", enabled: "{{ sonarr_enabled }}" }
64 - { name: "Radarr", url: "http://localhost:{{ radarr_host_port }}", enabled: "{{ radarr_enabled }}" }
65 - { name: "Prowlarr", url: "http://localhost:{{ prowlarr_host_port }}", enabled: "{{ prowlarr_enabled }}" }
66 - { name: "LazyLibrarian", url: "http://localhost:{{ lazylibrarian_host_port }}", enabled: "{{ lazylibrarian_enabled }}" }
67 - { name: "Jellyseer", url: "http://localhost:{{ jellyseer_host_port }}", enabled: "{{ jellyseer_enabled }}" }
68 - { name: "Flaresolverr", url: "http://localhost:{{ flaresolverr_host_port }}/health", enabled: "{{ flaresolverr_enabled }}" }
69 - { name: "Lidarr", url: "http://localhost:{{ lidarr_host_port }}", enabled: "{{ lidarr_enabled }}" }
70 - { name: "qBittorrent", url: "http://localhost:{{ qbittorrent_host_port }}", status_code: "[200,401]", enabled: "{{ qbittorrent_enabled }}" }
71 - { name: "Calibre Server", url: "http://localhost:{{ calibre_desktop_gui_host_port }}", enabled: "{{ calibre_server_enabled }}" }
72 - { name: "Calibre-Web", url: "http://localhost:{{ calibre_web_host_port }}", enabled: "{{ calibre_web_enabled }}" }
73 when: item.enabled
74
75- name: Verify directory permissions
76 stat:
77 path: "{{ item }}"
78 register: dir_stats
79 loop:
80 - "{{ storage_docker_dir }}"
81 - "{{ storage_base_path }}"
82 - "{{ jellyfin_data_dir }}"
83 - "{{ arr_config_dir }}"
84 - "{{ music_assistant_config_dir }}"
85 - "{{ calibre_config_dir }}"
86 - "{{ restic_backup_config_dir }}"
87
88- name: Display directory permission status
89 debug:
90 msg: |
91 Directory: {{ item.item }}
92 Owner: {{ item.stat.pw_name | default('unknown') }}:{{ item.stat.gr_name | default('unknown') }}
93 Permissions: {{ item.stat.mode | default('unknown') }}
94 Accessible: {{ item.stat.exists | default(false) }}
95 loop: "{{ dir_stats.results }}"
96 when: item.stat is defined
97
98- name: Check for common configuration issues
99 block:
100 - name: Verify VPN configuration if enabled
101 debug:
102 msg: "WARNING: VPN credentials may need configuration in vault"
103 when:
104 - gluetun_enabled
105 - vpn_service_provider == ""
106
107 - name: Verify backup authentication if enabled
108 debug:
109 msg: "WARNING: Restic authentication credentials need configuration in vault"
110 when:
111 - restic_backup_server_enabled
112 - restic_backup_username == ""
113
114 - name: Check media directory accessibility
115 stat:
116 path: "{{ item }}"
117 register: media_access
118 changed_when: false
119 loop: "{{ media_directories }}"
120
121 - name: Display media directory status
122 debug:
123 msg: "Media directory {{ item.item }} exists: {{ item.stat.exists | default(false) }}"
124 loop: "{{ media_access.results }}"
125 when: item.stat is defined
126
127 rescue:
128 - name: Display configuration warnings
129 debug:
130 msg: |
131 Some configuration issues detected:
132 - Check that all required vault variables are configured
133 - Verify storage paths are accessible
134 - Ensure VPN credentials are set if using Gluetun
135 - Confirm backup authentication is configured
136