Доступ к Базе

Введите секретный ключ, полученный после оплаты.

Ключ не найден или срок действия истек.

Базовая настройка (Стандарт)

Классическая первичная настройка сервера: создание 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} Не закрывай текущую сессию терминала, пока не проверишь подключение в новом окне!"

Базовая настройка (Extra)

Продвинутая версия настройки: дополнительно включает установку 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 "Плановое обслуживание завершено. Сервер работает в оптимальном режиме."

Легковесный мониторинг ресурсов (Watchdog)

Скрипт для 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