Initial Ansible automation for hobbs.farm infrastructure

Complete IaC covering:
- 14 roles: common, docker, traefik, vaultwarden, monitoring, media, matrix,
  home_assistant, frigate, adguard, gitea, semaphore, openclaw, security, backup
- Inventory for all hosts (Peggy, Bart, Yoda, NAS, Firewalla)
- Stack playbooks: core-infrastructure, monitoring, media, communication,
  automation, smarthome, security-hardening
- Maintenance playbooks: update-containers, backup, health-check
- Production Docker Compose templates with Traefik labels
- Security hardening (sysctl, auditd, UFW, fail2ban)
- Automated backups with retention policy
This commit is contained in:
2026-02-01 23:14:46 -06:00
parent 02beae23a0
commit b9be45dc71
74 changed files with 2110 additions and 2 deletions
+12
View File
@@ -0,0 +1,12 @@
---
- name: Deploy automation stack
hosts: peggy
roles:
- role: docker
tags: [docker]
- role: gitea
tags: [automation, gitea]
- role: semaphore
tags: [automation, semaphore]
- role: openclaw
tags: [automation, openclaw]
+8
View File
@@ -0,0 +1,8 @@
---
- name: Deploy communication stack
hosts: peggy
roles:
- role: docker
tags: [docker]
- role: matrix
tags: [communication, matrix]
+14
View File
@@ -0,0 +1,14 @@
---
- name: Deploy core infrastructure
hosts: peggy
roles:
- role: common
tags: [common]
- role: docker
tags: [docker]
- role: traefik
tags: [traefik]
- role: vaultwarden
tags: [vaultwarden]
- role: adguard
tags: [adguard]
+42
View File
@@ -0,0 +1,42 @@
---
- name: Run backups
hosts: docker_hosts
become: true
tasks:
- name: Ensure backup destination exists
ansible.builtin.file:
path: "{{ backup_destination }}"
state: directory
mode: "0750"
tags: [backup]
- name: Run backup script
ansible.builtin.command:
cmd: /usr/local/bin/homelab-backup.sh
register: backup_result
changed_when: backup_result.rc == 0
tags: [backup]
- name: Display backup result
ansible.builtin.debug:
msg: "{{ backup_result.stdout_lines }}"
tags: [backup]
- name: Clean up backups older than 30 days
ansible.builtin.find:
paths: "{{ backup_destination }}"
age: 30d
recurse: false
file_type: file
patterns: "*.tar.gz"
register: old_backups
tags: [backup, cleanup]
- name: Remove old backups
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_backups.files }}"
loop_control:
label: "{{ item.path | basename }}"
tags: [backup, cleanup]
+87
View File
@@ -0,0 +1,87 @@
---
- name: Health check all services
hosts: docker_hosts
become: true
tasks:
- name: Check Docker daemon is running
ansible.builtin.systemd:
name: docker
state: started
check_mode: true
register: docker_status
tags: [health]
- name: Get running containers
community.docker.docker_host_info:
containers: true
register: docker_info
tags: [health]
- name: Display container count
ansible.builtin.debug:
msg: "{{ inventory_hostname }}: {{ docker_info.containers | length }} containers running"
tags: [health]
- name: Check for unhealthy containers
ansible.builtin.shell: |
docker ps --filter health=unhealthy --format '{{ '{{' }}.Names{{ '}}' }}'
register: unhealthy
changed_when: false
tags: [health]
- name: Report unhealthy containers
ansible.builtin.debug:
msg: "WARNING: Unhealthy containers on {{ inventory_hostname }}: {{ unhealthy.stdout_lines }}"
when: unhealthy.stdout | length > 0
tags: [health]
- name: Check disk usage
ansible.builtin.shell: |
df -h / /data | tail -n +2 | awk '{print $1, $5, $6}'
register: disk_usage
changed_when: false
tags: [health]
- name: Display disk usage
ansible.builtin.debug:
msg: "{{ disk_usage.stdout_lines }}"
tags: [health]
- name: Check memory usage
ansible.builtin.shell: |
free -h | grep Mem | awk '{print "Total:", $2, "Used:", $3, "Free:", $4}'
register: mem_usage
changed_when: false
tags: [health]
- name: Display memory usage
ansible.builtin.debug:
msg: "{{ mem_usage.stdout }}"
tags: [health]
- name: Check key services via HTTP
ansible.builtin.uri:
url: "https://{{ item }}.{{ domain }}"
validate_certs: false
status_code: [200, 301, 302, 303, 401, 403]
timeout: 10
loop:
- traefik
- vault
- grafana
- jellyfin
- gitea
- ha
register: http_checks
ignore_errors: true
tags: [health]
when: inventory_hostname == 'peggy'
- name: Report HTTP check results
ansible.builtin.debug:
msg: "{{ item.item }}.{{ domain }}: {{ item.status | default('FAILED') }}"
loop: "{{ http_checks.results | default([]) }}"
loop_control:
label: "{{ item.item | default('unknown') }}"
when: inventory_hostname == 'peggy'
tags: [health]
@@ -0,0 +1,47 @@
---
- name: Update Docker containers
hosts: docker_hosts
become: true
vars:
update_stack: all
tasks:
- name: Get list of compose directories
ansible.builtin.find:
paths: "{{ docker_compose_base }}"
file_type: directory
recurse: false
register: compose_dirs
tags: [update]
- name: Pull latest images for each stack
community.docker.docker_compose_v2_pull:
project_src: "{{ item.path }}"
loop: "{{ compose_dirs.files }}"
loop_control:
label: "{{ item.path | basename }}"
when: update_stack == 'all' or (item.path | basename) == update_stack
tags: [update]
- name: Recreate containers with new images
community.docker.docker_compose_v2:
project_src: "{{ item.path }}"
state: present
recreate: auto
loop: "{{ compose_dirs.files }}"
loop_control:
label: "{{ item.path | basename }}"
when: update_stack == 'all' or (item.path | basename) == update_stack
tags: [update]
- name: Prune unused Docker images
community.docker.docker_prune:
images: true
images_filters:
dangling: false
tags: [cleanup]
- name: Prune unused Docker volumes
community.docker.docker_prune:
volumes: true
tags: [cleanup]
when: prune_volumes | default(false) | bool
+8
View File
@@ -0,0 +1,8 @@
---
- name: Deploy media stack
hosts: peggy
roles:
- role: docker
tags: [docker]
- role: media
tags: [media, jellyfin, sonarr, radarr]
+8
View File
@@ -0,0 +1,8 @@
---
- name: Deploy monitoring stack
hosts: peggy
roles:
- role: docker
tags: [docker]
- role: monitoring
tags: [monitoring, prometheus, grafana, alertmanager]
+8
View File
@@ -0,0 +1,8 @@
---
- name: Apply security hardening
hosts: docker_hosts
roles:
- role: common
tags: [common]
- role: security
tags: [security]
+71
View File
@@ -0,0 +1,71 @@
---
# Full site deployment for hobbs.farm
- name: Apply common configuration
hosts: docker_hosts
tags: [common]
roles:
- common
- name: Configure Docker
hosts: docker_hosts
tags: [docker]
roles:
- docker
- name: Deploy core infrastructure
hosts: peggy
tags: [core]
roles:
- traefik
- vaultwarden
- adguard
- name: Deploy monitoring stack
hosts: peggy
tags: [monitoring]
roles:
- monitoring
- name: Deploy media stack
hosts: peggy
tags: [media]
roles:
- media
- name: Deploy communication stack
hosts: peggy
tags: [communication]
roles:
- matrix
- name: Deploy smart home stack
hosts: peggy
tags: [smarthome]
roles:
- home_assistant
- name: Deploy automation stack
hosts: peggy
tags: [automation]
roles:
- gitea
- semaphore
- openclaw
- name: Deploy Frigate NVR
hosts: bart
tags: [frigate]
roles:
- frigate
- name: Apply security hardening
hosts: docker_hosts
tags: [security]
roles:
- security
- name: Configure backups
hosts: docker_hosts
tags: [backup]
roles:
- backup
+8
View File
@@ -0,0 +1,8 @@
---
- name: Deploy smart home stack
hosts: peggy
roles:
- role: docker
tags: [docker]
- role: home_assistant
tags: [smarthome, homeassistant, esphome]