Введите секретный ключ, полученный после оплаты.
Классическая первичная настройка сервера: создание sudo-пользователя, установка ключей, базовая защита SSH, UFW и Fail2Ban.
#!/bin/bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
SSHD_CONFIG_DROPIN="/etc/ssh/sshd_config.d/yokai-secure.conf"
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
PURPLE='\033[0;35m'
NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[УСПЕХ]${NC} $1"; }
warning() { echo -e "${YELLOW}[ВНИМАНИЕ]${NC} $1"; }
error() { echo -e "${RED}[ОШИБКА]${NC} $1"; exit 1; }
print_logo() {
echo -e "${PURPLE}> YOKAI TECH"
echo -e "${CYAN} > Первичная настройка и защита сервера < ${NC}"
echo ""
}
if [[ "${EUID}" -ne 0 ]]; then
error "Этот скрипт должен быть запущен с правами root. Используй sudo."
fi
print_logo
info "Я начинаю процесс базовой настройки и защиты сервера..."
echo ""
info "Для начала мне нужны некоторые данные."
read -r -p " Введи имя для нового sudo-пользователя: " NEW_USER
if [[ -z "$NEW_USER" ]]; then
error "Имя пользователя не может быть пустым."
fi
read -r -p " Введи публичный SSH-ключ (ssh-rsa / ssh-ed25519 ...) для пользователя $NEW_USER: " SSH_KEY
if [[ -z "$SSH_KEY" ]]; then
error "SSH-ключ обязателен для настройки безопасного входа."
fi
RANDOM_PORT=$((RANDOM % 49152 + 10000))
read -r -p " Введи новый порт для SSH [нажми Enter, чтобы использовать случайный $RANDOM_PORT]: " INPUT_PORT
SSH_PORT=${INPUT_PORT:-$RANDOM_PORT}
echo ""
success "Данные собраны. Приступаю к применению конфигураций."
echo ""
info "Обновляю списки пакетов и устанавливаю базовые утилиты (curl, htop, git, fail2ban)..."
apt-get update -yqq
apt-get upgrade -yqq
apt-get install -yqq curl htop git fail2ban ufw
success "Системные пакеты успешно обновлены и установлены."
info "Проверяю наличие пользователя $NEW_USER..."
if id "$NEW_USER" &>/dev/null; then
warning "Пользователь $NEW_USER уже существует. Пропускаю создание."
else
info "Создаю пользователя $NEW_USER и добавляю его в группу sudo..."
useradd -m -s /bin/bash "$NEW_USER"
usermod -aG sudo "$NEW_USER"
success "Пользователь $NEW_USER создан."
fi
USER_HOME=$(eval echo "~$NEW_USER")
SSH_DIR="$USER_HOME/.ssh"
AUTH_KEYS="$SSH_DIR/authorized_keys"
info "Настраиваю публичный ключ для $NEW_USER..."
mkdir -p "$SSH_DIR"
chmod 700 "$SSH_DIR"
if ! grep -q "$SSH_KEY" "$AUTH_KEYS" 2>/dev/null; then
echo "$SSH_KEY" >> "$AUTH_KEYS"
fi
chmod 600 "$AUTH_KEYS"
chown -R "$NEW_USER:$NEW_USER" "$SSH_DIR"
success "SSH-ключ успешно установлен."
info "Настраиваю параметры безопасности SSH-сервера..."
cat < "$SSHD_CONFIG_DROPIN"
Port $SSH_PORT
PermitRootLogin no
PasswordAuthentication no
UsePAM yes
X11Forwarding no
EOF
chmod 644 "$SSHD_CONFIG_DROPIN"
info "Перезапускаю службу SSH для применения настроек..."
if systemctl restart ssh; then
success "SSH перезапущен. Теперь он слушает порт $SSH_PORT."
else
error "Не удалось перезапустить службу SSH. Проверь логи."
fi
info "Настраиваю правила файрвола (UFW)..."
yes | ufw reset > /dev/null
ufw default deny incoming > /dev/null
ufw default allow outgoing > /dev/null
info "Открываю порты: $SSH_PORT (SSH), 80 (HTTP), 443 (HTTPS)..."
ufw allow "$SSH_PORT"/tcp > /dev/null
ufw allow 80/tcp > /dev/null
ufw allow 443/tcp > /dev/null
yes | ufw enable > /dev/null
success "Файрвол UFW активирован и настроен."
info "Запускаю и добавляю в автозагрузку Fail2Ban..."
systemctl enable --now fail2ban > /dev/null
success "Fail2Ban работает и защищает сервер от брутфорс-атак."
echo ""
success "Первичная настройка сервера (Bootstrap) успешно завершена!"
echo -e "${CYAN}[ВАЖНО]${NC} Подробности для следующего подключения:"
echo -e " Пользователь : ${GREEN}$NEW_USER${NC}"
echo -e " SSH Порт : ${GREEN}$SSH_PORT${NC}"
echo -e " Команда : ${YELLOW}ssh -p $SSH_PORT $NEW_USER@${NC}"
echo -e "${RED}Внимание:${NC} Не закрывай текущую сессию терминала, пока не проверишь подключение в новом окне!"
Продвинутая версия настройки: дополнительно включает установку Docker, включение TCP BBR, настройку Swap-файла и авто-обновлений.
#!/bin/bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
SSHD_CONFIG_DROPIN="/etc/ssh/sshd_config.d/yokai-secure.conf"
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
PURPLE='\033[0;35m'
NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[УСПЕХ]${NC} $1"; }
warning() { echo -e "${YELLOW}[ВНИМАНИЕ]${NC} $1"; }
error() { echo -e "${RED}[ОШИБКА]${NC} $1"; exit 1; }
print_logo() {
echo -e "${PURPLE}> YOKAI TECH"
echo -e "${CYAN} > Улучшенная первичная настройка и защита сервера"
echo -e "${PURPLE}> Отлично подойдет для слабых ВМ < ${NC}"
}
if [[ "${EUID}" -ne 0 ]]; then
error "Скрипт должен быть запущен с правами root. Используй sudo."
fi
print_logo
info "Начинаю сбор данных для настройки..."
read -r -p " Введи имя для нового sudo-пользователя: " NEW_USER
if [[ -z "$NEW_USER" ]]; then error "Имя пользователя не может быть пустым."; fi
read -r -p " Введи публичный SSH-ключ для пользователя $NEW_USER: " SSH_KEY
if [[ -z "$SSH_KEY" ]]; then error "SSH-ключ обязателен."; fi
RANDOM_PORT=$((RANDOM % 49152 + 10000))
read -r -p " Введи новый порт для SSH [Enter для случайного $RANDOM_PORT]: " INPUT_PORT
SSH_PORT=${INPUT_PORT:-$RANDOM_PORT}
echo ""
success "Данные собраны. Начинаю развертывание."
echo ""
info "Настраиваю часовой пояс (Europe/Moscow)..."
timedatectl set-timezone Europe/Moscow
systemctl enable --now systemd-timesyncd > /dev/null
success "Время синхронизировано."
info "Проверяю наличие Swap-файла..."
if grep -q "swap" /etc/fstab; then
warning "Swap уже настроен. Пропускаю."
else
info "Создаю Swap-файл на 2GB..."
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile > /dev/null
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
sysctl vm.swappiness=10 > /dev/null
echo 'vm.swappiness=10' >> /etc/sysctl.conf
success "Swap-файл создан и оптимизирован."
fi
info "Обновляю систему и устанавливаю curl, htop, git, fail2ban, ufw..."
apt-get update -yqq
apt-get upgrade -yqq
apt-get install -yqq curl htop git fail2ban ufw unattended-upgrades
success "Утилиты установлены."
info "Настраиваю пользователя $NEW_USER..."
if id "$NEW_USER" &>/dev/null; then
warning "Пользователь $NEW_USER уже существует."
else
useradd -m -s /bin/bash "$NEW_USER"
usermod -aG sudo "$NEW_USER"
success "Пользователь $NEW_USER создан."
fi
USER_HOME=$(eval echo "~$NEW_USER")
SSH_DIR="$USER_HOME/.ssh"
AUTH_KEYS="$SSH_DIR/authorized_keys"
mkdir -p "$SSH_DIR"
chmod 700 "$SSH_DIR"
if ! grep -q "$SSH_KEY" "$AUTH_KEYS" 2>/dev/null; then
echo "$SSH_KEY" >> "$AUTH_KEYS"
fi
chmod 600 "$AUTH_KEYS"
chown -R "$NEW_USER:$NEW_USER" "$SSH_DIR"
success "SSH-ключ установлен."
info "Проверяю наличие Docker..."
if command -v docker &> /dev/null; then
warning "Docker уже установлен."
else
info "Устанавливаю Docker..."
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh > /dev/null 2>&1
rm get-docker.sh
usermod -aG docker "$NEW_USER"
success "Docker установлен."
fi
info "Применяю хард-секьюрити для SSH..."
cat < "$SSHD_CONFIG_DROPIN"
Port $SSH_PORT
PermitRootLogin no
PasswordAuthentication no
UsePAM yes
X11Forwarding no
EOF
chmod 644 "$SSHD_CONFIG_DROPIN"
systemctl restart ssh
success "SSH защищен и перенесен на порт $SSH_PORT."
info "Настраиваю UFW (Файрвол)..."
yes | ufw reset > /dev/null
ufw default deny incoming > /dev/null
ufw default allow outgoing > /dev/null
ufw allow "$SSH_PORT"/tcp > /dev/null
ufw allow 80/tcp > /dev/null
ufw allow 443/tcp > /dev/null
yes | ufw enable > /dev/null
success "UFW активирован."
info "Запускаю Fail2Ban..."
systemctl enable --now fail2ban > /dev/null
success "Fail2Ban работает."
info "Оптимизирую сеть: включаю TCP BBR..."
cat < /etc/sysctl.d/99-yokai-bbr.conf
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
EOF
sysctl --system > /dev/null
success "TCP BBR активирован. Сетевая пропускная способность максимизирована."
info "Включаю автоматические патчи безопасности..."
cat < /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
EOF
success "Авто-обновления настроены."
info "Оптимизирую Bash History..."
cat < /etc/profile.d/bash_history_tuning.sh
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTCONTROL=ignoreboth
export HISTTIMEFORMAT="%F %T "
EOF
chmod +x /etc/profile.d/bash_history_tuning.sh
success "Bash History настроена."
info "Настраиваю ежедневное обслуживание (Cron)..."
cat < /etc/cron.d/daily-maintenance
0 4 * * * root /sbin/reboot
EOF
chmod 644 /etc/cron.d/daily-maintenance
success "Авто-ребут сервера запланирован на 4:00."
echo ""
success "СЕРВЕР УСПЕШНО НАСТРОЕН И ЗАЩИЩЕН!"
echo -e "${CYAN}[ВАЖНО]${NC} Твои данные для подключения:"
echo -e " Пользователь : ${GREEN}$NEW_USER${NC}"
echo -e " SSH Порт : ${GREEN}$SSH_PORT${NC}"
echo -e " Команда : ${YELLOW}ssh -p $SSH_PORT $NEW_USER@${NC}"
echo -e "${RED}Внимание:${NC} Обязательно проверь подключение в новом окне терминала перед тем, как закрыть это!"
Настройка cron-задач для ежедневной очистки кэша APT, ротации логов, удаления мусора Docker и плановой перезагрузки.
#!/bin/bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
LOG_FILE="/var/log/maintenance.log"
CRON_FILE="/etc/cron.d/maintenance"
MAX_LOG_AGE_DAYS=7
MAX_JOURNAL_AGE="7d"
C_RESET='\033[0m'
C_CYAN='\033[0;36m'
C_GREEN='\033[0;32m'
C_YELLOW='\033[1;33m'
C_RED='\033[0;31m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
info() { echo -e "${C_CYAN}[INFO]${C_RESET} $1"; }
success() { echo -e "${C_GREEN}[УСПЕХ]${C_RESET} $1"; }
warning() { echo -e "${C_YELLOW}[ВНИМАНИЕ]${C_RESET} $1"; }
error() { echo -e "${C_RED}[ОШИБКА]${C_RESET} $1"; exit 1; }
print_header() {
echo -e "${PURPLE}> YOKAI TECH"
echo -e "${CYAN} > Автоматическое обслуживание сервера < ${NC}"
echo ""
}
get_free_space() {
df -k / | tail -1 | awk '{print $4}'
}
cleanup_apt() {
info "Шаг 1: Запускаю глубокую очистку менеджера пакетов (APT)..."
apt-get clean >> "$LOG_FILE" 2>&1
apt-get autoremove -y >> "$LOG_FILE" 2>&1
success "Кэш APT очищен, осиротевшие пакеты удалены."
}
cleanup_docker() {
info "Шаг 2: Проверяю наличие Docker для очистки..."
if command -v docker &> /dev/null; then
info "Docker найден. Начинаю тотальную очистку неиспользуемых данных..."
docker system prune -a -f --volumes >> "$LOG_FILE" 2>&1
success "Мусор в Docker успешно уничтожен."
else
warning "Docker не установлен в системе. Пропускаю этот шаг."
fi
}
cleanup_logs_and_tmp() {
info "Шаг 3: Навожу порядок в логах и временных файлах..."
info "Ищу старые логи (старше $MAX_LOG_AGE_DAYS дней) в /var/log..."
find /var/log -type f \( -name "*.gz" -o -name "*.log.*" -o -name "*.1" \) -mtime +$MAX_LOG_AGE_DAYS -exec rm -f {} \; >> "$LOG_FILE" 2>&1
info "Сокращаю системный журнал (journalctl) до $MAX_JOURNAL_AGE..."
journalctl --vacuum-time=$MAX_JOURNAL_AGE >> "$LOG_FILE" 2>&1
info "Удаляю временные файлы старше $MAX_LOG_AGE_DAYS дней из /tmp и /var/tmp..."
find /tmp -type f -mtime +$MAX_LOG_AGE_DAYS -exec rm -f {} \; >> "$LOG_FILE" 2>&1 || true
find /var/tmp -type f -mtime +$MAX_LOG_AGE_DAYS -exec rm -f {} \; >> "$LOG_FILE" 2>&1 || true
success "Работа с логами и временными файлами завершена."
}
install_cron() {
echo " YOKAI TECH: Установка автоматического обслуживания"
local script_path
script_path=$(realpath "$0")
echo "[ИНФО] Генерирую cron-конфигурацию в $CRON_FILE..."
cat < "$CRON_FILE"
0 3 * * * root $script_path
TZ=Europe/Moscow
0 4 * * * root /sbin/reboot
EOF
chmod 644 "$CRON_FILE"
echo "[УСПЕХ] Задачи успешно добавлены в планировщик!"
echo "[УСПЕХ] 1. Очистка системы будет выполняться ежедневно в 03:00."
echo "[УСПЕХ] 2. Перезагрузка сервера будет выполняться ежедневно в 04:00 (МСК)."
exit 0
}
if [[ "${EUID}" -ne 0 ]]; then
echo "ОШИБКА: Скрипт должен быть запущен с правами root." >&2
exit 1
fi
if [[ "${1:-}" == "--install-cron" ]]; then
install_cron
fi
touch "$LOG_FILE"
chmod 640 "$LOG_FILE"
info "Начинаю плановое обслуживание сервера..."
SPACE_BEFORE=$(get_free_space)
cleanup_apt
cleanup_docker
cleanup_logs_and_tmp
SPACE_AFTER=$(get_free_space)
if [[ -n "$SPACE_BEFORE" && -n "$SPACE_AFTER" ]]; then
FREED_KB=$(( SPACE_AFTER - SPACE_BEFORE ))
if [[ $FREED_KB -gt 0 ]]; then
FREED_MB=$(( FREED_KB / 1024 ))
success "ИТОГИ ОЧИСТКИ: Освобождено $FREED_MB MB дискового пространства! Отличный результат."
else
info "ИТОГИ ОЧИСТКИ: Система уже была чистой, место не изменилось."
fi
else
success "ИТОГИ ОЧИСТКИ: Обслуживание завершено успешно."
fi
success "Плановое обслуживание завершено. Сервер работает в оптимальном режиме."
Скрипт для cron, отслеживающий CPU, RAM и диск. Умеет очищать PageCache и автоматически поднимать упавшие службы (Self-Healing).
#!/bin/bash
set -euo pipefail
LOG_FILE="/var/log/watchdog.log"
STATE_FILE="/tmp/watchdog_strikes.state"
LOCK_FILE="/tmp/watchdog.lock"
CPU_THRESHOLD=85
RAM_THRESHOLD=85
DISK_THRESHOLD_USED=90
SERVICES=("nginx" "docker")
C_RESET='\033[0m'
C_CYAN='\033[0;36m'
C_GREEN='\033[0;32m'
C_YELLOW='\033[1;33m'
C_RED='\033[0;31m'
C_PURPLE='\033[0;35m'
info() {
echo -e "${C_CYAN}[INFO]${C_RESET} $1"
echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] ➔ $1" >> "$LOG_FILE"
}
success() {
echo -e "${C_GREEN}[УСПЕХ]${C_RESET} $1"
echo "$(date '+%Y-%m-%d %H:%M:%S') [SUCCESS] ➔ $1" >> "$LOG_FILE"
}
warning() {
echo -e "${C_YELLOW}[ВНИМАНИЕ]${C_RESET} $1"
echo "$(date '+%Y-%m-%d %H:%M:%S') [WARNING] ➔ $1" >> "$LOG_FILE"
}
error() {
echo -e "${C_RED}[ОШИБКА]${C_RESET} $1" >&2
echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] ➔ $1" >> "$LOG_FILE"
}
print_header() {
echo -e "${C_PURPLE}> YOKAI TECH"
echo -e "${C_CYAN} > Мониторинг и самовосстановление сервера < ${C_RESET}"
echo ""
}
exec 9>"$LOCK_FILE"
flock -n 9 || exit 0
CPU_IDLE=$(vmstat 1 2 | tail -1 | awk '{print $15}')
CPU_USAGE=$((100 - CPU_IDLE))
RAM_USAGE=$(free -m | awk 'NR==2{printf "%d", $3/$2*100}')
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
if [[ -f "$STATE_FILE" ]]; then
STRIKES=$(cat "$STATE_FILE")
else
STRIKES=0
fi
if [[ "$CPU_USAGE" -gt "$CPU_THRESHOLD" ]] || [[ "$RAM_USAGE" -gt "$RAM_THRESHOLD" ]]; then
STRIKES=$((STRIKES + 1))
if [[ "$STRIKES" -lt 3 ]]; then
warning "Повышенная нагрузка ($STRIKES/3). CPU: ${CPU_USAGE}%, RAM: ${RAM_USAGE}%"
fi
else
STRIKES=0
fi
echo "$STRIKES" > "$STATE_FILE"
if [[ "$STRIKES" -ge 3 ]]; then
error "Критическая нагрузка сохраняется! CPU: ${CPU_USAGE}%, RAM: ${RAM_USAGE}%"
sync; echo 3 > /proc/sys/vm/drop_caches
info "Системный PageCache экстренно очищен."
info "ТОП-5 процессов, потребляющих ресурсы:"
ps -eo pid,user,%cpu,%mem,comm --sort=-%cpu | head -n 6 >> "$LOG_FILE"
echo "0" > "$STATE_FILE"
fi
CLEANUP_REQUIRED=false
if [[ "$DISK_USAGE" -ge "$DISK_THRESHOLD_USED" ]]; then
error "Критически мало места на диске! Занято: ${DISK_USAGE}%"
CLEANUP_REQUIRED=true
fi
for srv in "${SERVICES[@]}"; do
if ! systemctl is-active --quiet "$srv"; then
error "Служба $srv УПАЛА! Пытаюсь восстановить..."
if systemctl restart "$srv"; then
success "Служба $srv успешно перезапущена (Self-Healed)."
else
error "Не удалось поднять службу $srv. Требуется вмешательство!"
fi
CLEANUP_REQUIRED=true
fi
done
if [[ "$CLEANUP_REQUIRED" == true ]]; then
info "Инициирую процедуру экстренной очистки системы..."
if command -v docker >/dev/null; then
if docker system prune -f >/dev/null 2>&1; then
success "Экстренная очистка Docker завершена без потери пользовательских данных."
else
error "Произошла ошибка при выполнении docker system prune."
fi
else
warning "Docker не установлен, экстренная очистка пропущена."
fi
journalctl --vacuum-time=1d >/dev/null 2>&1 || true
fi
exit 0