#!/usr/bin/env bash # Аудит нового выделенного сервера ДО того, как на него что-либо поставлено. # # Только чтение — ничего не меняет. Задача одна: собрать факты, по которым # принимается решение «работаем на этой установке» или «переставляем ОС». # # Главный вопрос — RAID. На AR32-NVMe два диска по 1 ТБ. Если они отданы # по отдельности или собраны в RAID0, смерть одного диска = потеря всего, # а память на этой платформе non-ECC. Переставить ОС можно только пока # сервер пустой, поэтому проверка идёт первой и до всего остального. # # Запуск: ssh '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'