Руководство по развертыванию защищенного статического веб-сервера на Debian 13
Введение
Данный документ описывает полный процесс настройки production-ready веб-сервера на базе Debian 13 (Trixie) с ядром 6.18.15. Целевая конфигурация предназначена для VPS с ограниченными ресурсами (1 vCPU, 2 GB RAM) и включает:
- Оптимизацию ядра Linux для сетевых нагрузок
- Веб-сервер Caddy с автоматическим HTTPS через Let’s Encrypt
- Встроенный rate limiter для защиты от DDoS-атак
- Reverse proxy для WebSocket
- Публикацию статического контента с правильной маршрутизацией
Документ отражает все технические нюансы, выявленные в ходе настройки, включая актуальные имена модулей ядра для kernel 6.x, корректный синтаксис внешних модулей Caddy и современные подходы к управлению capabilities через systemd.
1. Подготовка системы
1.1. Обновление базовой системы
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget gnupg2 ca-certificates lsb-release \
debian-keyring debian-archive-keyring apt-transport-https \
software-properties-common build-essential git1.2. Создание swap-файла
Для VPS с 2 GB RAM наличие swap-файла является обязательным для предотвращения OOM Killer при пиковых нагрузках.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Проверка
free -h | grep Swap1.3. Проверка версии ядра
uname -rТребуется ядро версии 6.18.x или новее.
2. Конфигурирование модулей ядра
В ядре 6.x произошло массовое переименование crypto-модулей с подчеркиваний на дефисы. Ниже приведен список, верифицированный для Debian 13 с kernel 6.18.15 на AMD CPU.
2.1. Создание конфигурации автозагрузки
sudo tee /etc/modules-load.d/vps.conf <<'EOF'
# =============================================================================
# Kernel modules for VPS: Caddy
# Debian 13, kernel 6.18.15, AMD CPU
# Имена модулей актуализированы для kernel 6.x (дефисы вместо подчеркиваний)
# Верифицировано через: find /lib/modules/$(uname -r) -name "*.ko*"
# =============================================================================
# === Туннелирование (для TUN inbound) ===
tun
# === Сетевые алгоритмы (критично для производительности TCP) ===
# BBR congestion control - максимизирует throughput через интернет с потерями
tcp_bbr
# Fair Queue - оптимальный qdisc для BBR, управляет очередями пакетов
sch_fq
# === Криптография с аппаратным ускорением ===
# AES-NI (флаг CPU: aes) - HW-ускорение TLS AES-GCM
aesni-intel
# GHASH через PCLMULQDQ (флаг CPU: pclmulqdq) - критично для AES-GCM
ghash-clmulni-intel
# ChaCha20-Poly1305 AEAD (флаги CPU: avx2, ssse3) - TLS fallback cipher
chacha20poly1305
# NHPoly1305 для Adiantum/fscrypt (флаги CPU: avx2, sse2)
nhpoly1305
nhpoly1305-avx2
nhpoly1305-sse2
# === Netfilter (firewall + conntrack + NAT) ===
nf_tables
nft_chain_nat
nf_conntrack
nf_nat
nf_log_syslog
# === НЕ загружать явно (встроено в ядро) ===
# SHA-1/SHA-256/SHA-512: CONFIG_CRYPTO_SHA256=y
# Curve25519: подтягивается автоматически через libcurve25519
# Poly1305: подтягивается автоматически через libpoly1305
# Базовый AES: CONFIG_CRYPTO_AES=y (но aesni-intel даёт HW-ускорение)
EOF2.2. Применение и проверка
sudo systemctl restart systemd-modules-load.service
sudo systemctl status systemd-modules-load.service --no-pager
journalctl -u systemd-modules-load.service -n 20 --no-pager | grep -E "Inserted|Failed"Ожидаемый результат - все модули загружены без ошибок “Failed to find module”.
lsmod | grep -E "tcp_bbr|sch_fq|aesni|ghash|chacha|nf_conntrack"2.3. Верификация доступности crypto-алгоритмов
cat /proc/crypto | grep -B1 "gcm(aes)" | head -4
# Ожидаемо: name: gcm(aes) / module: aesni_intel
cat /proc/crypto | grep -B1 "sha256" | head -4
# Ожидаемо: name: sha256 / module: kernel (встроено)3. Конфигурирование параметров ядра (sysctl)
Параметры оптимизированы для VPS с 2 GB RAM и сценария reverse proxy.
3.1. Создание конфигурации sysctl
sudo tee /etc/sysctl.d/99-vps.conf <<'EOF'
# =============================================================================
# VPS Server Tuning - Debian 13 / Kernel 6.18.15 / 2GB RAM
# =============================================================================
# === IP Forwarding (для маршрутизации трафика) ===
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
# === Reverse Path Filtering (защита от IP spoofing) ===
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# === Отключение source routing и redirects (безопасность) ===
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# === SYN Cookies (защита от SYN flood) ===
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
# === TCP Congestion Control ===
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
# === TCP Buffer Sizes (оптимизировано для 2GB RAM) ===
net.ipv4.tcp_rmem = 4096 262144 16777216
net.ipv4.tcp_wmem = 4096 262144 16777216
# === TCP Performance Optimizations ===
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
# === Conntrack (таблица соединений для firewall + NAT) ===
# 262144 записей x ~300 bytes = ~75MB RAM (приемлемо для 2GB)
net.netfilter.nf_conntrack_max = 262144
net.nf_conntrack_max = 262144
net.netfilter.nf_conntrack_tcp_timeout_established = 43200
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 120
# === Network Queues (оптимизировано для 1 vCPU) ===
net.core.netdev_max_backlog = 16384
net.core.somaxconn = 8192
# === Kernel Security Hardening ===
kernel.sysrq = 0
kernel.yama.ptrace_scope = 1
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1
kernel.unprivileged_bpf_disabled = 1
# === File Descriptors ===
fs.file-max = 2097152
fs.nr_open = 2097152
# === Virtual Memory (критично для 2GB RAM) ===
vm.swappiness = 30
vm.vfs_cache_pressure = 75
vm.dirty_background_ratio = 3
vm.dirty_ratio = 10
vm.min_free_kbytes = 45056
EOF3.2. Применение параметров
sudo sysctl --system
# Проверка критичных параметров
sysctl net.ipv4.tcp_congestion_control net.core.default_qdisc
sysctl net.netfilter.nf_conntrack_max
sysctl kernel.sysrq kernel.yama.ptrace_scope kernel.kptr_restrict3.3. Верификация BBR в действии
sysctl net.ipv4.tcp_available_congestion_control
# Ожидаемый вывод: reno bic cubic bbr
ss -ti | grep -i bbr | head -34. Установка базового Caddy
Caddy выбран как оптимальный веб-сервер благодаря автоматическому HTTPS, встроенной поддержке HTTP/3 (QUIC) и минимальной конфигурации.
4.1. Добавление официального репозитория
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \
sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \
sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update4.2. Установка стандартного пакета
sudo apt install -y caddy
caddy version
sudo systemctl status caddy --no-pagerСтандартный пакет Caddy из репозитория Debian не содержит модуль rate limiting. Для production-конфигурации с защитой от DDoS требуется сборка через xcaddy (раздел 5).
5. Сборка Caddy с модулем rate limiter
Модуль github.com/mholt/caddy-ratelimit является внешним модулем и не входит в стандартную поставку Caddy. Требуется самостоятельная компиляция.
5.1. Установка Go
cd /tmp
wget https://go.dev/dl/go1.24.4.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.24.4.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> ~/.bashrc
source ~/.bashrc
go version5.2. Установка xcaddy
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
xcaddy version5.3. Компиляция Caddy с модулями
mkdir -p ~/caddy-build && cd ~/caddy-build
xcaddy build \
--with github.com/mholt/caddy-ratelimit \
--with github.com/caddyserver/transform-encoder \
--output /tmp/caddy
/tmp/caddy version
/tmp/caddy list-modules | grep -iE "rate|transform"Ожидаемый вывод должен содержать http.handlers.rate_limit.
5.4. Замена системного Caddy
sudo systemctl stop caddy
sudo cp /usr/bin/caddy /usr/bin/caddy.orig
sudo cp /tmp/caddy /usr/bin/caddy
sudo chown root:root /usr/bin/caddy
sudo chmod +x /usr/bin/caddy
sudo systemctl start caddy5.5. Настройка capabilities через systemd (современный подход)
Использование setcap на бинарнике требует capability CAP_SETFCAP, которую systemd не предоставляет сервисам по соображениям безопасности. Правильный подход - использование AmbientCapabilities в unit-файле.
sudo mkdir -p /etc/systemd/system/caddy.service.d
sudo tee /etc/systemd/system/caddy.service.d/capabilities.conf <<'EOF'
[Service]
# Дать возможность привязываться к портам 80/443 без setcap
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
# Очистить проблемный setcap из оригинального unit
ExecStartPre=
# Вернуть валидацию конфига
ExecStartPre=/usr/bin/caddy validate --config /etc/caddy/Caddyfile
EOF
sudo systemctl daemon-reloadУдаление capabilities с бинарника (если были установлены ранее):
sudo setcap -r /usr/bin/caddy
getcap /usr/bin/caddy
# Вывод должен быть пустым6. Настройка HTTPS с Let’s Encrypt
Caddy автоматически получает и обновляет TLS-сертификаты Let’s Encrypt. Ниже приведены best practices для безопасной конфигурации.
6.1. Best practices для TLS-ключей
| Параметр | Рекомендация | Обоснование |
|---|---|---|
| Тип ключа | ECDSA P-256 (по умолчанию) | Быстрее RSA, меньше размер сертификата, сопоставимая безопасность |
| Альтернатива | ECDSA P-384 | Выше уровень безопасности, чуть медленнее |
| Протокол | TLS 1.3 + TLS 1.2 | TLS 1.3 обязателен, TLS 1.2 для совместимости |
| Cipher suites | Modern (AES-GCM, ChaCha20) | Отключение устаревших алгоритмов |
| HSTS | Включен с preload | Защита от downgrade-атак |
| OCSP Stapling | Автоматически (Caddy) | Ускорение TLS handshake |
6.2. Создание директорий
sudo mkdir -p /var/www/html
sudo chown -R caddy:caddy /var/www/html
sudo chmod 755 /var/www/html
sudo mkdir -p /var/log/caddy
sudo chown caddy:caddy /var/log/caddy6.3. Подготовка DNS
Перед настройкой HTTPS необходимо:
- Зарегистрировать домен (например,
example.com) - Создать A-запись, указывающую на IP VPS
- Создать AAAA-запись (опционально, для IPv6)
- Дождаться распространения DNS (
dig example.com +short)
7. Публикация статического контента
7.1. Создание главной страницы
sudo tee /var/www/html/index.html <<'EOF'
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Главная - Защищенный сайт</title>
</head>
<body>
<h1>Главная страница</h1>
<nav>
<ul>
<li><a href="/about">О нас</a></li>
<li><a href="/products">Продукты</a></li>
<li><a href="/contact">Контакты</a></li>
</ul>
</nav>
</body>
</html>
EOF
sudo chown caddy:caddy /var/www/html/index.html7.2. Создание вложенных страниц
sudo tee /var/www/html/about.html <<'EOF'
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>О нас</title>
</head>
<body>
<h1>О нас</h1>
<p>Информация о компании.</p>
<a href="/">На главную</a>
</body>
</html>
EOF
sudo chown caddy:caddy /var/www/html/about.html7.3. Создание страницы ошибки 404
sudo tee /var/www/html/404.html <<'EOF'
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>404 - Страница не найдена</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 600px; margin: 10vh auto; text-align: center; }
.error-code { font-size: 6rem; color: #dc3545; margin: 0; }
</style>
</head>
<body>
<p class="error-code">404</p>
<h1>Страница не найдена</h1>
<p>Запрошенный ресурс не существует.</p>
<a href="/">Вернуться на главную</a>
</body>
</html>
EOF
sudo chown caddy:caddy /var/www/html/404.html8. Полная конфигурация Caddyfile
Ниже приведена финальная конфигурация, учитывающая все технические нюансы модуля caddy-ratelimit.
Ключевые особенности синтаксиса:
rate_limit- внешний модуль, требует xcaddy (см. раздел 5)- Зоны определяются в месте применения - каждый
handleсодержит полное определение своей зоны с параметрамиeventsиwindow(неrateиburst) try_files- отдельная директива верхнего уровня, размещается передfile_server, а не внутри негоhandle_errors- должен быть размещен после всехhandleдля корректной обработки ошибок с сохранением HTTP-статуса
Создание Caddyfile
sudo tee /etc/caddy/Caddyfile <<'EOF'
# =============================================================================
# Caddyfile for VPS: Static site + reverse proxy
# Debian 13, kernel 6.18.15, 2GB RAM
# Требует сборки через xcaddy с модулем github.com/mholt/caddy-ratelimit
# =============================================================================
# =============================================================================
# ГЛОБАЛЬНЫЕ ОПЦИИ
# =============================================================================
{
email admin@example.com
admin off
http_port 80
https_port 443
log {
output file /var/log/caddy/global.log {
roll_size 50mb
roll_keep 5
roll_keep_for 720h
}
level INFO
}
}
# =============================================================================
# Основной сайт с HTTPS и rate limiting
# =============================================================================
example.com {
root * /var/www/html
log {
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 10
roll_keep_for 720h
}
format json
}
# === TLS конфигурация (Let's Encrypt) ===
tls {
key_type p256
protocols tls1.2 tls1.3
}
# === Security headers ===
header {
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
X-XSS-Protection "1; mode=block"
Referrer-Policy "strict-origin-when-cross-origin"
Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
Permissions-Policy "geolocation=(), microphone=(), camera=()"
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
-Server
-X-Powered-By
}
# === Matchers ===
@websocket {
path /ws
header Connection *Upgrade*
header Upgrade websocket
}
@api {
path /api/*
}
@static_files {
path *.css *.js *.jpg *.jpeg *.png *.gif *.ico *.woff *.woff2 *.ttf *.svg
}
@html_files {
path *.html
}
@blocked {
path /.git/* /.env /*.php /*.asp /*.jsp /wp-* /admin*
}
# === Блокировка нежелательных путей ===
respond @blocked "Access denied" 403
# === WebSocket reverse proxy ===
# Зона определяется непосредственно в месте применения
handle @websocket {
rate_limit {
zone websocket_zone {
key {remote_host}
events 30
window 1s
}
}
reverse_proxy localhost:10000 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# === API endpoints ===
handle @api {
rate_limit {
zone api_zone {
key {remote_host}
events 10
window 1s
}
}
respond "API endpoint protected" 200
}
# === Статический контент ===
handle {
rate_limit {
zone static_zone {
key {remote_host}
events 100
window 1s
}
}
encode gzip zstd
header @static_files Cache-Control "public, max-age=31536000, immutable"
header @html_files Cache-Control "public, max-age=3600"
# try_files - ОТДЕЛЬНАЯ директива перед file_server
# Ищет: точный путь -> директорию -> .html файл -> 404
try_files {path} {path}/ {path}.html =404
file_server {
index index.html
hide .git .env
}
}
# === Обработка ошибок (ВСЕГДА В КОНЦЕ site block) ===
# Сохраняет оригинальный HTTP-статус (404, 500 и т.д.)
handle_errors {
@404 expression {err.status_code} == 404
rewrite @404 /404.html
file_server
}
}
# =============================================================================
# Redirects
# =============================================================================
www.example.com {
redir https://example.com{uri} permanent
}
http://example.com, http://www.example.com {
redir https://example.com{uri} permanent
}
EOFПрименение и валидация
sudo caddy validate --config /etc/caddy/Caddyfile
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo systemctl reload caddy
sudo systemctl status caddy --no-pagerЗамена домена
sudo sed -i 's/example.com/your-domain.com/g' /etc/caddy/Caddyfile
sudo systemctl reload caddy9. Firewall (nftables)
9.1. Создание конфигурации
sudo tee /etc/nftables.conf <<'EOF'
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
iifname "lo" accept
ct state established,related accept
ct state invalid drop
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
tcp dport 22 accept
tcp dport 80 accept
tcp dport 443 accept
udp dport 443 accept
udp dport 8443 accept
ct state new limit rate over 100/second drop
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
}
chain output {
type filter hook output priority filter; policy accept;
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "eth0" masquerade
}
}
EOF9.2. Применение
sudo nft -c -f /etc/nftables.conf
sudo systemctl enable --now nftables
sudo systemctl restart nftables
sudo nft list ruleset10. Верификация и мониторинг
10.1. Скрипт комплексной проверки
sudo tee /usr/local/bin/verify-vps-setup.sh <<'EOF'
#!/bin/bash
echo "=== 1. Kernel Modules ==="
lsmod | grep -E "tcp_bbr|sch_fq|aesni|ghash|nf_conntrack" | awk '{print "[OK] " $1}'
echo ""
echo "=== 2. BBR + FQ ==="
echo "TCP CC: $(sysctl -n net.ipv4.tcp_congestion_control)"
echo "Qdisc: $(sysctl -n net.core.default_qdisc)"
echo ""
echo "=== 3. Conntrack ==="
echo "Used: $(cat /proc/sys/net/netfilter/nf_conntrack_count)"
echo "Max: $(cat /proc/sys/net/netfilter/nf_conntrack_max)"
echo ""
echo "=== 4. Caddy Status ==="
systemctl is-active caddy
caddy version | head -1
echo ""
echo "=== 5. Caddy Modules ==="
caddy list-modules 2>/dev/null | grep -iE "rate|transform" | awk '{print "[OK] " $1}'
echo ""
echo "=== 6. Listening Ports ==="
ss -tlnp | grep caddy
echo ""
echo "=== 7. Memory Usage ==="
free -h | grep -E "Mem|Swap"
echo ""
echo "=== 8. Security Hardening ==="
echo "SysRq: $(sysctl -n kernel.sysrq) (expect 0)"
echo "Ptrace: $(sysctl -n kernel.yama.ptrace_scope) (expect 1)"
echo "Kptr: $(sysctl -n kernel.kptr_restrict) (expect 2)"
EOF
sudo chmod +x /usr/local/bin/verify-vps-setup.sh
/usr/local/bin/verify-vps-setup.sh10.2. Тестирование rate limiter
for i in {1..15}; do
curl -s -o /dev/null -w "Request $i: %{http_code}\n" \
https://example.com/api/test
done
# Ожидаемый результат: первые 10 - 200 OK, далее - 429 Too Many Requests10.3. Тестирование навигации
curl -I https://example.com/
curl -I https://example.com/about
curl -I https://example.com/about.html
curl -I https://example.com/nonexistentОжидаемые статусы: 200, 200, 200, 404 соответственно.
10.4. Проверка TLS
Используйте онлайн-сервисы:
- SSL Labs: https://www.ssllabs.com/ssltest/ (ожидаемая оценка A+)
- Mozilla Observatory: https://observatory.mozilla.org/ (ожидаемая оценка A)
- HSTS Preload: https://hstspreload.org/
10.5. Мониторинг в реальном времени
sudo journalctl -u caddy -f
sudo tail -f /var/log/caddy/access.log
watch -n 2 'cat /proc/sys/net/netfilter/nf_conntrack_count; echo "/"; cat /proc/sys/net/netfilter/nf_conntrack_max'
watch -n 5 'free -h'11. Обслуживание
11.1. Автоматическое обновление сертификатов
Caddy автоматически продлевает сертификаты Let’s Encrypt за 30 дней до истечения. Дополнительных cron-задач не требуется. Проверить статус:
sudo ls -la /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/11.2. Ротация логов
Caddy имеет встроенную ротацию логов через параметры roll_size и roll_keep. Для дополнительной страховки:
sudo tee /etc/logrotate.d/caddy-custom <<'EOF'
/var/log/caddy/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 caddy caddy
}
EOF11.3. Бэкап конфигурации
sudo tar -czf ~/vps-config-backup-$(date +%Y%m%d).tar.gz \
/etc/caddy/ \
/etc/modules-load.d/vps.conf \
/etc/sysctl.d/99-vps.conf \
/etc/nftables.conf \
/etc/systemd/system/caddy.service.d/ \
/var/www/html/11.4. Обновление Caddy
При использовании custom build через xcaddy обновления через apt не применяются. Для обновления:
cd ~/caddy-build
git pull # если используется git-репозиторий xcaddy
xcaddy build \
--with github.com/mholt/caddy-ratelimit \
--with github.com/caddyserver/transform-encoder \
--output /tmp/caddy
sudo systemctl stop caddy
sudo cp /tmp/caddy /usr/bin/caddy
sudo systemctl start caddy
caddy version12. Чек-лист развёртывания
Фаза 1: Подготовка системы
- Система обновлена (apt upgrade)
- Swap-файл 2GB создан и активирован
- Ядро 6.18.x или новее (uname -r)
- Базовые утилиты установлены (curl, git, build-essential)
Фаза 2: Модули ядра
-
/etc/modules-load.d/vps.confсоздан с именами через дефисы - Модули
tcp_bbr,sch_fq,aesni-intel,ghash-clmulni-intelзагружены -
nf_conntrackиnf_tablesактивны -
systemd-modules-load.serviceбез ошибок
Фаза 3: Параметры ядра
-
/etc/sysctl.d/99-vps.confсоздан -
sysctl --systemприменён без ошибок - BBR активен (sysctl net.ipv4.tcp_congestion_control = bbr)
- FQ активен (sysctl net.core.default_qdisc = fq)
- Conntrack max = 262144
- Security hardening применен (sysrq=0, ptrace=1, kptr=2)
Фаза 4: Caddy
- Официальный репозиторий Caddy добавлен
- Go установлен
-
xcaddyустановлен - Caddy собран с модулями
caddy-ratelimitиtransform-encoder - Systemd override с
AmbientCapabilities=CAP_NET_BIND_SERVICEсоздан - Capabilities с бинарника удалены (
setcap -r) - Сервис запущен и слушает порты 80/443
Фаза 5: Конфигурация
- DNS A-запись указывает на IP VPS
-
/etc/caddy/Caddyfileсоздан с реальной доменной зоной - Зоны rate_limit определены с параметрами
eventsиwindow -
try_filesразмещен как отдельная директива передfile_server -
handle_errorsразмещен в конце site block - Конфигурация провалидирована (
caddy validate) - Статический контент размещен в
/var/www/html/ - Страницы
index.html,about.html,404.htmlсозданы - Права на директории установлены (caddy:caddy)
Фаза 6: Firewall и сервисы
-
/etc/nftables.confсоздан - Порты 22, 80, 443 (TCP), 443 (UDP/QUIC) открыты
-
nftablesактивен и автозапускается
Фаза 7: Верификация
-
https://your-domain.comоткрывается с валидным сертификатом - SSL Labs показывает оценку A или A+
- Mozilla Observatory показывает A
- Rate limiter блокирует избыточные запросы (HTTP 429)
- Security headers присутствуют в ответах
- HSTS активен
- Навигация между страницами работает (
/aboutотдаётabout.html) - Несуществующие страницы возвращают HTTP 404 с кастомной страницей
- WebSocket endpoint проксируется корректно
- Логи пишутся в
/var/log/caddy/
Фаза 8: Мониторинг
- Скрипт
verify-vps-setup.shсоздан и работает - Настроена дополнительная ротация логов через logrotate
- Swap используется умеренно (vm.swappiness = 30)
- Использование RAM в пределах 1.5-1.8 GB