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:
@@ -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]
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Deploy communication stack
|
||||
hosts: peggy
|
||||
roles:
|
||||
- role: docker
|
||||
tags: [docker]
|
||||
- role: matrix
|
||||
tags: [communication, matrix]
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Deploy media stack
|
||||
hosts: peggy
|
||||
roles:
|
||||
- role: docker
|
||||
tags: [docker]
|
||||
- role: media
|
||||
tags: [media, jellyfin, sonarr, radarr]
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Deploy monitoring stack
|
||||
hosts: peggy
|
||||
roles:
|
||||
- role: docker
|
||||
tags: [docker]
|
||||
- role: monitoring
|
||||
tags: [monitoring, prometheus, grafana, alertmanager]
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Apply security hardening
|
||||
hosts: docker_hosts
|
||||
roles:
|
||||
- role: common
|
||||
tags: [common]
|
||||
- role: security
|
||||
tags: [security]
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Deploy smart home stack
|
||||
hosts: peggy
|
||||
roles:
|
||||
- role: docker
|
||||
tags: [docker]
|
||||
- role: home_assistant
|
||||
tags: [smarthome, homeassistant, esphome]
|
||||
Reference in New Issue
Block a user