/
/
/
1---
2# ========================================
3# DNS STACK DEPLOYMENT (Pi-hole + Unbound)
4# ========================================
5# Deploys Pi-hole with Unbound as recursive DNS resolver
6# Provides ad-blocking and custom DNS resolution
7
8- name: "Display DNS stack deployment information"
9 ansible.builtin.debug:
10 msg:
11 - "Deploying DNS stack (Pi-hole + Unbound)"
12 - "Pi-hole enabled: {{ connectivity_pihole_enabled }}"
13 - "Unbound enabled: {{ connectivity_unbound_enabled }}"
14 - "Pi-hole Web Port: {{ connectivity_pihole_web_port }}"
15 - "DNS Port: {{ connectivity_pihole_dns_port }}"
16 - "Unbound Port: {{ connectivity_unbound_port }}"
17 tags: [dns-stack]
18
19# ========================================
20# UNBOUND RECURSIVE DNS RESOLVER
21# ========================================
22- name: "Deploy Unbound recursive DNS resolver"
23 block:
24 - name: "Create Unbound configuration directory"
25 ansible.builtin.file:
26 path: "{{ connectivity_docker_base_path }}/unbound/config"
27 state: directory
28 owner: "{{ connectivity_docker_owner }}"
29 group: "{{ connectivity_docker_group }}"
30 mode: "0755"
31
32 - name: "Create Unbound configuration file"
33 ansible.builtin.template:
34 src: unbound.conf.j2
35 dest: "{{ connectivity_docker_base_path }}/unbound/config/unbound.conf"
36 owner: "{{ connectivity_docker_owner }}"
37 group: "{{ connectivity_docker_group }}"
38 mode: "0644"
39 notify: restart unbound
40
41 - name: "Create Unbound Docker Compose file"
42 ansible.builtin.template:
43 src: unbound-compose.yml.j2
44 dest: "{{ connectivity_docker_base_path }}/unbound/docker-compose.yml"
45 owner: "{{ connectivity_docker_owner }}"
46 group: "{{ connectivity_docker_group }}"
47 mode: "0644"
48 notify: restart unbound
49
50 - name: "Start Unbound service"
51 community.docker.docker_compose:
52 project_src: "{{ connectivity_docker_base_path }}/unbound"
53 pull: yes
54 state: present
55
56 - name: "Wait for Unbound to be ready"
57 ansible.builtin.wait_for:
58 port: "{{ connectivity_unbound_port }}"
59 host: 127.0.0.1
60 delay: 5
61 timeout: 30
62
63 when: unbound_enabled | default(true)
64 tags: [dns-stack, unbound]
65
66# ========================================
67# PI-HOLE DNS SINKHOLE
68# ========================================
69- name: "Deploy Pi-hole DNS sinkhole"
70 block:
71 - name: "Create Pi-hole configuration directories"
72 ansible.builtin.file:
73 path: "{{ connectivity_docker_base_path }}/pihole/{{ item }}"
74 state: directory
75 owner: "{{ connectivity_docker_owner }}"
76 group: "{{ connectivity_docker_group }}"
77 mode: "0755"
78 loop:
79 - config
80 - dnsmasq.d
81
82 - name: "Create Pi-hole custom DNS configuration"
83 ansible.builtin.template:
84 src: pihole-custom.conf.j2
85 dest: "{{ connectivity_docker_base_path }}/pihole/dnsmasq.d/99-custom.conf"
86 owner: "{{ connectivity_docker_owner }}"
87 group: "{{ connectivity_docker_group }}"
88 mode: "0644"
89 notify: restart pihole
90
91 - name: "Create Pi-hole Docker Compose file"
92 ansible.builtin.template:
93 src: pihole-compose.yml.j2
94 dest: "{{ connectivity_docker_base_path }}/pihole/docker-compose.yml"
95 owner: "{{ connectivity_docker_owner }}"
96 group: "{{ connectivity_docker_group }}"
97 mode: "0644"
98 notify: restart pihole
99
100 - name: "Create Pi-hole environment file"
101 ansible.builtin.template:
102 src: pihole.env.j2
103 dest: "{{ connectivity_docker_base_path }}/pihole/.env"
104 owner: "{{ connectivity_docker_owner }}"
105 group: "{{ connectivity_docker_group }}"
106 mode: "0600" # Secure environment file
107 notify: restart pihole
108
109
110 - name: "Start Pi-hole service"
111 community.docker.docker_compose:
112 project_src: "{{ connectivity_docker_base_path }}/pihole"
113 pull: yes
114 state: present
115
116 - name: "Wait for Pi-hole to be ready"
117 ansible.builtin.wait_for:
118 port: "{{ connectivity_pihole_web_port }}"
119 host: "{{ ansible_default_ipv4.address }}"
120 delay: 10
121 timeout: 60
122
123 when: pihole_enabled | default(true)
124 tags: [dns-stack, pihole]
125
126# ========================================
127# DNS STACK INTEGRATION WITH NPM
128# ========================================
129- name: "Create integrated DNS stack Docker Compose file"
130 ansible.builtin.template:
131 src: dns-stack-compose.yml.j2
132 dest: "{{ connectivity_docker_base_path }}/dns-stack-compose.yml"
133 owner: "{{ connectivity_docker_owner }}"
134 group: "{{ connectivity_docker_group }}"
135 mode: "0644"
136 when: connectivity_pihole_enabled and connectivity_unbound_enabled
137 tags: [dns-stack, compose]
138
139- name: "Configure Nginx Proxy Manager for DNS services"
140 block:
141 - name: "Create NPM proxy configuration for Pi-hole"
142 ansible.builtin.template:
143 src: npm-pihole-proxy.conf.j2
144 dest: "{{ connectivity_docker_base_path }}/nginx-proxy/conf.d/pihole-proxy.conf"
145 owner: "{{ connectivity_docker_owner }}"
146 group: "{{ connectivity_docker_group }}"
147 mode: "0644"
148 when: connectivity_nginx_proxy_enabled and connectivity_pihole_enabled
149
150 - name: "Create NPM proxy configuration for Unbound"
151 ansible.builtin.template:
152 src: npm-unbound-proxy.conf.j2
153 dest: "{{ connectivity_docker_base_path }}/nginx-proxy/conf.d/unbound-proxy.conf"
154 owner: "{{ connectivity_docker_owner }}"
155 group: "{{ connectivity_docker_group }}"
156 mode: "0644"
157 when: connectivity_nginx_proxy_enabled and connectivity_unbound_enabled
158
159 tags: [dns-stack, npm-integration]
160
161# ========================================
162# SERVICE VERIFICATION
163# ========================================
164- name: "Verify Unbound container is running"
165 community.docker.docker_container_info:
166 name: "{{ connectivity_unbound_container_name }}"
167 register: connectivity_unbound_container_status
168 when: unbound_enabled | default(true)
169 tags: [dns-stack, verify]
170
171- name: "Verify Pi-hole container is running"
172 community.docker.docker_container_info:
173 name: "{{ connectivity_pihole_container_name }}"
174 register: connectivity_pihole_container_status
175 when: pihole_enabled | default(true)
176 tags: [dns-stack, verify]
177
178- name: "Test DNS resolution through Pi-hole"
179 ansible.builtin.command: "dig @{{ ansible_default_ipv4.address }} google.com +short"
180 register: dns_test_result
181 changed_when: false
182 failed_when: false
183 when: pihole_enabled | default(true)
184 tags: [dns-stack, test]
185
186# ========================================
187# STATUS AND INFORMATION
188# ========================================
189- name: "Display DNS stack service status"
190 ansible.builtin.debug:
191 msg:
192 - "DNS stack deployed successfully"
193 - "Unbound status: {{ connectivity_unbound_container_status.container.State.Status | default('Disabled') }}"
194 - "Pi-hole status: {{ connectivity_pihole_container_status.container.State.Status | default('Disabled') }}"
195 - "Pi-hole Web UI: http://{{ ansible_default_ipv4.address }}:{{ connectivity_pihole_web_port }}/admin"
196 - "Pi-hole Password: {{ connectivity_pihole_password }}"
197 - "DNS Server: {{ ansible_default_ipv4.address }}:{{ connectivity_pihole_dns_port }}"
198 - "DNS Test Result: {{ dns_test_result.stdout | default('Not tested') }}"
199 - ""
200 - "Configuration:"
201 - "- Pi-hole uses Unbound as upstream DNS"
202 - "- Unbound performs recursive DNS resolution"
203 - "- Ad-blocking and custom DNS rules via Pi-hole"
204 - ""
205 - "Next steps:"
206 - "1. Configure client devices to use {{ ansible_default_ipv4.address }} as DNS"
207 - "2. Access Pi-hole admin interface to customize blocking lists"
208 - "3. Add custom DNS entries via Pi-hole interface"
209 tags: [dns-stack, info]
210
211
212# ========================================
213# SERVICE LABELING
214# ========================================
215- name: "Label DNS stack containers for connectivity service group"
216 community.docker.docker_container:
217 name: "{{ item.name }}"
218 labels:
219 com.connectivity.service: "dns-stack"
220 com.connectivity.type: "{{ item.type }}"
221 com.connectivity.port: "{{ item.port }}"
222 state: started
223 recreate: no
224 loop:
225 - { name: "{{ connectivity_unbound_container_name }}", type: "recursive-dns", port: "{{ connectivity_unbound_port }}" }
226 - { name: "{{ connectivity_pihole_container_name }}", type: "dns-sinkhole", port: "{{ connectivity_pihole_dns_port }}" }
227 when:
228 - item.name in (ansible_facts.docker_containers | default([]))
229 - (item.name == connectivity_unbound_container_name and connectivity_unbound_enabled) or (item.name == connectivity_pihole_container_name and connectivity_pihole_enabled)
230 tags: [dns-stack, labels]
231
232# ========================================
233# OPTIONAL DHCP CONFIGURATION
234# ========================================
235- name: "Configure Pi-hole DHCP (if enabled)"
236 block:
237 - name: "Enable Pi-hole DHCP server"
238 ansible.builtin.lineinfile:
239 path: "{{ connectivity_docker_base_path }}/pihole/dnsmasq.d/99-custom.conf"
240 line: "dhcp-range={{ connectivity_pihole_dhcp_range | default('192.168.1.100,192.168.1.200,24h') }}"
241 create: yes
242 notify: restart pihole
243
244
245 when: connectivity_pihole_dhcp_enabled | default(false)
246 tags: [dns-stack, dhcp]