Поиск
Показаны результаты для тегов 'caddy'.
Найдено 2 результата
-
Всем привет! Уже опубликовав статью про установку MarzNeshin, понял что старая версия моей инструкции устарела и морально и технически, учитывая что вышла свежая версия Marzban, которая привнесла большое количество изменений. С момента написания моей статьи по ФэнШую прошло больше полугода, а она остается актуальной. И этой концепции я придерживаюсь. Сегодня мы разберем установку с нуля. 0. Вводная. На момент написания статьи, мой PR к скриптам установки находится на рассмотрении, ждем пока Saint сам протестирует установку и примет PR. https://github.com/Gozargah/Marzban-scripts/pull/29 Что изменилось в скрипте: Добавлена возможность выбора версии --dev Добавлена возможность установки сразу с базой данных --database mysql или --database mariadb Обновлена функцию обновления ядра Xray, сделал также красиво как и обновление в marzban-node, без лишних текстов и уведомлений. Изменился формат выбора версии для установки: --version v0.5.2 Пока ждем обновления офф скриптов, можно воспользоваться моей репой: https://github.com/DigneZzZ/Marzban-scripts-beta Что изменилось в Marzban начиная с версии 0.7.0 я расписывал здесь: Что изменилось в концепции установки: Теперь все свои сборки я ставлю в сеть Docker, а доступ к ним организовываю через Caddy. В целом это легко и просто. А главное быстро. Каждой ноде свой инбаунд Мэйн панель - только для администрирования БД только MySQL/MariaDB 1. Подготовка сервера 1.1. Аренда сервера Если ваш сервер Marzban уже приносит, или планирует приносить хороший доход, тогда вам нужно обеспечить достаточный уровень надежности вашей инфраструктуры. 1. Не нужно экономить на хороших и надежных серверах 2. Не нужно экономить на ресурсах для хорошей нагрузки 3. Не нужно экономить на стоимости ваш серверов для НОД - стабильность подключений и качество связи - это обязательное условия роста вашего "бизнеса"/"проекта" 1. Брать сервера под Мэйн в идеале нужно у крупных провайдеров, ориентированных на корпоративных клиентов. Примеры: Selectel, Cloud.Vk.Com, Yandex Cloud, Cloud.ru и др.. Также можно рассматривать крупных провайдеров типа: AWS, Vultr, Kamatera, Hetzner, но опять же - тарифы выбираем с выделенными ядрами, не Шэред, и главное - должна быть 100% гарантия что ваш сервер не удалят и вы сможете всегда его оплачивать. 2. Ситуации с сайтами могут быть самыми разными, начиная от ДДоС атак, заканчивая наплывом клиентов. Но конечно про экономику забывать не нужно. 3. Чем лучше провайдер и каналы - тем довольнее будут клиенты. Не нужно стараться дать им 30 стран на выбор, уверяю вас, они не оценят. Отталкивайтесь от географии ваших клиентов. Для РФ это сервер в Европе. ОООЧень редко кому нужна локация в США.. и тем более где нибудь в Чили или Австралии.. Нахрена им? Поэтому, провайдер должен быть стабильный, компания иностранная. Своими рекомендациями я уже поделился в канале VPS Insider (но по причине отсутствия заинтересованности я перестал его поддерживать, оставив всю историю там) вступить можно по ссылке за 170 Звёзд ТГ: https://t.me/+lQBQTGym57hmOTAy Скорость должна быть 10Гбс - минимум 2-5Гбс. Трафика от 3-5Тб (суммарного). Конечно лучше безлимит, но качественный сервер обычно имеет лимитированный трафик. Давайте возьмем сервер здесь: https://procloud.ru?referral_id=274473 Локацию берите Москва (для Мэйн сервера - без разницы) ОСь берите Ubuntu 24.04 ЦП - 2 ядра Память - 4 Гб. Диск - 30 Гб. Желательно максимально быстрый. 1.2. Взяли? Теперь подключаемся. Как и раньше я использую Termius для работы с серверами. 1.3. Первым делом запускаем обновление системы: apt update && apt upgrade -yqq 1.4. Запускаем установку Caddy Ставим Caddy sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl 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 update sudo apt install caddy 1.5. Ставим мой сервис CADD: sudo nano /usr/local/bin/cadd 1.6. Заполняем в открытом редакторе файл: #!/bin/bash CONFIG_FILE="/etc/caddy/Caddyfile" # Путь к файлу конфигурации Caddy LOG_LINES=20 # Количество строк журнала для вывода # Цвета для вывода в консоль RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Без цвета (сброс) case "$1" in e) # Редактирование конфигурации nano "$CONFIG_FILE" ;; r) # Рестарт сервиса Caddy systemctl restart caddy echo -e "${GREEN}Caddy restarted.${NC}" ;; v) # Валидация конфигурационного файла caddy validate --config "$CONFIG_FILE" ;; s) # Статус сервиса Caddy systemctl status caddy | head -n 10 ;; l) # Логи сервиса Caddy journalctl -u caddy.service -n "$LOG_LINES" ;; f) # Форматирование Caddyfile caddy fmt --overwrite "$CONFIG_FILE" echo -e "${GREEN}File ${YELLOW} $CONFIG_FILE ${GREEN}has been formatted.${NC}" ;; h) # Вывод помощи echo -e "${YELLOW}Usage:${NC}" echo -e "${BLUE}cadd e${NC} - edit Caddyfile" echo -e "${BLUE}cadd r${NC} - restart Caddy" echo -e "${BLUE}cadd v${NC} - validate Caddyfile" echo -e "${BLUE}cadd s${NC} - check status of Caddy" echo -e "${BLUE}cadd l${NC} - show last ${LOG_LINES} lines from Caddy log" echo -e "${BLUE}cadd f${NC} - format file ${CONFIG_FILE}" echo -e "${BLUE}cadd h${NC} - display this help" ;; *) # Неправильный ввод команды echo -e "${RED}Invalid option!${NC} Usage: cadd {e|r|v|s|l|h|f}" ;; esac Сохранили и закрыли 1.7. Выдаем права файлу на исполнение: sudo chmod +x /usr/local/bin/cadd 1.8. Теперь поставим Docker curl -fsSL https://get.docker.com | sh 1.9. Теперь создадим нашу докер-сеть: Назовем ее caddy_net: docker network create \ --driver bridge \ --subnet 10.0.0.0/16 \ --gateway 10.0.0.1 \ caddy_net Диапазон у нас будет адресов 10.0.[0-255].[1-255] Но это с запасом. 2. Ставим Marzban. Ставить будем вариант сразу с MariaDB: sudo bash -c "$(curl -sL https://github.com/DigneZzZ/Marzban-scripts-beta/raw/main/marzban.sh)" @ install --database mariadb 2.1. Останавливаем Marzban: marzban down 2.2. Редактируем docker-compose: nano /opt/marzban/docker-compose.yml 2.3. Смотрим внимательно. Исходный вид: services: marzban: image: gozargah/marzban:latest restart: always env_file: .env network_mode: host volumes: - /var/lib/marzban:/var/lib/marzban - /var/lib/marzban/logs:/var/lib/marzban-node depends_on: mariadb: condition: service_healthy mariadb: image: mariadb:lts env_file: .env network_mode: host restart: always environment: MYSQL_ROOT_PASSWORD: password MYSQL_ROOT_HOST: '%' MYSQL_DATABASE: marzban MYSQL_USER: marzban MYSQL_PASSWORD: password command: - --bind-address=127.0.0.1 - --character_set_server=utf8mb4 - --collation_server=utf8mb4_unicode_ci - --host-cache-size=0 - --innodb-open-files=1024 - --innodb-buffer-pool-size=268435456 - --binlog_expire_logs_seconds=5184000 # 60 days volumes: - /var/lib/marzban/mysql:/var/lib/mysql healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] start_period: 10s start_interval: 3s interval: 10s timeout: 5s retries: 3 Приводим содержимое к нужному виду: services: marzban: image: gozargah/marzban:latest restart: always env_file: .env # network_mode: host volumes: - /var/lib/marzban:/var/lib/marzban - /var/lib/marzban/logs:/var/lib/marzban-node depends_on: mariadb: condition: service_healthy networks: caddy_net: ipv4_address: 10.0.10.2 mariadb: image: mariadb:lts env_file: .env # network_mode: host restart: always environment: MYSQL_ROOT_PASSWORD: password MYSQL_ROOT_HOST: '%' MYSQL_DATABASE: marzban MYSQL_USER: marzban MYSQL_PASSWORD: password command: # - --bind-address=127.0.0.1 - --character_set_server=utf8mb4 - --collation_server=utf8mb4_unicode_ci - --host-cache-size=0 - --innodb-open-files=1024 - --innodb-buffer-pool-size=268435456 - --binlog_expire_logs_seconds=5184000 # 60 days volumes: - /var/lib/marzban/mysql:/var/lib/mysql healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] start_period: 10s start_interval: 3s interval: 10s timeout: 5s retries: 3 networks: caddy_net: ipv4_address: 10.0.10.3 networks: caddy_net: external: true комментируем строку # network_mode: host Добавляем адреса в сети докер (хотя они нам не понадобятся уже) Gtht 2.4. Заходим в .env и приводим к виду: #UVICORN_HOST = "0.0.0.0" #UVICORN_PORT = 8000 # ALLOWED_ORIGINS=http://localhost,http://localhost:8000,http://example.com ## We highly recommend add admin using `marzban cli` tool and do not use ## the following variables which is somehow hard codded infrmation. # SUDO_USERNAME = "admin" # SUDO_PASSWORD = "admin" UVICORN_UDS: "/var/lib/marzban/marzban.socket" # UVICORN_SSL_CERTFILE = "/var/lib/marzban/certs/example.com/fullchain.pem" # UVICORN_SSL_KEYFILE = "/var/lib/marzban/certs/example.com/key.pem" DASHBOARD_PATH = "/d-dash/" XRAY_JSON = "/var/lib/marzban/xray_config.json" XRAY_SUBSCRIPTION_URL_PREFIX = "https://sub.domain.com" XRAY_SUBSCRIPTION_PATH = "yourSub" # XRAY_EXECUTABLE_PATH = "/usr/local/bin/xray" # XRAY_ASSETS_PATH = "/usr/local/share/xray" # XRAY_EXCLUDE_INBOUND_TAGS = "INBOUND_X INBOUND_Y" # XRAY_FALLBACKS_INBOUND_TAG = "INBOUND_X" TELEGRAM_API_TOKEN = 511414455:AsdgSDGsHfhFDbdfbFDFDFbdfCgw TELEGRAM_ADMIN_ID = 1111111111 TELEGRAM_LOGGER_CHANNEL_ID = -1234567890123 TELEGRAM_DEFAULT_VLESS_FLOW = "xtls-rprx-vision" # TELEGRAM_PROXY_URL = "http://localhost:8080" # DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/xxxxxxx" CUSTOM_TEMPLATES_DIRECTORY="/var/lib/marzban/templates/" # CLASH_SUBSCRIPTION_TEMPLATE="clash/my-custom-template.yml" SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html" # HOME_PAGE_TEMPLATE="home/index.html" # V2RAY_SUBSCRIPTION_TEMPLATE="v2ray/default.json" # V2RAY_SETTINGS_TEMPLATE="v2ray/settings.json" # SINGBOX_SUBSCRIPTION_TEMPLATE="singbox/default.json" # SINGBOX_SETTINGS_TEMPLATE="singbox/settings.json" # MUX_TEMPLATE="mux/default.json" ## Enable JSON config for compatible clients to use mux, fragment, etc. Default False. # USE_CUSTOM_JSON_DEFAULT=True ## Your preferred config type for different clients ## If USE_CUSTOM_JSON_DEFAULT is set True, all following programs will use the JSON config # USE_CUSTOM_JSON_FOR_V2RAYN=False # USE_CUSTOM_JSON_FOR_V2RAYNG=True # USE_CUSTOM_JSON_FOR_STREISAND=False ## Set headers for subscription SUB_PROFILE_TITLE = "Susbcription" SUB_SUPPORT_URL = "https://t.me/support" SUB_UPDATE_INTERVAL = "2" ## External config to import into v2ray format subscription # EXTERNAL_CONFIG = "config://..." # SQLALCHEMY_DATABASE_URL = "sqlite:///db.sqlite3" # SQLALCHEMY_POOL_SIZE = 10 # SQLIALCHEMY_MAX_OVERFLOW = 30 ## Custom text for STATUS_TEXT variable # ACTIVE_STATUS_TEXT = "Active" # EXPIRED_STATUS_TEXT = "Expired" # LIMITED_STATUS_TEXT = "Limited" # DISABLED_STATUS_TEXT = "Disabled" # ONHOLD_STATUS_TEXT = "On-Hold" ### Use negative values to disable auto-delete by default USERS_AUTODELETE_DAYS = -1 USER_AUTODELETE_INCLUDE_LIMITED_ACCOUNTS = false ## Customize all notifications # NOTIFY_STATUS_CHANGE = True # NOTIFY_USER_CREATED = True # NOTIFY_USER_UPDATED = True # NOTIFY_USER_DELETED = True # NOTIFY_USER_DATA_USED_RESET = True # NOTIFY_USER_SUB_REVOKED = True # NOTIFY_IF_DATA_USAGE_PERCENT_REACHED = True # NOTIFY_IF_DAYS_LEF_REACHED = True # NOTIFY_LOGIN = True ## Whitelist of IPs/hosts to disable login notifications # LOGIN_NOTIFY_WHITE_LIST = '1.1.1.1,127.0.0.1' ### for developers # DOCS=True # DEBUG=True # If You Want To Send Webhook To Multiple Server Add Multi Address # WEBHOOK_ADDRESS = "http://127.0.0.1:9000/,http://127.0.0.1:9001/" # WEBHOOK_SECRET = "something-very-very-secret" # VITE_BASE_API="https://example.com/api/" JWT_ACCESS_TOKEN_EXPIRE_MINUTES = 0 # JOB_CORE_HEALTH_CHECK_INTERVAL = 10 # JOB_RECORD_NODE_USAGES_INTERVAL = 30 # JOB_RECORD_USER_USAGES_INTERVAL = 10 # JOB_REVIEW_USERS_INTERVAL = 10 # JOB_SEND_NOTIFICATIONS_INTERVAL = 30 SQLALCHEMY_DATABASE_URL = "mysql+pymysql://marzban:[email protected]:3306/marzban" Собственно мы корректируем параметры: Отключаем параметры: #UVICORN_HOST = "0.0.0.0" #UVICORN_PORT = 8000 Создаем параметры: UVICORN_UDS: "/var/lib/marzban/marzban.socket" XRAY_SUBSCRIPTION_URL_PREFIX = "https://sub.domain.com" XRAY_SUBSCRIPTION_PATH = "yourSub" DASHBOARD_PATH = "/d-dash/" TELEGRAM_API_TOKEN = 511414455:AsdgSDGsHfhFDbdfbFDFDFbdfCgw TELEGRAM_ADMIN_ID = 1111111111 TELEGRAM_LOGGER_CHANNEL_ID = -1234567890123 TELEGRAM_DEFAULT_VLESS_FLOW = "xtls-rprx-vision" CUSTOM_TEMPLATES_DIRECTORY="/var/lib/marzban/templates/" SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html" SUB_PROFILE_TITLE = "Susbcription" SUB_SUPPORT_URL = "https://t.me/support" SUB_UPDATE_INTERVAL = "2" USERS_AUTODELETE_DAYS = -1 USER_AUTODELETE_INCLUDE_LIMITED_ACCOUNTS = false Корректируем IP адрес подключения к нашей БД: SQLALCHEMY_DATABASE_URL = "mysql+pymysql://marzban:[email protected]:3306/marzban" Фуф. Ура. Теперь все. 2.5. Перезагружаем marzban marzban restart выглядеть должно вот так: 3.1.. Заходим в редактирование файла Caddy: cadd e 3.8. Файл будет предзаполнен. Удаляем все в файле и заполняем файл: { storage file_system { root /var/lib/caddy } email [email protected] acme_ca https://acme-v02.api.letsencrypt.org/directory log { output file /var/log/caddy/server.log { roll_size 30mb roll_keep 10 roll_keep_for 720h } level INFO } } sub.domain.com { # Логирование запросов log { output file /var/log/caddy/link-access.log } # Определение разрешённых путей с использованием matchers @allowed path /yourSub* # Прокси для разрешённых путей handle @allowed { reverse_proxy unix//var/lib/marzban/marzban.socket { header_up Host {host} header_up X-Real-IP {remote} } } # Для всех остальных запросов — 403 Forbidden handle { respond "403 Get the FUCK OUT!" 403 } } panel.domain.com { # Логирование запросов log { output file /var/log/caddy/panel-access.log } # Определение разрешённых путей с использованием matchers @allowed path /statics* /d-dash* /d-dash/#/login* /api* /docs* /redoc* /openapi.json # Прокси для разрешённых путей handle @allowed { reverse_proxy unix//var/lib/marzban/marzban.socket { header_up Host {host} header_up X-Real-IP {remote} } } # Для всех остальных запросов — 403 Forbidden handle { respond "403 Get the FUCK OUT!" 403 } } Сохраняем файл. 4. Проверяем и Перезапускаем Caddy проверяем файл: cadd v Если ошибок нет, тогда перезапускаем: cadd r Дальше все настройки как и всегда
-
caddy Настройка реверс прокси Caddy и Fail2Ban в docker
Deniom опубликовал тема в Домашняя инфраструктура
Вступление, или немного о том зачем и почему В моей домашней системе за последнее время накопилось значительное число сервисов, для того что бы их использовать в какой то момент стало банально не удобно и не рационально использовать доступ по http и порту. Кроме того существует ряд сервисов которое в принципе не будут работать без использования шифрования. Первоначально в моей системе использовался реверс прокси nginx proxy manager с бесплатными duckdns адресами. Со временем я перешел на использование своего домена. Важной особенностью моего сценария использования являлось то что реверс прокси использовалось только внутри локальной\впн сети и не имело внешнего доступа на 80/443 порту в сеть. Для получения сертификата обычными средствами необходимо что бы сервер мог оставить запись на 80 порту, но такой сценарий не выполним если у вас нет белого ip или возможности пробросить порты. Сценарий со временным открытием портов для обновления так же мной был признан не самым удобным по причине того что можно банально забыть. Благо для такого есть решение под названием dns challenge. При использовании такого метода подтверждения подлинности сайта выполняется путем изменения dns записи с использованием api. Такой сервис предоставляет ряд провайдеров dns, из подходящих под мои задачи это cloudflare и duckdns. Для использования многих сервисов cloudflare таких как api и защита от ddos не обязательно покупать у них домен, достаточно просто перенести управление в cloudflare. Все бы было хорошо система работала с использованием nginx proxy manager, а для внешнего доступа к ресурсам использовалась встроенная публикация сервисов keenetic. Но в один не особо прекрасный момент использования реверс прокси я столкнулся с проблемой что перестали обновляться автоматически сертификаты. Проблема как оказалось достаточна старая и исправления к ней полноценного не было, да и сам npm как по мне казался несколько избыточным и перегруженным для моего сценария использования. Таким образом началось изучение альтернативных решений для организации реверс прокси. Две самые популярные альтернативы из доступных решений это traefik и caddy. traefik - это достаточно интересное и универсальное решение, но оно в первую очередь делает упор на динамически изменяемые системы. Очень хорошо работает с докер контейнерами путем установки настроек в метках контейнеров. Но в моем кейсе использования динамическое масштабирование не планировалось и существовало много сервисов которые были запущены без использования докера. caddy в свою очередь является очень легким в настройке сервисом с большим количеством различных модулей на все случаи жизни. Единственным минусом можно выделить отсутствие интерфейса для настройки, все настройки задаются в файле (но об этом дальше). В данной статье я не планирую проводить сравнение возможностей traefik и caddy подобных сравнений на просторах сети достаточно, для моей задачи больше подошел caddy. Все дальнейшее развертывание будет показано с использованием docker-compose. Запуск контейнеров и сборка контейнеров выполнялась в portainer, но вы можете просто создать свой docker-compose файл и запустить без использования portainer. Базовый вариант настройки Сaddy Отдельно стоит отметить что сам по себе caddy крайне легковесный но и ограниченный в функционале, значительная часть возможностей предложена в дополнительных модулях. Эти модули можно как добавлять самому при сборке докер контейнера или при запуске apt пакета так и использовать готовые сборки docker с включенными модулями. На самом деле настройка реверс прокси в Caddy это крайне простая задача. Запустим докер контейнер с использованием следующего docker-compose version: '3.8' services: caddy: image: 'slothcroissant/caddy-cloudflaredns:latest' container_name: caddy restart: unless-stopped ports: - '80:80' - '443:443' environment: ACME_AGREE: true CLOUDFLARE_API_TOKEN: "aaaaaaaaadssssssssssssssssss" CLOUDFLARE_EMAIL: "[email protected]" volumes: - /docker/caddy/data:/data - /docker/caddy/config:/config - /docker/caddy/Caddyfile:/etc/caddy/Caddyfile В данном примере использован готовый caddy контейнер для получения сертификатов с использованием dns challenge cloudflare. Так же существуют готовые сборки для других провайдеров например вот тут предложена неплохая подборка самых распространенных сборок. Для получения с сертификата через dns chelenge необходимо создать api ключ на cloudflare, подробней об этом приведено тут. Теперь создадим файл конфигурации на основании которого будет работать наш сервер. Этот файл называется Caddyfile он не имеет расширения и должен располагаться по пути /docker/caddy/Caddyfile (для данного варианта docker-compose). nextcloud.mydomain.ru { tls [email protected] { dns cloudflare {env.CLOUDFLARE_API_TOKEN} } reverse_proxy 192.168.0.101:1234 } Фактически у нас есть всего две секции tls и reverse_proxy. Секция tls отвечает за получение сертификата, email можно не указывать он необходим для получения напоминаний от acme о продлении сертификатов. Секция reverse_proxy описывает сами правила переадресации, для подавляющего большинства сервисов такого варианта настройки будет достаточно, но бывают исключения например vaultwarden. vaultwarden.mydomain.ru { tls [email protected] { dns cloudflare {env.CLOUDFLARE_API_TOKEN} } reverse_proxy 192.168.0.132:10380 { header_up X-Real-IP {remote_host} } } Обычно если сервис требует особых настроек для реверс прокси в документации приводятся примеры для самых популярных решений, в том числе и caddy. Для применения изменений необходимо перезапустить докер контейнер. На этом простой вариант настройки caddy закончен, если вы не планируете использовать его для публикации в интернет то можно использовать как есть и наслаждаться. Главное не забыть правильно указать dns записи. Если в настройках доменов в cloudflare указать внутренний ip например 192.168.0.132 тогда при использовании их dns можно обойтись без перезаписи и ходить только внутри своей локальной сети по https. А теперь все становиться чуточку сложнее... настройка Caddy для публикации в интернет Для использования fail2ban нам необходимо настроить правильное и удобное логирование в caddy. Сам по себе caddy формирует логи в формате json которые в принципе достаточно удобно парсятся но с ними не очень удобно работать для fail2ban, в таком случаем нам на помощь приходит модуль transform-encoder данный модуль позволяет указать шаблон форматирования для логов. Готового решения докер контейнера caddy-dns/cloudflare и caddyserver/transform-encoder увы найти мне не удалось так что будем создавать свой докер образ. Для этого нам понадобиться следующий Dockerfile. FROM caddy:builder AS builder RUN xcaddy build \ --with github.com/caddy-dns/cloudflare \ --with github.com/caddyserver/transform-encoder \ --with github.com/abiosoft/caddy-exec FROM caddy:latest COPY --from=builder /usr/bin/caddy /usr/bin/caddy Dockerfile размещаем в той же папке где и наш docker-compose файл со следующим содержимым version: '3.9' services: caddy: image: caddy-cloudflare-transform:latest build: context: . dockerfile: ./Dockerfile container_name: caddy restart: unless-stopped cap_add: - NET_ADMIN ports: - 80:80 - 443:443 environment: ACME_AGREE: true CLOUDFLARE_API_TOKEN: "aaaaaaaaassdsadfasfasf" CLOUDFLARE_EMAIL: "[email protected]" DOMAIN: mydomain.ru volumes: - /docker/caddy/data:/data - /docker/caddy/config:/config - /docker/caddy/logs:/logs - /docker/caddy/Caddyfile:/etc/caddy/Caddyfile Или можно воспользоваться моим собранным образом размещенным в репозитории https://github.com/Deniom3/caddy-cloudflare-transform Тогда docker-compose файл будет иметь вид version: '3.9' services: caddy: image: ghcr.io/deniom3/caddy-cloudflare-transform:latest container_name: caddy restart: unless-stopped cap_add: - NET_ADMIN ports: - 80:80 - 443:443 environment: ACME_AGREE: true CLOUDFLARE_API_TOKEN: "aaaaaaaaassdsadfasfasf" CLOUDFLARE_EMAIL: "[email protected]" DOMAIN: mydomain.ru volumes: - /docker/caddy/data:/data - /docker/caddy/config:/config - /docker/caddy/logs:/logs - /docker/caddy/Caddyfile:/etc/caddy/Caddyfile Отдельно обращаю внимание на environment DOMAIN она нам нужна для более простого (и безопасного) формирования Caddyfile. Создадим Caddyfile с такой структурой: (common) { header /* { -Server } } (cloudflare) { import common tls { dns cloudflare {env.CLOUDFLARE_API_TOKEN} } } (local) { @allowed remote_ip 192.168.0.0/24 handle { respond 401 } } { log access-log { include http.log.access output file /logs/access.log { roll_keep_for 48h } format transform `{ts} {request>headers>X-Forwarded-For>[0]:request>remote_ip} {request>host} {request>method} {request>uri} {status}` { time_format "02/Jan/2006:15:04:05" } } } jackett.{env.DOMAIN} { import local import cloudflare log handle @allowed { reverse_proxy 192.168.0.134:9117 } } home-assistant.{env.DOMAIN} { import cloudflare log reverse_proxy 192.168.0.125:8123 } vaultwarden.{env.DOMAIN} { import cloudflare log reverse_proxy 192.168.0.132:10380 { header_up X-Real-IP {remote_host} } } Пройдемся немного по блокам что бы понимать для чего каждый из них нужен. Секции которые объявляются в скобках () являются импортируемым, это настройки которые мы определяем один раз и можем использовать для наших остальных настроек путем вызова через import. При этом каждый такой блок может импортировать в себя другие, тем самым создавая сложные структуры. Секция common отвечает за удаление из ответа сервера имени сервера в нашем случае Caddy, это небольшая перестраховка для того что бы злоумышленники не могли по виду сервера использовать его уязвимости. Секция cloudflare отвечает за настройки получения сертификата с использованием dns challenge. Секция local служит для ограничения доступности к опубликованному сайту. В remote_ip указываются подсети или ip для которых доступ должен быть РАЗРЕШЕН, все остальные будут блокироваться и получать ответ указанный в handle respond в данном случае 401. Эта секция позволяет нам разделить и использовать один реверс прокси для внешней публикации и внутренней локальной сети. Еще одна важная секция необходимая для работы f2b это секция описания логов и их преобразования. Переопределение настроек логирования без указания конкретных hostname применяет эту настройку на все. В данном примере файл храниться в /logs/access.log внутри контейнера который соответствует на сервере /docker/caddy/logs Логи будут храниться 48 часов. Теперь рассмотрим более подробно добавление конкретных сайтов, если нам надо использовать реверс прокси только для локальной сети используем import local и запись как на примере с jackett, при этом домен можно подставлять путем автозамены как в примере, так как мы его передавали в переменные окружения при запуске контейнера. Если нам надо что бы наш реверс прокси пускал не только с ограниченного списка сетей то используем запись как в примере home-assistant, тут у нас нет секции local и простая запись reverse_proxy без проверки допустимых сетей. Если для сайта необходимо включить fail2ban обязательно указываем что должны вестись логи путем добавления записи log. На этом основная настройка закончена, прокидываем 443 порт с роутера на наш сервер через переадресацию портов и наслаждаемся нашествием китайских ботов. Кыш ботнет, или настройка f2b в докере для caddy Для своей работы f2b использует логи которые предоставляют другие сервисы, на предыдущем этапе мы настроили логи caddy для их использования с f2b теперь запустим сам docker контейнер с f2b. version: "3.9" services: fail2ban: image: crazymax/fail2ban:latest container_name: fail2ban network_mode: host cap_add: - NET_ADMIN - NET_RAW environment: F2B_LOG_LEVEL: INFO F2B_LOG_TARGET: STDOUT F2B_DB_PURGE_AGE: 1d volumes: - /docker/fail2ban/data:/data - /docker/caddy/logs/access.log:/docker/caddy/logs/access.log:ro restart: unless-stopped Обязательно даем право на чтение файла логов доступа caddy - /docker/caddy/logs/access.log:/docker/caddy/logs/access.log:ro Если данного файла еще нет то может возникнуть ошибка в работе так как docker создаст вместо файла папку с именем access.log Для исправления необходимо зайти на несколько сайтов через реверс прокси и проверить что логи создаются. Теперь настроим параметры работы f2b В папке /docker/fail2ban/data/filter.d размещаем файл caddy-custom.conf со следующими настройками. При такой настройке все обращения которые получили ответ 401 будут попадать в бан лист. # data/filter.d/caddy-custom.conf [Definition] # catch all lines that terminate with an unauthorized error failregex = <HOST> \S+ \S+ \S+ (401)$ ignoreregex = В папке /docker/fail2ban/data/jail.d файл caddy.conf [caddy] backend = auto enabled = true chain = FORWARD protocol = tcp port = http,https filter = caddy-custom maxretry = 3 bantime = 86400 findtime = 43200 logpath = /docker/caddy/logs/access.log ignoreip = 192.168.0.0/24 Запись ignoreip служит для того что бы наша локальная сеть в случае каких то ошибок с нашей стороны не улетела в бан. Перезапускаем контейнер и наслаждаемся спокойной жизнью. Но это не точно.... Подсказки и заметки на полях Некогда не удаляет файл логов при работе caddy, в некоторых случаях система может повести себя крайне не адекватно и файл больше не создастся. Если это необходимо перед удалением обязательно останавливать контейнер. Ротация логов настраивается отдельно в Caddyfile Для того что бы разбанить кого то в f2b при использовании в докере нам необходимо для стандартных команд добавлять команды по обращению внутрь контейнера: Выводим статус fail2ban docker exec -it fail2ban fail2ban-client status Выводим статус конкретной цепочки (имя цепочки берётся из Jail list предыдущей команды) docker exec -it fail2ban fail2ban-client status ИМЯ_ИЗ_JAIL_LIST Разблокируем требуемый IP-адрес из соответствующей цепочки docker exec -it fail2ban fail2ban-client set ИМЯ_ИЗ_JAIL_LIST unbanip IP_ДЛЯ_РАЗБЛОКИРОВКИ Для случая с использованием caddy команда разбана будет выглядеть так docker exec -it fail2ban fail2ban-client set caddy unbanip IP_ДЛЯ_РАЗБЛОКИРОВКИ Спасибо за внимание