Add Pi-hole and Traefik LXC containers
- LXC 103 (pihole): Debian 12, 10.10.1.2, Pi-hole v6 with local DNS for gitea/grafana/traefik/pihole.homelab, Proxmox dnsmasq updated to use Pi-hole upstream - LXC 104 (traefik): Debian 12, 10.10.1.3, Traefik v3 routing gitea.homelab → 10.10.1.125:3000, grafana.homelab → 10.10.1.137:3000 - DNAT rules on vmbr0 forwarding :80/:443 to Traefik, persisted in /etc/network/interfaces - Ansible roles: pihole, traefik; playbooks: pihole.yml, traefik.yml - site.yml excludes Debian containers from Arch-specific common role Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
---
|
||||
pihole_password: "{{ vault_pihole_password }}"
|
||||
pihole_dns_upstream1: "8.8.8.8"
|
||||
pihole_dns_upstream2: "8.8.4.4"
|
||||
pihole_local_domain: "homelab"
|
||||
pihole_interface: "eth0"
|
||||
pihole_dns_hosts:
|
||||
- { ip: "10.10.1.2", host: "pihole.homelab" }
|
||||
- { ip: "10.10.1.3", host: "traefik.homelab" }
|
||||
- { ip: "10.10.1.125", host: "gitea.homelab" }
|
||||
- { ip: "10.10.1.137", host: "grafana.homelab" }
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Restart pihole-FTL
|
||||
ansible.builtin.service:
|
||||
name: pihole-FTL
|
||||
state: restarted
|
||||
|
||||
- name: Update pihole hosts
|
||||
ansible.builtin.command:
|
||||
cmd: python3 /tmp/pihole_update_hosts.py
|
||||
notify: Restart pihole-FTL
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
- name: Install Pi-hole dependencies
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- curl
|
||||
- git
|
||||
- libcap2-bin
|
||||
- dns-root-data
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Create Pi-hole config directory
|
||||
ansible.builtin.file:
|
||||
path: /etc/pihole
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Write Pi-hole setup vars
|
||||
ansible.builtin.template:
|
||||
src: setupVars.conf.j2
|
||||
dest: /etc/pihole/setupVars.conf
|
||||
mode: "0644"
|
||||
|
||||
- name: Check if Pi-hole is already installed
|
||||
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/pihole-install.sh
|
||||
mode: "0755"
|
||||
when: not pihole_binary.stat.exists
|
||||
|
||||
- name: Run Pi-hole unattended installer
|
||||
ansible.builtin.command:
|
||||
cmd: /tmp/pihole-install.sh --unattended
|
||||
creates: /usr/local/bin/pihole
|
||||
when: not pihole_binary.stat.exists
|
||||
|
||||
- name: Set Pi-hole web password
|
||||
ansible.builtin.command:
|
||||
cmd: /usr/local/bin/pihole setpassword "{{ pihole_password }}"
|
||||
changed_when: true
|
||||
|
||||
- name: Set local DNS hosts in pihole.toml
|
||||
ansible.builtin.template:
|
||||
src: update_hosts.py.j2
|
||||
dest: /tmp/pihole_update_hosts.py
|
||||
mode: "0755"
|
||||
notify: Update pihole hosts
|
||||
|
||||
- name: Ensure pihole-FTL is running
|
||||
ansible.builtin.service:
|
||||
name: pihole-FTL
|
||||
state: started
|
||||
enabled: true
|
||||
@@ -0,0 +1,15 @@
|
||||
PIHOLE_INTERFACE={{ pihole_interface }}
|
||||
PIHOLE_DNS_1={{ pihole_dns_upstream1 }}
|
||||
PIHOLE_DNS_2={{ pihole_dns_upstream2 }}
|
||||
QUERY_LOGGING=true
|
||||
INSTALL_WEB_SERVER=true
|
||||
INSTALL_WEB_INTERFACE=true
|
||||
LIGHTTPD_ENABLED=true
|
||||
CACHE_SIZE=10000
|
||||
DNS_FQDN_REQUIRED=false
|
||||
DNS_BOGUS_PRIV=true
|
||||
DNSMASQ_LISTENING=local
|
||||
WEBPASSWORD=
|
||||
BLOCKING_ENABLED=true
|
||||
PIHOLE_DOMAIN={{ pihole_local_domain }}
|
||||
IPV4_ADDRESS=10.10.1.2/24
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python3
|
||||
import re
|
||||
|
||||
hosts = [
|
||||
{% for h in pihole_dns_hosts %}
|
||||
"{{ h.ip }} {{ h.host }}",
|
||||
{% endfor %}
|
||||
]
|
||||
|
||||
hosts_str = "[" + ", ".join('"' + h + '"' for h in hosts) + "]"
|
||||
|
||||
with open("/etc/pihole/pihole.toml", "r") as f:
|
||||
content = f.read()
|
||||
|
||||
content = re.sub(
|
||||
r"(?m)^( *hosts\s*=\s*)\[.*\]",
|
||||
r"\g<1>" + hosts_str,
|
||||
content,
|
||||
)
|
||||
|
||||
with open("/etc/pihole/pihole.toml", "w") as f:
|
||||
f.write(content)
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
traefik_version: "3.3.4"
|
||||
traefik_http_port: 80
|
||||
traefik_https_port: 443
|
||||
traefik_dashboard_port: 8080
|
||||
traefik_log_level: "INFO"
|
||||
|
||||
traefik_services:
|
||||
- name: gitea
|
||||
host: "gitea.homelab"
|
||||
backend: "http://10.10.1.125:3000"
|
||||
- name: grafana
|
||||
host: "grafana.homelab"
|
||||
backend: "http://10.10.1.137:3000"
|
||||
- name: pihole
|
||||
host: "pihole.homelab"
|
||||
backend: "http://10.10.1.2:80"
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: Reload systemd
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart traefik
|
||||
ansible.builtin.systemd:
|
||||
name: traefik
|
||||
state: restarted
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
- name: Install dependencies
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- curl
|
||||
- ca-certificates
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Create traefik user
|
||||
ansible.builtin.user:
|
||||
name: traefik
|
||||
system: true
|
||||
shell: /usr/sbin/nologin
|
||||
home: /etc/traefik
|
||||
create_home: false
|
||||
|
||||
- name: Create traefik directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: traefik
|
||||
group: traefik
|
||||
mode: "0750"
|
||||
loop:
|
||||
- /etc/traefik
|
||||
- /etc/traefik/conf.d
|
||||
|
||||
- name: Check installed Traefik version
|
||||
ansible.builtin.command:
|
||||
cmd: /usr/local/bin/traefik version
|
||||
register: traefik_installed_version
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Download Traefik binary
|
||||
ansible.builtin.get_url:
|
||||
url: "https://github.com/traefik/traefik/releases/download/v{{ traefik_version }}/traefik_v{{ traefik_version }}_linux_amd64.tar.gz"
|
||||
dest: /tmp/traefik.tar.gz
|
||||
mode: "0644"
|
||||
when: traefik_version not in (traefik_installed_version.stdout | default(''))
|
||||
|
||||
- name: Extract Traefik binary
|
||||
ansible.builtin.unarchive:
|
||||
src: /tmp/traefik.tar.gz
|
||||
dest: /usr/local/bin
|
||||
include:
|
||||
- traefik
|
||||
remote_src: true
|
||||
mode: "0755"
|
||||
when: traefik_version not in (traefik_installed_version.stdout | default(''))
|
||||
notify: Restart traefik
|
||||
|
||||
- name: Write Traefik static config
|
||||
ansible.builtin.template:
|
||||
src: traefik.yml.j2
|
||||
dest: /etc/traefik/traefik.yml
|
||||
owner: traefik
|
||||
group: traefik
|
||||
mode: "0640"
|
||||
notify: Restart traefik
|
||||
|
||||
- name: Write Traefik dynamic routes config
|
||||
ansible.builtin.template:
|
||||
src: routes.yml.j2
|
||||
dest: /etc/traefik/conf.d/routes.yml
|
||||
owner: traefik
|
||||
group: traefik
|
||||
mode: "0640"
|
||||
notify: Restart traefik
|
||||
|
||||
- name: Write Traefik systemd service
|
||||
ansible.builtin.template:
|
||||
src: traefik.service.j2
|
||||
dest: /etc/systemd/system/traefik.service
|
||||
mode: "0644"
|
||||
notify:
|
||||
- Reload systemd
|
||||
- Restart traefik
|
||||
|
||||
- name: Enable and start Traefik
|
||||
ansible.builtin.systemd:
|
||||
name: traefik
|
||||
state: started
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
@@ -0,0 +1,17 @@
|
||||
http:
|
||||
routers:
|
||||
{% for svc in traefik_services %}
|
||||
{{ svc.name }}:
|
||||
rule: "Host(`{{ svc.host }}`)"
|
||||
service: {{ svc.name }}
|
||||
entryPoints:
|
||||
- web
|
||||
{% endfor %}
|
||||
|
||||
services:
|
||||
{% for svc in traefik_services %}
|
||||
{{ svc.name }}:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "{{ svc.backend }}"
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,18 @@
|
||||
[Unit]
|
||||
Description=Traefik reverse proxy
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
User=traefik
|
||||
Group=traefik
|
||||
ExecStart=/usr/local/bin/traefik --configFile=/etc/traefik/traefik.yml
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
NoNewPrivileges=true
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,15 @@
|
||||
api:
|
||||
dashboard: true
|
||||
insecure: true
|
||||
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":{{ traefik_http_port }}"
|
||||
|
||||
providers:
|
||||
file:
|
||||
directory: /etc/traefik/conf.d
|
||||
watch: true
|
||||
|
||||
log:
|
||||
level: {{ traefik_log_level }}
|
||||
Reference in New Issue
Block a user