Ansible ins Repo migrieren und zentrale SSH-Keys in shared/ssh.
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>
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
---
|
||||
journal_max_size: 200M
|
||||
docker_prune_stopped_containers_older_than: 168h
|
||||
docker_prune_dangling_images: true
|
||||
docker_prune_unused_images_older_than: 336h
|
||||
docker_prune_build_cache_older_than: 336h
|
||||
docker_prune_dangling_volumes: true
|
||||
docker_log_truncate_threshold: 50M
|
||||
docker_log_truncate_target: 10M
|
||||
fstrim_enabled: true
|
||||
frigate_recordings_retain_days: 30
|
||||
frigate_clips_retain_days: 14
|
||||
jellyfin_cache_max_age_days: 30
|
||||
npm_cache_clean: false
|
||||
apt_clean: true
|
||||
disk_warn_percent: 80
|
||||
thin_pool_warn_percent: 85
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: Restart docker
|
||||
ansible.builtin.service:
|
||||
name: docker
|
||||
state: restarted
|
||||
@@ -0,0 +1,224 @@
|
||||
---
|
||||
- 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') }}
|
||||
Reference in New Issue
Block a user