Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dhcp support #20

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f26d20d
Include wildcard dns config in sync
ohthehugemanatee Jun 5, 2024
009fd89
Add capabilities to the container per https://github.com/pi-hole/dock…
ohthehugemanatee Jun 6, 2024
c6dc143
Fix extra closing fi in pihole_sync script template
ohthehugemanatee Jun 6, 2024
7c4500b
Add hardcoded dhcp check to keepalive script
ohthehugemanatee Jun 16, 2024
e8eedab
Refactor check_pihole script
ohthehugemanatee Jun 17, 2024
1ab888d
Move check_pihole to a template
ohthehugemanatee Jun 17, 2024
3695a28
Add ansible vars to check_pihole script
ohthehugemanatee Jun 17, 2024
f6b23dd
Add dhcp options to inventory
ohthehugemanatee Jun 17, 2024
b1ba41c
Add dhcp options to README
ohthehugemanatee Jun 17, 2024
acb5eed
Add explanatory comments to new inventory items
ohthehugemanatee Jun 17, 2024
4b1e1ea
Tell ansible about the check_pihole template
ohthehugemanatee Jun 17, 2024
fc44c1c
Add dhcp options to pihole role
ohthehugemanatee Jun 17, 2024
a833aff
Explain DHCP options in readme
ohthehugemanatee Jun 17, 2024
59c790a
Change how DHCP_ENABLED var is set in check_pihole.sh
ohthehugemanatee Jun 17, 2024
846106b
Sync leases and the whole dnsmasq directory
ohthehugemanatee Jun 17, 2024
ddec71b
Debug ansible template
ohthehugemanatee Jun 17, 2024
9f7a735
Clarify true/false in check_pihole script
ohthehugemanatee Jun 17, 2024
f497600
Fix typo
ohthehugemanatee Jun 17, 2024
fc449f9
Fix logical error in health check
ohthehugemanatee Jun 17, 2024
da8964a
Create dnsmasq config for DHCP/DNS config in pihole role
ohthehugemanatee Jun 17, 2024
5d6fcbe
Only sync gravity every 12 hours
ohthehugemanatee Jun 17, 2024
6d9736a
Increase sync frequency to every 5 minutes.
ohthehugemanatee Jun 17, 2024
0bcaf48
fix wrong user directory in check_pihole
ohthehugemanatee Jun 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ These roles are included:
The options prefixed with `pihole_ftl_` are described in the official [Pi-hole FTL Configuration](https://docs.pi-hole.net/ftldns/configfile/)
- The [`pihole_ha_mode`](inventory.yaml#L24) option is used to switch between HA or Single mode to determine the IPv4/IPv6 addresses for the Pi-hole services (bind IPs for Web/DNS, pi.hole DNS record) and is enabled by default.
⚠️ Disable this if you don't intend to deploy a HA setup with keepalived.
- The [`dhcp_server`](inventory.yaml#L28) option and other options prefixed with `dhcp_` are for configuring Pihole's optional DHCP support. This is disabled by default. If you enable the DHCP server, consider a shorter sync cron interval [here](master/roles/sync/tasks/main.yaml#L33) to catch changes in dhcp leases.

## `update-pihole.yaml`
This playbook is for subsequent runs after the `bootstrap-pihole.yaml` playbook was run at least once.
Expand Down
6 changes: 6 additions & 0 deletions inventory.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@ all:
pihole_vip_ipv4: "192.168.178.10/24"
pihole_vip_ipv6: "fd00::10/64"
sync_target: "{{ pihole_vip_ipv4.split('/')[0] }}"
dhcp_server: "false" # If enabled, consider a shorter sync interval to catch dhcp leases (see README)
dhcp_start: "192.168.178.100"
dhcp_end: "192.168.178.250"
dhcp_router: "192.168.178.1"
dhcp_domain: "local"
dhcp_lease_time: "24" # In hours
3 changes: 0 additions & 3 deletions roles/keepalived/files/check_pihole.sh

This file was deleted.

6 changes: 3 additions & 3 deletions roles/keepalived/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
force_apt_get: yes
name: keepalived

- name: Copy check_pihole.sh
copy:
- name: Configure check_pihole.sh
template:
dest: /etc/keepalived/check_pihole.sh
src: check_pihole.sh
src: check_pihole.j2
mode: 0755

- name: Configure keepalived
Expand Down
38 changes: 38 additions & 0 deletions roles/keepalived/templates/check_pihole.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash
set -e

## This script checks the health of the pihole container and enables/disables DHCP as needed.
PIHOLE_DIR="/home/{{ ansible_user }}/pihole"
[ "{{ dhcp_server }}" = "true" ] && DHCP_ENABLED=0 || DHCP_ENABLED=1 # enabled=0, disabled=1
VIP="{{ pihole_vip_ipv4 }}"
DHCP_START="{{ dhcp_start }}"
DHCP_END="{{ dhcp_end }}"
DHCP_GATEWAY="{{ dhcp_router }}"
DHCP_DOMAIN="{{ dhcp_domain }}"
DHCP_LEASE_TIME="{{ dhcp_lease_time }}"

# Check if the pihole container is healthy (0) or not (1).
[ "$(docker inspect -f "{{ '{{' }}.State.Health.Status{{ '}}' }}" pihole)" = "healthy" ] && HEALTHY=0 || HEALTHY=1

# If the container is not healthy, exit 1.
if [ ${HEALTHY} -eq 1 ]; then
exit ${HEALTHY}
fi

# If DHCP is not enabled, or we don't own the virtual IP
if [ ${DHCP_ENABLED} -eq 1 ] || ! /usr/sbin/ip a |grep -q ${VIP} ; then
# Ensure DHCP is disabled.
if [ -f ${PIHOLE_DIR}/dnsmasq.d/02-pihole-dhcp.conf ]; then
/usr/bin/docker exec -d pihole /usr/local/bin/pihole -a disabledhcp
fi
# Exit with the health status of the container (0).
exit ${HEALTHY}
fi

# Ensure DHCP is enabled.
if ! [ -f ${PIHOLE_DIR}/dnsmasq.d/02-pihole-dhcp.conf ]; then
/usr/bin/docker exec -d pihole /usr/local/bin/pihole -a enabledhcp "${DHCP_START}" "${DHCP_END}" "${DHCP_GATEWAY}" "${DHCP_LEASE_TIME}" "${DHCP_DOMAIN}"
fi

# Exit with the health status of the container (0).
exit ${HEALTHY}
32 changes: 32 additions & 0 deletions roles/pihole/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,27 @@
execution_mode: "HA setup with keepalived"
when: pihole_ha_mode

- name: Create dnsmasq.d directory for DHCP config (HA mode)
file:
path: "/home/{{ ansible_user }}/pihole/dnsmasq.d"
owner: "root"
group: "root"
state: directory
mode: 0755
when:
- pihole_ha_mode
- dhcp_server

- name: Set DHCP to give out HA mode IP
copy:
dest: "/home/{{ ansible_user }}/pihole/dnsmasq.d/03-pihole-dhcp-static-dns.conf"
owner: "root"
group: "root"
content: dhcp-option=6,{{pihole_local_ipv4}}
when:
- pihole_ha_mode
- dhcp_server

- name: Determine Pi-hole host IPs (single mode)
set_fact:
pihole_local_ipv4: "{{ ansible_host }}"
Expand All @@ -44,6 +65,11 @@
REV_SERVER_TARGET: "{{ pihole_rev_server_target }}"
REV_SERVER_CIDR: "{{ pihole_rev_server_cidr }}"
FTLCONF_MAXDBDAYS: "{{ pihole_ftl_max_db_days }}"
DHCP_ACTIVE: "{{ dhcp_server }}"
DHCP_START: "{{ dhcp_start }}"
DHCP_END: "{{ dhcp_end }}"
DHCP_ROUTER: "{{ dhcp_router }}"
DHCP_LEASETIME: "{{ dhcp_lease_time }}"
dns_servers:
- 127.0.0.1
- "{{ static_dns }}"
Expand All @@ -55,6 +81,12 @@
log_options:
max-size: "10m"
max-file: "5"
capabilities:
- CAP_NET_BIND_SERVICE
- CAP_NET_RAW
- CAP_NET_ADMIN
- CAP_SYS_NICE
- CAP_CHOWN

- name: Check pihole container
uri:
Expand Down
4 changes: 2 additions & 2 deletions roles/sync/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

- name: Schedule sync with cron
ansible.builtin.cron:
hour: "2,14"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert those values to the originals please since the shorter sync interval is only needed for dhcp.
Maybe you can provide some example values, that you consider good, in the readme.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least in my experience the dns performance was impaired pretty easily, so I would like to keep the sync jobs to a minimum by default.

minute: "0"
hour: "*"
minute: "*/5"
job: "{{ ansible_user_dir }}/{{ sync_dir.path }}/pihole_sync.sh"
name: pihole-sync
59 changes: 46 additions & 13 deletions roles/sync/templates/pihole_sync.j2
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,30 @@ host_key_check="-o StrictHostKeyChecking=no"
target="{{ ansible_user }}@{{ sync_target }}"
sync_dir="{{ ansible_user_dir }}/{{ sync_dir.path }}"
pihole_dir="{{ ansible_user_dir }}/pihole"
dhcp_server="{{ dhcp_server }}"
[ $(ip a | grep {{ sync_target }}) ] && am_master=0 || am_master=1 # If the sync target is on this host, we are the master (0).

if [[ $(ip a | grep {{ sync_target }}) ]]; then
nice -n 19 sqlite3 $pihole_dir/pihole/gravity.db ".backup $sync_dir/gravity.dump"
fi

if [[ ! $(ip a | grep {{ sync_target }}) ]]; then
sleep 60

RSYNC_GRAVITY=$(rsync -a --info=name -e "ssh $key $host_key_check" $target:$sync_dir/gravity.dump $sync_dir)
if [ $? -eq 0 ]; then
if [ -n "$RSYNC_GRAVITY" ]; then
docker stop pihole
sudo sqlite3 $pihole_dir/pihole/gravity.db ".restore $sync_dir/gravity.dump"
docker start pihole
# If the gravity dump file is more than 12 hours old, sync it.
if [[ -f $sync_dir/gravity.dump ]] && [[ $(find $sync_dir/gravity.dump -mmin +719) ]]; then
# master generates a dump file.
if [[ $am_master -eq 0 ]]; then
nice -n 19 sqlite3 $pihole_dir/pihole/gravity.db ".backup $sync_dir/gravity.dump"
else
# not master waits for the dump, then rsyncs and imports it.
sleep 60
RSYNC_GRAVITY=$(rsync -a --info=name -e "ssh $key $host_key_check" $target:$sync_dir/gravity.dump $sync_dir)
if [ $? -eq 0 ]; then
if [ -n "$RSYNC_GRAVITY" ]; then
docker stop pihole
sudo sqlite3 $pihole_dir/pihole/gravity.db ".restore $sync_dir/gravity.dump"
docker start pihole
fi
fi
fi
fi

# not master syncs everything else.
if [[ $am_master -eq 1 ]]; then

RSYNC_DNS=$(rsync -a --info=name -e "ssh $key $host_key_check" $target:$pihole_dir/pihole/custom.list $sync_dir)
if [ $? -eq 0 ]; then
Expand All @@ -35,4 +43,29 @@ if [[ ! $(ip a | grep {{ sync_target }}) ]]; then
sudo cp --preserve=timestamps $sync_dir/05-pihole-custom-cname.conf $pihole_dir/dnsmasq.d
fi
fi

RSYNC_WILDCARD=$(rsync -a --info=name -e "ssh $key $host_key_check" $target:$pihole_dir/dnsmasq.d/02-cluster.vert-wildcard.conf $sync_dir)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason to sync this file separately when you later on sync the whole dnsmasq.d directory?

if [ $? -eq 0 ]; then
if [ -n "$RSYNC_WILDCARD" ]; then
sudo cp --preserve=timestamps $sync_dir/02-cluster.vert-wildcard.conf $pihole_dir/dnsmasq.d
fi
fi

RSYNC_LEASES=$(rsync -a --info=name -e "ssh $key $host_key_check" $target:$pihole_dir/pihole/dhcp.leases $sync_dir)
if [ $? -eq 0 ]; then
if [ -n "$RSYNC_LEASES" ]; then
sudo cp --preserve=timestamps $sync_dir/dhcp.leases $pihole_dir/pihole
fi
fi

if ! [ -d ${pihole_dir}/dnsmasq.d ]; then
mkdir -p ${pihole_dir}/dnsmasq.d
fi

RSYNC_DNSMASQ=$(rsync -a --info=name -e "ssh $key $host_key_check" --exclude '02-pihole-dhcp.conf' $target:$pihole_dir/dnsmasq.d/* $sync_dir/dnsmasq.d/)
if [ $? -eq 0 ]; then
if [ -n "$RSYNC_DNSMASQ" ]; then
sudo cp --preserve=timestamps $sync_dir/dnsmasq.d/* $pihole_dir/dnsmasq.d
fi
fi
fi