gendesign/ops/selectel-audit.sh
bot-backend 6484116079
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
chore(ops): скрипты аудита и первичной настройки выделенного сервера Selectel
Сервер Poincare (SPB-4, 188.246.224.93) поднят 22.08.2026. Два скрипта под
переезд (#2989, #3027-#3032).

selectel-audit.sh — только чтение. Отвечает на вопрос, который надо закрыть
до установки чего бы то ни было: собраны ли диски в зеркало. Переставить ОС
можно только пока сервер пустой.

Результат первого прогона: RAID1 на всех трёх разделах ([2/2] [UU] на /boot,
swap и /), память non-ECC подтверждена (Error Correction Type: None),
910G свободно из 924G.

selectel-bootstrap.sh — идемпотентная настройка: пользователь с ключом,
ufw, Docker версий текущего прода (29.4.1 / v5.1.3), лимит журналов
контейнеров, sysctl, unattended-upgrades, fail2ban, ужесточение sshd.

Порядок шагов выбран так, чтобы не потерять доступ: правило для SSH
добавляется ДО включения файрвола, а sshd в конце намеренно НЕ
перезапускается — сначала проверяется вход по ключу в отдельном окне.
При выключенном PasswordAuthentication ошибка означала бы IP-KVM за 1320 руб.

Два умолчания выставлены по факту, а не по привычке:

- часовой пояс Europe/Moscow, а не UTC — оба хоста сейчас на MSK, и смена
  пояса сдвинула бы все шесть cron-задач (бэкапы, геокодинг) на три часа;
- swap не создаётся, если он уже есть — установщик Selectel отдаёт раздел
  4.7G в зеркале, добавлять файл поверх незачем при 62G памяти.

.gitattributes: *.sh с LF — иначе скрипт, отредактированный под Windows,
падает на удалённом хосте с `$'\r': command not found`.
2026-08-22 12:49:09 +03:00

84 lines
4.1 KiB
Bash
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.

#!/usr/bin/env bash
# Аудит нового выделенного сервера ДО того, как на него что-либо поставлено.
#
# Только чтение — ничего не меняет. Задача одна: собрать факты, по которым
# принимается решение «работаем на этой установке» или «переставляем ОС».
#
# Главный вопрос — RAID. На AR32-NVMe два диска по 1 ТБ. Если они отданы
# по отдельности или собраны в RAID0, смерть одного диска = потеря всего,
# а память на этой платформе non-ECC. Переставить ОС можно только пока
# сервер пустой, поэтому проверка идёт первой и до всего остального.
#
# Запуск: ssh <host> 'bash -s' < ops/selectel-audit.sh
set -uo pipefail
section() { printf '\n=== %s ===\n' "$1"; }
section "Идентификация"
. /etc/os-release 2>/dev/null && echo "OS: ${PRETTY_NAME:-unknown}"
echo "Kernel: $(uname -r)"
echo "Hostname: $(hostname)"
echo "Uptime: $(uptime -p 2>/dev/null || true)"
section "CPU / память"
lscpu 2>/dev/null | grep -E '^(Model name|CPU\(s\)|Thread|Core|Socket|CPU max MHz)' || nproc
free -h | head -2
echo "--- ECC (пусто = не-ECC либо недоступно из ОС) ---"
dmidecode -t memory 2>/dev/null | grep -iE 'error correction|^\s+Type:' | sort -u | head -5 \
|| echo "dmidecode недоступен (нужен root)"
section "ДИСКИ — ключевой вопрос"
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,MODEL
echo "--- программный RAID ---"
if [ -f /proc/mdstat ]; then cat /proc/mdstat; else echo "/proc/mdstat отсутствует"; fi
echo "--- аппаратный RAID / NVMe ---"
lspci 2>/dev/null | grep -iE 'raid|nvme' || echo "контроллеров RAID не видно"
nvme list 2>/dev/null || echo "nvme-cli не установлен"
echo "--- LVM ---"
pvs 2>/dev/null; vgs 2>/dev/null; lvs 2>/dev/null
echo "--- монтирование ---"
df -hT -x tmpfs -x devtmpfs
echo
echo ">>> ВЕРДИКТ ПО ДИСКАМ читать так:"
echo ">>> raid1 / mirror в mdstat → зеркало есть, можно работать"
echo ">>> raid0 / linear / дисков нет → зеркала НЕТ, переставить ОС до установки чего-либо"
echo ">>> один диск в df, второй пуст → второй не используется, решить как задействовать"
section "Сеть"
ip -brief addr show | grep -v '^lo'
ip route | head -5
echo "--- DNS ---"
grep -E '^nameserver' /etc/resolv.conf 2>/dev/null | head -3
section "Что уже слушает"
ss -tulpn 2>/dev/null | grep LISTEN || netstat -tulpn 2>/dev/null | grep LISTEN
section "Безопасность — текущее состояние"
echo "--- sshd (значимые директивы) ---"
sshd -T 2>/dev/null | grep -E '^(permitrootlogin|passwordauthentication|pubkeyauthentication|port|permitemptypasswords)' \
|| grep -E '^\s*(PermitRootLogin|PasswordAuthentication|Port)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* 2>/dev/null
echo "--- файрвол ---"
ufw status 2>/dev/null || echo "ufw не установлен"
nft list ruleset 2>/dev/null | head -20 || iptables -S 2>/dev/null | head -20
echo "--- пользователи с shell ---"
awk -F: '$7 !~ /(nologin|false)$/ {print $1" "$7}' /etc/passwd
section "Swap / sysctl"
swapon --show || echo "swap отсутствует"
sysctl vm.swappiness vm.overcommit_memory 2>/dev/null
section "Уже установленное ПО"
for b in docker containerd git curl ufw fail2ban-server unattended-upgrade; do
if command -v "$b" >/dev/null 2>&1; then
printf '%-22s %s\n' "$b" "$($b --version 2>/dev/null | head -1)"
else
printf '%-22s %s\n' "$b" "НЕ установлен"
fi
done
section "Время"
timedatectl 2>/dev/null | head -5 || date
printf '\n=== Аудит закончен ===\n'