Skip to content

Commit 5538ae6

Browse files
committed
feat: upgrading the always-on infra to use multiple individual stacks
1 parent d441090 commit 5538ae6

14 files changed

Lines changed: 221 additions & 118 deletions

File tree

infrastructure/always-on/README.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ This directory contains the complete implementation spec and automation for the
55
## Overview
66

77
Three machines (`srv-26`, `srv-27`, `srv-28`) form the backbone of the homelab infrastructure, providing:
8-
- **srv-26**: DNS, VPN gateway, WLAN controller, monitoring clients, GitHub Actions runner, Portainer server
9-
- **srv-27**: Secondary DNS, Grafana, Prometheus, Loki, InfluxDB (observability stack)
10-
- **srv-28**: Home Assistant, Matterbridge, FreePBX + VOIP, Portainer agent
8+
- **srv-26**: Primary DNS (Technitium), network fabric (Tailscale, Gatus, ntfy), WLAN controller (Omada), GitHub Actions runner
9+
- **srv-27**: Secondary DNS (Technitium, zone transfer from srv-26), observability stack (Prometheus, Grafana, Loki, InfluxDB, Promtail)
10+
- **srv-28**: Home automation (Home Assistant, Matterbridge, python-matter-server, matter-hub, ESPHome, Zigbee2MQTT, Mosquitto), VoIP (FreePBX, TFTP, MariaDB)
1111

1212
## Quick Start
1313

@@ -109,9 +109,17 @@ infrastructure/always-on/
109109
│ └── portainer/ # Deploy Portainer server/agent
110110
111111
├── stacks/ # Docker Compose workloads (managed by Portainer)
112-
│ ├── srv-26/docker-compose.yml
113-
│ ├── srv-27/docker-compose.yml
114-
│ └── srv-28/docker-compose.yml
112+
│ ├── srv-26/
113+
│ │ ├── dns/docker-compose.yml # Technitium DNS
114+
│ │ ├── infra/docker-compose.yml # Tailscale, Gatus, ntfy
115+
│ │ ├── wlan/docker-compose.yml # Omada controller
116+
│ │ └── cicd/docker-compose.yml # GitHub Actions runner
117+
│ ├── srv-27/
118+
│ │ ├── dns/docker-compose.yml # Technitium DNS (secondary)
119+
│ │ └── observability/docker-compose.yml # Prometheus, Grafana, Loki, InfluxDB, Promtail
120+
│ └── srv-28/
121+
│ ├── ha/docker-compose.yml # Home Assistant, Matterbridge, Matter, ESPHome, Zigbee2MQTT, Mosquitto
122+
│ └── voip/docker-compose.yml # FreePBX, TFTP, MariaDB
115123
116124
├── vault/ # Vault configuration
117125
│ ├── policies/ # Vault policies (shared, srv-26, srv-27, srv-28)
@@ -139,8 +147,10 @@ infrastructure/always-on/
139147
- Or manually trigger: `ssh ansible@srv-host sudo systemctl start ansible-pull.service`
140148

141149
**For Docker/application changes:**
142-
- Edit `stacks/<hostname>/docker-compose.yml`
143-
- Add as a Git-backed stack in Portainer, or push and let Portainer auto-sync
150+
- Edit the relevant `stacks/<hostname>/<stack>/docker-compose.yml`
151+
- Each stack is registered independently in Portainer as a Git-backed stack
152+
- Portainer stack path format: `infrastructure/always-on/stacks/<hostname>/<stack>`
153+
- Push to main branch and trigger a pull in Portainer, or let auto-sync run
144154

145155
**For new secrets:**
146156
- Add to Vault: `vault kv put secrets/infra/srv-xx/app-name key=value`

infrastructure/always-on/ansible/bootstrap.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Bootstrap playbook to be run once from operator laptop
33
# Usage: ansible-playbook infrastructure/always-on/ansible/bootstrap.yml \
44
# --inventory infrastructure/always-on/ansible/inventory/hosts.yml \
5-
# --extra-vars "vault_token=hvs.xxxxx" \
5+
# --extra-vars "vault_token=hvs.xxxxx vault_addr=https://vault.your-domain.com" \
66
# --ask-become-pass
77
#
88
# This playbook Sets up Vault policies and AppRoles, then applies common roles to all machines

