Это подробное, пошаговое руководство, основанное на реальном опыте. Вы развернёте полноценный стек безопасности для домашних сервисов: Traefik как обратный прокси с автоматическим HTTPS, CrowdSec как систему обнаружения вторжений и AppSec WAF для защиты на уровне веб-приложений. Всё будет работать в изолированном LXC-контейнере под управлением Debian 12 на платформе Proxmox 9.1.x
Оглавление
-
Цели и используемые технологии
-
Предварительные требования
-
Часть 1: Создание и подготовка LXC-контейнера
-
Часть 2: Установка Traefik
-
Часть 3: Установка и настройка CrowdSec
-
Часть 4: Интеграция Traefik с CrowdSec через плагин
-
Часть 5: Включение AppSec WAF
-
Часть 6: Настройка middleware и цепочек для сервисов
-
Часть 7: Примеры конфигураций для реальных сервисов
-
Часть 8: Финальные штрихи – права доступа, logrotate, автоматические обновления
-
Вишенка на торте
Цели и используемые технологии
-
Traefik – современный обратный прокси с автоматическим получением SSL-сертификатов от Let’s Encrypt. Мы будем использовать его как единую точку входа для всех наших внутренних сервисов (Seafile, OnlyOffice, Immich, Home Assistant, Proxmox VE, qBittorrent и др.).
-
CrowdSec – open-source IPS/IDS, который анализирует логи и блокирует вредоносные IP. В отличии от Fail2ban, он использует глобальные списки угроз и поведенческий анализ.
-
AppSec WAF – встроенный в CrowdSec модуль для анализа содержимого HTTP-запросов (SQL-инъекции, XSS, эксплуатация уязвимостей). Работает как дополнительный уровень защиты поверх блокировки по IP.
-
LXC-контейнер на Proxmox – легковесная изоляция, простота управления.
В результате мы получим безопасную среду, в которой все сервисы доступны по HTTPS с валидными сертификатами, а любые подозрительные запросы будут автоматически блокироваться.
Предварительные требования
-
Рабочая установка Proxmox VE (версия 8+).
-
Зарегистрированное доменное имя (например,
example.ru) и возможность управлять его DNS-записями (для получения сертификатов Let’s Encrypt через HTTP-01 challenge требуется доступ к порту 80 из интернета; если домен используется только локально, потребуется DNS-01 challenge - “Вишенка на торте“). -
Свободный IP-адрес в вашей локальной сети (мы будем использовать
192.168.1.100как пример). -
Базовое знакомство с командной строкой Linux и редактором
nano(илиvim).
Часть 1: Создание и подготовка LXC-контейнера
1.1. Загрузка шаблона Debian 12
В веб-интерфейсе Proxmox:
-
Выберите хранилище (например,
local). -
Перейдите на вкладку Content (Содержимое).
-
Нажмите Templates.
-
Найдите
debian-12-standard...и скачайте его.
1.2. Создание контейнера
Нажмите Create CT и заполните поля:
-
General:
-
CT ID:
100(или любой свободный). -
Hostname:
traefik-crowdsec. -
Unprivileged container:
(включено). -
Password: установите надёжный пароль для root.
-
-
Template:
-
Storage:
local. -
Template: выберите скачанный Debian 12.
-
-
Disks:
-
Storage:
local-lvm. -
Disk size (GiB):
8.
-
-
CPU: Cores:
1. -
Memory: Memory (MiB):
1024, Swap (MiB):512. -
Network:
-
Bridge:
vmbr0. -
IPv4/CIDR:
192.168.1.100/24(замените на свой IP). -
Gateway (IPv4):
192.168.1.1(ваш шлюз).
-
-
DNS: можно оставить пустым (будут использованы настройки хоста) или указать ваш локальный DNS (например,
192.168.1.1).
Проверьте параметры и нажмите Finish. Запустите контейнер.
1.3. Вход и базовая настройка
Войдите в контейнер с хоста:
bash
pct enter 100
Обновите систему и установите необходимые пакеты:
bash
apt update && apt upgrade -y
apt install -y curl wget sudo nano gnupg htop lsb-release apache2-utils
1.4. Настройка локали (UTF-8)
bash
apt install -y locales
dpkg-reconfigure locales
В меню выберите ru_RU.UTF-8 UTF-8 и en_US.UTF-8 UTF-8. Затем выберите локаль по умолчанию, например ru_RU.UTF-8. Перезапустите контейнер для применения:
bash
exit
pct restart 100
pct enter 100
Проверьте:
bash
locale
echo "Привет, мир"
1.5. Создание административного пользователя
Создайте пользователя, от которого будете работать (замените username на своё имя):
bash
useradd -m -s /bin/bash -G sudo username
passwd username
Для удобства можно разрешить sudo без пароля:
bash
echo "username ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/username
1.6. Настройка SSH (опционально, но рекомендуется)
Установите SSH-сервер, если его нет:
bash
apt install -y openssh-server
Отредактируйте /etc/ssh/sshd_config, добавив в конец:
text
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers username
Перезапустите SSH:
bash
systemctl restart ssh
Скопируйте свой публичный ключ в /home/username/.ssh/authorized_keys. Теперь можно подключаться по SSH под пользователем username.
Часть 2: Установка Traefik
Мы установим Traefik версии 3.6.9 как бинарный файл и запустим через systemd.
2.1. Скачивание и проверка
bash
cd /tmp
TRAEFIK_VERSION="v3.6.9"
ARCH="amd64"
wget "https://github.com/traefik/traefik/releases/download/${TRAEFIK_VERSION}/traefik_${TRAEFIK_VERSION}_linux_${ARCH}.tar.gz"
wget "https://github.com/traefik/traefik/releases/download/${TRAEFIK_VERSION}/traefik_${TRAEFIK_VERSION}_checksums.txt"
grep "traefik_${TRAEFIK_VERSION}_linux_${ARCH}.tar.gz" traefik_${TRAEFIK_VERSION}_checksums.txt | sha256sum -c -
Ожидаемый вывод: traefik_v3.6.9_linux_amd64.tar.gz: OK.
2.2. Установка бинарного файла
bash
tar -xzf "traefik_${TRAEFIK_VERSION}_linux_${ARCH}.tar.gz"
sudo mv traefik /usr/local/bin/
sudo chmod +x /usr/local/bin/traefik
traefik version # должно показать 3.6.9
2.3. Создание системного пользователя для Traefik
bash
sudo groupadd --system traefik
sudo useradd --system --no-create-home --home-dir / --shell /bin/false -g traefik traefik
2.4. Подготовка структуры директорий
bash
sudo mkdir -p /etc/traefik/{conf.d,plugins-storage,ssl}
sudo mkdir -p /var/log/traefik
sudo chown -R traefik:traefik /var/log/traefik
sudo chmod 755 /var/log/traefik
2.5. Минимальная статическая конфигурация (/etc/traefik/traefik.yml)
На этом этапе мы создадим базовую конфигурацию, чтобы убедиться, что Traefik работает и панель управления доступна. Позже мы её расширим.
bash
sudo tee /etc/traefik/traefik.yml > /dev/null <<'EOF'
entryPoints:
web:
address: ":80"
traefik:
address: ":8080"
providers:
file:
directory: /etc/traefik/conf.d
watch: true
api:
dashboard: true
insecure: true # временно, только для отладки
log:
level: INFO
filePath: /var/log/traefik/traefik.log
accessLog:
filePath: /var/log/traefik/access.log
EOF
2.6. Динамическая конфигурация для панели управления
Создайте файл /etc/traefik/conf.d/10-traefik-dashboard.yml:
bash
sudo tee /etc/traefik/conf.d/10-traefik-dashboard.yml > /dev/null <<'EOF'
http:
routers:
dashboard:
rule: "Host(`traefik.local`) || PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
entryPoints:
- traefik
service: api@internal
middlewares: []
EOF
2.7. Файл окружения (обязателен, даже пустой)
bash
sudo touch /etc/traefik/traefik.env
sudo chown traefik:traefik /etc/traefik/traefik.env
sudo chmod 600 /etc/traefik/traefik.env
2.8. Systemd unit для Traefik
Важно: В unit-файле обязательно должна быть указана рабочая директория WorkingDirectory=/etc/traefik, иначе плагин CrowdSec будет работать некорректно. Также добавим --pidfile для корректной ротации логов.
bash
sudo tee /etc/systemd/system/traefik.service > /dev/null <<'EOF'
[Unit]
Description=Traefik Proxy
Documentation=https://doc.traefik.io/traefik/
After=network.target
[Service]
User=traefik
Group=traefik
WorkingDirectory=/etc/traefik
Type=simple
EnvironmentFile=/etc/traefik/traefik.env
ExecStart=/usr/local/bin/traefik --pidfile=/run/traefik.pid --configFile=/etc/traefik/traefik.yml
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
[Install]
WantedBy=multi-user.target
EOF
2.9. Запуск Traefik
bash
sudo systemctl daemon-reload
sudo systemctl enable --now traefik
sudo systemctl status traefik
Проверьте доступность панели: http://<IP-контейнера>:8080/dashboard/ (если вы ещё не пробросили порты, панель будет доступна только изнутри контейнера или с хоста Proxmox).
Примечание: Если вы планируете выпускать SSL-сертификаты через HTTP-01 challenge, необходимо, чтобы порт 80 был доступен из интернета. На этом этапе можно не беспокоиться, мы настроим HTTPS позже.
Часть 3: Установка и настройка CrowdSec
3.1. Добавление репозитория и установка
bash
curl -s https://install.crowdsec.net | sudo sh
sudo apt update
sudo apt install crowdsec -y
3.2. Разрешение конфликта портов
Traefik уже слушает порт 8080, а CrowdSec по умолчанию пытается запустить LAPI на том же порту. Изменим порт LAPI на 8081.
Отредактируйте /etc/crowdsec/config.yaml:
bash
sudo nano /etc/crowdsec/config.yaml
Найдите строку listen_uri: и измените:
yaml
api:
server:
listen_uri: 127.0.0.1:8081 # было 8080
Сохраните. Затем отредактируйте /etc/crowdsec/local_api_credentials.yaml:
bash
sudo nano /etc/crowdsec/local_api_credentials.yaml
Измените url на http://127.0.0.1:8081.
Запустите CrowdSec и проверьте статус:
bash
sudo systemctl start crowdsec
sudo systemctl status crowdsec
sudo ss -tlnp | grep 8081 # должен быть LISTEN
3.3. Настройка сбора логов Traefik (acquisition)
CrowdSec должен читать логи Traefik. Создайте /etc/crowdsec/acquis.d/traefik.yaml:
bash
sudo tee /etc/crowdsec/acquis.d/traefik.yaml > /dev/null <<EOF
filenames:
- /var/log/traefik/access.log
- /var/log/traefik/traefik.log
labels:
type: traefik
EOF
sudo systemctl reload crowdsec
3.4. Подключение к CrowdSec Console (рекомендуется)
CrowdSec Console позволяет получать глобальные списки угроз и управлять инстансами.
-
Зарегистрируйтесь на https://app.crowdsec.net.
-
В разделе Instances нажмите Enroll Your First Instance и скопируйте команду вида:
bash
sudo cscli console enroll clXXXXXXXXXX --name "traefik-crowdsec" -
Выполните её в контейнере.
-
Вернитесь в консоль и примите инстанс.
-
Перезапустите CrowdSec и проверьте статус:
bash
sudo systemctl restart crowdsec
sudo cscli console status
Все опции, кроме console_management, должны быть активны.
3.5. Создание белого списка для локальных сетей
Чтобы CrowdSec не блокировал IP из вашей внутренней сети, создадим парсер-whitelist. Файл /etc/crowdsec/parsers/s02-enrich/my-whitelist.yaml:
bash
sudo tee /etc/crowdsec/parsers/s02-enrich/my-whitelist.yaml > /dev/null <<'EOF'
name: crowdsecurity/my-whitelists
description: "Whitelist events from local ipv4 networks"
filter: "1 == 1"
whitelist:
reason: "local network ranges"
ip:
- "127.0.0.1"
cidr:
- "192.168.1.0/24" # замените на вашу сеть
- "10.0.0.0/8"
- "172.16.0.0/12"
EOF
sudo systemctl reload crowdsec
sudo cscli parsers list | grep my-whitelists # должен быть enabled,local
3.6. Установка необходимых коллекций
Коллекции содержат парсеры и сценарии для конкретных типов логов.
bash
sudo cscli collections install crowdsecurity/traefik crowdsecurity/base-http-scenarios crowdsecurity/http-cve
sudo cscli collections upgrade crowdsecurity/sshd crowdsecurity/linux
sudo systemctl reload crowdsec
Проверьте список коллекций:
bash
sudo cscli collections list
Часть 4: Интеграция Traefik с CrowdSec через плагин
Используем официальный плагин crowdsec-bouncer-traefik-plugin версии 1.5.1. Он работает непосредственно внутри Traefik, без внешнего bouncer-сервиса.
4.1. Добавление секции experimental в статическую конфигурацию Traefik
Отредактируйте /etc/traefik/traefik.yml и добавьте в конец:
yaml
experimental:
plugins:
crowdsec-bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: v1.5.1
4.2. Генерация API-ключа для плагина
bash
sudo cscli bouncers add traefik-plugin -o raw
# скопируйте длинный ключ (например, aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd)
4.3. Создание middleware для плагина
Создайте файл /etc/traefik/conf.d/01-crowdsec.yml. Внимание: замените 192.168.1.0/24 на свою подсеть и вставьте скопированный ключ.
bash
sudo tee /etc/traefik/conf.d/01-crowdsec.yml > /dev/null <<EOF
http:
middlewares:
crowdsec-bouncer:
plugin:
crowdsec-bouncer:
CrowdsecMode: "stream"
CrowdsecLapiHost: "127.0.0.1:8081"
CrowdsecLapiPath: "/"
CrowdsecLapiKey: "aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd"
LogLevel: "INFO"
ClientTrustedIPs:
- "192.168.1.0/24"
- "10.0.0.0/8"
- "172.16.0.0/12"
- "127.0.0.1/32"
EOF
Пояснение параметров:
-
CrowdsecMode: "stream"– самый производительный режим: Traefik раз в минуту запрашивает список забаненных IP и кэширует его. -
ClientTrustedIPs– IP-адреса, для которых проверка CrowdSec не выполняется (ваша локальная сеть).
4.4. Создание тестового маршрута (опционально)
Для проверки можно создать простой маршрут с заглушкой, например /etc/traefik/conf.d/00-test.yml:
yaml
http:
routers:
test:
rule: "Host(`test.example.ru`)"
middlewares:
- crowdsec-bouncer
service: test
services:
test:
loadBalancer:
servers:
- url: "http://127.0.0.1:8080"
4.5. Перезапуск Traefik
bash
sudo systemctl restart traefik
Проверьте, что плагин загрузился:
bash
sudo journalctl -u traefik -f | grep plugin
4.6. Проверка доступности LAPI
bash
curl http://127.0.0.1:8081/health
# должен вернуть {"status":"up"}
Часть 5: Включение AppSec WAF
AppSec WAF анализирует содержимое запросов. Для его работы нужны дополнительные коллекции и настройка acquisition.
5.1. Установка AppSec-коллекций
bash
sudo cscli collections install crowdsecurity/appsec-virtual-patching crowdsecurity/appsec-generic-rules
5.2. Создание acquisition для AppSec
Создайте файл /etc/crowdsec/acquis.d/appsec.yaml:
bash
sudo tee /etc/crowdsec/acquis.d/appsec.yaml > /dev/null <<'EOF'
appsec_config: crowdsecurity/appsec-default
labels:
type: appsec
listen_addr: 127.0.0.1:7422
source: appsec
EOF
Пояснение: listen_addr: 127.0.0.1:7422 – AppSec Component будет слушать только на локальном интерфейсе.
5.3. Перезагрузка CrowdSec
bash
sudo systemctl reload crowdsec
Проверьте, что AppSec запустился:
bash
sudo ss -tlnp | grep 7422
sudo journalctl -u crowdsec -f | grep appsec # не должно быть ошибок
5.4. Настройка плагина Traefik для использования AppSec
Отредактируйте /etc/traefik/conf.d/01-crowdsec.yml, добавив параметры AppSec (выделены +):
yaml
http:
middlewares:
crowdsec-bouncer:
plugin:
crowdsec-bouncer:
CrowdsecMode: "stream"
CrowdsecLapiHost: "127.0.0.1:8081"
CrowdsecLapiPath: "/"
CrowdsecLapiKey: "aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd"
# --- AppSec WAF ---
crowdsecAppsecEnabled: true
crowdsecAppsecHost: "127.0.0.1:7422"
crowdsecAppsecFailureBlock: true
crowdsecAppsecUnreachableBlock: true
# -----------------
LogLevel: "INFO"
ClientTrustedIPs:
- "192.168.1.0/24"
- "10.0.0.0/8"
- "172.16.0.0/12"
- "127.0.0.1/32"
5.5. Перезапуск Traefik
bash
sudo systemctl restart traefik
Проверьте логи на наличие сообщений об AppSec:
bash
sudo journalctl -u traefik -f | grep appsec
5.6. Проверка работы AppSec
Сделайте тестовый вредоносный запрос к любому защищённому маршруту (например, к панели Traefik, если она защищена middleware crowdsec-bouncer):
bash
curl -k -H "Host: traefik.example.ru" "https://192.168.1.100/?q=%27%20OR%201=1--"
Ожидаемый ответ: 403 Forbidden (если AppSec сработает). Также можно посмотреть метрики CrowdSec:
bash
sudo cscli metrics
В секциях Appsec Metrics и Bouncer Metrics должны появиться счётчики.
Часть 6: Настройка middleware и цепочек для сервисов
Для удобства и переиспользования создадим набор стандартных middleware (аутентификация, rate limit, заголовки безопасности) и объединим их в цепочки (chains). Это позволит легко применять одинаковые политики к разным сервисам.
6.1. Основные middleware (/etc/traefik/conf.d/00-core.yml)
bash
sudo tee /etc/traefik/conf.d/00-core.yml > /dev/null <<'EOF'
http:
middlewares:
# Аутентификация (basic auth)
auth-basic:
basicAuth:
users:
- "username:$apr1$jkae0qdh$LJVQSVKCe0ZfYbJ/p6wK6/" # замените на свой хеш
# Rate limit (защита от перебора)
rate-limit:
rateLimit:
average: 50
burst: 100
# Ограничение по IP (только локальная сеть)
ip-whitelist-lan:
ipWhiteList:
sourceRange:
- "192.168.1.0/24" # замените на вашу сеть
- "127.0.0.1/32"
# Заголовки безопасности (строгие)
headers-default:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
browserXssFilter: true
contentTypeNosniff: true
frameDeny: true
referrerPolicy: "strict-origin-when-cross-origin"
permissionsPolicy: "geolocation=(), camera=(), microphone=()"
# Заголовки для приложений, которым нужны камера/микрофон (например, VoIP)
headers-media:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
browserXssFilter: true
contentTypeNosniff: true
frameDeny: true
referrerPolicy: "strict-origin-when-cross-origin"
permissionsPolicy: "geolocation=(self), camera=(self), microphone=(self)"
# Заголовки для приложений, которым нужен iframe (например, Proxmox, OnlyOffice)
headers-allow-iframe:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
browserXssFilter: true
contentTypeNosniff: true
frameDeny: false
customFrameOptionsValue: "SAMEORIGIN"
referrerPolicy: "strict-origin-when-cross-origin"
permissionsPolicy: "geolocation=(self), camera=(self), microphone=(self)"
# --- Цепочки (chains) ---
# Для административных интерфейсов (CrowdSec + auth + rate-limit + строгие заголовки)
chain-admin:
chain:
middlewares:
- crowdsec-bouncer@file
- auth-basic@file
- rate-limit@file
- headers-default@file
# Для административных интерфейсов, которым нужен iframe
chain-admin-iframe:
chain:
middlewares:
- crowdsec-bouncer@file
- auth-basic@file
- rate-limit@file
- headers-allow-iframe@file
# Для публичных сервисов (CrowdSec + rate-limit + строгие заголовки, без аутентификации)
chain-public:
chain:
middlewares:
- crowdsec-bouncer@file
- rate-limit@file
- headers-default@file
# Для публичных сервисов с медиа-доступом
chain-public-media:
chain:
middlewares:
- crowdsec-bouncer@file
- rate-limit@file
- headers-media@file
# Для публичных сервисов с iframe
chain-public-iframe:
chain:
middlewares:
- crowdsec-bouncer@file
- rate-limit@file
- headers-allow-iframe@file
# Для внутренних сервисов (только LAN, CrowdSec не нужен, так как IP доверенные)
chain-lan:
chain:
middlewares:
- ip-whitelist-lan@file
- rate-limit@file
- headers-default@file
# Для внутренних сервисов с iframe
chain-lan-iframe:
chain:
middlewares:
- ip-whitelist-lan@file
- rate-limit@file
- headers-allow-iframe@file
EOF
Примечание: Хеш пароля можно сгенерировать командой htpasswd -nB username. Если у вас ещё не установлен apache2-utils, выполните sudo apt install apache2-utils.
6.2. TLS-опции (/etc/traefik/conf.d/03-tls.yml)
Зададим минимальную версию TLS:
bash
sudo tee /etc/traefik/conf.d/03-tls.yml > /dev/null <<'EOF'
tls:
options:
modern:
minVersion: VersionTLS12
EOF
6.3. Маршрут для панели Traefik (с HTTPS и аутентификацией)
Обновим файл /etc/traefik/conf.d/10-traefik-dashboard.yml для работы через HTTPS с использованием цепочки chain-admin:
bash
sudo tee /etc/traefik/conf.d/10-traefik-dashboard.yml > /dev/null <<'EOF'
http:
routers:
traefik-dashboard:
rule: "Host(`traefik.example.ru`)" # замените на ваш домен
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-admin@file
service: "api@internal"
EOF
6.4. Обновление статической конфигурации для HTTPS
Теперь нужно дополнить /etc/traefik/traefik.yml точками входа для HTTPS и резолвером Let’s Encrypt. Приведём файл к окончательному виду (замените your-email@example.com на свой email):
bash
sudo tee /etc/traefik/traefik.yml > /dev/null <<'EOF'
providers:
file:
directory: /etc/traefik/conf.d/
watch: true
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: 600s
idleTimeout: 600s
writeTimeout: 600s
certificatesResolvers:
letsencrypt:
acme:
email: "your-email@example.com"
storage: /etc/traefik/ssl/acme.json
httpChallenge:
entryPoint: web
api:
dashboard: true
insecure: false
log:
filePath: /var/log/traefik/traefik.log
format: json
level: INFO
accessLog:
filePath: /var/log/traefik/traefik-access.log
format: json
filters:
statusCodes:
- "400-599"
retryAttempts: true
minDuration: "10ms"
bufferingSize: 0
fields:
headers:
defaultMode: drop
names:
User-Agent: keep
experimental:
plugins:
crowdsec-bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: v1.5.1
EOF
6.5. Перезапуск Traefik
bash
sudo systemctl restart traefik
Если вы ещё не пробросили порты 80 и 443 на контейнер, Traefik будет пытаться их слушать, но извне они будут недоступны. Это нормально на этапе локальной настройки.
Часть 7: Примеры конфигураций для реальных сервисов
Ниже приведены примеры файлов для популярных self-hosted приложений. Все они используют созданные ранее middleware и цепочки. Не забудьте заменить домены и IP-адреса на свои.
7.1. Proxmox VE
Файл /etc/traefik/conf.d/20-proxmox.yml:
yaml
http:
routers:
proxmox:
rule: "Host(`pve.example.ru`)"
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-admin-iframe@file # используем iframe для консоли
service: proxmox
services:
proxmox:
loadBalancer:
serversTransport: proxmox-transport
passHostHeader: true
servers:
- url: "https://192.168.1.99:8006"
serversTransports:
proxmox-transport:
insecureSkipVerify: true # игнорируем самоподписанный сертификат Proxmox
7.2. Seafile + OnlyOffice
Seafile часто требует отдельного эндпоинта для уведомлений. Файл /etc/traefik/conf.d/30-seafile.yml:
yaml
http:
routers:
seafile-main:
rule: "Host(`drive.example.ru`) && !PathPrefix(`/notification`)"
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-public@file
- seafile-headers@file
service: seafile-main
seafile-notification:
rule: "Host(`drive.example.ru`) && PathPrefix(`/notification`)"
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-public@file
- notification-headers@file
service: seafile-notification
onlyoffice:
rule: "Host(`office.example.ru`)"
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-public@file
- onlyoffice-headers@file
service: onlyoffice
services:
seafile-main:
loadBalancer:
servers:
- url: "http://192.168.1.30:8080"
seafile-notification:
loadBalancer:
servers:
- url: "http://192.168.1.30:8083"
healthCheck:
path: /ping
interval: 10s
timeout: 3s
onlyoffice:
loadBalancer:
passHostHeader: true
servers:
- url: "http://192.168.1.30:6233"
middlewares:
seafile-headers:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
X-Forwarded-Host: "drive.example.ru"
customResponseHeaders:
X-Frame-Options: "SAMEORIGIN"
Content-Security-Policy: "frame-ancestors 'self' https://drive.example.ru"
notification-headers:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
X-Forwarded-Host: "drive.example.ru"
onlyoffice-headers:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
X-Forwarded-Host: "office.example.ru"
customResponseHeaders:
X-Frame-Options: ""
Content-Security-Policy: "frame-ancestors 'self' https://drive.example.ru"
7.3. Immich
Файл /etc/traefik/conf.d/40-immich.yml:
yaml
http:
routers:
immich:
rule: "Host(`photos.example.ru`)"
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-public-media@file
service: immich
services:
immich:
loadBalancer:
passHostHeader: true
servers:
- url: "http://192.168.1.102:2283"
7.4. Matrix (Synapse)
Файл /etc/traefik/conf.d/50-matrix.yml:
yaml
http:
routers:
matrix-web:
rule: "Host(`matrix.example.ru`)"
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-public@file
service: matrix-nginx
services:
matrix-nginx:
loadBalancer:
servers:
- url: "http://192.168.1.108:80"
7.5. Home Assistant
Файл /etc/traefik/conf.d/60-homeassistant.yml:
yaml
http:
routers:
homeassistant:
rule: "Host(`ha.example.ru`)"
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-public-iframe@file
service: homeassistant
services:
homeassistant:
loadBalancer:
passHostHeader: true
servers:
- url: "http://192.168.1.200:8123"
7.6. qBittorrent
Файл /etc/traefik/conf.d/70-qbittorrent.yml:
yaml
http:
routers:
qbittorrent:
rule: "Host(`qb.example.ru`)"
entryPoints: ["websecure"]
tls:
certResolver: letsencrypt
options: modern@file
middlewares:
- chain-admin@file
service: qbittorrent
services:
qbittorrent:
loadBalancer:
passHostHeader: true
servers:
- url: "http://192.168.1.103:8090"
healthCheck:
path: /
interval: 10s
timeout: 3s
Часть 8: Финальные штрихи – права доступа, logrotate, автоматические обновления
8.1. Установка правильных прав доступа
После того как все конфигурационные файлы созданы, необходимо установить корректные владельца и права, чтобы Traefik мог их читать, а другие пользователи (например, вы) – при необходимости просматривать.
bash
# Владелец всех файлов в /etc/traefik – traefik, группа – traefik
sudo chown -R traefik:traefik /etc/traefik
# Директории: права 750 (владелец всё, группа чтение+выполнение)
sudo find /etc/traefik -type d -exec chmod 750 {} \;
# Файлы конфигурации (кроме .env и acme.json): права 640
sudo find /etc/traefik -type f -not -name "*.env" -not -name "acme.json" -exec chmod 640 {} \;
# Файл .env: права 600
sudo chmod 600 /etc/traefik/traefik.env
# Папка plugins-storage и её содержимое
sudo chown -R traefik:traefik /etc/traefik/plugins-storage
sudo find /etc/traefik/plugins-storage -type d -exec chmod 755 {} \;
sudo find /etc/traefik/plugins-storage -type f -exec chmod 644 {} \;
# Логи
sudo chown -R traefik:traefik /var/log/traefik
sudo chmod 755 /var/log/traefik
Важно: Если вы добавили своего административного пользователя в группу traefik, то после изменения прав вы сможете просматривать файлы без sudo. Для этого выполните:
bash
sudo usermod -aG traefik username
Выйдите и зайдите заново (или выполните newgrp traefik в текущей сессии).
8.2. Настройка ротации логов (logrotate) для Traefik
CrowdSec имеет встроенную ротацию логов, а Traefik – нет. Настроим logrotate для файлов в /var/log/traefik.
Создайте файл /etc/logrotate.d/traefik:
bash
sudo tee /etc/logrotate.d/traefik > /dev/null <<'EOF'
/var/log/traefik/*.log {
daily
rotate 7
maxsize 50M
compress
delaycompress
missingok
notifempty
create 640 traefik traefik
sharedscripts
postrotate
if [ -f /run/traefik.pid ]; then
kill -USR1 `cat /run/traefik.pid`
else
PID=$(pidof traefik)
if [ -n "$PID" ]; then
kill -USR1 $PID
fi
fi
endscript
}
EOF
Проверьте синтаксис:
bash
sudo logrotate -d /etc/logrotate.d/traefik
8.3. Настройка автоматических обновлений безопасности (unattended-upgrades)
Это гарантирует, что система будет получать критические обновления без вашего участия.
Установите пакет:
bash
sudo apt install unattended-upgrades apt-listchanges -y
Настройте его:
bash
sudo dpkg-reconfigure -plow unattended-upgrades
При запросе выберите Yes.
Отредактируйте /etc/apt/apt.conf.d/50unattended-upgrades, чтобы разрешить только обновления безопасности (обычно настройки по умолчанию уже корректны). Убедитесь, что активны строки:
text
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
По умолчанию обновления запускаются ежедневно в случайное время (6:00 + случайная задержка до 60 минут). Чтобы изменить интервал, например, на 5:00–7:00, создайте override для таймера:
bash
sudo mkdir -p /etc/systemd/system/apt-daily-upgrade.timer.d
sudo tee /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf <<EOF
[Timer]
OnCalendar=
OnCalendar=*-*-* 5:00
RandomizedDelaySec=2h
Persistent=true
EOF
sudo systemctl daemon-reload
Проверьте статус таймера:
bash
systemctl status apt-daily-upgrade.timer
В строке Trigger должно быть время в интервале 5:00–7:00.
Заключение и полезные советы
Таким образом Вы развернули полноценный, безопасный и современный стек для управления домашними сервисами. Подведём итог того, что у вас теперь есть:
-
Единая точка входа – Traefik принимает все запросы по HTTPS, автоматически перенаправляет HTTP на HTTPS, управляет сертификатами.
-
Защита на уровне IP – CrowdSec анализирует логи и блокирует подозрительные IP как на основе локальных правил, так и на основе глобальных списков (CAPI).
-
Защита на уровне приложений – AppSec WAF анализирует содержимое запросов и блокирует сложные атаки (SQLi, XSS, эксплуатацию уязвимостей).
-
Гибкая маршрутизация – через цепочки middleware вы можете легко применять единые политики безопасности к разным сервисам.
-
Автоматическое обслуживание – logrotate для логов и unattended-upgrades для системных обновлений.
P.S. Надеюсь я смог создать максимально подробное руководство по разворачиванию Traefik и Crowdsec с почти всеми возможностями, которые могут понадобится самохостеру, которое не займет у Вас много времени в отличии от меня.
Естественно текст был отредактирован с помощью Ai, за что ему спасибо!
P.P.S. У меня домен на sweb.ru (не реклама), и я смог настроить получение wildcard-сертификата для домена типа *.lan.example.ru. Это и есть та сама “Вишенка на торте“ если она будет кому интересна, я постараюсь так же подробно все описать.
Если вы обнаружили ошибки, нестыковки или в процессе у вас возникли какие либо трудности обязательно пишите. Мы попробуем решить Вашу проблему и исправим неточности в статье.
Спасибо за внимание!

