server_automation

This repo is destined for my server automations and setup.

13.9 KBYML
storage.yml
13.9 KB339 lines • yaml
1---
2# Storage Services Playbook
3# Comprehensive deployment for media automation and backup services
4
5# PHASE 1: Setup NAS exports for storage services (if needed for other hosts)
6# Note: Storage server typically hosts its own storage, so this phase may be empty
7- name: Storage Server Local Setup
8  hosts: storage_servers
9  become: yes
10  gather_facts: yes
11  
12  vars:
13    # Enable basic system monitoring (mdadm, smartd)
14    nas_raid_monitoring: true
15    nas_smartmontools_enabled: true
16    
17  pre_tasks:
18    - name: Verify storage server local requirements
19      assert:
20        that:
21          - storage_base_path is defined
22          - storage_raid_arrays is defined
23          - ansible_default_ipv4.address is defined
24        fail_msg: "Storage server local requirements not met. Check host variables."
25        
26    - name: Display storage local setup information
27      debug:
28        msg: |
29          Setting up local storage services on: {{ inventory_hostname }}
30          Storage Base: {{ storage_base_path }}
31          RAID Arrays: {{ storage_raid_arrays | length }}
32          
33          Local Services to Enable:
34          - RAID Health Monitoring
35          - SMART Drive Monitoring
36          - Storage Path Validation
37          
38  roles:
39    # Only run monitoring tasks from NAS role for local storage
40    - role: nas
41      tags: ['storage', 'raid']
42      vars:
43        nas_nfs_enabled: false
44        nas_network_bonding_enabled: false
45        nas_performance_tuning_enabled: false
46        nas_backup_integration: false
47        nas_enable_runner_exports: false
48        nas_raid_monitoring: true
49        nas_smartmontools_enabled: true
50
51  post_tasks:
52    - name: Verify local monitoring services are active
53      systemd:
54        name: "{{ item }}"
55        state: started
56        enabled: yes
57      loop:
58        - mdmonitor
59        - smartd
60      tags: ['verification']
61
62# PHASE 2: Deploy storage services  
63- name: Storage Services Deployment
64  hosts: storage_servers
65  become: yes
66  gather_facts: yes
67  
68  vars:
69    # Override defaults for storage-specific deployment
70    storage_enabled: true
71    backup_enabled: true
72
73  pre_tasks:
74    - name: Verify storage server requirements
75      assert:
76        that:
77          - storage_base_path is defined
78          - storage_docker_dir is defined  
79          - ansible_default_ipv4.address is defined
80          - storage_user is defined
81          - storage_group is defined
82          - storage_raid_arrays is defined
83        fail_msg: "Storage server requirements not met. Check host variables."
84
85    - name: Validate storage paths exist and are accessible
86      block:
87        - name: Check storage base path
88          stat:
89            path: "{{ storage_base_path }}"
90          register: storage_base_stat
91          failed_when: not storage_base_stat.stat.exists
92          
93        - name: Check storage base path permissions
94          assert:
95            that:
96              - storage_base_stat.stat.readable
97              - storage_base_stat.stat.writable
98            fail_msg: "Storage base path {{ storage_base_path }} is not readable/writable"
99            
100        - name: Check storage docker directory
101          stat:
102            path: "{{ storage_docker_dir }}"
103          register: storage_docker_stat
104          failed_when: not storage_docker_stat.stat.exists
105          
106        - name: Check storage docker directory permissions
107          assert:
108            that:
109              - storage_docker_stat.stat.readable
110              - storage_docker_stat.stat.writable
111            fail_msg: "Storage docker directory {{ storage_docker_dir }} is not readable/writable"
112            
113      rescue:
114        - name: Display storage path error
115          debug:
116            msg: |
117              ERROR: Storage path validation failed!
118              Path: {{ storage_base_path }}
119              Docker Directory: {{ storage_docker_dir }}
120              Ensure the storage array is mounted and accessible
121              Current mounts: {{ ansible_mounts | map(attribute='mount') | list }}
122              Available space: {{ ansible_mounts | selectattr('mount', 'equalto', storage_base_path) | map(attribute='size_available') | first | default('unknown') | filesizeformat }}
123
124    - name: Display storage deployment information
125      debug:
126        msg: |
127          🚀 Deploying Storage Services to: {{ inventory_hostname }}
128          
129          📊 Server Information:
130          - IP Address: {{ ansible_default_ipv4.address }}
131          - Storage Base: {{ storage_base_path }}
132          - Docker Directory: {{ storage_docker_dir }}
133          - User: {{ storage_user }}:{{ storage_group }}
134          - RAID Monitoring: {{ 'Active' if mdmonitor_status is defined and mdmonitor_status.rc == 0 else 'Pending' }}
135          - SMART Monitoring: {{ 'Active' if smartd_status is defined and smartd_status.rc == 0 else 'Pending' }}
136          - GPU Acceleration: Disabled (CPU only)
137          - Available Storage: {{ ansible_mounts | selectattr('mount', 'equalto', storage_base_path) | map(attribute='size_available') | first | default('unknown') | filesizeformat }}
138          - Total Storage: {{ ansible_mounts | selectattr('mount', 'equalto', storage_base_path) | map(attribute='size_total') | first | default('unknown') | filesizeformat }}
139          
140          📦 Services to Deploy:
141          {% if jellyfin_enabled | default(true) %}
142          - Jellyfin Media Server (Port {{ jellyfin_host_port | default(8096) }}) - CPU Hardware Acceleration
143          {% endif %}
144          {% if arr_stack_enabled | default(true) %}
145          - Arr Stack with Gluetun VPN:
146            * Sonarr TV (Port {{ sonarr_host_port | default(8989) }})
147            * Radarr Movies (Port {{ radarr_host_port | default(7878) }})  
148            * Prowlarr Indexers (Port {{ prowlarr_host_port | default(9696) }})
149            * LazyLibrarian Books (Port {{ lazylibrarian_host_port | default(5299) }})
150            * Jellyseer (Port {{ jellyseer_host_port | default(5055) }}) - Media Requests
151            * Flaresolverr (Port {{ flaresolverr_host_port | default(8191) }}) - Cloudflare bypass
152          {% endif %}
153          {% if calibre_enabled | default(true) %}
154          - Calibre Stack:
155            * Calibre Server (Port {{ calibre_server_host_port | default(8083) }})
156            * Calibre-Web (Port {{ calibre_web_host_port | default(8084) }})
157          {% endif %}
158          {% if restic_backup_server_enabled | default(true) %}
159          - Restic Backup Server (Port {{ restic_backup_host_port | default(8000) }})
160          {% endif %}
161          
162          🛡️  Monitoring:
163          - RAID Health Monitoring: Enabled (mdadm)
164          - SMART Monitoring: Enabled
165          - Service Health Checks: Comprehensive
166          - Storage Health: Active monitoring
167          
168          📁 Directory Structure:
169          - Service configs: {{ storage_docker_dir }}/[service-name]
170          - Environment files: {{ storage_docker_dir }}/[service-name]/.env
171          - Individual service directories for ARR stack
172          - Media Storage: {{ storage_base_path }}/media
173          - Downloads: {{ storage_base_path }}/downloads
174          - Backups: {{ storage_base_path }}/backups
175          
176          🔧 Management Tools:
177          - Health monitoring will be provided by netdata (to be deployed separately)
178
179  roles:
180    # Core prerequisites
181    - role: user
182      tags: ['core', 'user']
183
184    - role: system  
185      tags: ['core', 'system']
186
187    - role: geerlingguy.docker
188      tags: ['core', 'docker']
189
190    - role: geerlingguy.security
191      tags: ['core', 'security']
192
193    - role: docker-framework
194      tags: ['docker-framework', 'core', 'docker']
195
196    # Storage-specific services
197    - role: storage
198      tags: ['storage', 'media', 'backup']
199
200    # RAID monitoring for storage server
201    - role: nas
202      tags: ['storage', 'raid']
203      vars:
204        # Only run monitoring tasks from NAS role
205        nas_nfs_enabled: false
206        nas_network_bonding_enabled: false
207        nas_performance_tuning_enabled: false
208        nas_backup_integration: false
209        nas_enable_runner_exports: false
210        nas_raid_monitoring: true
211        nas_smartmontools_enabled: true
212
213    # Backup role for system-level backups
214    - role: backup
215      tags: ['system-backup']
216      when: backup_enabled | default(true)
217
218  post_tasks:
219    - name: Verify core services are running
220      systemd:
221        name: "{{ item }}"
222        state: started
223        enabled: yes
224      loop:
225        - docker
226        - mdmonitor
227        - smartd
228      tags: ['verification']
229
230    - name: Verify RAID monitoring is active
231      command: systemctl is-active mdmonitor
232      register: mdmonitor_status
233      changed_when: false
234      ignore_errors: true
235      tags: ['verification', 'raid']
236
237    - name: Verify SMART monitoring is active
238      command: systemctl is-active smartd
239      register: smartd_status
240      changed_when: false
241      ignore_errors: true
242      tags: ['verification', 'smart']
243
244    - name: Generate storage access summary
245      template:
246        src: "{{ role_path }}/templates/storage-access-summary.txt.j2"
247        dest: "{{ storage_docker_dir }}/storage-access-info.txt"
248        owner: "{{ storage_user | default(ansible_user) }}"
249        group: "{{ storage_group | default(ansible_user) }}"
250        mode: '0644'
251      vars:
252        role_path: "roles/storage"
253      tags: ['summary']
254
255
256    - name: Wait for all storage services to be healthy
257      uri:
258        url: "http://{{ ansible_default_ipv4.address }}:{{ item.port }}{{ item.path | default('') }}"
259        method: GET
260        status_code: [200, 302, 401]  # Some services redirect or require auth
261      loop:
262        - { port: "{{ jellyfin_host_port | default(8096) }}", path: "/health", service: "Jellyfin" }
263        - { port: "{{ sonarr_host_port | default(8989) }}", path: "/ping", service: "Sonarr" }
264        - { port: "{{ radarr_host_port | default(7878) }}", path: "/ping", service: "Radarr" }
265        - { port: "{{ prowlarr_host_port | default(9696) }}", path: "/ping", service: "Prowlarr" }
266        - { port: "{{ lazylibrarian_host_port | default(5299) }}", path: "/", service: "LazyLibrarian" }
267        - { port: "{{ jellyseer_host_port | default(5055) }}", path: "/", service: "Jellyseer" }
268        - { port: "{{ flaresolverr_host_port | default(8191) }}", path: "/health", service: "Flaresolverr" }
269        - { port: "{{ calibre_web_host_port | default(8084) }}", path: "/", service: "Calibre-Web" }
270        - { port: "{{ restic_backup_host_port | default(8000) }}", path: "/", service: "Restic Backup" }
271      retries: 15
272      delay: 10
273      ignore_errors: yes
274      tags: ['verification', 'health-check']
275
276    - name: Display deployment completion summary
277      debug:
278        msg: |
279          🚀 Storage Services Deployment Complete!
280          
281          Server: {{ inventory_hostname }} ({{ ansible_default_ipv4.address }})
282          
283          📊 Monitoring Status:
284          - RAID Monitoring: {{ 'Active' if mdmonitor_status is defined and mdmonitor_status.rc == 0 else 'Pending' }}
285          - SMART Monitoring: {{ 'Active' if smartd_status is defined and smartd_status.rc == 0 else 'Pending' }}
286          - Docker: Active
287          
288          📁 Access Information:
289          {% if jellyfin_enabled | default(true) %}
290          - Jellyfin: http://{{ ansible_default_ipv4.address }}:{{ jellyfin_host_port | default(8096) }} (CPU Hardware Acceleration)
291          {% endif %}
292          {% if arr_stack_enabled | default(true) %}
293          - Sonarr: http://{{ ansible_default_ipv4.address }}:{{ sonarr_host_port | default(8989) }}
294          - Radarr: http://{{ ansible_default_ipv4.address }}:{{ radarr_host_port | default(7878) }}
295          - Prowlarr: http://{{ ansible_default_ipv4.address }}:{{ prowlarr_host_port | default(9696) }}
296          - LazyLibrarian: http://{{ ansible_default_ipv4.address }}:{{ lazylibrarian_host_port | default(5299) }}
297          - Jellyseer: http://{{ ansible_default_ipv4.address }}:{{ jellyseer_host_port | default(5055) }} (NEW!)
298          - Flaresolverr: http://{{ ansible_default_ipv4.address }}:{{ flaresolverr_host_port | default(8191) }} (Cloudflare bypass)
299          {% endif %}
300          {% if calibre_enabled | default(true) %}
301          - Calibre-Web: http://{{ ansible_default_ipv4.address }}:{{ calibre_web_host_port | default(8084) }}
302          {% endif %}
303          {% if restic_backup_server_enabled | default(true) %}
304          - Restic Backup: http://{{ ansible_default_ipv4.address }}:{{ restic_backup_host_port | default(8000) }}
305          {% endif %}
306          
307          📂 File Locations:
308          - Docker Configs: {{ storage_docker_dir }}
309          - Media Storage: {{ storage_base_path }}/media
310          - Downloads: {{ storage_base_path }}/downloads  
311          - Backups: {{ storage_base_path }}/backups
312          - Access Info: {{ storage_docker_dir }}/storage-access-info.txt
313          - SMART Monitoring: /etc/smartd.conf
314          
315          🛡️  Monitoring Commands:
316          - RAID Status: cat /proc/mdstat
317          - SMART Status: smartctl -a /dev/sdX
318          - Service Health: Will be monitored by netdata (to be deployed separately)
319          
320          🔧 Next Steps:
321          1. Configure VPN credentials in vault for Gluetun
322          2. Set up indexers in Prowlarr
323          3. Configure quality profiles in Arr applications
324          4. Add media libraries in Jellyfin  
325          5. Import books to Calibre library
326          6. Configure Jellyseer with Jellyfin and Arr app integration
327          7. Set up backup clients using: {{ storage_docker_dir }}/restic-server/client-setup-example.sh
328          
329          ⚡ Management Commands:
330          - Restart All: docker restart $(docker ps -q)
331          - View Logs: docker compose logs -f (in service directories)
332          - Monitor RAID: watch cat /proc/mdstat
333          
334          💡 Important Notes:
335          - RAID arrays monitored every 5 minutes
336          - SMART monitoring active for drive health
337          - All services configured for CPU-only operation (no GPU)
338          - Individual service directories for ARR stack components
339      tags: ['always']