e98e3a2b84
Playbooks liegen unter pve1/ansible und pve2/ansible; authorized_keys als Fragmente mit Deploy-Skript und Ziel-Matrix für Proxmox, VM 101 und CTs. Co-authored-by: Cursor <cursoragent@cursor.com>
225 lines
6.7 KiB
YAML
225 lines
6.7 KiB
YAML
---
|
|
- name: Disk usage before maintenance
|
|
ansible.builtin.shell: df -hT / | tail -1
|
|
register: disk_before
|
|
changed_when: false
|
|
|
|
- name: Show disk before
|
|
ansible.builtin.debug:
|
|
msg: "{{ inventory_hostname }} before: {{ disk_before.stdout }}"
|
|
|
|
- name: Vacuum systemd journal
|
|
ansible.builtin.command: "journalctl --vacuum-size={{ journal_max_size }}"
|
|
register: journal_vacuum
|
|
changed_when: "'Vacuuming done' in journal_vacuum.stdout"
|
|
failed_when: false
|
|
|
|
- name: Clean apt cache
|
|
ansible.builtin.apt:
|
|
autoclean: true
|
|
autoremove: true
|
|
clean: true
|
|
when: apt_clean | bool
|
|
|
|
- name: Check if docker is available
|
|
ansible.builtin.command: docker info
|
|
register: docker_info
|
|
changed_when: false
|
|
failed_when: false
|
|
tags: [always, docker]
|
|
|
|
- name: Truncate oversized Docker container logs
|
|
ansible.builtin.shell: |
|
|
set -o pipefail
|
|
find /var/lib/docker/containers -name '*-json.log' -size +{{ docker_log_truncate_threshold }} \
|
|
-exec truncate -s {{ docker_log_truncate_target }} {} \;
|
|
echo done
|
|
args:
|
|
executable: /bin/bash
|
|
register: log_truncate
|
|
changed_when: log_truncate.stdout is search('done')
|
|
when: docker_info is defined and docker_info.rc == 0
|
|
|
|
- name: Prune stopped containers
|
|
ansible.builtin.command: >-
|
|
docker container prune -f --filter until={{ docker_prune_stopped_containers_older_than }}
|
|
register: container_prune
|
|
changed_when: "'Total reclaimed space' in container_prune.stdout and '0B' not in container_prune.stdout.split('Total reclaimed space')[1].split('\n')[0]"
|
|
when: docker_info is defined and docker_info.rc == 0
|
|
|
|
- name: Prune dangling images
|
|
ansible.builtin.command: docker image prune -f
|
|
register: image_prune_dangling
|
|
changed_when: "'Total reclaimed space' in image_prune_dangling.stdout and '0B' not in image_prune_dangling.stdout.split('Total reclaimed space')[1].split('\n')[0]"
|
|
when:
|
|
- docker_info is defined
|
|
- docker_info.rc == 0
|
|
- docker_prune_dangling_images | bool
|
|
|
|
- name: Prune unused images older than threshold
|
|
ansible.builtin.command: >-
|
|
docker image prune -af --filter until={{ docker_prune_unused_images_older_than }}
|
|
register: image_prune_old
|
|
changed_when: "'Total reclaimed space' in image_prune_old.stdout and '0B' not in image_prune_old.stdout.split('Total reclaimed space')[1].split('\n')[0]"
|
|
when:
|
|
- docker_info is defined
|
|
- docker_info.rc == 0
|
|
- docker_prune_unused_images_older_than | length > 0
|
|
tags:
|
|
- aggressive
|
|
|
|
- name: Prune docker build cache
|
|
ansible.builtin.command: >-
|
|
docker builder prune -af --filter until={{ docker_prune_build_cache_older_than }}
|
|
register: builder_prune
|
|
changed_when: "'Total:' in builder_prune.stdout"
|
|
failed_when: false
|
|
when: docker_info is defined and docker_info.rc == 0
|
|
|
|
- name: Prune dangling docker volumes
|
|
ansible.builtin.command: docker volume prune -f
|
|
register: volume_prune
|
|
changed_when: "'Total reclaimed space' in volume_prune.stdout and '0B' not in volume_prune.stdout.split('Total reclaimed space')[1].split('\n')[0]"
|
|
when:
|
|
- docker_info is defined
|
|
- docker_info.rc == 0
|
|
- docker_prune_dangling_volumes | bool
|
|
|
|
- name: Check for existing Docker daemon.json
|
|
ansible.builtin.stat:
|
|
path: /etc/docker/daemon.json
|
|
register: docker_daemon_json
|
|
when: docker_info is defined and docker_info.rc == 0
|
|
|
|
- name: Ensure Docker log rotation defaults
|
|
ansible.builtin.copy:
|
|
dest: /etc/docker/daemon.json
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
force: false
|
|
content: |
|
|
{
|
|
"log-driver": "json-file",
|
|
"log-opts": {
|
|
"max-size": "10m",
|
|
"max-file": "3"
|
|
}
|
|
}
|
|
notify: Restart docker
|
|
when:
|
|
- docker_info is defined
|
|
- docker_info.rc == 0
|
|
- not docker_daemon_json.stat.exists
|
|
|
|
- name: Remove old Frigate recording day folders
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
retain={{ frigate_recordings_retain_days }}
|
|
cutoff=$(date -d "-${retain} days" +%Y-%m-%d)
|
|
removed=0
|
|
for d in "{{ frigate_recordings_path }}"/20??-??-??; do
|
|
[ -d "$d" ] || continue
|
|
day=$(basename "$d")
|
|
if [[ "$day" < "$cutoff" ]]; then
|
|
rm -rf "$d"
|
|
echo "removed $day"
|
|
removed=1
|
|
fi
|
|
done
|
|
[ "$removed" -eq 0 ] || true
|
|
args:
|
|
executable: /bin/bash
|
|
register: frigate_recording_cleanup
|
|
changed_when: frigate_recording_cleanup.stdout | length > 0
|
|
when:
|
|
- frigate_recordings_path is defined
|
|
- frigate_recordings_path | length > 0
|
|
tags:
|
|
- frigate
|
|
|
|
- name: Remove old Frigate clip previews
|
|
ansible.builtin.find:
|
|
paths: "{{ frigate_clips_path | default('') }}/previews"
|
|
age: "{{ frigate_clips_retain_days }}d"
|
|
file_type: any
|
|
recurse: true
|
|
register: old_frigate_clips
|
|
when:
|
|
- frigate_clips_path is defined
|
|
- frigate_clips_path | length > 0
|
|
|
|
- name: Delete old Frigate clip files
|
|
ansible.builtin.file:
|
|
path: "{{ item.path }}"
|
|
state: absent
|
|
loop: "{{ old_frigate_clips.files | default([]) }}"
|
|
when:
|
|
- frigate_clips_path is defined
|
|
- frigate_clips_path | length > 0
|
|
loop_control:
|
|
label: "{{ item.path }}"
|
|
tags:
|
|
- frigate
|
|
|
|
- name: Clean stale Jellyfin cache files
|
|
ansible.builtin.find:
|
|
paths: "{{ jellyfin_cache_path | default('') }}"
|
|
age: "{{ jellyfin_cache_max_age_days }}d"
|
|
file_type: file
|
|
recurse: true
|
|
register: old_jellyfin_cache
|
|
when:
|
|
- jellyfin_cache_path is defined
|
|
- jellyfin_cache_path | length > 0
|
|
|
|
- name: Delete stale Jellyfin cache
|
|
ansible.builtin.file:
|
|
path: "{{ item.path }}"
|
|
state: absent
|
|
loop: "{{ old_jellyfin_cache.files | default([]) }}"
|
|
when:
|
|
- jellyfin_cache_path is defined
|
|
- jellyfin_cache_path | length > 0
|
|
loop_control:
|
|
label: "{{ item.path }}"
|
|
tags:
|
|
- jellyfin
|
|
|
|
- name: Clean npm cache on dev hosts
|
|
ansible.builtin.command: npm cache clean --force
|
|
when:
|
|
- dev_tooling_cleanup | default(false) | bool
|
|
- npm_cache_clean | bool
|
|
changed_when: true
|
|
failed_when: false
|
|
tags:
|
|
- dev-tooling
|
|
|
|
- name: Run fstrim on root filesystem
|
|
ansible.builtin.command: fstrim -v /
|
|
register: fstrim_result
|
|
changed_when: "'trimmed' in fstrim_result.stdout and '0 B' not in fstrim_result.stdout"
|
|
when: fstrim_enabled | bool
|
|
|
|
- name: Docker disk summary
|
|
ansible.builtin.command: docker system df
|
|
register: docker_df
|
|
changed_when: false
|
|
failed_when: false
|
|
when: docker_info is defined and docker_info.rc == 0
|
|
|
|
- name: Disk usage after maintenance
|
|
ansible.builtin.shell: df -hT / | tail -1
|
|
register: disk_after
|
|
changed_when: false
|
|
|
|
- name: Maintenance summary
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
{{ inventory_hostname }}:
|
|
before: {{ disk_before.stdout }}
|
|
after: {{ disk_after.stdout }}
|
|
fstrim: {{ fstrim_result.stdout | default('skipped') }}
|
|
docker: {{ docker_df.stdout | default('n/a') }}
|