Simplify backend configuration to HTTP only
Remove SSL/QUIC backend templates - all backends now use HTTP only with SSL termination at HAProxy frontend. This improves performance (~33% faster than HTTPS backends based on benchmarks). Changes: - server.py: Remove https_port parameter from all functions - haproxy.cfg: Remove ssl/h3 server templates from pool backends - CLAUDE.md: Update docs for HTTP-only backends and acme.sh Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
88
CLAUDE.md
88
CLAUDE.md
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Project Overview
|
||||
|
||||
HAProxy Dynamic Load Balancer Management Suite - a system for runtime management of HAProxy without restarts. Provides MCP interface for dynamic domain/server management with HTTP, HTTPS, and HTTP/3 (QUIC) support.
|
||||
HAProxy Dynamic Load Balancer Management Suite - a system for runtime management of HAProxy without restarts. Provides MCP interface for dynamic domain/server management. Frontend supports HTTP/HTTPS/HTTP3, backends use HTTP only (SSL termination at HAProxy).
|
||||
|
||||
**Key Feature:** Zero-reload domain management using HAProxy map files and pool backends.
|
||||
|
||||
@@ -70,32 +70,27 @@ journalctl -u haproxy-mcp -f # Logs
|
||||
|
||||
### Adding a Domain
|
||||
|
||||
**Default (HTTP/HTTPS/H3):**
|
||||
```bash
|
||||
haproxy_add_domain("example.com", "10.0.0.1")
|
||||
# Creates: pool_N_1 (80), pool_N_ssl_1 (443), pool_N_h3_1 (443)
|
||||
```
|
||||
# Creates: pool_N_1 → 10.0.0.1:80
|
||||
|
||||
**Custom port (HTTP only):**
|
||||
```bash
|
||||
haproxy_add_domain("api.example.com", "10.0.0.1", 8080)
|
||||
# Creates: pool_N_1 (8080) only
|
||||
# Creates: pool_N_1 → 10.0.0.1:8080
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Find available pool (e.g., `pool_5`)
|
||||
2. Add to `domains.map`: `example.com pool_5`
|
||||
3. Update HAProxy runtime map: `add map ... example.com pool_5`
|
||||
4. Configure server(s) in pool via Runtime API
|
||||
4. Configure server in pool via Runtime API (HTTP only)
|
||||
5. Save to `servers.json` for persistence
|
||||
|
||||
**No HAProxy reload required!**
|
||||
|
||||
### Port Logic
|
||||
| Setting | Servers Created |
|
||||
|---------|-----------------|
|
||||
| Default (80/443) | HTTP + HTTPS + HTTP/3 (3 servers) |
|
||||
| Custom port | HTTP only (1 server) |
|
||||
### Backend Configuration
|
||||
- Backends always use HTTP (port 80 or custom)
|
||||
- SSL/TLS termination happens at HAProxy frontend
|
||||
- Each pool has 10 server slots (pool_N_1 to pool_N_10)
|
||||
|
||||
### Files
|
||||
| File | Purpose |
|
||||
@@ -109,51 +104,35 @@ This will:
|
||||
### Current Setup
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| ACME Client | certbot + dns-cloudflare |
|
||||
| ACME Client | acme.sh (Google Trust Services CA) |
|
||||
| Cert Directory | `/opt/haproxy/certs/` (auto-loaded by HAProxy) |
|
||||
| Deploy Hook | `/etc/letsencrypt/renewal-hooks/deploy/haproxy-deploy.sh` |
|
||||
| acme.sh Home | `~/.acme.sh/` |
|
||||
|
||||
### How It Works
|
||||
1. HAProxy binds with `crt /etc/haproxy/certs/` (directory, not file)
|
||||
2. All `.pem` files in directory are auto-loaded
|
||||
3. SNI selects correct certificate based on domain
|
||||
4. Certbot deploy hook auto-creates combined PEM on issue/renewal
|
||||
4. acme.sh deploy hook auto-creates combined PEM on issue/renewal
|
||||
|
||||
### Adding New Certificate
|
||||
```bash
|
||||
# Issue certificate (Let's Encrypt)
|
||||
certbot certonly \
|
||||
--dns-cloudflare \
|
||||
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
|
||||
-d "newdomain.com" -d "*.newdomain.com"
|
||||
```
|
||||
|
||||
Deploy hook automatically:
|
||||
1. Combines `fullchain.pem + privkey.pem` → `/opt/haproxy/certs/newdomain.com.pem`
|
||||
2. Restarts HAProxy
|
||||
3. **No manual cfg modification needed!**
|
||||
|
||||
### Google Trust Services (optional)
|
||||
```bash
|
||||
certbot certonly \
|
||||
--server https://dv.acme-v02.api.pki.goog/directory \
|
||||
--eab-kid "KEY_ID" \
|
||||
--eab-hmac-key "HMAC_KEY" \
|
||||
--dns-cloudflare \
|
||||
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
|
||||
-d "domain.com" -d "*.domain.com"
|
||||
# Issue certificate (Google Trust Services)
|
||||
~/.acme.sh/acme.sh --issue \
|
||||
--dns dns_cf \
|
||||
-d "newdomain.com" -d "*.newdomain.com" \
|
||||
--reloadcmd "cat ~/.acme.sh/newdomain.com_ecc/fullchain.cer ~/.acme.sh/newdomain.com_ecc/newdomain.com.key > /opt/haproxy/certs/newdomain.com.pem && podman exec haproxy kill -USR2 1"
|
||||
```
|
||||
|
||||
### Certificate Commands
|
||||
```bash
|
||||
# List certificates
|
||||
certbot certificates
|
||||
~/.acme.sh/acme.sh --list
|
||||
|
||||
# Renew all (dry run)
|
||||
certbot renew --dry-run
|
||||
# Renew all
|
||||
~/.acme.sh/acme.sh --cron
|
||||
|
||||
# Renew all (force)
|
||||
certbot renew --force-renewal
|
||||
# Force renew specific domain
|
||||
~/.acme.sh/acme.sh --renew -d "domain.com" --force
|
||||
|
||||
# Check loaded certs in HAProxy
|
||||
ls -la /opt/haproxy/certs/
|
||||
@@ -162,6 +141,7 @@ ls -la /opt/haproxy/certs/
|
||||
### Cloudflare Credentials
|
||||
- File: `~/.secrets/cloudflare.ini`
|
||||
- Format: `dns_cloudflare_api_token = TOKEN`
|
||||
- Also export: `export CF_Token="your_token"`
|
||||
|
||||
## HTTP/3 (QUIC)
|
||||
|
||||
@@ -245,18 +225,17 @@ curl -X POST https://mcp.inouter.com/mcp \
|
||||
- Each pool has 10 server slots
|
||||
|
||||
### Server Naming
|
||||
Pool backends use this naming:
|
||||
- `pool_N_1` to `pool_N_10` - HTTP (always created)
|
||||
- `pool_N_ssl_1` to `pool_N_ssl_10` - HTTPS (default ports only)
|
||||
- `pool_N_h3_1` to `pool_N_h3_10` - HTTP/3 QUIC (default ports only)
|
||||
Pool backends use simple naming: `pool_N_1` to `pool_N_10`
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
example.com (80/443 default):
|
||||
└─ pool_5_1, pool_5_ssl_1, pool_5_h3_1
|
||||
example.com → pool_5
|
||||
└─ pool_5_1 (slot 1)
|
||||
└─ pool_5_2 (slot 2)
|
||||
└─ ... up to pool_5_10
|
||||
|
||||
api.example.com (custom port 8080):
|
||||
└─ pool_6_1 only
|
||||
api.example.com → pool_6
|
||||
└─ pool_6_1 (slot 1)
|
||||
```
|
||||
|
||||
### Persistence
|
||||
@@ -302,10 +281,9 @@ echo "set server pool_1/pool_1_1 state ready" | nc localhost 9999
|
||||
├── scripts/ # Utility scripts
|
||||
└── run/ # Runtime socket files
|
||||
|
||||
/etc/letsencrypt/
|
||||
├── live/ # Certbot certificates
|
||||
└── renewal-hooks/deploy/
|
||||
└── haproxy-deploy.sh # Auto-combine PEM & restart HAProxy
|
||||
~/.acme.sh/
|
||||
├── *_ecc/ # Certificate directories (one per domain)
|
||||
└── acme.sh # ACME client script
|
||||
|
||||
/etc/containers/systemd/
|
||||
└── haproxy.container # Podman Quadlet config
|
||||
@@ -322,7 +300,7 @@ echo "set server pool_1/pool_1_1 state ready" | nc localhost 9999
|
||||
| `/etc/containers/systemd/haproxy.container` | Podman Quadlet |
|
||||
| `/etc/systemd/system/haproxy-mcp.service` | MCP service |
|
||||
| `/opt/haproxy/conf/mcp-token.env` | MCP auth token |
|
||||
| `/etc/letsencrypt/renewal-hooks/deploy/haproxy-deploy.sh` | Cert deploy hook |
|
||||
| `~/.acme.sh/` | acme.sh certificates and config |
|
||||
| `~/.secrets/cloudflare.ini` | Cloudflare API token |
|
||||
|
||||
## Startup Sequence
|
||||
|
||||
Reference in New Issue
Block a user