summaryrefslogtreecommitdiffstats
path: root/roles/pihole
diff options
context:
space:
mode:
authorAhmed Abdelhalim <[email protected]>2025-08-11 21:50:28 +0200
committerAhmed Abdelhalim <[email protected]>2025-08-11 23:28:42 +0200
commit8f539a76effcfb794145905736106de9e7f6aa8d (patch)
tree2538bb504082370f3d14da549b6a5e7e6f5ad487 /roles/pihole
parentbed8aaaeb0b63b2072fbd030d76f8f928432e7b8 (diff)
Add pihole role to configure raspberry pi
Diffstat (limited to 'roles/pihole')
-rw-r--r--roles/pihole/README.md13
-rw-r--r--roles/pihole/defaults/main.yml11
-rw-r--r--roles/pihole/handlers/main.yml5
-rw-r--r--roles/pihole/meta/argument_specs.yml36
-rw-r--r--roles/pihole/meta/main.yml16
-rw-r--r--roles/pihole/tasks/main.yml62
-rw-r--r--roles/pihole/templates/pihole.toml.j261
7 files changed, 204 insertions, 0 deletions
diff --git a/roles/pihole/README.md b/roles/pihole/README.md
new file mode 100644
index 00000000..719020b5
--- /dev/null
+++ b/roles/pihole/README.md
@@ -0,0 +1,13 @@
+# Ansible Role: pihole
+
+This role configure the [pihole](https://github.com/pi-hole/pi-hole) DNS Sinkhole.
+
+## Role Variables
+
+- `pihole_password` the pi-hole web-server plain text password (default: `changeme`).
+- `pihole_totp_secret` the pi-hole TOTP 2FA secret (default: `CHANGEME`).
+- `pihole_interface` the interface to bind the pi-hole on (default: "{{ ansible_default_ipv4.interface }}").
+- `pihole_dns` the list of DNS servers to use as upstreams (default: `[9.9.9.9, 1.1.1.1, 8.8.8.8]`).
+- `pihole_dns_blocking_enabled` the boolean flag to toggle DNS blocking (default: true).
+- `pihole_dhcp_enabled` the boolean flag to toggle DHCP on the pi-hole (default: false).
+- `pihole_domain` the domain name to be configured when the pi is exposed over the internet (default: "").
diff --git a/roles/pihole/defaults/main.yml b/roles/pihole/defaults/main.yml
new file mode 100644
index 00000000..e5edf117
--- /dev/null
+++ b/roles/pihole/defaults/main.yml
@@ -0,0 +1,11 @@
+---
+pihole_password: "{{ ('changeme' | hash('sha256') | hash('sha256'))[:64] }}"
+pihole_totp_secret: "CHANGEME"
+pihole_dns:
+ - "9.9.9.9" # Quad9
+ - "1.1.1.1" # Cloudflare
+ - "8.8.8.8" # Google
+pihole_interface: "{{ ansible_default_ipv4.interface }}"
+pihole_dns_blocking_enabled: true
+pihole_dhcp_enabled: false
+pihole_domain: ""
diff --git a/roles/pihole/handlers/main.yml b/roles/pihole/handlers/main.yml
new file mode 100644
index 00000000..f400be2c
--- /dev/null
+++ b/roles/pihole/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: "Restart pihole"
+ ansible.builtin.systemd_service:
+ name: "pihole-FTL"
+ state: "restarted"
diff --git a/roles/pihole/meta/argument_specs.yml b/roles/pihole/meta/argument_specs.yml
new file mode 100644
index 00000000..b50fc5c5
--- /dev/null
+++ b/roles/pihole/meta/argument_specs.yml
@@ -0,0 +1,36 @@
+---
+argument_specs:
+ main:
+ options:
+ pihole_password:
+ type: "str"
+ description: "The pi-hole web-server plain text password (double sha265 hashed) default: changeme"
+ default: "{{ ('changeme' | hash('sha256') | hash('sha256'))[:64] }}"
+ pihole_totp_secret:
+ type: "str"
+ description: "The pi-hole TOTP 2FA secret"
+ default: "CHANGEME"
+ pihole_dns:
+ type: "list"
+ description: "The list of DNS servers to use as upstreams"
+ elements: "str"
+ default:
+ - "9.9.9.9" # Quad9
+ - "1.1.1.1" # Cloudflare
+ - "8.8.8.8" # Google
+ pihole_interface:
+ type: "str"
+ description: "The interface to bind the pi-hole on"
+ default: "{{ ansible_default_ipv4.interface }}"
+ pihole_dns_blocking_enabled:
+ type: "bool"
+ description: "The boolean flag to toggle DNS blocking"
+ default: true
+ pihole_dhcp_enabled:
+ type: "bool"
+ description: "The boolean flag to toggle DHCP on the pi-hole"
+ default: false
+ pihole_domain:
+ type: "str"
+ description: "The domain name to be configured when the pi is exposed over the internet"
+ default: ""
diff --git a/roles/pihole/meta/main.yml b/roles/pihole/meta/main.yml
new file mode 100644
index 00000000..8b21005e
--- /dev/null
+++ b/roles/pihole/meta/main.yml
@@ -0,0 +1,16 @@
+---
+dependencies: []
+galaxy_info:
+ role_name: pihole
+ author: a14m
+ description: "Configure pihole on supported devices"
+ company: "kartoffeln.work GmbH."
+ license: "license MIT"
+ min_ansible_version: "2.18"
+ platforms:
+ - name: Ubuntu
+ versions:
+ - noble
+ - name: Debian
+ versions:
+ - bookworm
diff --git a/roles/pihole/tasks/main.yml b/roles/pihole/tasks/main.yml
new file mode 100644
index 00000000..bb377957
--- /dev/null
+++ b/roles/pihole/tasks/main.yml
@@ -0,0 +1,62 @@
+---
+- name: "Crete Pi-hole user"
+ ansible.builtin.user:
+ name: "pihole"
+ system: true
+ shell: "/usr/sbin/nologin"
+ home: "/var/lib/pihole"
+ create_home: true
+
+- name: "Create Pi-hole directories"
+ ansible.builtin.file:
+ path: "{{ item }}"
+ state: "directory"
+ owner: "pihole"
+ group: "pihole"
+ mode: "0755"
+ with_items:
+ - "/etc/pihole"
+ - "/var/lib/pihole"
+ - "/var/log/pihole"
+
+- name: "Create Pi-hole configuration file"
+ ansible.builtin.template:
+ src: "pihole.toml.j2"
+ dest: "/etc/pihole/pihole.toml"
+ owner: "pihole"
+ group: "pihole"
+ mode: "0644"
+ notify: "Restart pihole"
+ tags:
+ - molecule-idempotence-notest
+
+- name: "Download Pi-hole installer"
+ ansible.builtin.get_url:
+ url: "https://install.pi-hole.net"
+ dest: "/tmp/install_pihole.sh"
+ mode: "0755"
+
+- name: "Run Pi-hole installer"
+ ansible.builtin.command:
+ cmd: "/tmp/install_pihole.sh --unattended"
+ register: pihole_install
+ environment:
+ PIHOLE_SKIP_OS_CHECK: "true"
+ args:
+ creates: "/usr/local/bin/pihole"
+
+- name: "Show install output"
+ ansible.builtin.debug:
+ var: pihole_install.stdout
+
+- name: "Ensure Pi-hole started/enabled"
+ ansible.builtin.systemd_service:
+ name: "pihole-FTL"
+ enabled: true
+ state: "started"
+ daemon_reload: true
+
+- name: "Update Pi-hole blocklists"
+ ansible.builtin.command:
+ cmd: "pihole -g"
+ changed_when: false
diff --git a/roles/pihole/templates/pihole.toml.j2 b/roles/pihole/templates/pihole.toml.j2
new file mode 100644
index 00000000..6d730d11
--- /dev/null
+++ b/roles/pihole/templates/pihole.toml.j2
@@ -0,0 +1,61 @@
+# Based on https://github.com/pi-hole/FTL/blob/bc185680fc2af2f7e21bd120f56749051207914f/test/pihole.toml
+
+[misc]
+# Put configuration into read-only mode. This will prevent any changes to the
+# configuration file via the API or CLI. This setting useful when a configuration is
+# to be forced/modified by some third-party application (like infrastructure-as-code
+# providers) and should not be changed by any means.
+readOnly = false
+
+[dns]
+# Array of upstream DNS servers used by Pi-hole
+# Example: [ "8.8.8.8", "127.0.0.1#5335", "docker-resolver" ]
+upstreams = {{ pihole_dns }}
+
+domainNeeded = true # Never forward plain names (without dots or domain parts)
+expandHosts = true # Add the domain to simple names in /etc/hosts
+domain = "lan" # Local domain name
+bogusPriv = true # Don't forward reverse DNS queries for private IP ranges
+dnssec = false # Validate DNS replies using DNSSEC
+port = 53 # Port used by the DNS Server
+
+# Network interface Pi-hole should listen on
+# Usually "eth0" for Ethernet or "wlan0" for WiFi
+interface = "{{ pihole_interface }}"
+
+# Pi-hole interface listening modes
+# - "LOCAL" (default)
+# Allow only local requests. This setting accepts DNS queries only from hosts
+# whose address is on a local subnet.
+# - "SINGLE"
+# Permit all origins, accept only on the specified interface. Respond only to
+# queries arriving on the specified interface.
+# - "BIND"
+# By default, FTL binds the wildcard address.
+# - "ALL"
+# Permit all origins, accept on all interfaces. Make sure your Pi-hole is firewalled.
+# - "NONE"
+# Do not add any configuration concerning the listening mode to the dnsmasq config file.
+listeningMode = "SINGLE"
+
+[dns.cache]
+size = 10000 # Cache size of the DNS server.
+
+[dns.blocking]
+# Master switch for Pi-hole's blocking functionality
+active = {{ pihole_dns_blocking_enabled | lower }}
+
+[dhcp]
+active = {{ pihole_dhcp_enabled | lower }}
+
+[webserver]
+{% if (pihole_domain is defined) and (pihole_domain != '') %}
+domain = {{ pihole_domain }}
+{% endif %}
+
+[webserver.tls]
+cert = "/etc/pihole/tls.pem"
+
+[webserver.api]
+pwhash = "{{ pihole_password }}" # valid double hashed string
+totp_secret = "{{ pihole_totp_secret }}" # valid TOTP secret (20 Bytes in Base32 encoding)