Compare commits
2 Commits
0fbfbd589f
...
74b8676244
| Author | SHA1 | Date | |
|---|---|---|---|
| 74b8676244 | |||
| 1fd47e9d97 |
@@ -42,6 +42,11 @@ gitea:
|
||||
children:
|
||||
postgres:
|
||||
|
||||
pihole:
|
||||
hosts:
|
||||
pi1:
|
||||
pi3:
|
||||
|
||||
all:
|
||||
children:
|
||||
raspberries:
|
||||
3
ansible/arcodange/factory/playbooks/06_dns.yml
Normal file
3
ansible/arcodange/factory/playbooks/06_dns.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
- name: dns
|
||||
ansible.builtin.import_playbook: ./dns/dns.yml
|
||||
2
ansible/arcodange/factory/playbooks/dns/dns.yml
Normal file
2
ansible/arcodange/factory/playbooks/dns/dns.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
- name: pihole
|
||||
ansible.builtin.import_playbook: pihole.yml
|
||||
213
ansible/arcodange/factory/playbooks/dns/pihole.yml
Normal file
213
ansible/arcodange/factory/playbooks/dns/pihole.yml
Normal file
@@ -0,0 +1,213 @@
|
||||
---
|
||||
- name: Installer et configurer Pi-hole sur pi1
|
||||
hosts: raspberries:&local #pihole # change with pihole group
|
||||
become: yes
|
||||
vars:
|
||||
|
||||
pihole_custom_dns:
|
||||
".arcodange.duckdns.org": "{{ hostvars['pi1'].preferred_ip }}"
|
||||
roles:
|
||||
- pihole
|
||||
|
||||
# tasks:
|
||||
|
||||
# - name: Proposer la commande d'installation manuelle de Pi-hole
|
||||
# debug:
|
||||
# msg: |
|
||||
# Veuillez installer Pi-hole manuellement sur ce host avec la commande suivante :
|
||||
# # curl -sSL https://install.pi-hole.net | sudo bash
|
||||
# L'installation sera vérifiée automatiquement dans les 10 prochaines minutes.
|
||||
|
||||
# - name: Attendre que Pi-hole soit installé (vérification service et fichier config)
|
||||
# wait_for:
|
||||
# path: /etc/pihole/pihole-FTL.db
|
||||
# state: present
|
||||
# timeout: 600 # 10 minutes
|
||||
# register: pihole_config_ready
|
||||
|
||||
# - name: Vérifier que le service pihole-FTL est actif
|
||||
# wait_for:
|
||||
# port: 53 # port interne par défaut Pi-hole
|
||||
# state: started
|
||||
# timeout: 60
|
||||
# when: pihole_config_ready is succeeded
|
||||
|
||||
# - name: Modifier le fichier /etc/pihole/pihole.toml pour changer le port
|
||||
# replace:
|
||||
# path: /etc/pihole/pihole.toml
|
||||
# regexp: '^\s*port\s*=\s*".*"'
|
||||
# replace: ' port = "{{ pihole_ports }}"'
|
||||
|
||||
# - name: Modifier le fichier /etc/pihole/pihole.toml pour autoriser toutes les origines DNS
|
||||
# replace:
|
||||
# path: /etc/pihole/pihole.toml
|
||||
# regexp: '^\s*listeningMode\s*=\s*".*"'
|
||||
# replace: ' listeningMode = "ALL"'
|
||||
|
||||
# - name: Activer le chargement des fichiers /etc/dnsmasq.d/ dans Pi-hole
|
||||
# lineinfile:
|
||||
# path: /etc/pihole/pihole.toml
|
||||
# regexp: '^\s*etc_dnsmasq_d\s*='
|
||||
# line: ' etc_dnsmasq_d = true'
|
||||
# state: present
|
||||
# create: yes
|
||||
|
||||
# - name: Créer le fichier dnsmasq pour le wildcard
|
||||
# copy:
|
||||
# dest: /etc/dnsmasq.d/10-arcodange-wildcard.conf
|
||||
# content: |
|
||||
# address=/{{ pihole_wildcard_rule }}/{{ pihole_dns_ip }}
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: '0644'
|
||||
|
||||
# - name: Créer les entrées DNS locales pour les RPis (pi*.home)
|
||||
# copy:
|
||||
# dest: /etc/dnsmasq.d/20-rpis.conf
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: '0644'
|
||||
# content: |
|
||||
# # Generated by Ansible – Raspberry Pi local DNS
|
||||
# {% for host in groups['raspberries']
|
||||
# if host is match('^pi[0-9]+$')
|
||||
# and hostvars[host].preferred_ip is defined %}
|
||||
# address=/{{ host }}.home/{{ hostvars[host].preferred_ip }}
|
||||
# {% endfor %}
|
||||
|
||||
# - name: Configurer resolv.conf pour DNS croisé
|
||||
# copy:
|
||||
# dest: /etc/resolv.conf
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: '0644'
|
||||
# content: |
|
||||
# {% if inventory_hostname == 'pi1' %}
|
||||
# nameserver {{ hostvars['pi3'].preferred_ip }}
|
||||
# {% elif inventory_hostname == 'pi3' %}
|
||||
# nameserver {{ hostvars['pi1'].preferred_ip }}
|
||||
# {% endif %}
|
||||
|
||||
# - name: Redémarrer le service Pi-hole FTL
|
||||
# service:
|
||||
# name: pihole-FTL
|
||||
# state: restarted
|
||||
|
||||
|
||||
# ############################################################
|
||||
# # 2. Configuration DNS des Raspberry Pi clients
|
||||
# ############################################################
|
||||
# - name: Configurer Docker via systemd override (DNS Pi-hole)
|
||||
# hosts: raspberries:&local
|
||||
# become: yes
|
||||
|
||||
# vars:
|
||||
# docker_dns_servers:
|
||||
# - "{{ hostvars['pi1']['preferred_ip'] }}"
|
||||
# - "8.8.8.8"
|
||||
# - "1.1.1.1"
|
||||
|
||||
# docker_override_dir: /etc/systemd/system/docker.service.d
|
||||
# docker_override_file: /etc/systemd/system/docker.service.d/override.conf
|
||||
|
||||
# tasks:
|
||||
|
||||
# - name: Créer le dossier systemd override pour Docker
|
||||
# file:
|
||||
# path: "{{ docker_override_dir }}"
|
||||
# state: directory
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: '0755'
|
||||
# tags: docker, override
|
||||
|
||||
# - name: Déployer l'override systemd pour dockerd (DNS + IPv4 only)
|
||||
# copy:
|
||||
# dest: "{{ docker_override_file }}"
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: '0644'
|
||||
# content: |
|
||||
# [Service]
|
||||
# ExecStart=
|
||||
# ExecStart=/usr/bin/dockerd \
|
||||
# -H fd:// \
|
||||
# --containerd=/run/containerd/containerd.sock \
|
||||
# {% for dns in docker_dns_servers %}
|
||||
# --dns={{ dns }} \
|
||||
# {% endfor %}
|
||||
# --ipv6=false
|
||||
# notify:
|
||||
# - Reexec systemd
|
||||
# - Restart Docker
|
||||
# - Restart k3s
|
||||
# tags: docker, override
|
||||
|
||||
# # -------- ROLLBACK --------
|
||||
|
||||
# - name: Rollback - Supprimer l'override systemd Docker
|
||||
# file:
|
||||
# path: "{{ docker_override_file }}"
|
||||
# state: absent
|
||||
# notify:
|
||||
# - Reexec systemd
|
||||
# - Restart Docker
|
||||
# - Restart k3s
|
||||
# when: "'rollbacks' in ansible_run_tags"
|
||||
|
||||
# handlers:
|
||||
|
||||
# - name: Reexec systemd
|
||||
# command: systemctl daemon-reexec
|
||||
|
||||
# - name: Restart Docker
|
||||
# service:
|
||||
# name: docker
|
||||
# state: restarted
|
||||
|
||||
# - name: Restart k3s
|
||||
# service:
|
||||
# name: k3s
|
||||
# state: restarted
|
||||
# ignore_errors: yes
|
||||
|
||||
# - name: Restart k3s-agent
|
||||
# service:
|
||||
# name: k3s-agent
|
||||
# state: restarted
|
||||
# ignore_errors: yes
|
||||
|
||||
|
||||
## 3 configurer traefik
|
||||
|
||||
# apiVersion: v1
|
||||
# kind: Service
|
||||
# metadata:
|
||||
# name: pihole-external
|
||||
# namespace: kube-system
|
||||
# spec:
|
||||
# type: ExternalName
|
||||
# externalName: {{ hostvars[groups.pihole[0]]['preferred_ip'] }}
|
||||
# ports:
|
||||
# - port: 3000
|
||||
# targetPort: 3000
|
||||
# ---
|
||||
# apiVersion: traefik.io/v1alpha1
|
||||
# kind: IngressRoute
|
||||
# metadata:
|
||||
# name: pihole
|
||||
# namespace: kube-system
|
||||
# spec:
|
||||
# entryPoints:
|
||||
# - web
|
||||
# routes:
|
||||
# - match: Host(`gitea.arcodange.fr`)
|
||||
# kind: Rule
|
||||
# middlewares:
|
||||
# - name: crowdsec
|
||||
# namespace: kube-system
|
||||
# services:
|
||||
# - kind: Service
|
||||
# name: gitea-external
|
||||
# namespace: kube-system
|
||||
# port: 3000
|
||||
@@ -0,0 +1,7 @@
|
||||
pihole_primary: pi1
|
||||
pihole_user_gravity: pihole_gravity
|
||||
pihole_gravity_home: /var/lib/pihole_gravity
|
||||
pihole_dns_domain: lab
|
||||
pihole_ports: '8081o,443os,[::]:8081o,[::]:443os' # web interface
|
||||
pihole_gravity_conf: /etc/gravity-sync/gravity-sync.conf # should not be changed
|
||||
pihole_custom_dns: {}
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: Restart Pi-hole
|
||||
service:
|
||||
name: pihole-FTL
|
||||
state: restarted
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
- name: Build DNS server list (exclude self)
|
||||
set_fact:
|
||||
pihole_dns_servers: >-
|
||||
{{
|
||||
groups['pihole']
|
||||
| reject('equalto', inventory_hostname)
|
||||
| map('extract', hostvars, 'preferred_ip')
|
||||
| list
|
||||
}}
|
||||
|
||||
# 1️⃣ Supprimer d’éventuelles anciennes entrées Pi-hole
|
||||
- name: Remove existing Pi-hole nameservers
|
||||
lineinfile:
|
||||
path: /etc/resolv.conf
|
||||
regexp: '^nameserver ({{ pihole_dns_servers | join("|") }})$'
|
||||
state: absent
|
||||
when: pihole_dns_servers | length > 0
|
||||
|
||||
# 2️⃣ Insérer les Pi-hole juste après la ligne search
|
||||
- name: Insert Pi-hole nameservers with priority
|
||||
lineinfile:
|
||||
path: /etc/resolv.conf
|
||||
insertafter: '^search'
|
||||
line: "nameserver {{ item }}"
|
||||
state: present
|
||||
loop: "{{ pihole_dns_servers }}"
|
||||
@@ -0,0 +1,153 @@
|
||||
---
|
||||
# -------------------------------------------------------------------
|
||||
# Gravity Sync HA setup – final version with SSH key rotation
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
- name: Determine primary Pi-hole
|
||||
set_fact:
|
||||
pihole_primary: "{{ groups['pihole'] | first }}"
|
||||
|
||||
- name: Set secondary Pi-hole hosts
|
||||
set_fact:
|
||||
pihole_secondaries: "{{ groups['pihole'] | difference([pihole_primary]) }}"
|
||||
|
||||
#################################################################
|
||||
# 1️⃣ Ensure gravity user exists on all Pi-hole nodes
|
||||
#################################################################
|
||||
|
||||
- name: Ensure gravity user exists
|
||||
user:
|
||||
name: "{{ pihole_user_gravity }}"
|
||||
home: "{{ pihole_gravity_home }}"
|
||||
shell: /bin/bash
|
||||
system: yes
|
||||
create_home: yes
|
||||
|
||||
- name: Create .ssh directory for gravity user
|
||||
file:
|
||||
path: "{{ pihole_gravity_home }}/.ssh"
|
||||
state: directory
|
||||
owner: "{{ pihole_user_gravity }}"
|
||||
group: "{{ pihole_user_gravity }}"
|
||||
mode: '0700'
|
||||
|
||||
#################################################################
|
||||
# 2️⃣ Generate SSH key for each host (rotation at each run)
|
||||
#################################################################
|
||||
|
||||
- name: Generate SSH keypair for gravity user
|
||||
openssh_keypair:
|
||||
path: "{{ pihole_gravity_home }}/.ssh/id_ed25519"
|
||||
type: ed25519
|
||||
owner: "{{ pihole_user_gravity }}"
|
||||
group: "{{ pihole_user_gravity }}"
|
||||
mode: '0600'
|
||||
register: gravity_key
|
||||
no_log: true
|
||||
|
||||
- name: Set gravity key in hostvars
|
||||
set_fact:
|
||||
gravity_pubkey: "{{ gravity_key.public_key }}"
|
||||
|
||||
- name: Clean authorized_keys for gravity user
|
||||
file:
|
||||
path: "{{ pihole_gravity_home }}/.ssh/authorized_keys"
|
||||
state: absent
|
||||
|
||||
- name: Authorize SSH keys from other Pi-hole hosts
|
||||
authorized_key:
|
||||
user: "{{ pihole_user_gravity }}"
|
||||
key: "{{ hostvars[item].gravity_pubkey }}"
|
||||
state: present
|
||||
loop: "{{ groups['pihole'] }}"
|
||||
when: inventory_hostname != item
|
||||
|
||||
- name: Add all Pi-hole hosts to known_hosts
|
||||
known_hosts:
|
||||
path: "{{ pihole_gravity_home }}/.ssh/known_hosts"
|
||||
name: "{{ item }}"
|
||||
key: "{{ lookup('pipe', 'ssh-keyscan -t ed25519 ' ~ item) }}"
|
||||
state: present
|
||||
loop: "{{ groups['pihole'] }}"
|
||||
when: inventory_hostname != item
|
||||
become: yes
|
||||
become_user: "{{ pihole_user_gravity }}"
|
||||
|
||||
#################################################################
|
||||
# Install Gravity Sync binary if absent
|
||||
#################################################################
|
||||
|
||||
- name: Check if Gravity Sync binary exists
|
||||
stat:
|
||||
path: /usr/local/bin/gravity-sync
|
||||
register: gravity_sync_bin
|
||||
|
||||
- name: Download installer
|
||||
get_url:
|
||||
url: https://raw.githubusercontent.com/vmstan/gs-install/main/gs-install.sh
|
||||
dest: /tmp/gs-install.sh
|
||||
mode: '0755'
|
||||
when: not gravity_sync_bin.stat.exists
|
||||
|
||||
- name: Give full sudo to gravity user
|
||||
copy:
|
||||
dest: /etc/sudoers.d/gravity-sync
|
||||
mode: '0440'
|
||||
content: "{{ pihole_user_gravity }} ALL=(ALL) NOPASSWD: ALL"
|
||||
when: not gravity_sync_bin.stat.exists
|
||||
|
||||
- name: Execute Gravity Sync installer non-interactively
|
||||
command: bash /tmp/gs-install.sh
|
||||
become: yes
|
||||
become_user: "{{ pihole_user_gravity }}"
|
||||
environment:
|
||||
HOME: "{{ pihole_gravity_home }}"
|
||||
when: not gravity_sync_bin.stat.exists
|
||||
|
||||
#################################################################
|
||||
# Generate gravity-sync.conf for non-interactive use
|
||||
#################################################################
|
||||
|
||||
- name: Set remote host for gravity-sync.conf
|
||||
set_fact:
|
||||
remote_pihole: "{{ (inventory_hostname == pihole_primary) | ternary(pihole_secondaries[0] ~ '.home', pihole_primary ~ '.home') }}"
|
||||
|
||||
- name: Create gravity-sync.conf file
|
||||
copy:
|
||||
dest: "{{ pihole_gravity_conf }}"
|
||||
owner: "{{ pihole_user_gravity }}"
|
||||
group: "{{ pihole_user_gravity }}"
|
||||
mode: '0600'
|
||||
content: |
|
||||
# REQUIRED SETTINGS
|
||||
REMOTE_HOST='{{ remote_pihole }}'
|
||||
REMOTE_USER='{{ pihole_user_gravity }}'
|
||||
|
||||
# CUSTOM VARIABLES
|
||||
# LOCAL_PIHOLE_DIRECTORY='/etc/pihole'
|
||||
# REMOTE_PIHOLE_DIRECTORY='/etc/pihole'
|
||||
# LOCAL_FILE_OWNER='{{ pihole_user_gravity }}'
|
||||
# REMOTE_FILE_OWNER='{{ pihole_user_gravity }}'
|
||||
|
||||
# LOCAL_DOCKER_CONTAINER='' # optional
|
||||
# REMOTE_DOCKER_CONTAINER='' # optional
|
||||
|
||||
- name: Create symlink for gravity-sync.rsa
|
||||
file:
|
||||
src: "{{ pihole_gravity_home }}/.ssh/id_ed25519"
|
||||
dest: /etc/gravity-sync/gravity-sync.rsa
|
||||
owner: "{{ pihole_user_gravity }}"
|
||||
group: "{{ pihole_user_gravity }}"
|
||||
mode: '0600'
|
||||
state: link
|
||||
|
||||
#################################################################
|
||||
# Execute Gravity Sync with non-interactive config
|
||||
#################################################################
|
||||
|
||||
- name: Run Gravity Sync script
|
||||
command: bash /usr/local/bin/gravity-sync
|
||||
become: yes
|
||||
become_user: "{{ pihole_user_gravity }}"
|
||||
environment:
|
||||
HOME: "{{ pihole_gravity_home }}"
|
||||
@@ -0,0 +1,100 @@
|
||||
#################################################################
|
||||
# Bootstrap Pi-hole (installation manuelle attendue)
|
||||
#################################################################
|
||||
|
||||
- name: Proposer la commande d'installation manuelle de Pi-hole
|
||||
debug:
|
||||
msg: |
|
||||
Veuillez installer Pi-hole manuellement sur ce host avec la commande suivante :
|
||||
------------------------------------------------------------
|
||||
curl -sSL https://install.pi-hole.net | sudo bash
|
||||
------------------------------------------------------------
|
||||
L'installation sera vérifiée automatiquement dans les 10 prochaines minutes.
|
||||
|
||||
#################################################################
|
||||
# Vérification installation Pi-hole
|
||||
#################################################################
|
||||
|
||||
- name: Attendre que Pi-hole soit installé (FTL DB)
|
||||
wait_for:
|
||||
path: /etc/pihole/pihole-FTL.db
|
||||
state: present
|
||||
timeout: 600 # 10 minutes
|
||||
register: pihole_config_ready
|
||||
|
||||
- name: Vérifier que le service pihole-FTL est actif
|
||||
wait_for:
|
||||
port: 53
|
||||
state: started
|
||||
timeout: 60
|
||||
when: pihole_config_ready is succeeded
|
||||
|
||||
#################################################################
|
||||
# Configuration Pi-hole (commune HA)
|
||||
#################################################################
|
||||
|
||||
- name: Modifier le port d'écoute Pi-hole
|
||||
replace:
|
||||
path: /etc/pihole/pihole.toml
|
||||
regexp: '^\s*port\s*=\s*".*"'
|
||||
replace: ' port = "{{ pihole_ports }}"'
|
||||
notify: Restart Pi-hole
|
||||
|
||||
- name: Autoriser Pi-hole à écouter sur toutes les interfaces
|
||||
replace:
|
||||
path: /etc/pihole/pihole.toml
|
||||
regexp: '^\s*listeningMode\s*=\s*".*"'
|
||||
replace: ' listeningMode = "ALL"'
|
||||
notify: Restart Pi-hole
|
||||
|
||||
- name: Activer le chargement de /etc/dnsmasq.d
|
||||
lineinfile:
|
||||
path: /etc/pihole/pihole.toml
|
||||
regexp: '^\s*etc_dnsmasq_d\s*='
|
||||
line: ' etc_dnsmasq_d = true'
|
||||
state: present
|
||||
notify: Restart Pi-hole
|
||||
|
||||
#################################################################
|
||||
# DNS custom (wildcard + locaux)
|
||||
#################################################################
|
||||
|
||||
- name: Validate custom DNS IPs
|
||||
assert:
|
||||
that:
|
||||
- ip is match('^([0-9]{1,3}\.){3}[0-9]{1,3}$')
|
||||
fail_msg: "Invalid IP for {{ fqdn }}"
|
||||
loop: "{{ pihole_custom_dns | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item.key }}"
|
||||
vars:
|
||||
fqdn: "{{ item.key }}"
|
||||
ip: "{{ item.value }}"
|
||||
|
||||
- name: Générer les règles DNS custom (wildcards + FQDN)
|
||||
copy:
|
||||
dest: /etc/dnsmasq.d/10-custom-rules.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
content: |
|
||||
# Generated by Ansible – Pi-hole custom DNS rules
|
||||
{% for fqdn, ip in pihole_custom_dns.items() %}
|
||||
address=/{{ fqdn }}/{{ ip }}
|
||||
{% endfor %}
|
||||
when: pihole_custom_dns | length > 0
|
||||
notify: Restart Pi-hole
|
||||
|
||||
- name: Créer les entrées DNS locales pour les RPis
|
||||
copy:
|
||||
dest: /etc/dnsmasq.d/20-rpis.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
content: |
|
||||
# Generated by Ansible – Raspberry Pi local DNS
|
||||
{% for host in groups['raspberries']
|
||||
if hostvars[host].preferred_ip is defined %}
|
||||
address=/{{ host }}.home/{{ hostvars[host].preferred_ip }}
|
||||
{% endfor %}
|
||||
notify: Restart Pi-hole
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Setup Pi-hole HA
|
||||
include_tasks: ha_pihole_setup.yml
|
||||
when: "'pihole' in group_names"
|
||||
|
||||
- name: Setup Gravity Sync
|
||||
include_tasks: gravity_setup.yml
|
||||
when: "'pihole' in group_names"
|
||||
|
||||
- name: Setup DNS client
|
||||
include_tasks: client_setup.yml
|
||||
@@ -3,8 +3,9 @@ roles:
|
||||
- name: geerlingguy.docker
|
||||
|
||||
collections:
|
||||
- name: community.general
|
||||
- name: community.docker
|
||||
- name: ansible.posix
|
||||
- name: community.crypto
|
||||
- name: community.docker
|
||||
- name: community.general
|
||||
- name: kubernetes.core
|
||||
- name: git+https://github.com/k3s-io/k3s-ansible.git
|
||||
@@ -7,7 +7,9 @@ gitea_applications:
|
||||
tools:
|
||||
annotations: {}
|
||||
webapp:
|
||||
annotations: {}
|
||||
annotations:
|
||||
argocd-image-updater.argoproj.io/image-list: webapp=gitea.arcodange.duckdns.org/arcodange-org/webapp:latest
|
||||
argocd-image-updater.argoproj.io/webapp.update-strategy: digest
|
||||
erp:
|
||||
annotations: {}
|
||||
cms:
|
||||
|
||||
Reference in New Issue
Block a user