# Зворотний проксі NetPulse.
#
# Caddy бере на себе сертифікати Let's Encrypt і оновлює їх сам. Це
# знімає з розгортання найчастішу причину нічного дзвінка — прострочений
# сертифікат на системі, яка сама має повідомляти про проблеми.


{
	# Яким сертифікатом відповідати, коли клієнт не назвав імені.
	#
	# SNI не містить IP-адрес: стандарт дозволяє там лише доменні імена,
	# тож браузер, який іде на https://93.171.243.247, не каже нічого — і
	# Caddy не має за чим обрати сертифікат. Рукостискання обривається
	# «internal error», сайт виглядає мертвим.
	#
	# З доменом ця настройка нічого не міняє: SNI приходить, і збіг
	# знаходиться звичайним шляхом.
	default_sni {$NETPULSE_DOMAIN}
}

# Одна директива на два випадки.
#
#   tls <пошта>   — сертифікат від Let's Encrypt на цю адресу;
#   tls internal  — власний самопідписаний.
#
# Значення приходить із NETPULSE_TLS, яке compose виводить із ACME_EMAIL:
# пошта задана — беремо справжній сертифікат, порожньо — самопідписаний.
#
# Порожнє значення тут не працює: Let's Encrypt не видає сертифікатів на
# публічні IP-адреси, і Caddy вічно повторював би спробу, а сайт лежав
# би без TLS. Перевірено живим розгортанням на голому IP.

# --- інтерфейс і API -------------------------------------------------
{$NETPULSE_DOMAIN} {
	tls {$NETPULSE_TLS}

	encode zstd gzip

	# WebSocket живих оновлень. Окремим блоком, бо йому не можна
	# ставити таймаут на відповідь: зʼєднання висить годинами й
	# мовчить, поки на мапі нічого не змінюється.
	@ws path /api/v1/ws
	reverse_proxy @ws api:8080 {
		flush_interval -1
	}

	# API і вшитий у бінарник інтерфейс — за однією адресою, тож
	# розділяти їх не потрібно: SPA віддає той самий процес.
	reverse_proxy api:8080

	header {
		Strict-Transport-Security "max-age=31536000; includeSubDomains"
		X-Content-Type-Options "nosniff"
		X-Frame-Options "DENY"
		Referrer-Policy "strict-origin-when-cross-origin"
		-Server
	}

	log {
		output stdout
		format console
	}
}

# --- колектор зондів -------------------------------------------------
#
# Зонди говорять gRPC поверх HTTP/2. Усередині мережі — h2c без TLS:
# сертифікат живе тут, а не в кожному примірнику колектора.
{$NETPULSE_DOMAIN}:9443 {
	tls {$NETPULSE_TLS}

	reverse_proxy h2c://collector:9443 {
		# Потік Control двонаправлений і довгий: агент тримає його
		# відкритим, доки живий. Буферизація тут ламає саме те, заради
		# чого потік існує — миттєву доставку команд.
		flush_interval -1
	}

	log {
		output stdout
		format console
	}
}