infrastructure/always-on/ansible/roles/common/handlers/main.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@
1313
- name: reload systemd
1414
ansible.builtin.systemd:
1515
daemon_reload: yes
16+
17+
- name: restart systemd-resolved
18+
ansible.builtin.systemd:
19+
name: systemd-resolved
20+
state: restarted

infrastructure/always-on/ansible/roles/common/tasks/main.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,22 @@
121121
ansible.builtin.systemd:
122122
name: ansible-pull.timer
123123
state: started
124+
125+
- name: Ensure [Resolve] section exists in resolved.conf for Technitium hosts
126+
ansible.builtin.lineinfile:
127+
path: /etc/systemd/resolved.conf
128+
regexp: '^\[Resolve\]$'
129+
line: '[Resolve]'
130+
insertafter: EOF
131+
state: present
132+
when: "'technitium' in host_stacks"
133+
134+
- name: Disable systemd-resolved DNS stub listener for Technitium hosts
135+
ansible.builtin.lineinfile:
136+
path: /etc/systemd/resolved.conf
137+
regexp: '^DNSStubListener='
138+
line: DNSStubListener=no
139+
insertafter: '^\[Resolve\]$'
140+
state: present
141+
when: "'technitium' in host_stacks"
142+
notify: restart systemd-resolved

infrastructure/always-on/ansible/roles/portainer/tasks/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
volumes:
2020
- /var/run/docker.sock:/var/run/docker.sock
2121
- portainer_data:/data
22+
- /opt/secrets:/opt/secrets:ro
2223
when: portainer_role == "server"
2324

2425
- name: Deploy Portainer agent
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: '3.8'
2+
3+
services:
4+
github-runner:
5+
image: myoung34/github-runner:latest
6+
container_name: github-runner
7+
restart: unless-stopped
8+
volumes:
9+
- /var/run/docker.sock:/var/run/docker.sock
10+
- runner_data:/home/runner
11+
env_file:
12+
- /opt/secrets/github-runner/github-runner.env
13+
14+
volumes:
15+
runner_data:

infrastructure/always-on/stacks/srv-27/docker-compose-dns.yml renamed to infrastructure/always-on/stacks/srv-26/dns/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ services:
1515
- /opt/secrets/technitium/technitium.env
1616

1717
volumes:
18-
technitium_data:
18+
technitium_data:

infrastructure/always-on/stacks/srv-26/docker-compose.yml

Lines changed: 0 additions & 81 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
version: '3.8'
2+
3+
services:
4+
tailscale:
5+
image: tailscale/tailscale:latest
6+
container_name: tailscale
7+
restart: unless-stopped
8+
network_mode: host
9+
cap_add:
10+
- NET_ADMIN
11+
volumes:
12+
- tailscale_data:/var/lib/tailscale
13+
env_file:
14+
- /opt/secrets/tailscale/tailscale.env
15+
16+
gatus:
17+
image: twinproduction/gatus:v5.5.1
18+
container_name: gatus
19+
restart: unless-stopped
20+
ports:
21+
- "8080:8080/tcp"
22+
volumes:
23+
- ./gatus-config.yaml:/etc/gatus/config.yaml
24+
env_file:
25+
- /opt/secrets/gatus/gatus.env
26+
27+
ntfy:
28+
image: binwiederhier/ntfy:latest
29+
container_name: ntfy
30+
restart: unless-stopped
31+
ports:
32+
- "8090:80/tcp"
33+
volumes:
34+
- ntfy_data:/var/lib/ntfy
35+
env_file:
36+
- /opt/secrets/ntfy/ntfy.env
37+
38+
volumes:
39+
tailscale_data:
40+
ntfy_data:
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: '3.8'
2+
3+
services:
4+
omada-controller:
5+
image: mbentley/omada-controller:latest
6+
container_name: omada
7+
restart: unless-stopped
8+
ports:
9+
- "8088:8088/tcp"
10+
- "8043:8043/tcp"
11+
- "29810:29810/udp"
12+
- "29811:29811/tcp"
13+
- "29812:29812/tcp"
14+
volumes:
15+
- omada_data:/opt/tplink/EAPController/data
16+
env_file:
17+
- /opt/secrets/omada/omada.env
18+
19+
volumes:
20+
omada_data:

0 commit comments

Comments
 (0)