Caddyfile без предупреждений при запуске

Caddy ругался на два места. header_up X-Forwarded-For был лишним: Caddy сам
игнорирует этот заголовок из входящего запроса и подставляет реальный адрес,
защита от подделки обеспечивается его поведением по умолчанию. Пустая строка
перед глобальным блоком делала файл неформатированным по мнению caddy fmt.

Проверено caddy fmt и caddy validate на сгенерированном файле.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vladimir Bryzgalov
2026-08-16 19:00:49 +05:00
co-authored by Claude Opus 5
parent 7494883309
commit cd02fabb2e
2 changed files with 25 additions and 10 deletions
+7 -6
View File
@@ -22,9 +22,10 @@ CADDY_WAIT_SEC = 3
def render_caddyfile(domains: str, port: int, max_upload_mb: int) -> str:
"""Собирает конфигурацию Caddy из настроек сервиса."""
listed = ", ".join(d.strip() for d in domains.split(",") if d.strip())
# Пустой строки перед блоком быть не должно: caddy fmt считает это
# неформатированным файлом и ругается при каждом запуске.
return f"""{MARK}
# Домены и предел размера берутся из config.toml, менять нужно там.
{{
\t# Caddy очень подробно рассказывает про сертификаты. В консоли из-за этого
\t# не видно сообщений сервиса, поэтому его вывод уходит в файл.
@@ -39,11 +40,11 @@ def render_caddyfile(domains: str, port: int, max_upload_mb: int) -> str:
}}
{listed} {{
\treverse_proxy 127.0.0.1:{port} {{
\t\t# Реальный адрес клиента - иначе список разрешённых адресов
\t\t# увидит вместо него localhost и пустит кого угодно.
\t\theader_up X-Forwarded-For {{remote_host}}
\t}}
\t# X-Forwarded-For здесь намеренно не задаётся: Caddy сам игнорирует этот
\t# заголовок из входящего запроса и подставляет реальный адрес клиента.
\t# Не добавляйте сюда trusted_proxies - тогда Caddy начнёт верить заголовку
\t# от клиента, и любой сможет назваться разрешённым адресом.
\treverse_proxy 127.0.0.1:{port}
\trequest_body {{
\t\tmax_size {max_upload_mb}MB
+18 -4
View File
@@ -16,10 +16,19 @@ class TestRender:
assert "reverse_proxy 127.0.0.1:9000" in text
assert "max_size 250MB" in text
def test_real_client_address_is_forwarded(self):
"""Без этого заголовка список разрешённых адресов увидит localhost."""
text = render_caddyfile("a.example.com", 8756, 500)
assert "header_up X-Forwarded-For {remote_host}" in text
def test_xff_is_left_to_caddy_default(self):
"""Caddy сам игнорирует X-Forwarded-For от клиента и ставит реальный адрес.
Свой header_up был лишним - Caddy предупреждал об этом при каждом
запуске. Важнее обратное: trusted_proxies появляться не должен, иначе
Caddy начнёт верить заголовку клиента и адрес станет подделываемым.
"""
# Комментарии не в счёт: в них эти слова упомянуты как предостережение.
directives = "\n".join(
line for line in render_caddyfile("a.example.com", 8756, 500).splitlines()
if not line.strip().startswith("#"))
assert "header_up" not in directives
assert "trusted_proxies" not in directives
def test_caddy_log_goes_to_file(self):
"""Иначе Caddy забивает консоль сообщениями про сертификаты."""
@@ -29,6 +38,11 @@ class TestRender:
def test_generated_file_is_marked(self):
assert render_caddyfile("a.example.com", 8756, 500).startswith(MARK)
def test_no_blank_line_before_global_block(self):
"""caddy fmt считает такой файл неформатированным и ругается при запуске."""
lines = render_caddyfile("a.example.com", 8756, 500).splitlines()
assert lines[lines.index("{") - 1].strip() != ""
class TestEnsure:
def test_creates_file_when_missing(self, tmp_path):