Files
Cerbero-mcp/gateway/Caddyfile
T
AdrianoDev 867180f4bf feat(gateway): TLS auto + rate limit + IP allowlist su write endpoint
Configura il gateway Caddy per il deploy su cerbero-mcp.tielogic.xyz:

- Build custom Caddy con plugin mholt/caddy-ratelimit (Dockerfile +
  build via xcaddy).
- TLS automatico via Let's Encrypt (richiede DNS A record + porte
  80/443 raggiungibili), HSTS preload, header di sicurezza.
- Rate limit per IP (60 req/min sui read, 10 req/min sui write,
  sliding window).
- Allowlist IP sui write endpoint (place_*, cancel_*, set_*, close_*,
  transfer_*, amend_*, switch_*): IP non in WRITE_ALLOWLIST → 403.
- Default WRITE_ALLOWLIST copre loopback + Docker bridge: bot sulla
  stessa macchina (host o container) funziona senza configurazione,
  IP pubblici esterni vanno aggiunti esplicitamente.
- Smoke test e README aggiornati per il nuovo URL gateway.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:24:06 +02:00

80 lines
1.8 KiB
Caddyfile

{
admin off
email {$ACME_EMAIL:adrianodalpastro@tielogic.com}
# Plugin mholt/caddy-ratelimit
order rate_limit before basicauth
}
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
}
}