/
/
/
Ansible role that provisions my storage server.
1---
2# Storage Services - Arr Stack (Sonarr, Radarr, Prowlarr, LazyLibrarian + Gluetun VPN)
3
4- name: Create Arr Stack configuration directory structure
5 file:
6 path: "{{ item }}"
7 state: directory
8 owner: "{{ storage_user }}"
9 group: "{{ storage_group }}"
10 mode: '0775'
11 loop:
12 - "{{ arr_config_dir }}"
13 - "{{ sonarr_config_dir }}"
14 - "{{ radarr_config_dir }}"
15 - "{{ prowlarr_config_dir }}"
16 - "{{ lazylibrarian_config_dir }}"
17 - "{{ jellyseer_config_dir }}"
18 - "{{ gluetun_config_dir }}"
19 - "{{ flaresolverr_config_dir }}"
20 - "{{ qbittorrent_config_dir }}"
21
22- name: Set group sticky bit on Arr Stack directories for permission inheritance
23 file:
24 path: "{{ item }}"
25 state: directory
26 mode: "g+s"
27 loop:
28 - "{{ arr_config_dir }}"
29 - "{{ sonarr_config_dir }}"
30 - "{{ radarr_config_dir }}"
31 - "{{ prowlarr_config_dir }}"
32 - "{{ lazylibrarian_config_dir }}"
33 - "{{ jellyseer_config_dir }}"
34 - "{{ flaresolverr_config_dir }}"
35 - "{{ qbittorrent_config_dir }}"
36
37- name: Generate Arr Stack environment file
38 template:
39 src: arr-stack.env.j2
40 dest: "{{ arr_config_dir }}/.env"
41 owner: "{{ storage_user }}"
42 group: "{{ storage_group }}"
43 mode: '0660'
44 notify: restart arr-stack
45
46- name: Deploy Arr Stack Docker Compose file
47 template:
48 src: arr-stack-compose.yml.j2
49 dest: "{{ arr_config_dir }}/docker-compose.yml"
50 owner: "{{ storage_user }}"
51 group: "{{ storage_group }}"
52 mode: '0664'
53 notify: restart arr-stack
54
55- name: Check if Arr Stack directory exists
56 stat:
57 path: "{{ arr_config_dir }}"
58 register: arr_dir_stat
59 changed_when: false
60
61- name: Start Arr Stack services
62 community.docker.docker_compose_v2:
63 project_src: "{{ arr_config_dir }}"
64 state: present
65 register: arr_start_result
66 check_mode: no
67 when: arr_dir_stat.stat.exists
68
69- name: Wait for VPN connection if enabled
70 pause:
71 seconds: 30
72 when: gluetun_enabled
73
74- name: Verify Arr Stack services are running
75 uri:
76 url: "http://localhost:{{ item.port }}"
77 method: GET
78 status_code: [200, 302, 401]
79 register: arr_health
80 retries: 10
81 delay: 5
82 until: arr_health.status in [200, 302, 401]
83 ignore_errors: true
84 loop:
85 - { name: "Sonarr", port: "{{ sonarr_host_port }}" }
86 - { name: "Radarr", port: "{{ radarr_host_port }}" }
87 - { name: "Prowlarr", port: "{{ prowlarr_host_port }}" }
88 - { name: "LazyLibrarian", port: "{{ lazylibrarian_host_port }}" }
89 - { name: "Jellyseer", port: "{{ jellyseer_host_port }}" }
90 - { name: "Flaresolverr", port: "{{ flaresolverr_host_port }}" }
91 - { name: "qBittorrent", port: "{{ qbittorrent_host_port }}" }
92 when: arr_stack_enabled
93
94- name: Display Arr Stack deployment summary
95 debug:
96 msg: |
97 Arr Stack Deployment:
98 - Status: {{ 'Started' if arr_start_result is changed else 'Already running' }}
99 - VPN: {{ 'Enabled via Gluetun' if gluetun_enabled else 'Disabled' }}
100
101 Services:
102 {% if sonarr_enabled %}
103 - Sonarr (TV Shows): http://{{ ansible_default_ipv4.address }}:{{ sonarr_host_port }}
104 {% endif %}
105 {% if radarr_enabled %}
106 - Radarr (Movies): http://{{ ansible_default_ipv4.address }}:{{ radarr_host_port }}
107 {% endif %}
108 {% if prowlarr_enabled %}
109 - Prowlarr (Indexers): http://{{ ansible_default_ipv4.address }}:{{ prowlarr_host_port }}
110 {% endif %}
111 {% if lazylibrarian_enabled %}
112 - LazyLibrarian (Books): http://{{ ansible_default_ipv4.address }}:{{ lazylibrarian_host_port }}
113 {% endif %}
114 {% if jellyseer_enabled %}
115 - Jellyseer (Requests): http://{{ ansible_default_ipv4.address }}:{{ jellyseer_host_port }}
116 {% endif %}
117 {% if flaresolverr_enabled %}
118 - Flaresolverr (Cloudflare): http://{{ ansible_default_ipv4.address }}:{{ flaresolverr_host_port }}
119 {% endif %}
120 {% if qbittorrent_enabled %}
121 - qBittorrent (Downloads): http://{{ ansible_default_ipv4.address }}:{{ qbittorrent_host_port }}
122 {% endif %}
123
124 Directories:
125 - Configuration: {{ arr_config_dir }}
126 - Downloads: {{ arr_downloads_dir }}
127
128 Next Steps:
129 1. Configure VPN credentials in encrypted vault
130 2. Set up indexers in Prowlarr
131 3. Configure quality profiles in each Arr app
132 4. Add root folders for media types
133 5. Configure download client settings
134 6. Set up Jellyseer with Jellyfin integration
135