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