Ви просили — я зробила! Тут з нуля налаштуємо щотижневі оповіщення про доступні оновлення та критичні вразливості (CVE) у Debian/Ubuntu. Використаємо apt команди, компактні bash скрипти та надійні cron та systemd timers. І все це — акуратно, без зайвої магії 🛡️

Що ми отримаємо

Щотижня сервер або робоча станція надсилатиме короткий звіт на email: скільки пакетів оновлюється, чи є безпекові оновлення та чи знайдені critical/high уразливості. Основні цілі:

  • Автоматичний збір інформації через APT про оновлення Linux;
  • Скан критичних CVE (через debsecan);
  • Надсилання результату поштою або логування на випадок, якщо пошта не налаштована;
  • Запуск раз на тиждень через systemd timer.

Основний How‑to: bash-скрипт + systemd service/timer

1) Встановіть залежності

Пакет mailutils дасть команду mail для надсилання листів, а debsecan підкаже про відомі CVE для встановлених пакетів.

sudo apt update
sudo apt install -y mailutils debsecan

2) Створіть скрипт /usr/local/bin/weekly-apt-alert.sh

Скрипт оновлює індекси APT, рахує upgradable пакети, виділяє security-оновлення та, якщо доступний debsecan, збирає критичні/високі CVE. Потім надсилає звіт на email.

sudo tee /usr/local/bin/weekly-apt-alert.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
umask 027

ALERT_EMAIL="root"        # Змініть на вашу адресу, напр. ops@example.com
HOST="$(hostname -f || hostname)"
MAIL_BIN="$(command -v mail || command -v mailx || command -v s-nail || true)"
DEBSECAN="$(command -v debsecan || true)"
LOG_FILE="/var/log/weekly-apt-alert.log"

# Оновлюємо індекси APT (тихо)
apt-get update -qq || apt update -qq || true

# Список оновлень
UPGR_LIST="$(apt list --upgradable 2>/dev/null | tail -n +2 || true)"
UPGR_COUNT=$(printf "%s\n" "$UPGR_LIST" | sed '/^$/d' | wc -l | tr -d ' ')

# Безпекові оновлення (репозиторій *security*)
SEC_LIST=$(printf "%s\n" "$UPGR_LIST" | grep -i security || true)
SEC_COUNT=$(printf "%s\n" "$SEC_LIST" | sed '/^$/d' | wc -l | tr -d ' ')

# Критичні/високі CVE (якщо є debsecan)
CVE_SECTION=""
CVE_COUNT=0
if [[ -n "$DEBSECAN" ]]; then
  # Показуємо лише виправлені уразливості для встановлених пакетів
  CVE_RAW="$($DEBSECAN --only-fixed --severity critical,high --format detail 2>/dev/null || true)"
  CVE_COUNT=$(printf "%s\n" "$CVE_RAW" | grep -E '^CVE-' | wc -l | tr -d ' ')
  if [[ $CVE_COUNT -gt 0 ]]; then
    CVE_SECTION=$(printf "\nTop critical/high CVE (перші 20):\n%s\n" "$(printf "%s\n" "$CVE_RAW" | head -n 200)")
  else
    CVE_SECTION="\nКритичних/високих CVE не виявлено."
  fi
else
  CVE_SECTION="\ndebsecan не встановлено — пропущено перевірку CVE (apt install debsecan)."
fi

NOW="$(date -Is)"
REPORT=$(cat <<RPT
[Weekly APT/Security report]
Host: $HOST
Time: $NOW

Оновлень доступно: $UPGR_COUNT
З них безпекових (*security*): $SEC_COUNT
Критичних/високих CVE: $CVE_COUNT

Оновлення (перші 30):
$(printf "%s\n" "$UPGR_LIST" | head -n 30)

Безпекові оновлення (перші 30):
$(printf "%s\n" "$SEC_LIST" | head -n 30)

=== CVE ===
$CVE_SECTION
RPT
)

# Надсилання звіту
if [[ -n "$MAIL_BIN" ]]; then
  printf "%s\n" "$REPORT" | "$MAIL_BIN" -s "[$HOST] Weekly APT & Security report" "$ALERT_EMAIL" || true
else
  echo "$NOW [WARN] Mailer not found, writing to $LOG_FILE" | tee -a "$LOG_FILE" 1>/dev/null
fi

# Дублюємо у системний журнал і файл логів
logger -t weekly-apt-alert -- "$HOST: updates=$UPGR_COUNT security=$SEC_COUNT cve=$CVE_COUNT"
{
  echo "==== $NOW ===="
  echo "$REPORT"
} >> "$LOG_FILE"

echo "Done"
EOF
sudo chmod 750 /usr/local/bin/weekly-apt-alert.sh
sudo chown root:root /usr/local/bin/weekly-apt-alert.sh

3) Створіть systemd service і timer

Сервіс запускає скрипт один раз, а таймер — за розкладом щонеділі о 08:00 з випадковою затримкою до години (щоб тисячі машин не писали одночасно).

