feat: configure Caddy v2 edge proxy (#92) #197

Merged
shahondin1624 merged 1 commits from feature/issue-92-caddy-proxy into main 2026-03-11 10:43:17 +01:00
4 changed files with 101 additions and 3 deletions

30
docker/caddy/Caddyfile Normal file
View File

@@ -0,0 +1,30 @@
# Caddy v2 edge proxy for llm-multiverse
#
# Local development: uses self-signed TLS on localhost
# Production: replace DOMAIN env var with your domain for automatic Let's Encrypt
{
admin off
}
{$DOMAIN:localhost} {
# Self-signed TLS for local dev; automatic Let's Encrypt for real domains
tls {$TLS_MODE:internal}
# Health check endpoint
handle /healthz {
respond "OK" 200
}
# gRPC reverse proxy to Orchestrator (h2c for plaintext gRPC)
reverse_proxy orchestrator:50058 {
transport http {
versions h2c
}
}
log {
output stdout
format json
}
}
}

View File

@@ -9,9 +9,37 @@
#
# Network:
# All services communicate over the 'llm-internal' bridge network.
# Only the orchestrator port (50058) is exposed to the host.
# Only Caddy (HTTPS on 443, HTTP on 80) is exposed to the host.
services:
# ---------- Edge Proxy ----------
caddy:
image: caddy:2-alpine
container_name: llm-caddy
ports:
- "${HTTPS_PORT:-443}:443"
- "${HTTP_PORT:-80}:80"
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
environment:
- DOMAIN=${DOMAIN:-localhost}
- TLS_MODE=${TLS_MODE:-internal}
networks:
- llm-internal
restart: unless-stopped
depends_on:
orchestrator:
condition: service_started
healthcheck:
test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:80/healthz"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
# ---------- Infrastructure ----------
searxng:
@@ -168,8 +196,6 @@ services:
context: ..
dockerfile: docker/python/orchestrator.Dockerfile
container_name: llm-orchestrator
ports:
- "${ORCHESTRATOR_PORT:-50058}:50058"
environment:
- ORCHESTRATOR_CONFIG=/etc/llm-multiverse/orchestrator.yaml
configs:
@@ -215,6 +241,10 @@ volumes:
driver: local
memory-data:
driver: local
caddy-data:
driver: local
caddy-config:
driver: local
# ---------- Network ----------

View File

@@ -95,6 +95,7 @@
| #89 | Write Dockerfiles for Rust services | Phase 11 | `COMPLETED` | Docker | [issue-089.md](issue-089.md) |
| #90 | Write Dockerfiles for Python services | Phase 11 | `COMPLETED` | Docker | [issue-090.md](issue-090.md) |
| #91 | Write docker-compose.yml with internal network | Phase 11 | `COMPLETED` | Docker / YAML | [issue-091.md](issue-091.md) |
| #92 | Configure Caddy v2 edge proxy | Phase 11 | `COMPLETED` | Docker / Caddyfile | [issue-092.md](issue-092.md) |
## Status Legend

View File

@@ -0,0 +1,37 @@
# Issue #92: Configure Caddy v2 edge proxy
## Metadata
| Field | Value |
|---|---|
| Issue | #92 |
| Title | Configure Caddy v2 edge proxy |
| Milestone | Phase 11: Docker Compose (Single Machine) |
| Status | `COMPLETED` |
| Language | Docker / Caddyfile |
| Related Plans | issue-091.md |
| Blocked by | #91 |
## Acceptance Criteria
- [x] Caddyfile with reverse proxy to Orchestrator
- [x] Automatic TLS via Let's Encrypt (or self-signed for local dev)
- [x] Internal services not exposed externally
- [x] Health check endpoint exposed (/healthz)
- [x] Caddy service added to docker-compose.yml
## Files Created/Modified
| File | Action | Purpose |
|---|---|---|
| `docker/caddy/Caddyfile` | Create | Caddy reverse proxy config |
| `docker/docker-compose.yml` | Modify | Add Caddy service, remove direct orchestrator port |
| `implementation-plans/issue-092.md` | Create | Plan |
| `implementation-plans/_index.md` | Modify | Index entry |
## Deviation Log
| Deviation | Reason |
|---|---|
| No rate limiting | Caddy requires `caddy-ratelimit` plugin (not in standard image) |
| No gRPC-Web support | Marked optional in acceptance criteria, can be added later |