4f3e959805
Per VPS condiviso (es. con Gitea) dove Traefik gestisce già 80/443.
- gateway/Caddyfile: env-aware listen + auto_https + trusted_proxies
(defaults invariati per modalità standalone).
- docker-compose.traefik.yml: overlay che rimuove ports binding host,
attacca gateway alla network esterna di Traefik, set labels per
routing Host(cerbero-mcp.tielogic.xyz) + TLS via certresolver
Traefik. Caddy ascolta plain HTTP :80 interno.
- scripts/deploy.sh: rileva BEHIND_TRAEFIK=true → aggiunge -f
docker-compose.traefik.yml a tutti i docker compose call.
- DEPLOYMENT.md: nuova sezione 2a (topologia standalone vs behind-traefik)
+ sotto-sezione modalità behind-Traefik con env vars richieste.
Uso:
docker compose -f docker-compose.prod.yml -f docker-compose.traefik.yml \
--env-file .env up -d
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
2.1 KiB
Caddyfile
87 lines
2.1 KiB
Caddyfile
{
|
|
admin off
|
|
email {$ACME_EMAIL:adrianodalpastro@tielogic.com}
|
|
auto_https {$AUTO_HTTPS:on}
|
|
|
|
# Plugin mholt/caddy-ratelimit
|
|
order rate_limit before basicauth
|
|
|
|
# Trusted proxies: rispetta X-Forwarded-For quando dietro reverse proxy
|
|
# (es. Traefik). Default = solo private ranges.
|
|
servers {
|
|
trusted_proxies static {$TRUSTED_PROXIES:private_ranges}
|
|
}
|
|
}
|
|
|
|
{$LISTEN:cerbero-mcp.tielogic.xyz} {
|
|
log {
|
|
output stdout
|
|
format json
|
|
}
|
|
|
|
# ───── Security headers ─────
|
|
header {
|
|
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
|
X-Content-Type-Options "nosniff"
|
|
X-Frame-Options "DENY"
|
|
Referrer-Policy "no-referrer"
|
|
-Server
|
|
}
|
|
|
|
# ───── IP allowlist su endpoint write ─────
|
|
# WRITE_ALLOWLIST: CIDR space-separated (es. "1.2.3.4/32 5.6.7.0/24").
|
|
# Default 127.0.0.1/32 — fail-closed se non configurato.
|
|
@writes_blocked {
|
|
path_regexp ^/mcp-[a-z]+/tools/(place_|cancel_|set_|close_|transfer_|amend_|switch_)
|
|
not remote_ip {$WRITE_ALLOWLIST:127.0.0.1/32 ::1/128 172.16.0.0/12}
|
|
}
|
|
respond @writes_blocked "forbidden: source ip not in allowlist" 403
|
|
|
|
# ───── Rate limit ─────
|
|
# Reads: 60 req/min/IP, writes: 10 req/min/IP (sliding window).
|
|
rate_limit {
|
|
zone reads {
|
|
match {
|
|
not path_regexp ^/mcp-[a-z]+/tools/(place_|cancel_|set_|close_|transfer_|amend_|switch_)
|
|
}
|
|
key {remote_ip}
|
|
events 60
|
|
window 1m
|
|
}
|
|
zone writes {
|
|
match {
|
|
path_regexp ^/mcp-[a-z]+/tools/(place_|cancel_|set_|close_|transfer_|amend_|switch_)
|
|
}
|
|
key {remote_ip}
|
|
events 10
|
|
window 1m
|
|
}
|
|
}
|
|
|
|
# ───── Reverse proxy ─────
|
|
handle_path /mcp-deribit/* {
|
|
reverse_proxy mcp-deribit:9011
|
|
}
|
|
handle_path /mcp-bybit/* {
|
|
reverse_proxy mcp-bybit:9019
|
|
}
|
|
handle_path /mcp-hyperliquid/* {
|
|
reverse_proxy mcp-hyperliquid:9012
|
|
}
|
|
handle_path /mcp-alpaca/* {
|
|
reverse_proxy mcp-alpaca:9020
|
|
}
|
|
handle_path /mcp-macro/* {
|
|
reverse_proxy mcp-macro:9013
|
|
}
|
|
handle_path /mcp-sentiment/* {
|
|
reverse_proxy mcp-sentiment:9014
|
|
}
|
|
|
|
# Landing page statica
|
|
handle {
|
|
root * /srv
|
|
file_server
|
|
}
|
|
}
|