Files
ansible/readme.md
2026-07-12 08:44:40 +02:00

140 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ansible + PatchMon — zarządzanie flotą serwerów
Inwentarz jest pobierany dynamicznie z PatchMon (`patchmon_inventory.yml`, plugin
`patchmon.dynamic_inventory`). Grupy hostów pochodzą wprost z grup przypisanych
w PatchMon — filtrowanie na potrzeby playbooków (`--limit`) odbywa się przez te grupy,
nie przez ręczne listy hostów.
## Pierwsze uruchomienie (świeży klon repozytorium)
Sekrety nie są trzymane w gicie — trzeba je uzupełnić lokalnie:
```bash
cp patchmon_inventory.yml.example patchmon_inventory.yml
# uzupełnij api_url / api_key / api_secret w patchmon_inventory.yml
mkdir -p ssh_keys && chmod 700 ssh_keys
cp /ścieżka/do/twojego/klucza ssh_keys/id_rsa && chmod 600 ssh_keys/id_rsa
```
## Grupy PatchMon używane w tym projekcie
| Grupa | Znaczenie |
|---|---|
| `root` | Hosty logowane bezpośrednio na konto `root`. |
| `mgmt` | Hosty logowane na konto `mgmt` (z `sudo`). |
| `Update-now` | Wszystkie hosty dopuszczone do automatycznej aktualizacji (`root` `mgmt`). Domyślny cel dla crona/autopilota. |
| `Type-HOST` | Fizyczne hosty Proxmox — traktuj ostrożniej (restart hosta restartuje też jego VM/CT). |
| `Type-VM` / `Type-CT` | Maszyny wirtualne / kontenery LXC. |
| `Site-nni` / `Site-on` | Lokalizacje. |
Konto logowania (`ansible_user`) **nie** jest już podawane ręcznie przez `-e` — jest
ustawiane automatycznie przez `group_vars/root.yml` i `group_vars/mgmt.yml` na
podstawie grupy PatchMon danego hosta. Dzięki temu jedno uruchomienie playbooka na
grupie mieszanej (np. `Update-now`) obsłuży poprawnie oba typy kont.
## Struktura projektu
```
ssh_keys/
id_rsa # klucz prywatny SSH (poza gitem, patrz sekcja "Sekrety")
group_vars/
all.yml # klucz SSH, become, próg dysku, lista kluczy admina
root.yml / mgmt.yml # ansible_user per grupa PatchMon
playbooks/
playbook_upgrade.yml # apt update + dist-upgrade
playbook_cleanup.yml # autoremove/autoclean, czyszczenie journala, alarm dysku
playbook_docker_cleanup.yml # czyszczenie nieużywanych obrazów Docker (tylko hosty z Dockerem)
playbook_fleet_report.yml # raport: OS, uptime, dysk, liczba aktualizacji, reboot-required
playbook_security_baseline.yml # unattended-upgrades + wyłączenie logowania hasłem SSH
playbook_ssh.yml # blokada pustych haseł SSH
playbook_ssh_keys.yml # zarządzanie kluczami publicznymi na koncie logowania
playbook_autopilot.yml # orkiestracja pod cron: upgrade -> cleanup -> fleet_report
templates/
50unattended-upgrades.j2
fleet_report.j2
cron/
run-autopilot.sh # wrapper do crona (flock + log)
crontab.example
ansible-autopilot.logrotate
reports/ # tu trafiają wygenerowane raporty floty
```
## Użycie
```bash
# Aktualizacja pakietów na całej flocie dopuszczonej do auto-update
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_upgrade.yml --limit "Update-now"
# Sprzątanie/kondycja systemu (autoremove, journal, alarm zajętości dysku)
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_cleanup.yml --limit "Update-now"
# Czyszczenie nieużywanych obrazów Docker (tylko hosty, na których jest Docker)
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_docker_cleanup.yml --limit "Update-now"
# Raport stanu floty -> plik w reports/
# WAŻNE: dopisz ",localhost" do --limit, inaczej faza renderowania raportu
# zostanie pominięta ("skipping: no hosts matched").
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_fleet_report.yml --limit "Update-now,localhost"
# Baza bezpieczeństwa: unattended-upgrades + wyłączenie logowania hasłem SSH
# (dotyka sshd_config — uruchamiaj świadomie, ręcznie, nie z crona)
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_security_baseline.yml --limit "Update-now"
# Blokada logowania na puste hasła
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_ssh.yml --limit "Update-now"
# Zarządzanie kluczami SSH konta logowania (uzupełnij admin_ssh_keys w group_vars/all.yml)
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_ssh_keys.yml --limit "Update-now"
# Pełny przebieg autopilot ręcznie (to samo co robi cron)
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_autopilot.yml --limit "Update-now,localhost"
```
Można też celować w węższe grupy, np. `--limit "Site-on"`, `--limit "Type-CT"`,
albo pojedynczy host: `--limit "pve"`.
## Reboot — tylko raportowanie, nigdy automatycznie
`playbook_fleet_report.yml` sprawdza `/var/run/reboot-required` na każdym hoście
i wypisuje listę hostów wymagających restartu w raporcie (`reports/fleet_report_*.txt`).
**Żaden playbook w tym projekcie nie restartuje hostów automatycznie** — decyzję
i moment restartu (szczególnie dla `Type-HOST`, czyli fizycznego Proxmoksa) podejmuje
operator ręcznie, po przejrzeniu raportu.
## Bezobsługowe uruchamianie (cron)
`cron/run-autopilot.sh` to wrapper na `playbook_autopilot.yml`:
- blokuje się przez `flock`, żeby nie nakładały się dwa równoległe przebiegi,
- loguje przebieg (start/koniec/kod wyjścia) do `/var/log/ansible-autopilot.log`,
- domyślnie celuje w grupę `Update-now` (nadpisywalne zmienną `TARGET_GROUP`).
Instalacja:
```bash
chmod +x cron/run-autopilot.sh
crontab -e # wklej zawartość cron/crontab.example
sudo cp cron/ansible-autopilot.logrotate /etc/logrotate.d/ansible-autopilot
```
Każdy przebieg `playbook_fleet_report.yml` (w tym z crona) dokłada nowy plik do
`reports/` — warto od czasu do czasu posprzątać stare raporty, np.
`find reports/ -name 'fleet_report_*.txt' -mtime +30 -delete`.
## Sekrety
- **Klucz prywatny SSH** leży w `ssh_keys/id_rsa` (katalog `chmod 700`, plik `chmod 600`).
Katalog `ssh_keys/` jest w `.gitignore` — klucz nigdy nie trafia do repozytorium.
Ścieżka do niego jest ustawiona centralnie w `group_vars/all.yml`
(`ansible_ssh_private_key_file: "{{ playbook_dir }}/../ssh_keys/id_rsa"`), więc
wszystkie playbooki i `cron/run-autopilot.sh` korzystają z niej automatycznie —
nie trzeba nic dodatkowo konfigurować.
- **`api_key`/`api_secret`/`api_url` PatchMon** leżą w `patchmon_inventory.yml`, który
jest w `.gitignore` — nigdy nie trafia do repozytorium. Wersja do repo to
`patchmon_inventory.yml.example` (same placeholdery, bez sekretów). Przy zakładaniu
projektu od zera: `cp patchmon_inventory.yml.example patchmon_inventory.yml` i
uzupełnij `api_url`/`api_key`/`api_secret`.
(Plugin `patchmon.dynamic_inventory` wczytuje ten plik bezpośrednio, bez
templatowania Jinja2/Vault, dlatego to rozdzielenie na plik realny + `.example`,
a nie np. `{{ lookup('env', ...) }}`, jest tu jedynym niezawodnym sposobem.)