{"id":15148310,"url":"https://github.com/shaderecker/ansible-pihole","last_synced_at":"2025-04-05T02:04:35.392Z","repository":{"id":47022110,"uuid":"212913250","full_name":"shaderecker/ansible-pihole","owner":"shaderecker","description":"Bootstrap a Raspberry Pi  with Ansible and install Docker + Pi-hole","archived":false,"fork":false,"pushed_at":"2025-03-09T11:30:19.000Z","size":92,"stargazers_count":142,"open_issues_count":0,"forks_count":32,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-29T01:03:36.636Z","etag":null,"topics":["ansible","ansible-playbook","docker","high-availability","keepalived","pihole","raspberry-pi","sync"],"latest_commit_sha":null,"homepage":"","language":"YAML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shaderecker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-04T22:40:35.000Z","updated_at":"2025-03-23T18:58:27.000Z","dependencies_parsed_at":"2023-02-15T23:31:12.592Z","dependency_job_id":"a948f1d6-e511-4529-a93f-49cc5e0e0f52","html_url":"https://github.com/shaderecker/ansible-pihole","commit_stats":{"total_commits":151,"total_committers":3,"mean_commits":"50.333333333333336","dds":"0.013245033112582738","last_synced_commit":"9081021b5fbad76fd3896f7232d0164edd92a34f"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shaderecker%2Fansible-pihole","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shaderecker%2Fansible-pihole/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shaderecker%2Fansible-pihole/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shaderecker%2Fansible-pihole/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shaderecker","download_url":"https://codeload.github.com/shaderecker/ansible-pihole/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247276163,"owners_count":20912288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","ansible-playbook","docker","high-availability","keepalived","pihole","raspberry-pi","sync"],"created_at":"2024-09-26T13:02:41.157Z","updated_at":"2025-04-05T02:04:35.377Z","avatar_url":"https://github.com/shaderecker.png","language":"YAML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ansible-pihole\nBootstrap a Raspberry Pi with Ansible and install Docker + Pi-hole\n\nOptionally you can enable HA (high availability) with keepalived and sync settings between multiple instances.\n\nThe repository contains four Ansible Playbooks. Each one is described below.\n\nFor more info about the Docker Pi-hole image please check the official repository: https://github.com/pi-hole/docker-pi-hole\n\n## Base Setup\n- An [Ansible](https://www.ansible.com/) controller machine with Ansible [installed](https://docs.ansible.com/ansible/latest/installation_guide/index.html) (version 2.13 or later)\n- The [community.crypto](https://galaxy.ansible.com/ui/repo/published/community/crypto) Ansible collection installed\n- The [ansible.posix](https://galaxy.ansible.com/ui/repo/published/ansible/posix) Ansible collection installed\n- One or more Raspberry Pi's with [Raspberry Pi OS Lite (64-bit)](https://www.raspberrypi.com/software/operating-systems/) (bookworm)\n- I recommend using the [Raspberry Pi Imager](https://www.raspberrypi.com/software/) for preparing your SD Cards since this easily allows the initial image configuration:\n  - Set username and password\n  - Configure Wireless LAN\n  - Enable SSH (preferably use the option “Allow public-key authentication only”)\n\n- Set static IPs for your Raspberry Pi's (static DHCP assignment/reservation in your Router/DHCP server is sufficient)\n- Configure your hosts (IPs and user of your Raspberry Pi's) and other settings in the [`inventory.yaml`](inventory.yaml)  \n\n## `bootstrap-pihole.yaml`\nThis playbook is for the first time run (but it can be rerun any time).  \nIt will bootstrap a fresh Raspberry Pi OS installation, install Docker, and Pi-hole.  \nYou can run it with: `ansible-playbook -i inventory.yaml bootstrap-pihole.yaml`  \n\nIf the playbook fails during the first run while installing Docker, please reboot your Pi and re-run the playbook!\n\nThese roles are included:\n- [`bootstrap`](roles/bootstrap/tasks/main.yaml): Some basic configuration  \n  - Lock the password to prevent local terminal login\n  - Set some useful bash aliases\n  - Set timezone, configured in [`timezone`](inventory.yaml#L11)\n  - Set hostname to the respective Ansible inventory_hostname\n  - Set a static DNS server, configured in [`static_dns`](inventory.yaml#L12)\n- [`updates`](roles/updates/tasks/main.yaml): Update apt packages\n- [`docker`](roles/docker/tasks/main.yaml): Install and configure Docker\n- [`pihole`](roles/pihole/tasks/main.yaml): Start/Update Pi-hole container\n  - Pi-hole container settings are configured in [`inventory.yaml`](inventory.yaml)  \n    The options are described in the official [docker-pi-hole readme](https://github.com/pi-hole/docker-pi-hole?tab=readme-ov-file#configuration) and the official [Pi-hole FTL Configuration](https://docs.pi-hole.net/ftldns/configfile/)\n\n## `update-pihole.yaml`\nThis playbook is for subsequent runs after the `bootstrap-pihole.yaml` playbook was run at least once.  \nYou can run it with: `ansible-playbook -i inventory.yaml update-pihole.yaml`  \nIt contains only a subset of roles for faster runtime: [`updates`](roles/updates/tasks/main.yaml) and [`pihole`](roles/pihole/tasks/main.yaml)  \nThis will keep the system up to date and can be used to roll out changes to the Pi-hole docker container, for example a new image version.\n\n## `keepalived.yaml`\nThis playbook enables a high availability failover cluster with `keepalived` between multiple Pi-hole instances.  \nYou can run it with: `ansible-playbook -i inventory.yaml keepalived.yaml`  \n\nMotivation:  \n- Redundancy: Avoid a single point of failure (due to raspberry pi reboot, docker container failure/update/restart)\n- Architecture of DNS requires a HA solution on the DNS server side (most clients will not properly handle unavailable DNS servers; if a client has multiple DNS servers configured it will try them one after another only moving on if one times out)\n- Poor DNS query performance during system updates \u0026 docker image pulls (experienced on my Pi 3 Model B)\n\nAs healthcheck, the status of the Pi-hole docker container is evaluated.  \nCommunication happens over VRRP (Virtual Router Redundancy Protocol) which uses Multicast.  \nThe priority of each Pi-hole can be configured in [`inventory.yaml`](inventory.yaml), for example:\n```yaml\n    pihole-1:\n      ansible_host: 192.168.178.45\n      priority: 101\n```\nThe desired VIPs (Virtual IPs) for IPv4 and IPv6 can be configured in [`inventory.yaml`](inventory.yaml#L17-L18):\n```yaml\n    pihole_vip_ipv4: \"192.168.178.10/24\"\n    pihole_vip_ipv6: \"fd00::10/64\"\n```\n\nWhen maintaining and updating your Pi-hole instances with the `bootstrap-pihole.yaml` and `update-pihole.yaml` playbooks, the first step stops keepalived and therefore shifts the VIP to another instance so that the performance of DNS queries is not impeded.\n\n## `sync.yaml`\nThis playbook enables the synchronisation of settings between multiple Pi-hole instances.  \nYou can run it with: `ansible-playbook -i inventory.yaml sync.yaml`  \nOne Pi-hole functions as the primary instance and the others as secondaries which pull from the primary.  \nSyncing is scheduled as a cronjob and set to run two times per day (frequency can be changed [here](roles/sync/tasks/main.yaml#L34)).\nWhat gets synced:\n- `gravity.db` (Adlists, Domains, Clients, Groups, Group Assignments of all aforementioned items)\n- `pihole.toml` (All settings, including local DNS Records and local CNAME Records)\n\n#### Default: Pull from VIP\nIf you enabled HA (high availability) with the `keepalived.yaml` playbook, the primary instance will be the one currently occupying the Virtual IP address (evaluated at each cronjob run).\n\n```yaml\nsync_target: \"{{ pihole_vip_ipv4.split('/')[0] }}\"\n```\n\n#### Alternative: Pull from primary instance\nYou can set the [`sync_target`](inventory.yaml#L19) variable to the IP address of your primary Pi-hole instance (in my example `pihole-1`, otherwise adapt).\n```yaml\nsync_target: \"{{ hostvars['pihole-1'].ansible_host }}\"\n```\n\nFor syncing, `rsync` is used which will only transfer files if they contain changes.  \nChanges will trigger a docker container restart to apply the changes.  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshaderecker%2Fansible-pihole","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshaderecker%2Fansible-pihole","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshaderecker%2Fansible-pihole/lists"}