summaryrefslogtreecommitdiffstats
path: root/roles/pihole/tasks/main.yml
blob: f61016322c355dcee042292cb7f4c6c28472a265 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
---
- name: "Validate network_ipv*_dns params"
  ansible.builtin.fail:
    msg: "Pihole role cannot work when network_ipv4_dns or network_ipv6_dns are defined"
  when: network_ipv4_dns is defined or network_ipv6_dns is defined

- name: "Validate pihole_dhcp_* params"
  ansible.builtin.assert:
    that:
      - pihole_dhcp_start is defined
      - pihole_dhcp_end is defined
      - pihole_dhcp_router is defined
      - pihole_dhcp_lease_time is defined
      - pihole_dhcp_domain is defined
      - pihole_dhcp_hosts is defined
  when: pihole_dhcp_enabled

- name: "Crete Pi-hole user"
  become: true
  ansible.builtin.user:
    name: "pihole"
    system: true
    shell: "/usr/sbin/nologin"

- name: "Create Pi-hole directories"
  become: true
  ansible.builtin.file:
    path: "{{ item }}"
    state: "directory"
    owner: "pihole"
    group: "pihole"
    mode: "0755"
  loop:
    - "/etc/pihole"
    - "/var/log/pihole"

- name: "Create Pi-hole configuration file"
  become: true
  ansible.builtin.template:
    src: "pihole.toml.j2"
    dest: "/etc/pihole/pihole.toml"
    owner: "pihole"
    group: "pihole"
    mode: "0644"
  no_log: true
  # pihole.toml is being rewritten after successful setup
  # This is why this task is not idempotent and can't be.
  tags:
    - molecule-idempotence-notest

- name: "Check if pihole binary exists"
  ansible.builtin.stat:
    path: "/usr/local/bin/pihole"
  register: pihole_binary

- name: "Download Pi-hole installer"
  ansible.builtin.get_url:
    url: "https://install.pi-hole.net"
    dest: "/tmp/install_pihole.sh"
    mode: "0755"
  when: not pihole_binary.stat.exists

- name: "Run Pi-hole installer"
  become: true
  ansible.builtin.command:
    cmd: "/tmp/install_pihole.sh --unattended"
  register: pihole_install
  environment:
    PIHOLE_SKIP_OS_CHECK: "true"
  args:
    creates: "/usr/local/bin/pihole"
  when: not pihole_binary.stat.exists
  notify: "Show install output"

- name: "Ensure Pi-hole started/enabled"
  become: true
  ansible.builtin.systemd_service:
    name: "pihole-FTL"
    enabled: true
    state: "started"
    daemon_reload: true

- name: "Update Pi-hole blocklists"
  become: true
  ansible.builtin.command:
    cmd: "pihole -g"
  changed_when: false

- name: "Configure pihole as system DNS"
  become: true
  tags:
    # linking the systemd run files fails in molecule tests
    # This is not relevant to the testing itself, so it's safe to ignore
    # The other tasks override the network role configurations, this is
    # by design, and intentional, which conflicts with molecule-idempotent test
    # therefore it's safe and better to disable testing for these tasks
    # as these tasks also can't be tested without inspecting pihole logs to
    # verify that the DNS blocking is happening correctly
    - molecule-notest
  notify:
    - "Restart NetworkManager"
    - "Restart systemd-resolved"
  block:
    - name: "Configure NetworkManager to disable DNS management"
      ansible.builtin.copy:
        dest: "/etc/NetworkManager/NetworkManager.conf"
        owner: "root"
        group: "root"
        mode: "0644"
        content: |
          [main]
          dns=none

    - name: "Configure systemd-resolved for Pi-hole"
      ansible.builtin.copy:
        # NOTE: overwrites the network role's drop-in so DNSStubListener=no wins
        # (drop-ins beat /etc/systemd/resolved.conf, so writing here is required)
        dest: "/etc/systemd/resolved.conf.d/99-custom.conf"
        owner: "root"
        group: "root"
        mode: "0644"
        content: |
          [Resolve]
          DNS=127.0.0.1#53
          DNSStubListener=no
          MulticastDNS=yes
          LLMNR=no
          Cache=yes
          ReadEtcHosts=yes

    - name: "Configure system DNS"
      ansible.builtin.file:
        src: "/run/systemd/resolve/resolv.conf"
        dest: "/etc/resolv.conf"
        state: "link"
        force: true

- name: "Flush handlers before restarting pihole-FTL"
  # systemd-resolved must release port 53 before pihole-FTL binds it.
  # flush_handlers here makes that ordering a structural guarantee rather than
  # relying on handler definition order.
  ansible.builtin.meta: flush_handlers

- name: "Restart pihole-FTL"
  become: true
  ansible.builtin.systemd_service:
    name: "pihole-FTL"
    state: "restarted"
  tags:
    - molecule-idempotence-notest

- name: "Create pihole nginx vhost configuration"
  become: true
  when: proxy_type == "nginx" and pihole_hostname | length > 0
  ansible.builtin.template:
    src: "pihole.nginx.conf.j2"
    dest: "/etc/nginx/vhosts.d/pihole.conf"
    owner: "root"
    group: "root"
    mode: "0644"
    backup: true
    validate: >
      bash -c 'echo "events { worker_connections 64; } http { include %s; }" > /tmp/nginx-vhost.conf;
        sudo nginx -T -c /tmp/nginx-vhost.conf; ec=$?; rm -f /tmp/nginx-vhost.conf; exit $ec'
  notify: "Restart proxy"

- name: "Create pihole caddy configuration"
  become: true
  when: proxy_type == "caddy" and pihole_hostname | length > 0
  ansible.builtin.template:
    src: "pihole.caddy.j2"
    dest: "/etc/caddy/sites/pihole.caddy"
    owner: "root"
    group: "caddy"
    mode: "0640"
  notify: "Restart proxy"