Files
safe-monthly-maintenance/README.md
2026-07-31 12:40:04 +03:00

299 lines
11 KiB
Markdown
Raw 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.

# Safe Monthly Maintenance
Безопасное ежемесячное обслуживание Ubuntu/Debian одной командой.
Скрипт устанавливает systemd timer, обновляет пакеты без `dist-upgrade`, чистит
безопасные кэши и журналы, проверяет состояние `dpkg`, свободное место и
необходимость перезагрузки. Автоматическая перезагрузка, `autoremove` и очистка
Docker выключены по умолчанию.
> Проверено на Debian 12. Скрипт рассчитан на Ubuntu и Debian с systemd и APT.
> Перед массовым развертыванием проверьте его на одной тестовой VM.
## Установка одной командой
Закрепленная версия:
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh | sudo bash -s -- --run-now
```
Команда:
1. скачивает `install.sh`;
2. устанавливает maintenance-скрипт и systemd units;
3. включает ежемесячный timer;
4. сразу выполняет первое обслуживание.
Установка без немедленного запуска:
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh | sudo bash
```
Если `curl` отсутствует:
```bash
wget -qO- https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh | sudo bash -s -- --run-now
```
## Более безопасная установка с проверкой
Не запускайте неизвестный код от `root` вслепую. Скачайте, проверьте, затем
выполните:
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh -o /tmp/install-safe-maintenance.sh
sha256sum /tmp/install-safe-maintenance.sh
less /tmp/install-safe-maintenance.sh
sudo bash /tmp/install-safe-maintenance.sh --run-now
```
SHA-256 версии `v1.0.2`:
```text
247312aaca5eb5b40c8893edb065203b2e4f0121c47421d85b46f9ae46770367
```
## Что устанавливается
| Путь | Назначение |
|---|---|
| `/usr/local/sbin/safe-monthly-maintenance` | Основной maintenance-скрипт |
| `/etc/default/safe-monthly-maintenance` | Настройки конкретной VM |
| `/etc/systemd/system/safe-monthly-maintenance.service` | Одноразовый systemd service |
| `/etc/systemd/system/safe-monthly-maintenance.timer` | Ежемесячный запуск |
| `/var/backups/safe-monthly-maintenance/` | Снимки списка пакетов |
Повторный запуск installer обновляет скрипт и units, но сохраняет существующий
файл настроек.
## Расписание
Timer запускается первого числа каждого месяца в 03:00 с случайной задержкой до
шести часов:
```ini
OnCalendar=*-*-01 03:00:00
RandomizedDelaySec=6h
Persistent=true
```
Случайная задержка уменьшает одновременную нагрузку на репозитории, если один
installer установлен на много VM. `Persistent=true` выполняет пропущенный запуск
после включения сервера.
## Что делает обслуживание
### 1. Проверяет окружение
- требует права `root`;
- разрешает только Ubuntu/Debian и Debian-подобные системы;
- использует `flock`, поэтому два запуска не идут одновременно;
- использует ожидание APT-lock до 600 секунд;
- повторяет сетевые обращения APT до трех раз.
### 2. Сохраняет список пакетов
Перед обновлением выполняется:
```bash
dpkg --get-selections
```
Снимок записывается в `/var/backups/safe-monthly-maintenance/`. Снимки старше
120 дней удаляются. Это не полный rollback системы, но помогает восстановить
состав пакетов.
### 3. Чистит только безопасные данные
- `systemd-tmpfiles --clean` — применяет штатные политики очистки временных
файлов;
- `logrotate` — запускает штатную ротацию логов;
- `journalctl --vacuum-time=30d` — удаляет старый journal;
- `journalctl --vacuum-size=500M` — ограничивает размер journal;
- `apt-get autoclean` — удаляет устаревшие package-файлы;
- `apt-get clean` — очищает скачанный APT-кэш после обновления.
Скрипт не выполняет ручной `rm -rf` для `/tmp`, `/var/log`, Docker volumes или
пользовательских каталогов.
### 4. Проверяет пакетную систему
`dpkg --audit` запускается до обновления. Если пакетная операция была прервана,
обновление пропускается. Скрипт не пытается автоматически ремонтировать
неоднозначное состояние.
После обновления выполняется:
```bash
apt-get check
```
### 5. Проверяет свободное место
Обновление пропускается, если:
- на `/` осталось меньше 1 ГиБ;
- на отдельном `/boot` осталось меньше 200 МиБ.
Порог можно изменить в конфигурации.
### 6. Обновляет пакеты
Используется:
```bash
apt-get -y \
-o Dpkg::Options::=--force-confold \
--with-new-pkgs \
--no-remove \
upgrade
```
Почему:
- `upgrade`, не `dist-upgrade`/`full-upgrade`: пакеты не удаляются;
- `--with-new-pkgs`: разрешает новые зависимости, включая новое ядро;
- `--no-remove`: аварийно останавливает операцию, если APT захочет удалить
пакет;
- `--force-confold`: сохраняет локальные конфиги вместо тихой замены;
- `NEEDRESTART_MODE=l`: показывает сервисы со старыми библиотеками, но не
перезапускает все сервисы автоматически.
Пакетные maintainer scripts все равно могут перезапустить собственный сервис.
Абсолютно гарантировать отсутствие краткого service interruption при системном
обновлении невозможно.
### 7. Не удаляет зависимости автоматически
По умолчанию выполняется только dry-run:
```bash
apt-get --dry-run autoremove
```
Кандидаты попадают в журнал. Реальный `autoremove` включается только вручную
через конфигурацию.
### 8. Не перезагружает сервер
Скрипт проверяет `/var/run/reboot-required` и сравнивает текущее ядро с
`/vmlinuz`. При необходимости пишет:
```text
REBOOT REQUIRED. Automatic reboot disabled.
```
Решение о reboot остается у администратора.
### 9. Показывает итог
В конце журнал содержит:
- failed systemd units;
- использование диска;
- необходимость reboot;
- успешные и неуспешные этапы.
## Настройка
Файл:
```bash
sudo nano /etc/default/safe-monthly-maintenance
```
Параметры:
| Параметр | По умолчанию | Значение |
|---|---:|---|
| `ENABLE_AUTOREMOVE` | `0` | `1` разрешает `apt-get autoremove --purge` |
| `ENABLE_DOCKER_PRUNE` | `0` | `1` удаляет только dangling Docker images |
| `JOURNAL_MAX_AGE` | `30d` | Максимальный возраст systemd journal |
| `JOURNAL_MAX_SIZE` | `500M` | Максимальный размер journal |
| `MIN_ROOT_FREE_KB` | `1048576` | Минимум свободного места на `/` |
| `MIN_BOOT_FREE_KB` | `204800` | Минимум на отдельном `/boot` |
Для серверов с важными stopped-контейнерами и локальными Docker-образами
оставляйте `ENABLE_DOCKER_PRUNE=0`.
## Управление
Следующий запуск:
```bash
systemctl list-timers safe-monthly-maintenance.timer --all
```
Запустить вручную:
```bash
sudo systemctl start safe-monthly-maintenance.service
```
Последний статус:
```bash
systemctl status safe-monthly-maintenance.service
```
Логи:
```bash
journalctl -u safe-monthly-maintenance.service
```
Логи текущего запуска:
```bash
journalctl -u safe-monthly-maintenance.service --since today
```
Отключить автоматический запуск:
```bash
sudo systemctl disable --now safe-monthly-maintenance.timer
```
Удалить:
```bash
sudo systemctl disable --now safe-monthly-maintenance.timer
sudo rm -f /etc/systemd/system/safe-monthly-maintenance.timer
sudo rm -f /etc/systemd/system/safe-monthly-maintenance.service
sudo rm -f /usr/local/sbin/safe-monthly-maintenance
sudo systemctl daemon-reload
```
Конфигурация и package snapshots при удалении сохраняются намеренно.
## Массовое развертывание
Пример с локальным списком серверов:
```bash
for host in vm1.example.com vm2.example.com vm3.example.com; do
ssh "$host" \
'curl -fsSL https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh | sudo bash -s -- --run-now'
done
```
Сначала используйте одну тестовую VM. Для большой инфраструктуры лучше Ansible,
Salt или другой configuration-management инструмент.
## Ограничения
- Скрипт не делает filesystem/provider snapshot.
- Скрипт не исправляет сломанный `dpkg` автоматически.
- Скрипт не обновляет Ubuntu/Debian между major releases.
- Скрипт не управляет сторонними package managers.
- Скрипт не гарантирует отсутствие service restart от maintainer scripts.
- Скрипт не заменяет мониторинг, резервные копии и тестирование обновлений.
Подробная модель безопасности: [docs/SAFETY.md](docs/SAFETY.md).
## Лицензия
[MIT](LICENSE)