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:
Adyrem
2026-05-15 16:52:20 +02:00
parent c626177daa
commit afd240de86
19 changed files with 351 additions and 34 deletions
+1
View File
@@ -0,0 +1 @@
{"sessionId":"e2025a38-3d43-46f4-8c97-bbac5bc5681b","pid":40455,"procStart":"489090","acquiredAt":1778850952882}
+34 -32
View File
@@ -1,33 +1,35 @@
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256
34333966316434323536326366663637633834393865623238636338306361393837393530363665 30353336323330616638366131616265353935386336623962313139666630386233333435376132
3566366534376133643163376261343461653336643136330a356162653062663538636466346438 6632383465666533323435613938636564636166353265300a636531383030323130356439663538
31626464363033623331353037333131356434386631616566323337616166306431383330333261 39373933303438346138306430393831663236626132353031623837643563353536383432393866
6464656132613962610a306163353135653131623064386337643563646266623839383138326133 3963613139663531620a613631636261653764663539323363326538373438326666646666643432
31353466653633323030326432633364376236313239623439663265393365356262393138666263 66663430333263653439613937326134653830663631363236663238663933613363343039393734
62323962306439643166613930383933323132316132363236363639333336663237643966386337 62313035653337363836633333636231643635656134396639653431646236353737353133343631
63633764663263303933336332343266333161333835363235303965373134386434373532646137 30343237373232356532363732366236343565353739353065363562643932386164366163343235
38663965396332356561363932633736613836393861626435666162396666633033393963353264 33363837626434306339623733623464646633656431643732303330353232656439313639363362
35633438316238623933623966306330363432386632653936323436656337306430383439356462 33376364343965323464663634386530303462613833333136623635366537363265646163653038
64396137316464363835373137366434323263343330313163653638306434616635656537656264 38376563353865636437313838313236333662376430303930356432663261383834626563343139
66396366666562643734313235613364623734613662663161636332353035346666373732613165 66643730373239623737383138663935313031373062646363663865366233383663336330333134
64356630323239363665383933363139613738323866326134613661663731396566323065383438 30333032366131363630303735653265636337616531656133343935306136303830333439656230
39613335383434613432666266343935646537613266386335393131333635343633653736373634 36303565643939616138323932393637373935396264666162356538313165656438306232613665
64653164396439363631643565663839623966343165666236303434666431636431356136613335 64666334306134323730383665666664303930646630343636653335653735323561393061323031
36353166336664333031663435323161363137386237343034383863356430323433343766646134 65643831353464353235626535346337663263396432356232323434653562656365386663636131
36366665313130373363303136346239633538393230313832663430393233663062343834383534 39663136313664353331373164616331626135356234623961663430653661316465393439643033
64373363376139663165363663333962353538326461353838383865653963343036366336343563 64653562383533383839386237323439376139333962396336386633653566656563636533366336
65613336386438373262666263633761386332303737613038333735336639613230336636333265 35313366336266633636383763643463376134316366393235313964313239373836336665353339
30393735643432623935363832313738376630373036623630663735343935386165616133333563 66303531336333646333326265646331353363653036313261663462626462653964306465383665
63366637313961653264346539383233346465383263353566326134396333663632636630343133 66313331656538336534653166363535336232316363303335663835656566623132383131373436
64636261346437333166316430643437393032396237353231346136363634353838376238386335 36366235643935373061366565623761333335666163326464326636626462663661346163323438
39613865346266396639353838316331356430343331633330636534316335633563623464613661 64653234333236383039393963336235643163653834303237366363633330613639353332616535
34646132333135303361336135303263636362353937346635356464656438623539353836383132 61323265346161313561396435643630383435633466636639316665353366343266306232663439
65626566366539306536663462373236616430343135633439643836363365323761373463356131 32653662666631636662323833646562353861333365303430326130633832313162316337643063
65363337313334393265383362666639636132623032303764326335306336616136646165376264 34393038646164363837306461303634653464343232663139363237353939323137333238613537
30383561303866646138643734666462653765653362383163346432303435663738633936383866 34616139376632373931343437316337383332343162363939633634303831353336333433633935
39613831323436393061666532343765333331313961636164346338656561353731323064316630 39343439313865343036376634653863653137653131363866363761653065313738316663383239
32626238633863353530356436383665363239663965356564356239313334393732363265656665 38383232626262303463393164326366633138313932366530663136616233313831303337316537
30386266313538336339303731386634643839383261383361333931333739383563316134666331 38343661663264303337346161323135366164373039663934343261663237396563383239663262
66323064353733303838393635653037373538616138323763396536343064323633656562643337 39383765643765396331333938666335663862303962353562663361323764643031373431306664
39636138633066356134303739363061653065643464393331626531623030653766313764623630 61646561353732323765363034326362663239666634316639356232633934663130663431613236
64636434636233653065 64336335653664646430653061313836386361316564353334336364626332303839363335343363
65653931363331383834373364616538336135633936363533383461373931666666373863386438
3231333561313139393966383964613731616139666536613536
@@ -0,0 +1,2 @@
ansible_user: root
ansible_become: false
@@ -0,0 +1,2 @@
ansible_user: root
ansible_become: false
+12
View File
@@ -9,6 +9,10 @@ all:
ansible_host: 10.10.1.125 ansible_host: 10.10.1.125
monitoring: monitoring:
ansible_host: 10.10.1.137 ansible_host: 10.10.1.137
pihole:
ansible_host: 10.10.1.2
traefik:
ansible_host: 10.10.1.3
monitoring_servers: monitoring_servers:
hosts: hosts:
@@ -17,3 +21,11 @@ all:
gitea_servers: gitea_servers:
hosts: hosts:
gitea: gitea:
pihole_servers:
hosts:
pihole:
traefik_servers:
hosts:
traefik:
+5
View File
@@ -0,0 +1,5 @@
---
- name: Deploy Pi-hole
hosts: pihole_servers
roles:
- pihole
+12 -2
View File
@@ -1,6 +1,6 @@
--- ---
- name: Common setup for all VMs - name: Common setup for all Arch VMs
hosts: all hosts: all:!pihole_servers:!traefik_servers
roles: roles:
- common - common
- node_exporter - node_exporter
@@ -15,3 +15,13 @@
hosts: gitea_servers hosts: gitea_servers
roles: roles:
- gitea - gitea
- name: Pi-hole
hosts: pihole_servers
roles:
- pihole
- name: Traefik
hosts: traefik_servers
roles:
- traefik
+5
View File
@@ -0,0 +1,5 @@
---
- name: Deploy Traefik
hosts: traefik_servers
roles:
- traefik
+11
View File
@@ -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" }
+10
View File
@@ -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
+58
View File
@@ -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)
+17
View File
@@ -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"
+9
View File
@@ -0,0 +1,9 @@
---
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: true
- name: Restart traefik
ansible.builtin.systemd:
name: traefik
state: restarted
+86
View File
@@ -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 }}