v1.0.0
This commit is contained in:
22
playbooks/playbook_autopilot.yml
Normal file
22
playbooks/playbook_autopilot.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# Playbook do bezobsługowego uruchamiania z crona (patrz cron/run-autopilot.sh).
|
||||
# Kolejność: aktualizacja pakietów -> sprzątanie/kondycja -> raport floty.
|
||||
#
|
||||
# Świadomie NIE zawiera:
|
||||
# - playbook_security_baseline.yml (zmiany w sshd/unattended-upgrades — uruchamiać ręcznie)
|
||||
# - restartu hostów (reboot jest tylko raportowany w fleet_report, decyzję
|
||||
# o restarcie podejmuje operator ręcznie)
|
||||
#
|
||||
# Użycie: ansible-playbook -i patchmon_inventory.yml playbooks/playbook_autopilot.yml --limit "Update-now,localhost"
|
||||
#
|
||||
# WAŻNE: ",localhost" w --limit jest wymagane — playbook_fleet_report.yml ma
|
||||
# drugą fazę na hosts: localhost (renderowanie raportu), a --limit bez "localhost"
|
||||
# w wzorcu powoduje jej pominięcie ("skipping: no hosts matched").
|
||||
- name: Aktualizacja pakietów
|
||||
import_playbook: playbook_upgrade.yml
|
||||
|
||||
- name: Sprzątanie i kondycja systemu
|
||||
import_playbook: playbook_cleanup.yml
|
||||
|
||||
- name: Raport stanu floty
|
||||
import_playbook: playbook_fleet_report.yml
|
||||
46
playbooks/playbook_cleanup.yml
Normal file
46
playbooks/playbook_cleanup.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
# Rutynowe sprzątanie/kondycja systemu: apt autoremove/clean, czyszczenie journala,
|
||||
# sprawdzenie zajętości dysku z progiem ostrzegawczym (domyślnie 85%, group_vars/all.yml).
|
||||
- name: Sprzątanie i kondycja systemu
|
||||
hosts: all
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
- name: Usuń nieużywane pakiety (apt autoremove)
|
||||
ansible.builtin.apt:
|
||||
autoremove: yes
|
||||
purge: yes
|
||||
when: ansible_os_family in ["Debian", "Ubuntu"]
|
||||
|
||||
- name: Wyczyść lokalny cache pobranych pakietów (apt clean)
|
||||
ansible.builtin.apt:
|
||||
autoclean: yes
|
||||
when: ansible_os_family in ["Debian", "Ubuntu"]
|
||||
|
||||
- name: Wyczyść dziennik systemowy starszy niż 7 dni (journalctl --vacuum-time)
|
||||
ansible.builtin.command: journalctl --vacuum-time=7d
|
||||
register: journal_vacuum
|
||||
changed_when: "'Vacuuming done' in journal_vacuum.stdout and 'freed' in journal_vacuum.stdout"
|
||||
when: ansible_service_mgr == "systemd"
|
||||
|
||||
- name: Odśwież fakty o zajętości dysku (po sprzątaniu)
|
||||
ansible.builtin.setup:
|
||||
filter: ansible_mounts
|
||||
gather_timeout: 30
|
||||
|
||||
- name: Sprawdź zajętość dysku na partycji root
|
||||
ansible.builtin.set_fact:
|
||||
root_disk_percent_used: >-
|
||||
{{ (( (mount.size_total - mount.size_available) / mount.size_total * 100) | round(0, 'ceil')) | int }}
|
||||
vars:
|
||||
mount: "{{ ansible_mounts | selectattr('mount', 'equalto', '/') | first }}"
|
||||
when: ansible_mounts | selectattr('mount', 'equalto', '/') | list | length > 0
|
||||
|
||||
- name: OSTRZEŻENIE — zajętość dysku powyżej progu
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
WARN [{{ inventory_hostname }}]: dysk / zajęty w {{ root_disk_percent_used }}%
|
||||
(próg: {{ disk_usage_warn_percent }}%)
|
||||
when:
|
||||
- root_disk_percent_used is defined
|
||||
- root_disk_percent_used | int >= disk_usage_warn_percent | int
|
||||
56
playbooks/playbook_docker_cleanup.yml
Normal file
56
playbooks/playbook_docker_cleanup.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
# Czyszczenie nieużywanych obrazów Docker — tylko na hostach, na których Docker
|
||||
# jest faktycznie zainstalowany (pozostałe hosty są bezpiecznie pomijane).
|
||||
#
|
||||
# Domyślnie usuwa wyłącznie obrazy "dangling" (bez tagu) — bezpieczne, nie rusza
|
||||
# tagowanych obrazów, nawet jeśli akurat nie są używane przez żaden kontener.
|
||||
#
|
||||
# Aby usunąć WSZYSTKIE nieużywane obrazy (także tagowane, nieużywane przez żaden
|
||||
# kontener) — więcej odzyskanego miejsca, ale bardziej agresywne — uruchom z:
|
||||
# -e "docker_prune_all_images=true"
|
||||
- name: Czyszczenie nieużywanych obrazów Docker
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
vars:
|
||||
docker_prune_all_images: false
|
||||
|
||||
tasks:
|
||||
- name: Sprawdź, czy docker jest zainstalowany
|
||||
ansible.builtin.command: which docker
|
||||
register: docker_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Pomiń — Docker nie jest zainstalowany na tym hoście
|
||||
ansible.builtin.debug:
|
||||
msg: "Docker nie jest zainstalowany na {{ inventory_hostname }} — pomijam."
|
||||
when: docker_check.rc != 0
|
||||
|
||||
- name: Zajętość miejsca przez Dockera przed czyszczeniem
|
||||
ansible.builtin.command: docker system df
|
||||
register: docker_df_before
|
||||
changed_when: false
|
||||
when: docker_check.rc == 0
|
||||
|
||||
- name: Usuń nieużywane obrazy Docker (dangling)
|
||||
ansible.builtin.command: docker image prune -f
|
||||
register: prune_result
|
||||
changed_when: "'Total reclaimed space: 0B' not in prune_result.stdout"
|
||||
when:
|
||||
- docker_check.rc == 0
|
||||
- not docker_prune_all_images
|
||||
|
||||
- name: Usuń WSZYSTKIE nieużywane obrazy Docker (także tagowane)
|
||||
ansible.builtin.command: docker image prune -a -f
|
||||
register: prune_result_all
|
||||
changed_when: "'Total reclaimed space: 0B' not in prune_result_all.stdout"
|
||||
when:
|
||||
- docker_check.rc == 0
|
||||
- docker_prune_all_images
|
||||
|
||||
- name: Wynik czyszczenia obrazów
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{ (prune_result_all if docker_prune_all_images else prune_result).stdout_lines
|
||||
| default(['brak danych']) }}
|
||||
when: docker_check.rc == 0
|
||||
66
playbooks/playbook_fleet_report.yml
Normal file
66
playbooks/playbook_fleet_report.yml
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
# Raport stanu floty (tylko odczyt, bez żadnych zmian na hostach):
|
||||
# OS/wersja, uptime, zajętość dysku, liczba oczekujących aktualizacji
|
||||
# oraz flaga reboot-required (decyzję o restarcie podejmuje operator ręcznie).
|
||||
#
|
||||
# WAŻNE: druga faza (renderowanie raportu) działa na hosts: localhost — jeśli
|
||||
# używasz --limit, dopisz do niego ",localhost", inaczej ta faza zostanie pominięta,
|
||||
# np.: --limit "Update-now,localhost"
|
||||
- name: Zbierz stan floty
|
||||
hosts: all
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
- name: Sprawdź czy wymagany jest restart (reboot-required)
|
||||
ansible.builtin.stat:
|
||||
path: /var/run/reboot-required
|
||||
register: reboot_required_stat
|
||||
|
||||
- name: Policz pakiety oczekujące na aktualizację
|
||||
ansible.builtin.command: apt list --upgradable
|
||||
register: upgradable_raw
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: ansible_os_family in ["Debian", "Ubuntu"]
|
||||
|
||||
- name: Sprawdź zajętość dysku na partycji root
|
||||
ansible.builtin.set_fact:
|
||||
root_disk_percent_used: >-
|
||||
{{ (( (mount.size_total - mount.size_available) / mount.size_total * 100) | round(0, 'ceil')) | int }}
|
||||
vars:
|
||||
mount: "{{ ansible_mounts | selectattr('mount', 'equalto', '/') | first }}"
|
||||
when: ansible_mounts | selectattr('mount', 'equalto', '/') | list | length > 0
|
||||
|
||||
- name: Zbuduj podsumowanie hosta
|
||||
ansible.builtin.set_fact:
|
||||
host_report:
|
||||
os: "{{ ansible_distribution }} {{ ansible_distribution_version }}"
|
||||
uptime_days: "{{ (ansible_uptime_seconds / 86400) | round(1) }}"
|
||||
disk_root_percent: "{{ root_disk_percent_used | default('n/a') }}"
|
||||
upgradable_packages: >-
|
||||
{{ (upgradable_raw.stdout_lines | default([]) | length - 1)
|
||||
if (upgradable_raw is defined and upgradable_raw.stdout_lines is defined and upgradable_raw.stdout_lines | length > 0)
|
||||
else 0 }}
|
||||
reboot_required: "{{ reboot_required_stat.stat.exists }}"
|
||||
|
||||
- name: Wygeneruj raport floty
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
- name: Upewnij się, że katalog reports/ istnieje
|
||||
ansible.builtin.file:
|
||||
path: "{{ playbook_dir }}/../reports"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Renderuj raport floty
|
||||
ansible.builtin.template:
|
||||
src: "{{ playbook_dir }}/../templates/fleet_report.j2"
|
||||
dest: "{{ playbook_dir }}/../reports/fleet_report_{{ ansible_date_time.iso8601_basic_short }}.txt"
|
||||
mode: "0644"
|
||||
|
||||
- name: Ścieżka wygenerowanego raportu
|
||||
ansible.builtin.debug:
|
||||
msg: "Raport zapisany w reports/fleet_report_{{ ansible_date_time.iso8601_basic_short }}.txt"
|
||||
64
playbooks/playbook_security_baseline.yml
Normal file
64
playbooks/playbook_security_baseline.yml
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
# Baza bezpieczeństwa: unattended-upgrades (tylko aktualizacje bezpieczeństwa,
|
||||
# bez automatycznego restartu — patrz playbook_fleet_report.yml dla flagi reboot-required)
|
||||
# oraz wyłączenie logowania hasłem po SSH.
|
||||
- name: Baza bezpieczeństwa (unattended-upgrades + wyłączenie logowania hasłem)
|
||||
hosts: all
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
- name: Zainstaluj unattended-upgrades (Debian/Ubuntu)
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- unattended-upgrades
|
||||
- apt-listchanges
|
||||
state: present
|
||||
update_cache: yes
|
||||
cache_valid_time: 3600
|
||||
when: ansible_os_family in ["Debian", "Ubuntu"]
|
||||
|
||||
- name: Skonfiguruj unattended-upgrades (tylko aktualizacje bezpieczeństwa, bez auto-reboot)
|
||||
ansible.builtin.template:
|
||||
src: ../templates/50unattended-upgrades.j2
|
||||
dest: /etc/apt/apt.conf.d/50unattended-upgrades
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
when: ansible_os_family in ["Debian", "Ubuntu"]
|
||||
|
||||
- name: Włącz okresowe aktualizacje APT (20auto-upgrades)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
when: ansible_os_family in ["Debian", "Ubuntu"]
|
||||
|
||||
- name: Wyłącz logowanie hasłem (PasswordAuthentication no)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '(?i)^\s*#?\s*PasswordAuthentication'
|
||||
line: 'PasswordAuthentication no'
|
||||
state: present
|
||||
backup: yes
|
||||
validate: '/usr/sbin/sshd -t -f %s'
|
||||
notify: Restart SSH
|
||||
|
||||
- name: Ogranicz logowanie root do klucza (PermitRootLogin prohibit-password)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '(?i)^\s*#?\s*PermitRootLogin'
|
||||
line: 'PermitRootLogin prohibit-password'
|
||||
state: present
|
||||
backup: yes
|
||||
validate: '/usr/sbin/sshd -t -f %s'
|
||||
notify: Restart SSH
|
||||
|
||||
handlers:
|
||||
- name: Restart SSH
|
||||
ansible.builtin.service:
|
||||
name: ssh
|
||||
state: restarted
|
||||
23
playbooks/playbook_ssh.yml
Normal file
23
playbooks/playbook_ssh.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
- name: Konfiguracja SSH (blokada pustych haseł)
|
||||
hosts: all
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
- name: Zablokuj logowanie na puste hasła (PermitEmptyPasswords no)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
# Szuka linii zaczynającej się od PermitEmptyPasswords (również zakomentowanej)
|
||||
regexp: '(?i)^\s*#?\s*PermitEmptyPasswords'
|
||||
line: 'PermitEmptyPasswords no'
|
||||
state: present
|
||||
backup: yes
|
||||
# Sprawdza poprawność pliku przed zapisem, aby nie zepsuć SSH
|
||||
validate: '/usr/sbin/sshd -t -f %s'
|
||||
notify: Restart SSH
|
||||
|
||||
handlers:
|
||||
- name: Restart SSH
|
||||
ansible.builtin.service:
|
||||
name: ssh
|
||||
state: restarted
|
||||
32
playbooks/playbook_ssh_keys.yml
Normal file
32
playbooks/playbook_ssh_keys.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
# Zarządzanie kluczami publicznymi SSH konta logowania (root lub mgmt, w zależności
|
||||
# od grupy PatchMon hosta) na całej flocie jednym uruchomieniem.
|
||||
#
|
||||
# Lista kluczy: admin_ssh_keys w group_vars/all.yml (uzupełnij przed użyciem).
|
||||
#
|
||||
# Domyślnie tylko DODAJE brakujące klucze (bezpieczne). Aby wymusić, żeby
|
||||
# authorized_keys zawierał WYŁĄCZNIE klucze z admin_ssh_keys (usuwając inne),
|
||||
# uruchom z: -e "ssh_keys_exclusive=true" — rób to świadomie, może odciąć dostęp.
|
||||
- name: Zarządzanie kluczami SSH konta logowania
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
vars:
|
||||
ssh_keys_exclusive: false
|
||||
|
||||
tasks:
|
||||
- name: Sprawdź, czy admin_ssh_keys nie jest puste
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- admin_ssh_keys | length > 0
|
||||
fail_msg: >-
|
||||
admin_ssh_keys jest puste — uzupełnij listę kluczy w group_vars/all.yml
|
||||
przed uruchomieniem tego playbooka.
|
||||
run_once: true
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Zapewnij obecność kluczy publicznych w authorized_keys
|
||||
ansible.posix.authorized_key:
|
||||
user: "{{ ansible_user }}"
|
||||
key: "{{ admin_ssh_keys | join('\n') }}"
|
||||
state: present
|
||||
exclusive: "{{ ssh_keys_exclusive }}"
|
||||
16
playbooks/playbook_upgrade.yml
Normal file
16
playbooks/playbook_upgrade.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: Aktualizacja pakietów (Debian/Ubuntu)
|
||||
hosts: all
|
||||
gather_facts: true
|
||||
tasks:
|
||||
- name: Aktualizacja cache pakietów (Debian/Ubuntu)
|
||||
ansible.builtin.apt:
|
||||
update_cache: yes
|
||||
cache_valid_time: 3600
|
||||
when: ansible_os_family in ["Debian", "Ubuntu"]
|
||||
|
||||
- name: Aktualizacja wszystkich pakietów (Debian/Ubuntu)
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
when: ansible_os_family in ["Debian", "Ubuntu"]
|
||||
|
||||
Reference in New Issue
Block a user