# Service
sudo tee /etc/systemd/system/weekly-apt-alert.service >/dev/null <<'EOF'
[Unit]
Description=Weekly APT updates & CVE email alert
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
# Захист від одночасних запусків
ExecStart=/usr/bin/flock -n /run/weekly-apt-alert.lock /usr/local/bin/weekly-apt-alert.sh
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
PrivateTmp=yes
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
EOF

# Timer (щонеділі о 08:00)
sudo tee /etc/systemd/system/weekly-apt-alert.timer >/dev/null <<'EOF'
[Unit]
Description=Run weekly-apt-alert.service weekly

[Timer]
OnCalendar=Sun 08:00
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now weekly-apt-alert.timer

# Перша ручна перевірка
sudo systemctl start weekly-apt-alert.service
sudo systemctl status weekly-apt-alert.service --no-pager
journalctl -u weekly-apt-alert.service -n 100 --no-pager

Готово! Тепер у вас автоматичні щотижневі звіти про оновлення Linux і безпекові ризики.

Альтернативні способи

  • cron замість systemd: якщо дуже треба, додайте в root crontab: @weekly /usr/local/bin/weekly-apt-alert.sh. Але systemd timers надійніші (логування, залежності, Persistent=).
  • apticron: sudo apt install apticron — шле щоденні листи про оновлення. Можна зменшити частоту через systemd timer або cron.
  • unattended-upgrades: для автоматичної установки security-оновлень і (опційно) email-звітів. Добре поєднується з нашим звітом для подвійного контролю.

GUI-спосіб (робочий стіл)

Хочете просто нагадування на стільниці? Зробіть користувацький timer з нотифікацією notify-send

mkdir -p ~/.local/bin
tee ~/.local/bin/weekly-apt-notify.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
apt-get update -qq || true
UP=$(apt list --upgradable 2>/dev/null | tail -n +2 | wc -l | tr -d ' ')
notify-send "APT: доступні оновлення" "$UP пакет(ів) чекають на оновлення" -i software-update-available
EOF
chmod +x ~/.local/bin/weekly-apt-notify.sh

# user service
mkdir -p ~/.config/systemd/user
tee ~/.config/systemd/user/weekly-apt-notify.service >/dev/null <<'EOF'
[Unit]
Description=Weekly desktop APT notify

[Service]
Type=oneshot
ExecStart=%h/.local/bin/weekly-apt-notify.sh
EOF

tee ~/.config/systemd/user/weekly-apt-notify.timer >/dev/null <<'EOF'
[Unit]
Description=Run weekly-apt-notify.service weekly

[Timer]
OnCalendar=Sun 09:00
Persistent=true

[Install]
WantedBy=default.target
EOF

systemctl --user daemon-reload
systemctl --user enable --now weekly-apt-notify.timer

FAQ

Листи не приходять. Що робити?

Перевірте, чи є mail/mailx: command -v mail. Якщо ні — sudo apt install -y mailutils. На серверах без MTA налаштуйте postfix (режим Satellite/Smarthost) або легкий msmtp з SMTP вашого провайдера.

Як змінити адресу одержувача?

Відредагуйте змінну ALERT_EMAIL у скрипті та перезапустіть сервіс: sudo systemctl start weekly-apt-alert.service.

Як змінити час або день?

У файлі таймера змініть OnCalendar=Sun 08:00 на бажане, наприклад Mon *-*-* 07:30. Потім: sudo systemctl daemon-reload && sudo systemctl restart weekly-apt-alert.timer.

Звіт порожній, а оновлення точно є!

Команда apt list --upgradable іноді кешує старі дані — спробуйте вручну: sudo apt-get update і перевірте ще раз. Також гляньте journalctl -u weekly-apt-alert.service.

Чому не використали лише cron?

systemd timers краще логуються, підтримують Persistent= (пропущені старти при простої), а також обмеження ресурсів і sandboxing. Але cron — робоча альтернатива.

Чи коректний debsecan для Ubuntu?

Переважно так, але джерело CVE — Debian Security Tracker. Для Ubuntu інколи імена пакетів/версій відрізняються. Все одно це корисний сигнал. Хочете 100% для Ubuntu — додайте перевірку через ubuntu-security-status (пакет update-notifier-common), як альтернативу.

Можна додати автоінсталяцію security-оновлень?

Так. Встановіть unattended-upgrades і дозвольте security-покети. Наш звіт тоді радше підтверджуватиме стан.

Порада від Kernelka

Зробіть репетицію: одразу після налаштування запустіть сервіс вручну й переконайтеся, що лист дійшов. Ще класно додати у timer параметр RandomizedDelaySec= (ми вже додали) — це зменшує пікове навантаження на дзеркала APT і ваш SMTP 😊

Підсумок

  • Встановили інструменти для звітів і CVE: mailutils, debsecan.
  • Створили надійний bash-скрипт із логуванням та email-оповіщенням.
  • Налаштували systemd service + weekly timer з захистом від колізій.
  • Розглянули альтернативи: cron, apticron, unattended-upgrades, а також GUI-нагадування.
  • Тепер ви контролюєте оновлення Linux і критичні уразливості — спокійніше спиться!