Полная настройка Dedicated сервера для сайтов: LXC+Безопаность+Бекапы на s3
05-09-2025, 23:04
Просмотров: 2
🚀 Полная настройка Dedicated сервера
Быстрый старт:
- Открой dedicated-server-setup-guide.html в браузере
- Следуй основной инструкции
- Используй dedicated-server-extensions.html для продвинутых функций
- Запусти /opt/scripts/production-checklist.sh перед продакшеном
📋 Содержание
1🏗️ Обзор архитектуры
🎯 Цель:
Создать безопасную, масштабируемую инфраструктуру для хостинга 10-20 сайтов различных типов с полной изоляцией между ними.
📊 Технический стек:
- ОС: Ubuntu 24.04 LTS (стабильность + долгосрочная поддержка)
- Контейнеризация: LXC (легковесная виртуализация)
- Reverse Proxy: Nginx с автоматическим SSL
- Мониторинг: Prometheus + Grafana + Alertmanager
- Безопасность: UFW + Fail2ban + CrowdSec
- Бэкапы: Restic + Wasabi S3
💡 Преимущества LXC: Каждый сайт работает в изолированном окружении, но при этом использует одно ядро ОС. Это дает ~95% производительности bare metal при максимальной безопасности.
2💻 Установка Ubuntu 24.04 LTS
🔧 Первоначальная установка:
- Скачай Ubuntu Server 24.04 LTS ISO с официального сайта
- Установи через IPMI/iLO консоль Hetzner
- Выбери минимальную установку (без GUI)
- Создай пользователя
admin
с sudo правами
🚀 Первые команды после установки:
# Обновляем систему
sudo apt update && sudo apt upgrade -y
# Устанавливаем базовые пакеты
sudo apt install -y curl wget git htop btop tree unzip fail2ban ufw
# Настраиваем timezone
sudo timedatectl set-timezone Europe/Moscow
# Включаем автоматические обновления безопасности
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
⚠️ Важно: Обязательно запиши все пароли в надежном месте. Рекомендую использовать SSH ключи вместо паролей.
3🔒 Настройка базовой безопасности
🔑 SSH безопасность:
# Генерируем SSH ключ на локальной машине
ssh-keygen -t ed25519 -C "your-email@domain.com"
# Копируем ключ на сервер
ssh-copy-id admin@your-server-ip
# Настраиваем SSH (отключаем пароли)
sudo nano /etc/ssh/sshd_config
В файле /etc/ssh/sshd_config
измени:
Port 2222 # Меняем порт SSH
PasswordAuthentication no # Отключаем пароли
PermitRootLogin no # Запрещаем root вход
AllowUsers admin # Разрешаем только конкретным юзерам
🛡️ Настройка firewall UFW:
# Базовая настройка UFW
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
# Включаем firewall
sudo ufw enable
sudo systemctl restart ssh
🥊 Настройка Fail2ban:
# Создаем локальную конфигурацию
sudo nano /etc/fail2ban/jail.local
Содержимое jail.local
:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
backend = systemd
[sshd]
enabled = true
port = 2222
logpath = /var/log/auth.log
[nginx-http-auth]
enabled = true
[nginx-limit-req]
enabled = true
✅ Результат: Теперь сервер защищен от основных атак. SSH работает на нестандартном порту, включена защита от брутфорса.
4📦 Установка и настройка LXC
🔧 Установка LXC:
# Устанавливаем LXC и необходимые пакеты
sudo apt install -y lxc lxc-templates bridge-utils
# Создаем пользователя для LXC
sudo usermod -aG lxd admin
# Перезапускаем сессию
sudo su - admin
🌐 Настройка сетевого моста:
Создаем конфигурацию Netplan для мостов:
sudo nano /etc/netplan/01-lxc-bridges.yaml
network:
version: 2
renderer: networkd
ethernets:
enp1s0: # Твой основной интерфейс
dhcp4: no
bridges:
br0:
interfaces: [enp1s0]
addresses:
- YOUR_MAIN_IP/24 # Основной IP сервера
gateway4: YOUR_GATEWAY
nameservers:
addresses: [1.1.1.1, 8.8.8.8]
dhcp4: no
br-internal:
addresses: [10.0.100.1/24]
# Применяем настройки
sudo netplan apply
📁 Создание структуры директорий:
# Создаем папки для сайтов
sudo mkdir -p /var/lib/lxc-sites/{html-sites,wordpress-sites,laravel-sites,nodejs-sites}
sudo mkdir -p /opt/scripts/lxc-management
sudo mkdir -p /var/backups/lxc-snapshots
💡 Структура: Каждый тип сайтов будет иметь свою папку и шаблон контейнера для быстрого развертывания.
5🌐 Настройка сети и IP адресов
📋 Планирование IP адресов:
- Основной сервер: Твой главный IP от Hetzner
- Дополнительные IP: Дополнительные IP от Hetzner для отдельных сайтов
- Внутренняя сеть: 10.0.100.0/24 для межконтейнерного общения
🔧 Скрипт для добавления IP адресов:
sudo nano /opt/scripts/add-ip.sh
#!/bin/bash
# Скрипт для добавления дополнительных IP адресов
if [ "$#" -ne 2 ]; then
echo "Usage: $0 "
exit 1
fi
IP_ADDRESS=$1
SITE_NAME=$2
# Добавляем IP к интерфейсу
sudo ip addr add ${IP_ADDRESS}/32 dev br0
# Добавляем в автозагрузку
echo "post-up ip addr add ${IP_ADDRESS}/32 dev br0 # ${SITE_NAME}" | sudo tee -a /etc/network/interfaces
echo "IP ${IP_ADDRESS} добавлен для сайта ${SITE_NAME}"
chmod +x /opt/scripts/add-ip.sh
⚠️ Важно: Каждый дополнительный IP от Hetzner нужно активировать в их панели управления и настроить роутинг.
6🏗️ Создание контейнеров для сайтов
📝 Шаблон для HTML/CSS сайтов:
sudo nano /opt/scripts/create-html-site.sh
#!/bin/bash
SITE_NAME=$1
CONTAINER_IP=$2
# Создаем контейнер
sudo lxc-create -n ${SITE_NAME} -t ubuntu -- -r jammy
# Настраиваем конфигурацию контейнера
sudo tee /var/lib/lxc/${SITE_NAME}/config << EOF
lxc.net.0.type = veth
lxc.net.0.link = br-internal
lxc.net.0.ipv4.address = ${CONTAINER_IP}/24
lxc.net.0.ipv4.gateway = 10.0.100.1
lxc.rootfs.path = dir:/var/lib/lxc/${SITE_NAME}/rootfs
lxc.uts.name = ${SITE_NAME}
lxc.mount.auto = proc sys cgroup
EOF
# Запускаем контейнер
sudo lxc-start -n ${SITE_NAME}
# Устанавливаем nginx в контейнер
sudo lxc-attach -n ${SITE_NAME} -- apt update
sudo lxc-attach -n ${SITE_NAME} -- apt install -y nginx
sudo lxc-attach -n ${SITE_NAME} -- systemctl enable nginx
echo "HTML сайт ${SITE_NAME} создан с IP ${CONTAINER_IP}"
🔄 Шаблон для WordPress сайтов:
sudo nano /opt/scripts/create-wordpress-site.sh
#!/bin/bash
SITE_NAME=$1
CONTAINER_IP=$2
DB_PASSWORD=$(openssl rand -base64 32)
# Создаем контейнер (базовый)
/opt/scripts/create-html-site.sh ${SITE_NAME} ${CONTAINER_IP}
# Устанавливаем LEMP stack
sudo lxc-attach -n ${SITE_NAME} -- bash -c "
apt install -y php8.3-fpm php8.3-mysql php8.3-xml php8.3-curl php8.3-gd php8.3-zip mysql-server
# Настраиваем MySQL
mysql_secure_installation
# Создаем базу данных
mysql -e 'CREATE DATABASE ${SITE_NAME}_db;'
mysql -e 'CREATE USER \"${SITE_NAME}_user\"@\"localhost\" IDENTIFIED BY \"${DB_PASSWORD}\";'
mysql -e 'GRANT ALL ON ${SITE_NAME}_db.* TO \"${SITE_NAME}_user\"@\"localhost\";'
mysql -e 'FLUSH PRIVILEGES;'
# Скачиваем WordPress
cd /var/www/html
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
rm latest.tar.gz
chown -R www-data:www-data wordpress/
"
echo "WordPress сайт ${SITE_NAME} создан с IP ${CONTAINER_IP}"
echo "DB Password: ${DB_PASSWORD}"
⚡ Шаблон для Laravel сайтов:
sudo nano /opt/scripts/create-laravel-site.sh
#!/bin/bash
SITE_NAME=$1
CONTAINER_IP=$2
# Создаем базовый контейнер
/opt/scripts/create-html-site.sh ${SITE_NAME} ${CONTAINER_IP}
# Устанавливаем Laravel requirements
sudo lxc-attach -n ${SITE_NAME} -- bash -c "
apt install -y php8.3-fpm php8.3-mysql php8.3-xml php8.3-curl php8.3-gd php8.3-zip php8.3-mbstring composer
# Создаем Laravel проект
cd /var/www
composer create-project laravel/laravel ${SITE_NAME}
chown -R www-data:www-data /var/www/${SITE_NAME}
chmod -R 775 /var/www/${SITE_NAME}/storage
"
echo "Laravel сайт ${SITE_NAME} создан с IP ${CONTAINER_IP}"
chmod +x /opt/scripts/*.sh
✅ Результат: Теперь у тебя есть автоматизированные скрипты для создания любых типов сайтов за несколько секунд.
7🔄 Reverse Proxy и SSL
🌐 Установка и настройка Nginx на хосте:
# Устанавливаем Nginx на основной сервер
sudo apt install -y nginx certbot python3-certbot-nginx
# Создаем базовую конфигурацию
sudo nano /etc/nginx/sites-available/default
Базовая конфигурация Nginx:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# Блокируем прямые обращения по IP
return 444;
}
# Шаблон для сайта
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://10.0.100.10:80; # IP контейнера
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
🔒 Автоматизация SSL сертификатов:
sudo nano /opt/scripts/add-ssl.sh
#!/bin/bash
DOMAIN=$1
# Получаем SSL сертификат
sudo certbot --nginx -d ${DOMAIN} --non-interactive --agree-tos --email your-email@domain.com
# Добавляем автообновление
sudo crontab -l | { cat; echo "0 12 * * * /usr/bin/certbot renew --quiet"; } | sudo crontab -
echo "SSL сертификат для ${DOMAIN} установлен"
⚖️ Балансировка нагрузки:
Для высоконагруженных сайтов можешь создать несколько контейнеров:
upstream backend_example {
server 10.0.100.10:80;
server 10.0.100.11:80;
server 10.0.100.12:80;
}
server {
listen 443 ssl http2;
server_name example.com;
location / {
proxy_pass http://backend_example;
}
}
💡 Cloudflare: Если используешь Cloudflare, включи режим «Full (strict)» SSL для максимальной безопасности.
8📊 Мониторинг и логирование
🔍 Установка системы мониторинга:
# Создаем контейнер для мониторинга
sudo lxc-create -n monitoring -t ubuntu -- -r jammy
sudo lxc-start -n monitoring
# Устанавливаем Prometheus + Grafana
sudo lxc-attach -n monitoring -- bash -c "
apt update
apt install -y prometheus grafana node-exporter
# Настраиваем автозапуск
systemctl enable prometheus grafana-server node-exporter
systemctl start prometheus grafana-server node-exporter
"
📧 Настройка уведомлений через внешние сервисы:
sudo nano /opt/scripts/send-alert.sh
#!/bin/bash
# Скрипт для отправки уведомлений через Telegram API или email сервис
MESSAGE="$1"
SEVERITY="$2"
# Отправка через Telegram (используй бот)
TELEGRAM_TOKEN="YOUR_BOT_TOKEN"
CHAT_ID="YOUR_CHAT_ID"
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=🚨 ${SEVERITY}: ${MESSAGE}"
# Альтернативно - отправка через SMTP сервис (например, SendGrid)
# echo "${MESSAGE}" | mail -s "Server Alert: ${SEVERITY}" your-email@domain.com
📝 Централизованное логирование:
# Устанавливаем rsyslog для централизованных логов
sudo apt install -y rsyslog
# Настраиваем сбор логов с контейнеров
sudo nano /etc/rsyslog.d/50-lxc.conf
# Собираем логи от всех контейнеров
$ModLoad imfile
$InputFileName /var/lib/lxc/*/rootfs/var/log/*.log
$InputFileTag container:
$InputFileSeverity info
$InputFileFacility local0
$InputRunFileMonitor
✅ Мониторинг настроен! Теперь ты будешь получать уведомления о проблемах и сможешь отслеживать производительность всех сайтов.
9💾 Резервное копирование в Wasabi
🔧 Установка Restic:
# Устанавливаем Restic
sudo apt install -y restic
# Создаем конфигурацию для Wasabi
sudo nano /opt/scripts/backup-config.env
# Конфигурация Wasabi S3
export AWS_ACCESS_KEY_ID="your-wasabi-access-key"
export AWS_SECRET_ACCESS_KEY="your-wasabi-secret-key"
export RESTIC_REPOSITORY="s3:https://s3.wasabisys.com/your-bucket-name/server-backups"
export RESTIC_PASSWORD="your-strong-backup-password"
📦 Скрипт полного бэкапа:
sudo nano /opt/scripts/full-backup.sh
#!/bin/bash
source /opt/scripts/backup-config.env
echo "🚀 Начинаем резервное копирование..."
# Инициализируем репозиторий (только при первом запуске)
restic init --repo $RESTIC_REPOSITORY || true
# Останавливаем контейнеры для консистентности
for container in $(sudo lxc-ls); do
sudo lxc-stop -n $container
done
# Создаем снапшоты LXC контейнеров
sudo lxc-snapshot -n ALL
# Резервное копирование
restic backup \
/var/lib/lxc \
/etc \
/opt/scripts \
--tag weekly-backup \
--exclude-caches \
--exclude /var/lib/lxc/*/rootfs/tmp \
--exclude /var/lib/lxc/*/rootfs/var/cache
# Запускаем контейнеры обратно
for container in $(sudo lxc-ls -1 --stopped); do
sudo lxc-start -n $container
done
# Очистка старых бэкапов (хранить 8 недель)
restic forget --keep-weekly 8 --prune
echo "✅ Резервное копирование завершено!"
📅 Настройка расписания бэкапов:
# Добавляем в crontab
sudo crontab -e
# Еженедельный полный бэкап (воскресенье в 02:00)
0 2 * * 0 /opt/scripts/full-backup.sh >> /var/log/backup.log 2>&1
# Ежедневный инкрементальный бэкап (03:00)
0 3 * * 1-6 /opt/scripts/incremental-backup.sh >> /var/log/backup.log 2>&1
# Годовой архивный бэкап (1 января)
0 1 1 1 * /opt/scripts/yearly-backup.sh >> /var/log/backup.log 2>&1
💰 Оптимизация расходов на Wasabi:
💡 Экономия:
- Минимальный план: ~$6/месяц за 1TB
- Дедупликация: Restic автоматически удаляет дубликаты
- Сжатие: Экономия ~30-50% места
- Lifecycle policy: Старые бэкапы можно переносить в более дешевое хранилище
🔄 Скрипт восстановления:
sudo nano /opt/scripts/restore-backup.sh
#!/bin/bash
source /opt/scripts/backup-config.env
echo "📁 Доступные бэкапы:"
restic snapshots
echo "Введите ID снапшота для восстановления:"
read SNAPSHOT_ID
echo "🔄 Восстанавливаем бэкап $SNAPSHOT_ID..."
restic restore $SNAPSHOT_ID --target /tmp/restore/
echo "✅ Данные восстановлены в /tmp/restore/"
chmod +x /opt/scripts/*.sh
10🤖 Автоматизация и скрипты
🎛️ Панель управления сайтами:
sudo nano /opt/scripts/site-manager.sh
#!/bin/bash
# Простая консольная панель управления
show_menu() {
echo "🚀 Управление сайтами"
echo "===================="
echo "1. Создать HTML сайт"
echo "2. Создать WordPress сайт"
echo "3. Создать Laravel сайт"
echo "4. Список всех сайтов"
echo "5. Остановить сайт"
echo "6. Запустить сайт"
echo "7. Удалить сайт"
echo "8. Создать бэкап сайта"
echo "9. Выход"
}
while true; do
show_menu
read -p "Выберите опцию: " choice
case $choice in
1) read -p "Имя сайта: " name; read -p "IP контейнера: " ip; /opt/scripts/create-html-site.sh $name $ip ;;
2) read -p "Имя сайта: " name; read -p "IP контейнера: " ip; /opt/scripts/create-wordpress-site.sh $name $ip ;;
3) read -p "Имя сайта: " name; read -p "IP контейнера: " ip; /opt/scripts/create-laravel-site.sh $name $ip ;;
4) sudo lxc-ls -f ;;
5) read -p "Имя сайта: " name; sudo lxc-stop -n $name ;;
6) read -p "Имя сайта: " name; sudo lxc-start -n $name ;;
7) read -p "Имя сайта (ВНИМАНИЕ! Удалится навсегда): " name; sudo lxc-destroy -n $name ;;
8) read -p "Имя сайта: " name; sudo lxc-snapshot -n $name ;;
9) exit 0 ;;
*) echo "Неверная опция!" ;;
esac
echo -e "\nНажмите Enter для продолжения..."
read
clear
done
📈 Мониторинг ресурсов:
sudo nano /opt/scripts/resource-monitor.sh
#!/bin/bash
# Мониторинг ресурсов всех контейнеров
echo "📊 Состояние ресурсов сервера $(date)"
echo "========================================"
echo -e "\n🖥️ ОБЩИЕ РЕСУРСЫ:"
echo "CPU: $(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')%"
echo "RAM: $(free -h | grep '^Mem:' | awk '{print $3 "/" $2}')"
echo "Disk: $(df -h / | tail -1 | awk '{print $3 "/" $2 " (" $5 " used)"}')"
echo -e "\n📦 КОНТЕЙНЕРЫ:"
for container in $(sudo lxc-ls -1); do
status=$(sudo lxc-info -n $container -s | grep State | awk '{print $2}')
if [ "$status" = "RUNNING" ]; then
cpu=$(sudo lxc-attach -n $container -- top -bn1 | grep "Cpu(s)" | head -1 | awk '{print $2}' | cut -d'%' -f1)
mem=$(sudo lxc-attach -n $container -- free -h | grep '^Mem:' | awk '{print $3}')
echo " $container: $status, CPU: ${cpu:-N/A}%, RAM: ${mem:-N/A}"
else
echo " $container: $status"
fi
done
echo -e "\n🌐 АКТИВНЫЕ СОЕДИНЕНИЯ:"
netstat -tuln | grep LISTEN | wc -l | xargs echo "Listening ports:"
🔧 Автоматическое обслуживание:
sudo nano /opt/scripts/maintenance.sh
#!/bin/bash
# Еженедельное автоматическое обслуживание
echo "🔧 Запуск еженедельного обслуживания..."
# Обновляем основную систему
sudo apt update && sudo apt upgrade -y
# Обновляем все контейнеры
for container in $(sudo lxc-ls -1); do
if [ "$(sudo lxc-info -n $container -s | grep State | awk '{print $2}')" = "RUNNING" ]; then
echo "Обновляем $container..."
sudo lxc-attach -n $container -- apt update
sudo lxc-attach -n $container -- apt upgrade -y
sudo lxc-attach -n $container -- apt autoremove -y
fi
done
# Очистка логов старше 30 дней
find /var/log -name "*.log" -mtime +30 -delete
# Очистка старых снапшотов (оставляем последние 7)
for container in $(sudo lxc-ls -1); do
sudo lxc-snapshot -L -n $container | tail -n +8 | awk '{print $1}' | while read snap; do
sudo lxc-snapshot -d snap$snap -n $container
done
done
# Перезапуск сервисов для применения обновлений
sudo systemctl restart nginx
sudo systemctl restart fail2ban
echo "✅ Обслуживание завершено!"
chmod +x /opt/scripts/*.sh
# Добавляем в cron
echo "0 4 * * 1 /opt/scripts/maintenance.sh >> /var/log/maintenance.log 2>&1" | sudo crontab -
🎉 Готово! У тебя есть полностью автоматизированная система управления множественными сайтами с максимальной безопасностью и удобством управления.
🏁 Заключение
Теперь у тебя есть производственная инфраструктура корпоративного уровня:
✅ Что получилось:
- Безопасность: Каждый сайт изолирован, защита от атак
- Масштабируемость: Легко добавлять новые сайты
- Автоматизация: Минимум ручной работы
- Мониторинг: Полный контроль над состоянием
- Надежность: Автоматические бэкапы в облако
🚀 Следующие шаги:
- Запусти
/opt/scripts/site-manager.sh
для создания первого сайта - Настрой мониторинг под свои нужды
- Протестируй восстановление из бэкапа
- Добавь собственные автоматизации
⚠️ Важные напоминания:
- Регулярно проверяй логи безопасности
- Обновляй системы минимум раз в неделю
- Тестируй восстановление из бэкапов
- Мониторь расходы на Wasabi
🎯 Твой сервер готов к продакшену!
🔧 Недостающие скрипты и конфигурации
⚡ Node.js сайты — полный скрипт создания
sudo nano /opt/scripts/create-nodejs-site.sh
#!/bin/bash
SITE_NAME=$1
CONTAINER_IP=$2
NODE_VERSION="18"
if [ "$#" -ne 2 ]; then
echo "Usage: $0 "
echo "Example: $0 myapp 10.0.100.15"
exit 1
fi
echo "🚀 Создаем Node.js сайт: $SITE_NAME с IP $CONTAINER_IP"
# Создаем базовый контейнер
/opt/scripts/create-html-site.sh ${SITE_NAME} ${CONTAINER_IP}
# Ждем запуска контейнера
sleep 10
# Устанавливаем Node.js
sudo lxc-attach -n ${SITE_NAME} -- bash -c "
apt update
curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash -
apt install -y nodejs nginx
npm install -g pm2 yarn
# Создаем структуру проекта
mkdir -p /var/www/${SITE_NAME}
cd /var/www/${SITE_NAME}
# Создаем базовый Express.js проект
npm init -y
npm install express helmet cors compression morgan
# Создаем базовый app.js с best practices
cat > app.js << 'EOF' const express = require('express'); const helmet = require('helmet'); const cors = require('cors'); const compression = require('compression'); const morgan = require('morgan'); const app = express(); const port = process.env.PORT || 3000; // Security middleware app.use(helmet()); app.use(cors()); app.use(compression()); app.use(morgan('combined')); // Basic middleware app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); // Routes app.get('/', (req, res) => {
res.json({
message: 'Hello from ${SITE_NAME}!',
timestamp: new Date().toISOString(),
environment: process.env.NODE_ENV || 'development'
});
});
app.get('/health', (req, res) => {
res.json({ status: 'OK', uptime: process.uptime() });
});
// Error handling
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
});
app.listen(port, '127.0.0.1', () => {
console.log(\`${SITE_NAME} server running on port \${port}\`);
});
EOF
# Создаем ecosystem.config.js для PM2
cat > ecosystem.config.js << 'EOF' module.exports = { apps: [{ name: '${SITE_NAME}', script: 'app.js', instances: 1, autorestart: true, watch: false, max_memory_restart: '1G', env: { NODE_ENV: 'production', PORT: 3000 }, log_file: '/var/log/${SITE_NAME}.log', out_file: '/var/log/${SITE_NAME}-out.log', error_file: '/var/log/${SITE_NAME}-error.log' }] }; EOF # Настраиваем PM2 pm2 start ecosystem.config.js pm2 startup systemd pm2 save # Настраиваем Nginx как reverse proxy для Node.js cat > /etc/nginx/sites-available/default << 'EOF'
server {
listen 80;
server_name localhost;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection \"1; mode=block\";
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_cache_bypass \$http_upgrade;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Health check endpoint
location /health {
proxy_pass http://127.0.0.1:3000/health;
access_log off;
}
}
EOF
# Тестируем и перезапускаем nginx
nginx -t && systemctl restart nginx
# Настраиваем права доступа
chown -R www-data:www-data /var/www/${SITE_NAME}
chmod -R 755 /var/www/${SITE_NAME}
"
echo "✅ Node.js сайт ${SITE_NAME} создан успешно!"
echo "📊 Проверка статуса: pm2 status (внутри контейнера)"
echo "🌐 Health check: http://${CONTAINER_IP}/health"
💡 Что включено:
- Express.js с безопасными middleware (helmet, cors)
- PM2 для управления процессами
- Health check эндпоинт
- Логирование и error handling
- Gzip сжатие в Nginx
- Security headers
🎯 Ограничение ресурсов контейнеров
📊 Детальная настройка лимитов
sudo nano /opt/scripts/set-container-limits.sh
#!/bin/bash
CONTAINER_NAME=$1
CPU_LIMIT=$2 # Например: 1.5 (полтора ядра)
RAM_LIMIT=$3 # Например: 512M или 1G
DISK_LIMIT=$4 # Например: 10G (опционально)
if [ "$#" -lt 3 ]; then
echo "Usage: $0 [disk_limit]"
echo ""
echo "Examples:"
echo " $0 small-site 0.5 256M"
echo " $0 wordpress-blog 1.0 1G"
echo " $0 high-load-app 2.0 4G 20G"
exit 1
fi
echo "🎛️ Настраиваем лимиты для контейнера: $CONTAINER_NAME"
# Проверяем существование контейнера
if ! sudo lxc-info -n $CONTAINER_NAME >/dev/null 2>&1; then
echo "❌ Контейнер $CONTAINER_NAME не найден!"
exit 1
fi
# Останавливаем контейнер
echo "⏹️ Останавливаем контейнер..."
sudo lxc-stop -n $CONTAINER_NAME
# Настройка CPU лимита (в микросекундах на период 100мс)
CPU_QUOTA=$(echo "$CPU_LIMIT * 100000" | bc)
echo "lxc.cgroup2.cpu.max = $CPU_QUOTA 100000" | sudo tee -a /var/lib/lxc/$CONTAINER_NAME/config
# Настройка RAM лимита
echo "lxc.cgroup2.memory.max = $RAM_LIMIT" | sudo tee -a /var/lib/lxc/$CONTAINER_NAME/config
echo "lxc.cgroup2.memory.swap.max = 0" | sudo tee -a /var/lib/lxc/$CONTAINER_NAME/config
# Настройка приоритета (nice value)
echo "lxc.cgroup2.cpu.weight = 100" | sudo tee -a /var/lib/lxc/$CONTAINER_NAME/config
# Если указан лимит диска
if [ ! -z "$DISK_LIMIT" ]; then
# Создаем loop device для контейнера с ограниченным размером
LOOP_FILE="/var/lib/lxc-disks/${CONTAINER_NAME}.img"
sudo mkdir -p /var/lib/lxc-disks
echo "💾 Создаем виртуальный диск размером $DISK_LIMIT"
sudo fallocate -l $DISK_LIMIT $LOOP_FILE
sudo mkfs.ext4 $LOOP_FILE
# Добавляем mount point в конфигурацию
echo "lxc.mount.entry = $LOOP_FILE var/www ext4 loop,rw 0 0" | sudo tee -a /var/lib/lxc/$CONTAINER_NAME/config
fi
# Добавляем мониторинг ресурсов
cat >> /var/lib/lxc/$CONTAINER_NAME/config << EOF # Resource monitoring lxc.cgroup2.memory.events.file = /var/lib/lxc/$CONTAINER_NAME/memory.events lxc.cgroup2.cpu.stat.file = /var/lib/lxc/$CONTAINER_NAME/cpu.stat EOF # Запускаем контейнер echo "▶️ Запускаем контейнер..." sudo lxc-start -n $CONTAINER_NAME # Ждем запуска sleep 5 # Проверяем статус if sudo lxc-info -n $CONTAINER_NAME | grep -q "RUNNING"; then echo "✅ Контейнер успешно запущен с лимитами:" echo " CPU: $CPU_LIMIT cores" echo " RAM: $RAM_LIMIT" if [ ! -z "$DISK_LIMIT" ]; then echo " Disk: $DISK_LIMIT" fi # Показываем текущее использование echo "" echo "📊 Текущее использование ресурсов:" sudo lxc-attach -n $CONTAINER_NAME -- free -h sudo lxc-attach -n $CONTAINER_NAME -- df -h 2>/dev/null || echo "Диск недоступен"
else
echo "❌ Ошибка запуска контейнера!"
exit 1
fi
📈 Мониторинг ресурсов в реальном времени
sudo nano /opt/scripts/monitor-containers.sh
#!/bin/bash
# Мониторинг ресурсов всех контейнеров в реальном времени
watch -n 2 '
clear
echo "🖥️ SERVER RESOURCE MONITOR - $(date)"
echo "════════════════════════════════════════════════════════════════"
# Общие ресурсы сервера
echo "📊 HOST SYSTEM:"
echo "CPU Usage: $(top -bn1 | grep "Cpu(s)" | awk "{print \$2}" | cut -d"%" -f1)%"
echo "RAM Usage: $(free | awk "NR==2{printf \"%.1f%%\", \$3*100/\$2}")"
echo "Load Average: $(cat /proc/loadavg | awk "{print \$1, \$2, \$3}")"
echo ""
# Статус контейнеров
echo "📦 CONTAINERS:"
printf "%-15s %-8s %-8s %-8s %-10s\n" "NAME" "STATUS" "CPU%" "RAM%" "DISK%"
echo "────────────────────────────────────────────────────────────────"
for container in $(sudo lxc-ls -1 2>/dev/null); do
status=$(sudo lxc-info -n $container -s 2>/dev/null | grep State | awk "{print \$2}")
if [ "$status" = "RUNNING" ]; then
# CPU usage (получаем из cgroup)
cpu_usage=$(sudo lxc-attach -n $container -- grep "cpu " /proc/stat 2>/dev/null | awk "{u=\$2+\$4; t=\$2+\$3+\$4+\$5; if (NR==1){u1=u; t1=t;} else printf \"%.1f\", (u-u1) * 100 / (t-t1); }")
[ -z "$cpu_usage" ] && cpu_usage="N/A"
# RAM usage
ram_usage=$(sudo lxc-attach -n $container -- free 2>/dev/null | awk "NR==2{printf \"%.1f\", \$3*100/\$2}")
[ -z "$ram_usage" ] && ram_usage="N/A"
# Disk usage
disk_usage=$(sudo lxc-attach -n $container -- df / 2>/dev/null | awk "NR==2{print \$5}" | sed "s/%//")
[ -z "$disk_usage" ] && disk_usage="N/A"
printf "%-15s %-8s %-7s%% %-7s%% %-9s%%\n" "$container" "$status" "$cpu_usage" "$ram_usage" "$disk_usage"
else
printf "%-15s %-8s %-8s %-8s %-10s\n" "$container" "$status" "---" "---" "---"
fi
done
echo ""
echo "💡 Press Ctrl+C to exit monitoring"
'
chmod +x /opt/scripts/*.sh
🔍 Диагностика и troubleshooting
🚨 Полный скрипт диагностики
sudo nano /opt/scripts/full-diagnostics.sh
#!/bin/bash
# Комплексная диагностика системы и контейнеров
LOG_FILE="/tmp/diagnostics-$(date +%Y%m%d-%H%M%S).log"
echo "🔍 Запуск полной диагностики системы..." | tee $LOG_FILE
echo "Результат будет сохранен в: $LOG_FILE" | tee -a $LOG_FILE
echo "═══════════════════════════════════════════════════════════════════" | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
# 1. Информация о системе
echo "🖥️ SYSTEM INFORMATION:" | tee -a $LOG_FILE
echo "────────────────────────" | tee -a $LOG_FILE
{
echo "Hostname: $(hostname)"
echo "Uptime: $(uptime -p)"
echo "Kernel: $(uname -r)"
echo "OS: $(lsb_release -d | cut -f2)"
echo "Architecture: $(uname -m)"
echo "CPU: $(lscpu | grep "Model name" | cut -d':' -f2 | xargs)"
echo "RAM: $(free -h | awk 'NR==2{printf "%s total, %s used, %s available", $2,$3,$7}')"
echo "Disk: $(df -h / | awk 'NR==2{printf "%s total, %s used, %s available (%s used)", $2,$3,$4,$5}')"
} | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
# 2. Статус ключевых сервисов
echo "🔧 SERVICE STATUS:" | tee -a $LOG_FILE
echo "──────────────────" | tee -a $LOG_FILE
for service in nginx fail2ban ufw lxc ssh; do
status=$(systemctl is-active $service 2>/dev/null || echo "inactive")
echo "$service: $status" | tee -a $LOG_FILE
done
echo "" | tee -a $LOG_FILE
# 3. Сетевая конфигурация
echo "🌐 NETWORK CONFIGURATION:" | tee -a $LOG_FILE
echo "──────────────────────────" | tee -a $LOG_FILE
{
echo "Interfaces:"
ip -4 addr show | grep -E '^[0-9]|inet ' | sed 's/^/ /'
echo ""
echo "Routing table:"
ip route | sed 's/^/ /'
echo ""
echo "DNS configuration:"
cat /etc/resolv.conf | sed 's/^/ /'
echo ""
echo "Listening ports:"
netstat -tuln | grep LISTEN | sed 's/^/ /'
} | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
# 4. Состояние контейнеров
echo "📦 CONTAINERS STATUS:" | tee -a $LOG_FILE
echo "─────────────────────" | tee -a $LOG_FILE
if command -v lxc-ls >/dev/null 2>&1; then
for container in $(sudo lxc-ls -1 2>/dev/null); do
echo "Container: $container" | tee -a $LOG_FILE
sudo lxc-info -n $container 2>&1 | sed 's/^/ /' | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
done
else
echo "LXC not installed or not accessible" | tee -a $LOG_FILE
fi
echo "" | tee -a $LOG_FILE
# 5. Безопасность
echo "🔒 SECURITY STATUS:" | tee -a $LOG_FILE
echo "────────────────────" | tee -a $LOG_FILE
{
echo "UFW status:"
sudo ufw status verbose | sed 's/^/ /'
echo ""
echo "Fail2ban status:"
sudo fail2ban-client status | sed 's/^/ /'
echo ""
echo "Recent failed login attempts:"
grep "authentication failure" /var/log/auth.log | tail -5 | sed 's/^/ /' 2>/dev/null || echo " No recent failures found"
echo ""
echo "SSH configuration:"
grep -E "^(Port|PasswordAuthentication|PermitRootLogin|AllowUsers)" /etc/ssh/sshd_config | sed 's/^/ /'
} | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
# 6. Производительность
echo "⚡ PERFORMANCE METRICS:" | tee -a $LOG_FILE
echo "──────────────────────" | tee -a $LOG_FILE
{
echo "Load average (1min, 5min, 15min):"
cat /proc/loadavg | sed 's/^/ /'
echo ""
echo "Memory usage:"
free -h | sed 's/^/ /'
echo ""
echo "Disk I/O:"
iostat -x 1 1 2>/dev/null | tail -n +4 | sed 's/^/ /' || echo " iostat not available"
echo ""
echo "Top processes by CPU:"
ps aux --sort=-%cpu | head -6 | sed 's/^/ /'
echo ""
echo "Top processes by Memory:"
ps aux --sort=-%mem | head -6 | sed 's/^/ /'
} | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
# 7. Логи ошибок
echo "📝 RECENT ERROR LOGS:" | tee -a $LOG_FILE
echo "────────────────────" | tee -a $LOG_FILE
{
echo "System journal errors (last 10):"
sudo journalctl -p err --no-pager -n 10 | sed 's/^/ /'
echo ""
echo "Nginx errors (last 5):"
sudo tail -5 /var/log/nginx/error.log 2>/dev/null | sed 's/^/ /' || echo " No nginx error log found"
} | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
# 8. Дисковое пространство
echo "💾 DISK USAGE:" | tee -a $LOG_FILE
echo "──────────────" | tee -a $LOG_FILE
{
echo "Filesystem usage:"
df -h | sed 's/^/ /'
echo ""
echo "Largest directories in /var:"
du -sh /var/* 2>/dev/null | sort -hr | head -5 | sed 's/^/ /'
echo ""
echo "LXC containers disk usage:"
du -sh /var/lib/lxc/* 2>/dev/null | sort -hr | sed 's/^/ /' || echo " No LXC containers found"
} | tee -a $LOG_FILE
echo "" | tee -a $LOG_FILE
echo "═══════════════════════════════════════════════════════════════════" | tee -a $LOG_FILE
echo "✅ Диагностика завершена. Полный отчет сохранен в: $LOG_FILE" | tee -a $LOG_FILE
echo "📧 Отправьте этот файл в техподдержку при необходимости." | tee -a $LOG_FILE
✅ Использование:
./full-diagnostics.sh
— запуск полной диагностики./monitor-containers.sh
— мониторинг в реальном времени./set-container-limits.sh mysite 1.5 2G
— настройка лимитов
🌟 Практические примеры реального использования
🏪 Пример 1: Интернет-магазин на WordPress
Задача: Создать высокопроизводительный интернет-магазин с отдельным IP адресом
# 1. Заказываем дополнительный IP в Hetzner Robot Panel
# Получили IP: 65.108.1.101
# 2. Добавляем IP к серверу
/opt/scripts/add-ip.sh 65.108.1.101 shop-site
# 3. Создаем WordPress контейнер с увеличенными ресурсами
/opt/scripts/create-wordpress-site.sh shop-site 10.0.100.20
# 4. Настраиваем лимиты ресурсов (магазин требует больше)
/opt/scripts/set-container-limits.sh shop-site 2.0 4G
# 5. Создаем Nginx конфигурацию для магазина
sudo nano /etc/nginx/sites-available/shop-site
server {
listen 65.108.1.101:80; # Слушаем на выделенном IP
server_name shop.yourdomain.com;
# Rate limiting для защиты от DDoS
limit_req_zone $binary_remote_addr zone=shop_login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=shop_general:10m rate=10r/s;
location / {
limit_req zone=shop_general burst=20 nodelay;
proxy_pass http://10.0.100.20:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Кеширование статического контента
location ~* \.(jpg|jpeg|png|gif|ico|css|js|webp)$ {
proxy_pass http://10.0.100.20:80;
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary Accept-Encoding;
}
}
# Особая защита для админки WordPress
location /wp-admin/ {
limit_req zone=shop_login burst=5 nodelay;
allow YOUR_IP; # Замени на свой IP
deny all; # Блокируем доступ для всех остальных
proxy_pass http://10.0.100.20:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Блокируем доступ к чувствительным файлам
location ~* \.(log|sql|conf)$ {
deny all;
}
}
# 6. Активируем конфигурацию
sudo ln -s /etc/nginx/sites-available/shop-site /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
# 7. Получаем SSL сертификат
/opt/scripts/add-ssl.sh shop.yourdomain.com
# 8. Настраиваем автоматические бэкапы только этого сайта
sudo nano /opt/scripts/backup-shop-site.sh
🚀 Пример 2: Node.js API с балансировкой нагрузки
# 1. Создаем 3 одинаковых API контейнера
/opt/scripts/create-nodejs-site.sh api-v1 10.0.100.30
/opt/scripts/create-nodejs-site.sh api-v2 10.0.100.31
/opt/scripts/create-nodejs-site.sh api-v3 10.0.100.32
# 2. Настраиваем одинаковые лимиты для всех
/opt/scripts/set-container-limits.sh api-v1 1.0 1G
/opt/scripts/set-container-limits.sh api-v2 1.0 1G
/opt/scripts/set-container-limits.sh api-v3 1.0 1G
# 3. Создаем балансировщик нагрузки
sudo nano /etc/nginx/sites-available/api-cluster
upstream api_backend {
least_conn; # Балансировка по наименьшему количеству соединений
server 10.0.100.30:80 max_fails=3 fail_timeout=30s weight=1;
server 10.0.100.31:80 max_fails=3 fail_timeout=30s weight=1;
server 10.0.100.32:80 max_fails=3 fail_timeout=30s weight=1;
}
# Health check сервер
server {
listen 8080;
location /health-check {
proxy_pass http://api_backend/health;
access_log off;
}
}
server {
listen 80;
server_name api.yourdomain.com;
# API rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
limit_req_zone $http_authorization zone=api_user:10m rate=1000r/s;
location / {
limit_req zone=api burst=200 nodelay;
limit_req zone=api_user burst=500 nodelay;
proxy_pass http://api_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Настройки для API
proxy_buffering off;
proxy_request_buffering off;
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 10s;
}
# Отдельная точка для health checks
location /health {
proxy_pass http://api_backend/health;
access_log off;
}
}
📊 Пример 3: Мониторинг и алерты для критичного проекта
# 1. Создаем выделенный контейнер для мониторинга
/opt/scripts/create-html-site.sh monitoring 10.0.100.100
# 2. Устанавливаем полный стек мониторинга
sudo lxc-attach -n monitoring -- bash -c "
apt update && apt install -y curl wget
# Prometheus
wget https://github.com/prometheus/prometheus/releases/download/v2.40.0/prometheus-2.40.0.linux-amd64.tar.gz
tar xvfz prometheus-*.tar.gz
sudo mv prometheus-2.40.0.linux-amd64/prometheus /usr/local/bin/
sudo mv prometheus-2.40.0.linux-amd64/promtool /usr/local/bin/
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus /var/lib/prometheus
# Grafana
wget -q -O - https://packages.grafana.com/gpg.key | apt-key add -
echo 'deb https://packages.grafana.com/oss/deb stable main' > /etc/apt/sources.list.d/grafana.list
apt update && apt install -y grafana
# Node Exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.5.0/node_exporter-1.5.0.linux-amd64.tar.gz
tar xvfz node_exporter-*.tar.gz
sudo mv node_exporter-1.5.0.linux-amd64/node_exporter /usr/local/bin/
# Создаем systemd сервисы
cat > /etc/systemd/system/prometheus.service << EOF
[Unit]
Description=Prometheus
After=network.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus --config.file /etc/prometheus/prometheus.yml --storage.tsdb.path /var/lib/prometheus
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable prometheus grafana-server node-exporter
systemctl start prometheus grafana-server node-exporter
"
# 3. Настраиваем Telegram уведомления
sudo nano /opt/scripts/telegram-alert.sh
#!/bin/bash
# Отправка критичных алертов в Telegram
TELEGRAM_BOT_TOKEN="YOUR_BOT_TOKEN" # Получи у @BotFather
CHAT_ID="YOUR_CHAT_ID" # Твой chat ID
MESSAGE="$1"
SEVERITY="$2"
SERVER_NAME=$(hostname)
# Выбираем эмодзи в зависимости от серьезности
case "$SEVERITY" in
"CRITICAL") EMOJI="🚨" ;;
"WARNING") EMOJI="⚠️" ;;
"INFO") EMOJI="ℹ️" ;;
*) EMOJI="📢" ;;
esac
# Формируем сообщение
FULL_MESSAGE="${EMOJI} *${SEVERITY}* on *${SERVER_NAME}*
${MESSAGE}
Time: $(date '+%Y-%m-%d %H:%M:%S')
Server: ${SERVER_NAME}"
# Отправляем в Telegram
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=${FULL_MESSAGE}" \
-d "parse_mode=Markdown" \
-d "disable_notification=false"
# Дублируем в локальный лог
echo "$(date): [$SEVERITY] $MESSAGE" >> /var/log/alerts.log
🔐 Настройка Telegram бота:
- Напиши @BotFather в Telegram
- Создай нового бота:
/newbot
- Получи токен и вставь в скрипт
- Узнай свой chat_id: напиши боту, затем перейди по https://api.telegram.org/botYOUR_TOKEN/getUpdates
📋 Чеклист финальной проверки
✅ Обязательная проверка перед продакшеном
sudo nano /opt/scripts/production-checklist.sh
#!/bin/bash
# Чеклист готовности к продакшену
echo "🔍 PRODUCTION READINESS CHECKLIST"
echo "=================================="
echo ""
TOTAL_CHECKS=0
PASSED_CHECKS=0
check_item() {
local description="$1"
local command="$2"
local expected="$3"
TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
printf "%-50s " "$description"
if eval "$command" >/dev/null 2>&1; then
if [ -z "$expected" ] || eval "$command" | grep -q "$expected"; then
echo "✅ PASS"
PASSED_CHECKS=$((PASSED_CHECKS + 1))
else
echo "❌ FAIL"
fi
else
echo "❌ FAIL"
fi
}
echo "🔒 SECURITY CHECKS:"
echo "─────────────────"
check_item "SSH password authentication disabled" "grep '^PasswordAuthentication no' /etc/ssh/sshd_config"
check_item "SSH running on non-standard port" "grep '^Port [0-9]' /etc/ssh/sshd_config" "Port 2222"
check_item "UFW firewall is active" "sudo ufw status" "Status: active"
check_item "Fail2ban is running" "sudo systemctl is-active fail2ban" "active"
check_item "Root login disabled" "grep '^PermitRootLogin no' /etc/ssh/sshd_config"
echo ""
echo "📦 CONTAINER CHECKS:"
echo "──────────────────"
for container in $(sudo lxc-ls -1 2>/dev/null); do
check_item "Container $container is running" "sudo lxc-info -n $container -s" "RUNNING"
done
echo ""
echo "🌐 NETWORK CHECKS:"
echo "────────────────"
check_item "Nginx is running" "sudo systemctl is-active nginx" "active"
check_item "Port 80 is listening" "sudo netstat -tuln | grep ':80 '"
check_item "Port 443 is listening" "sudo netstat -tuln | grep ':443 '"
check_item "DNS resolution working" "nslookup google.com"
echo ""
echo "💾 BACKUP CHECKS:"
echo "───────────────"
check_item "Backup configuration exists" "test -f /opt/scripts/backup-config.env"
check_item "Restic is installed" "which restic"
check_item "Backup script is executable" "test -x /opt/scripts/full-backup.sh"
check_item "Backup cron job exists" "sudo crontab -l | grep backup"
echo ""
echo "📊 MONITORING CHECKS:"
echo "───────────────────"
check_item "Monitoring container exists" "sudo lxc-ls | grep -q monitoring"
check_item "Dashboard script exists" "test -x /opt/scripts/server-dashboard.sh"
check_item "Diagnostic script exists" "test -x /opt/scripts/full-diagnostics.sh"
echo ""
echo "⚡ PERFORMANCE CHECKS:"
echo "────────────────────"
check_item "System load is reasonable" "test $(cat /proc/loadavg | cut -d' ' -f1 | cut -d'.' -f1) -lt 4"
check_item "Free memory available" "test $(free | awk 'NR==2{print ($4/$2)*100}' | cut -d'.' -f1) -gt 20"
check_item "Root filesystem not full" "test $(df / | awk 'NR==2{print $5}' | sed 's/%//') -lt 90"
check_item "All containers have resource limits" "test $(sudo lxc-ls -1 | wc -l) -eq $(grep -l 'lxc.cgroup2.memory.max' /var/lib/lxc/*/config | wc -l)"
echo ""
echo "═════════════════════════════════════════════════════════════"
echo "📊 RESULTS: $PASSED_CHECKS/$TOTAL_CHECKS checks passed"
if [ $PASSED_CHECKS -eq $TOTAL_CHECKS ]; then
echo "🎉 ALL CHECKS PASSED! Server is production ready!"
echo ""
echo "🚀 Next steps:"
echo " 1. Run a backup test: /opt/scripts/full-backup.sh"
echo " 2. Monitor for 24h: /opt/scripts/monitor-containers.sh"
echo " 3. Set up alerting: /opt/scripts/telegram-alert.sh"
exit 0
else
echo "⚠️ Some checks failed. Please fix issues before production!"
exit 1
fi
🎯 Итог: Теперь у тебя есть enterprise-уровня инфраструктура с подробными примерами, мониторингом, диагностикой и чеклистом готовности!
🚀 Продвинутые оптимизации для AMD Ryzen 7 7700 сервера
Дополнительные критичные настройки для максимальной производительности и надёжности
1. 🎯 Гибкое управление ресурсами: приоритеты и жёсткие лимиты
Задача
Создать систему, где:
- Второстепенные сайты получают максимум 5% CPU (жёсткий лимит)
- Главный сайт получает 90% CPU как soft лимит + возможность burst до 100% при нагрузке
- Автоматическое перераспределение ресурсов в зависимости от загрузки
🔧 Реализация через cgroups v2
Создание скрипта гибких лимитов:
sudo nano /opt/scripts/flexible-resource-limits.sh
#!/bin/bash
# Гибкое управление ресурсами контейнеров с приоритетами
CONTAINER_NAME=$1
PRIORITY=$2 # high, medium, low, critical
CPU_CORES=$(nproc) # Общее количество ядер (16 для Ryzen 7700 с SMT)
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <container_name> <priority>"
echo "Priorities: critical, high, medium, low"
echo ""
echo "Examples:"
echo " $0 main-shop critical # 90% CPU, burst до 100%"
echo " $0 blog-site high # 30% CPU, burst до 50%"
echo " $0 test-site low # 5% CPU, жёсткий лимит"
exit 1
fi
echo "⚙️ Настраиваем приоритеты для контейнера: $CONTAINER_NAME (приоритет: $PRIORITY)"
# Останавливаем контейнер для изменения конфигурации
sudo lxc-stop -n $CONTAINER_NAME 2>/dev/null
# Создаём backup конфигурации
sudo cp /var/lib/lxc/$CONTAINER_NAME/config /var/lib/lxc/$CONTAINER_NAME/config.backup
# Удаляем старые лимиты
sudo sed -i '/lxc.cgroup2.cpu/d' /var/lib/lxc/$CONTAINER_NAME/config
sudo sed -i '/lxc.cgroup2.memory/d' /var/lib/lxc/$CONTAINER_NAME/config
case "$PRIORITY" in
"critical")
# Главный сайт: 90% soft limit, может использовать до 100% при необходимости
CPU_SOFT_LIMIT=$((CPU_CORES * 90 / 100)) # 14.4 ядра
CPU_HARD_LIMIT=$CPU_CORES # 16 ядер максимум
MEMORY_LIMIT="16G" # Много памяти
CPU_WEIGHT="1000" # Максимальный приоритет
echo "🔥 CRITICAL: Soft ${CPU_SOFT_LIMIT} cores, Hard ${CPU_HARD_LIMIT} cores, RAM ${MEMORY_LIMIT}"
;;
"high")
# Важный сайт: 30% soft, burst до 50%
CPU_SOFT_LIMIT=$((CPU_CORES * 30 / 100)) # 4.8 ядра
CPU_HARD_LIMIT=$((CPU_CORES * 50 / 100)) # 8 ядер максимум
MEMORY_LIMIT="4G"
CPU_WEIGHT="500"
echo "⭐ HIGH: Soft ${CPU_SOFT_LIMIT} cores, Hard ${CPU_HARD_LIMIT} cores, RAM ${MEMORY_LIMIT}"
;;
"medium")
# Обычный сайт: 15% soft, burst до 25%
CPU_SOFT_LIMIT=$((CPU_CORES * 15 / 100)) # 2.4 ядра
CPU_HARD_LIMIT=$((CPU_CORES * 25 / 100)) # 4 ядра максимум
MEMORY_LIMIT="2G"
CPU_WEIGHT="200"
echo "📊 MEDIUM: Soft ${CPU_SOFT_LIMIT} cores, Hard ${CPU_HARD_LIMIT} cores, RAM ${MEMORY_LIMIT}"
;;
"low")
# Тестовый/неважный сайт: жёсткий лимит 5%
CPU_SOFT_LIMIT=$((CPU_CORES * 5 / 100)) # 0.8 ядра
CPU_HARD_LIMIT=$CPU_SOFT_LIMIT # Никакого burst!
MEMORY_LIMIT="512M"
CPU_WEIGHT="50" # Минимальный приоритет
echo "⬇️ LOW: Hard limit ${CPU_HARD_LIMIT} cores, RAM ${MEMORY_LIMIT}"
;;
*)
echo "❌ Неизвестный приоритет: $PRIORITY"
exit 1
;;
esac
# Применяем настройки CPU
# Soft limit (средний уровень потребления)
SOFT_QUOTA=$((CPU_SOFT_LIMIT * 100000))
echo "lxc.cgroup2.cpu.max = $SOFT_QUOTA 100000" >> /var/lib/lxc/$CONTAINER_NAME/config
# Hard limit (максимальный burst)
if [ "$CPU_HARD_LIMIT" != "$CPU_SOFT_LIMIT" ]; then
HARD_QUOTA=$((CPU_HARD_LIMIT * 100000))
echo "lxc.cgroup2.cpu.max.burst = $HARD_QUOTA 100000" >> /var/lib/lxc/$CONTAINER_NAME/config
fi
# CPU Weight (приоритет при конкуренции за ресурсы)
echo "lxc.cgroup2.cpu.weight = $CPU_WEIGHT" >> /var/lib/lxc/$CONTAINER_NAME/config
# Лимиты памяти
echo "lxc.cgroup2.memory.max = $MEMORY_LIMIT" >> /var/lib/lxc/$CONTAINER_NAME/config
echo "lxc.cgroup2.memory.swap.max = 0" >> /var/lib/lxc/$CONTAINER_NAME/config
# Настройки I/O (дисковые операции)
case "$PRIORITY" in
"critical") IO_WEIGHT="1000" ;;
"high") IO_WEIGHT="500" ;;
"medium") IO_WEIGHT="200" ;;
"low") IO_WEIGHT="50" ;;
esac
echo "lxc.cgroup2.io.weight = $IO_WEIGHT" >> /var/lib/lxc/$CONTAINER_NAME/config
# Запускаем контейнер
echo "▶️ Запускаем контейнер с новыми настройками..."
sudo lxc-start -n $CONTAINER_NAME
# Ждём запуска
sleep 5
# Проверяем результат
if sudo lxc-info -n $CONTAINER_NAME | grep -q "RUNNING"; then
echo "✅ Контейнер успешно запущен!"
echo ""
echo "📊 Настройки ресурсов:"
echo " Приоритет: $PRIORITY"
echo " CPU Soft: ${CPU_SOFT_LIMIT} cores"
echo " CPU Hard: ${CPU_HARD_LIMIT} cores"
echo " Memory: $MEMORY_LIMIT"
echo " CPU Weight: $CPU_WEIGHT"
echo " IO Weight: $IO_WEIGHT"
# Создаём запись в реестре для мониторинга
echo "$CONTAINER_NAME:$PRIORITY:$(date)" >> /opt/scripts/container-priorities.log
else
echo "❌ Ошибка запуска контейнера!"
# Восстанавливаем backup
sudo cp /var/lib/lxc/$CONTAINER_NAME/config.backup /var/lib/lxc/$CONTAINER_NAME/config
exit 1
fi
Практические примеры использования:
# Делаем исполняемым
chmod +x /opt/scripts/flexible-resource-limits.sh
# Главный интернет-магазин - критичный приоритет
./flexible-resource-limits.sh main-shop critical
# Корпоративный блог - высокий приоритет
./flexible-resource-limits.sh company-blog high
# Личный сайт - средний приоритет
./flexible-resource-limits.sh personal-site medium
# Тестовая площадка - низкий приоритет (жёсткий лимит 5%)
./flexible-resource-limits.sh test-env low
📊 Мониторинг распределения ресурсов:
sudo nano /opt/scripts/priority-monitor.sh
#!/bin/bash
# Мониторинг использования ресурсов по приоритетам
echo "🎯 RESOURCE ALLOCATION BY PRIORITY - $(date)"
echo "════════════════════════════════════════════════════════════════"
# Заголовки таблицы
printf "%-15s %-10s %-8s %-12s %-12s %-8s %-8s\n" \
"CONTAINER" "PRIORITY" "STATUS" "CPU_ACTUAL" "CPU_LIMIT" "RAM_USE" "RAM_LIMIT"
echo "────────────────────────────────────────────────────────────────────────────"
TOTAL_CPU_USAGE=0
CRITICAL_COUNT=0
HIGH_COUNT=0
MEDIUM_COUNT=0
LOW_COUNT=0
for container in $(sudo lxc-ls -1 2>/dev/null); do
# Получаем приоритет из лога
priority=$(grep "^$container:" /opt/scripts/container-priorities.log 2>/dev/null | tail -1 | cut -d':' -f2)
[ -z "$priority" ] && priority="unknown"
status=$(sudo lxc-info -n $container -s 2>/dev/null | grep State | awk '{print $2}')
if [ "$status" = "RUNNING" ]; then
# Получаем актуальное использование CPU (примерно)
cpu_actual=$(sudo lxc-attach -n $container -- top -bn1 2>/dev/null | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
[ -z "$cpu_actual" ] && cpu_actual="0"
# Получаем лимиты из конфигурации
cpu_limit=$(grep "lxc.cgroup2.cpu.max" /var/lib/lxc/$container/config | awk '{print $3/100000}' | head -1)
[ -z "$cpu_limit" ] && cpu_limit="unlimited"
# Получаем использование памяти
ram_use=$(sudo lxc-attach -n $container -- free -h 2>/dev/null | grep '^Mem:' | awk '{print $3}')
ram_limit=$(grep "lxc.cgroup2.memory.max" /var/lib/lxc/$container/config | awk '{print $3}')
# Считаем по приоритетам
case "$priority" in
"critical") CRITICAL_COUNT=$((CRITICAL_COUNT + 1)) ;;
"high") HIGH_COUNT=$((HIGH_COUNT + 1)) ;;
"medium") MEDIUM_COUNT=$((MEDIUM_COUNT + 1)) ;;
"low") LOW_COUNT=$((LOW_COUNT + 1)) ;;
esac
TOTAL_CPU_USAGE=$(echo "$TOTAL_CPU_USAGE + $cpu_actual" | bc -l)
else
cpu_actual="--"
cpu_limit="--"
ram_use="--"
ram_limit="--"
fi
# Цветовая индикация приоритета
case "$priority" in
"critical") priority_display="🔥 CRIT" ;;
"high") priority_display="⭐ HIGH" ;;
"medium") priority_display="📊 MED" ;;
"low") priority_display="⬇️ LOW" ;;
*) priority_display="❓ UNK" ;;
esac
printf "%-15s %-10s %-8s %-12s %-12s %-8s %-8s\n" \
"$container" "$priority_display" "$status" "${cpu_actual}%" "$cpu_limit" "$ram_use" "$ram_limit"
done
echo ""
echo "📈 SUMMARY:"
echo "Total CPU Usage: ${TOTAL_CPU_USAGE}%"
echo "Containers by priority: CRITICAL($CRITICAL_COUNT), HIGH($HIGH_COUNT), MEDIUM($MEDIUM_COUNT), LOW($LOW_COUNT)"
# Проверяем не превышают ли лимиты
if (( $(echo "$TOTAL_CPU_USAGE > 80" | bc -l) )); then
echo "⚠️ WARNING: High CPU usage detected! Consider rebalancing priorities."
fi
2. 🔥 AMD Ryzen 7 7700: SMT и AMD-V настройки
Критичная важность для виртуализации
AMD Ryzen 7 7700 имеет:
- 8 физических ядер
- SMT (Simultaneous Multithreading) = 16 логических потоков
- AMD-V (Virtualization) — аппаратная виртуализация
- IOMMU — изоляция памяти для безопасности
🚨 БЕЗ правильной настройки ты теряешь 30-60% производительности!
Пошаговая настройка:
Шаг 1: Настройка BIOS/UEFI
Обязательные настройки в BIOS:
При загрузке: Del или F2 → Advanced Settings
🔧 CPU Configuration:
├─ AMD SVM Mode: [ENABLED] ⚠️ КРИТИЧНО!
├─ SMT (Simultaneous Multithreading): [ENABLED]
├─ Core Performance Boost: [ENABLED]
└─ Precision Boost Overdrive: [ENABLED]
🔧 Advanced → Chipset Configuration:
├─ IOMMU: [ENABLED] ⚠️ Для безопасности контейнеров
└─ ACS Enable: [ENABLED]
🔧 Power Management:
├─ Power Supply Idle Control: [Low Current Idle]
├─ CPPC: [ENABLED]
└─ Global C-state Control: [DISABLED] (для стабильной производительности)
Шаг 2: Проверка после загрузки
# Создаём скрипт проверки AMD настроек
sudo nano /opt/scripts/check-amd-features.sh
#!/bin/bash
# Проверка корректной настройки AMD Ryzen 7 7700
echo "🔍 AMD Ryzen 7 7700 Configuration Check"
echo "══════════════════════════════════════════════════════════"
# 1. Информация о процессоре
echo "💻 CPU Information:"
CPU_MODEL=$(lscpu | grep "Model name" | cut -d':' -f2 | xargs)
echo " Model: $CPU_MODEL"
# 2. Проверка SMT (должно быть 2 потока на ядро)
THREADS_PER_CORE=$(lscpu | grep "Thread(s) per core" | awk '{print $4}')
CORES=$(lscpu | grep "^CPU(s):" | awk '{print $2}')
PHYSICAL_CORES=$(lscpu | grep "Core(s) per socket" | awk '{print $4}')
echo " Physical cores: $PHYSICAL_CORES"
echo " Logical cores: $CORES"
echo " Threads per core: $THREADS_PER_CORE"
if [ "$THREADS_PER_CORE" = "2" ]; then
echo " ✅ SMT is ENABLED (16 logical cores available)"
else
echo " ❌ SMT is DISABLED! Enable in BIOS for better performance!"
exit 1
fi
# 3. Проверка AMD-V (виртуализация)
echo ""
echo "🚀 Virtualization Support:"
if grep -q "svm" /proc/cpuinfo; then
echo " ✅ AMD-V (SVM) is ENABLED"
else
echo " ❌ AMD-V is DISABLED! Enable SVM Mode in BIOS!"
exit 1
fi
# 4. Проверка IOMMU
echo ""
echo "🔒 IOMMU Support:"
if [ -d "/sys/kernel/iommu_groups" ] && [ "$(ls /sys/kernel/iommu_groups | wc -l)" -gt 0 ]; then
IOMMU_COUNT=$(ls /sys/kernel/iommu_groups | wc -l)
echo " ✅ IOMMU is ENABLED ($IOMMU_COUNT groups found)"
else
echo " ⚠️ IOMMU is DISABLED (less secure container isolation)"
fi
# 5. Проверка KVM готовности
echo ""
echo "📦 Container/VM Support:"
if [ -c /dev/kvm ]; then
echo " ✅ KVM device available"
else
echo " ❌ KVM device not found"
fi
# Устанавливаем cpu-checker если не установлен
if ! command -v kvm-ok >/dev/null 2>&1; then
echo " Installing cpu-checker..."
sudo apt update && sudo apt install -y cpu-checker >/dev/null 2>&1
fi
KVM_CHECK=$(kvm-ok 2>&1)
if echo "$KVM_CHECK" | grep -q "KVM acceleration can be used"; then
echo " ✅ KVM acceleration available"
else
echo " ❌ KVM acceleration not available:"
echo " $KVM_CHECK"
fi
# 6. Проверка LXC поддержки
echo ""
echo "🐧 LXC Support:"
if command -v lxc-checkconfig >/dev/null 2>&1; then
LXC_MISSING=$(lxc-checkconfig 2>&1 | grep -i "missing\|required" | wc -l)
if [ "$LXC_MISSING" -eq 0 ]; then
echo " ✅ LXC fully supported"
else
echo " ⚠️ LXC has $LXC_MISSING missing features"
echo " Details: $(lxc-checkconfig 2>&1 | grep -i "missing\|required" | head -3)"
fi
else
echo " ❌ LXC not installed"
fi
# 7. CPU Governor и частоты
echo ""
echo "⚡ CPU Performance:"
GOVERNOR=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "unknown")
echo " CPU Governor: $GOVERNOR"
if [ "$GOVERNOR" = "performance" ]; then
echo " ✅ Performance governor active"
elif [ "$GOVERNOR" = "ondemand" ]; then
echo " ⚠️ OnDemand governor (good for servers)"
else
echo " ❓ Governor: $GOVERNOR"
fi
# Показываем текущие частоты
echo " Current frequencies:"
for i in {0..15}; do
if [ -f "/sys/devices/system/cpu/cpu$i/cpufreq/scaling_cur_freq" ]; then
freq=$(cat /sys/devices/system/cpu/cpu$i/cpufreq/scaling_cur_freq)
freq_mhz=$((freq / 1000))
echo " CPU$i: ${freq_mhz}MHz"
fi
done | head -4
echo " ... (showing first 4 cores)"
# 8. Температурный мониторинг
echo ""
echo "🌡️ Temperature Monitoring:"
if command -v sensors >/dev/null 2>&1; then
CPU_TEMP=$(sensors 2>/dev/null | grep -i "Tctl\|Package" | head -1 | awk '{print $2}')
echo " CPU Temperature: $CPU_TEMP"
else
echo " ❌ lm-sensors not installed. Install: sudo apt install lm-sensors"
fi
echo ""
echo "══════════════════════════════════════════════════════════"
# Итоговая проверка
ERRORS=0
if [ "$THREADS_PER_CORE" != "2" ]; then
echo "❌ CRITICAL: SMT disabled"
ERRORS=$((ERRORS + 1))
fi
if ! grep -q "svm" /proc/cpuinfo; then
echo "❌ CRITICAL: AMD-V disabled"
ERRORS=$((ERRORS + 1))
fi
if [ ! -c /dev/kvm ]; then
echo "❌ ERROR: KVM not available"
ERRORS=$((ERRORS + 1))
fi
if [ "$ERRORS" -eq 0 ]; then
echo "🎉 ALL CHECKS PASSED! AMD Ryzen 7 7700 is optimally configured!"
echo ""
echo "💪 Your server can handle:"
echo " • 20+ lightweight containers (0.5-1 core each)"
echo " • 10-15 WordPress sites (1-2 cores each)"
echo " • 4-8 high-performance applications (2-4 cores each)"
echo " • Full 16-thread parallel processing power"
else
echo "⚠️ $ERRORS CRITICAL ISSUES found! Fix them for optimal performance."
exit 1
fi
Шаг 3: Оптимизация для контейнеров
# Оптимизация системы для AMD Ryzen 7700
sudo nano /etc/sysctl.d/99-amd-optimization.conf
# AMD Ryzen 7 7700 оптимизации для контейнеров
# CPU планировщик для многопоточности
kernel.sched_migration_cost_ns = 5000000
kernel.sched_autogroup_enabled = 0
kernel.sched_wakeup_granularity_ns = 15000000
# SMT оптимизации
kernel.sched_smt_power_savings = 0
# Виртуальная память для большого количества контейнеров
vm.max_map_count = 262144
vm.overcommit_memory = 1
vm.overcommit_ratio = 80
# Файловая система (для NVMe SSD)
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50
# Сетевые оптимизации для контейнеров
net.core.somaxconn = 32768
net.ipv4.ip_local_port_range = 1024 65535
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
# Применяем настройки
sudo sysctl -p /etc/sysctl.d/99-amd-optimization.conf
Примеры использования 16 потоков:
# Пример 1: Равномерное распределение
./flexible-resource-limits.sh shop1 medium # 2.4 ядра
./flexible-resource-limits.sh shop2 medium # 2.4 ядра
./flexible-resource-limits.sh blog1 low # 0.8 ядра
./flexible-resource-limits.sh blog2 low # 0.8 ядра
./flexible-resource-limits.sh api1 high # 4.8 ядра
./flexible-resource-limits.sh main critical # 5.6 ядра
# Итого: ~16 ядер полностью использованы
# Пример 2: Один доминирующий сайт
./flexible-resource-limits.sh main-site critical # 14.4 ядра + burst до 16
./flexible-resource-limits.sh test1 low # 0.8 ядра
./flexible-resource-limits.sh test2 low # 0.8 ядра
# Итого: главный сайт получает практически все ресурсы
3. 💾 Software RAID 1 для 2x 1TB NVMe SSD
Задача безопасности данных
С двумя NVMe дисками нужно настроить зеркалирование (RAID 1):
- Данные одновременно пишутся на оба диска
- При отказе одного диска система продолжает работать
- Автоматическое восстановление при замене диска
🔧 Настройка RAID 1 при установке системы
Вариант A: Настройка через Hetzner installimage
# Во время установки через rescue система
installimage
# В конфигурации диска используй:
PART /boot ext4 1G
PART / ext4 100G raid1
PART /var ext4 400G raid1
PART /home ext4 all raid1
# Система автоматически создаст RAID 1
Вариант B: Ручная настройка после установки
# ⚠️ ВНИМАНИЕ: Этот метод удалит все данные!
# Используй только на новом сервере или с полным бэкапом
sudo nano /opt/scripts/setup-raid1.sh
#!/bin/bash
# Настройка Software RAID 1 для двух NVMe дисков
DISK1="/dev/nvme0n1" # Первый NVMe диск
DISK2="/dev/nvme1n1" # Второй NVMe диск
echo "🚨 ВНИМАНИЕ: Этот скрипт УДАЛИТ ВСЕ ДАННЫЕ на дисках!"
echo "Диски для RAID 1: $DISK1 и $DISK2"
echo ""
read -p "Вы уверены? Введите 'YES' для продолжения: " confirm
if [ "$confirm" != "YES" ]; then
echo "Отменено пользователем"
exit 1
fi
echo "🔧 Начинаем настройку RAID 1..."
# 1. Устанавливаем необходимые пакеты
apt update
apt install -y mdadm parted gdisk
# 2. Очищаем диски
echo "🧹 Очищаем диски..."
wipefs -a $DISK1
wipefs -a $DISK2
# 3. Создаём разделы на обоих дисках
echo "📀 Создаём разделы..."
# Диск 1
parted $DISK1 --script mklabel gpt
parted $DISK1 --script mkpart primary 1MiB 513MiB # /boot (512MB)
parted $DISK1 --script mkpart primary 513MiB 50GiB # / (50GB)
parted $DISK1 --script mkpart primary 50GiB 100% # /var+/home (остальное)
parted $DISK1 --script set 1 boot on
parted $DISK1 --script set 2 raid on
parted $DISK1 --script set 3 raid on
# Диск 2 (идентично)
parted $DISK2 --script mklabel gpt
parted $DISK2 --script mkpart primary 1MiB 513MiB
parted $DISK2 --script mkpart primary 513MiB 50GiB
parted $DISK2 --script mkpart primary 50GiB 100%
parted $DISK2 --script set 1 boot on
parted $DISK2 --script set 2 raid on
parted $DISK2 --script set 3 raid on
# Ждём создания устройств
sleep 3
# 4. Создаём RAID массивы
echo "🔗 Создаём RAID 1 массивы..."
# RAID 1 для /boot (зеркалирование загрузчика)
mdadm --create /dev/md0 --level=1 --raid-devices=2 ${DISK1}p1 ${DISK2}p1
# RAID 1 для / (корневая система)
mdadm --create /dev/md1 --level=1 --raid-devices=2 ${DISK1}p2 ${DISK2}p2
# RAID 1 для /var (данные контейнеров)
mdadm --create /dev/md2 --level=1 --raid-devices=2 ${DISK1}p3 ${DISK2}p3
# 5. Ждём синхронизации
echo "⏳ Ждём инициализации RAID массивов (это может занять время)..."
sleep 10
# 6. Создаём файловые системы
echo "📁 Создаём файловые системы..."
mkfs.ext4 -L boot /dev/md0
mkfs.ext4 -L root /dev/md1
mkfs.ext4 -L data /dev/md2
# 7. Сохраняем конфигурацию RAID
mdadm --detail --scan >> /etc/mdadm/mdadm.conf
# 8. Показываем статус
echo ""
echo "✅ RAID 1 настроен успешно!"
echo ""
echo "📊 Статус RAID массивов:"
cat /proc/mdstat
echo ""
echo "📋 Детальная информация:"
mdadm --detail /dev/md0
mdadm --detail /dev/md1
mdadm --detail /dev/md2
echo ""
echo "🚀 Следующие шаги:"
echo "1. Смонтируй разделы и установи систему"
echo "2. Настрой GRUB на оба диска"
echo "3. Проверь автозапуск RAID при загрузке"
📊 Мониторинг RAID состояния
sudo nano /opt/scripts/raid-monitor.sh
#!/bin/bash
# Мониторинг состояния RAID массивов
echo "💾 RAID 1 Status Monitor - $(date)"
echo "═══════════════════════════════════════════════════════════════"
# 1. Общий статус всех RAID устройств
echo "📊 Overall RAID Status:"
if [ -f /proc/mdstat ]; then
cat /proc/mdstat
echo ""
else
echo "❌ No RAID devices found!"
exit 1
fi
# 2. Детальный статус каждого массива
for raid_device in $(ls /dev/md* 2>/dev/null); do
if [ -b "$raid_device" ]; then
echo "🔍 Detailed status for $raid_device:"
mdadm --detail $raid_device | grep -E "(State|Active Devices|Failed Devices|Spare Devices|Rebuild Status)"
echo ""
fi
done
# 3. Проверка дисков на ошибки
echo "🔧 Physical Disk Health:"
for disk in /dev/nvme0n1 /dev/nvme1n1; do
if [ -b "$disk" ]; then
echo "Disk $disk:"
# SMART статус (если доступен)
if command -v smartctl >/dev/null 2>&1; then
health=$(smartctl -H $disk 2>/dev/null | grep "SMART overall-health" | awk '{print $6}')
temp=$(smartctl -A $disk 2>/dev/null | grep Temperature | awk '{print $10}' | head -1)
echo " Health: $health"
echo " Temperature: ${temp}°C"
fi
# Проверка на bad blocks (примерная)
error_count=$(dmesg | grep -i "$disk" | grep -i "error" | wc -l)
echo " Error count in dmesg: $error_count"
echo ""
fi
done
# 4. Использование дискового пространства
echo "💽 Disk Space Usage:"
df -h | grep -E "(Filesystem|/dev/md)"
echo ""
# 5. Проверка на деградированное состояние
echo "⚠️ RAID Health Check:"
degraded_count=$(grep -E "\\[.*_.*\\]" /proc/mdstat | wc -l)
failed_count=$(grep -i "failed" /proc/mdstat | wc -l)
if [ "$degraded_count" -eq 0 ] && [ "$failed_count" -eq 0 ]; then
echo "✅ All RAID arrays are HEALTHY"
else
echo "🚨 WARNING: Found $degraded_count degraded and $failed_count failed arrays!"
echo ""
echo "🔧 Recovery commands:"
echo " Check failed disks: mdadm --detail /dev/mdX"
echo " Remove failed disk: mdadm /dev/mdX --remove /dev/sdXY"
echo " Add new disk: mdadm /dev/mdX --add /dev/sdXY"
echo " Monitor rebuild: watch cat /proc/mdstat"
# Отправка alert (если настроен)
if [ -x /opt/scripts/telegram-alert.sh ]; then
/opt/scripts/telegram-alert.sh "RAID degradation detected on $(hostname)" "CRITICAL"
fi
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo "💡 Run 'watch cat /proc/mdstat' for real-time monitoring"
🔧 Скрипт восстановления при отказе диска
sudo nano /opt/scripts/raid-recovery.sh
#!/bin/bash
# Автоматическое восстановление RAID при замене диска
NEW_DISK=$1 # Новый диск, например /dev/nvme1n1
if [ -z "$NEW_DISK" ]; then
echo "Usage: $0 <new_disk_device>"
echo "Example: $0 /dev/nvme1n1"
exit 1
fi
echo "🔧 RAID Recovery Tool"
echo "Новый диск: $NEW_DISK"
echo "══════════════════════════════════════════════════════════════"
# 1. Проверяем текущее состояние RAID
echo "📊 Current RAID status:"
cat /proc/mdstat
echo ""
# 2. Находим деградированные массивы
DEGRADED_ARRAYS=$(grep -l "degraded" /sys/block/md*/md/array_state 2>/dev/null)
if [ -z "$DEGRADED_ARRAYS" ]; then
echo "✅ No degraded RAID arrays found"
exit 0
fi
echo "🚨 Found degraded arrays:"
for array in $DEGRADED_ARRAYS; do
array_name=$(echo $array | cut -d'/' -f4)
echo " /dev/$array_name"
done
echo ""
# 3. Подготавливаем новый диск
echo "🛠️ Preparing new disk $NEW_DISK..."
# Получаем схему разделов с работающего диска
WORKING_DISK=$(lsblk -pno NAME | grep nvme | head -1)
echo "Using partition scheme from: $WORKING_DISK"
# Копируем схему разделов
sfdisk -d $WORKING_DISK | sfdisk $NEW_DISK
# Ждём создания разделов
sleep 3
echo "✅ Partitions created on $NEW_DISK"
# 4. Добавляем разделы в RAID массивы
echo ""
echo "🔄 Adding partitions to RAID arrays..."
for i in 1 2 3; do
raid_device="/dev/md$((i-1))"
new_partition="${NEW_DISK}p$i"
if [ -b "$raid_device" ]; then
echo "Adding $new_partition to $raid_device..."
mdadm $raid_device --add $new_partition
if [ $? -eq 0 ]; then
echo "✅ Successfully added $new_partition to $raid_device"
else
echo "❌ Failed to add $new_partition to $raid_device"
fi
fi
done
# 5. Показываем прогресс восстановления
echo ""
echo "⏳ Rebuild progress:"
watch -n 5 'cat /proc/mdstat; echo ""; echo "Progress details:"; for md in /dev/md*; do mdadm --detail $md 2>/dev/null | grep -E "(State|Rebuild Status)"; done'
📈 Практические кейсы использования
Кейс 1: Мониторинг производительности RAID
# Создаём скрипт для benchmarking RAID
sudo nano /opt/scripts/raid-performance-test.sh
#!/bin/bash
# Тест производительности RAID 1 на NVMe дисках
echo "🚀 RAID 1 Performance Test on NVMe"
echo "═══════════════════════════════════════════════════════════════"
# Создаём тестовый каталог
TEST_DIR="/tmp/raid-test"
mkdir -p $TEST_DIR
# 1. Sequential Read Test
echo "📖 Sequential Read Test (1GB file):"
dd if=/dev/zero of=$TEST_DIR/testfile bs=1M count=1024 oflag=direct 2>&1 | grep copied
echo "Sequential Write Test (1GB file):"
time sh -c "dd if=$TEST_DIR/testfile of=/dev/null bs=1M iflag=direct && sync"
# 2. Random I/O test (если fio установлен)
if command -v fio >/dev/null 2>&1; then
echo ""
echo "🎯 Random I/O Test:"
fio --name=random-rw --ioengine=libaio --rw=randrw --bs=4k --numjobs=4 \
--size=100m --runtime=30 --time_based --directory=$TEST_DIR \
--group_reporting --iodepth=8
else
echo ""
echo "💡 Install 'fio' for detailed I/O testing: apt install fio"
fi
# 3. Контейнер нагрузка тест
echo ""
echo "📦 Container Load Simulation:"
for i in {1..5}; do
echo "Creating container load simulation $i..."
dd if=/dev/zero of=$TEST_DIR/container$i bs=10M count=10 oflag=direct &
done
wait
echo "✅ All tests completed"
# Очистка
rm -rf $TEST_DIR
Кейс 2: Автоматический мониторинг в cron
# Добавляем регулярную проверку RAID
sudo crontab -e
# Добавить строки:
# Проверка RAID каждые 4 часа
0 */4 * * * /opt/scripts/raid-monitor.sh >> /var/log/raid-monitor.log
# Еженедельный отчёт о состоянии
0 8 * * 1 /opt/scripts/raid-monitor.sh | /opt/scripts/telegram-alert.sh "Weekly RAID status from $(hostname)" "INFO"
# Немедленный alert при проблемах
*/10 * * * * /opt/scripts/raid-monitor.sh | grep -q "WARNING\|CRITICAL" && /opt/scripts/telegram-alert.sh "RAID issue detected!" "CRITICAL"
Кейс 3: Интеграция RAID с системой бэкапов
# Модифицируем скрипт бэкапа для учёта RAID
sudo nano /opt/scripts/raid-aware-backup.sh
#!/bin/bash
# Бэкап с проверкой состояния RAID
source /opt/scripts/backup-config.env
echo "🔍 Checking RAID status before backup..."
# Проверяем RAID перед бэкапом
RAID_STATUS=$(cat /proc/mdstat | grep -c "\\[UU\\]")
EXPECTED_ARRAYS=3
if [ "$RAID_STATUS" -ne "$EXPECTED_ARRAYS" ]; then
echo "🚨 RAID arrays degraded! Found $RAID_STATUS healthy arrays, expected $EXPECTED_ARRAYS"
# Отправляем alert
/opt/scripts/telegram-alert.sh "RAID degraded during backup time on $(hostname)" "CRITICAL"
# Продолжаем бэкап но с предупреждением
echo "⚠️ Continuing backup despite RAID issues..."
fi
# Обычный процесс бэкапа
echo "💾 Starting backup process..."
# Создаём снапшот RAID информации для восстановления
mdadm --detail --scan > /tmp/mdadm.conf.backup
# Добавляем RAID конфигурацию в бэкап
restic backup \
/var/lib/lxc \
/etc \
/opt/scripts \
/tmp/mdadm.conf.backup \
--tag raid-aware-backup
echo "✅ RAID-aware backup completed"
🎯 Заключение
Эти три критичных аспекта кардинально влияют на производительность и надёжность сервера:
1. Гибкие лимиты ресурсов
- Позволяют выжать максимум из 16 потоков Ryzen 7700
- Защищают главные сайты от «соседей»
- Автоматически адаптируются к нагрузке
2. Правильная настройка AMD-V + SMT
- Без SMT: только 8 ядер вместо 16 потоков (-50% мощности!)
- Без AMD-V: программная виртуализация (-30-60% производительности!)
- С правильными настройками: полная мощность 16-поточного монстра
3. RAID 1 на NVMe
- Абсолютная защита от потери данных
- NVMe скорость с надёжностью зеркалирования
- Автоматическое восстановление при отказах
🚀 Итоговая мощность сервера:
- AMD Ryzen 7 7700: 8 ядер × SMT = 16 потоков
- 2× NVMe Gen4: ~7000 MB/s чтение с отказоустойчивостью
- 64GB DDR5: поддержка десятков контейнеров
- Гибкие лимиты: оптимальное распределение нагрузки
С этими настройками твой сервер работает на 100% возможностей! 🔥