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:
kaffa
2026-02-01 12:34:47 +00:00
parent 432154c850
commit 196374e70c
3 changed files with 60 additions and 309 deletions

View File

@@ -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

View File

@@ -83,62 +83,42 @@ backend default_backend
backend pool_1
balance roundrobin
server-template pool_1_ 10 0.0.0.0:0 check disabled
server-template pool_1_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_1_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_2
balance roundrobin
server-template pool_2_ 10 0.0.0.0:0 check disabled
server-template pool_2_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_2_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_3
balance roundrobin
server-template pool_3_ 10 0.0.0.0:0 check disabled
server-template pool_3_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_3_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_4
balance roundrobin
server-template pool_4_ 10 0.0.0.0:0 check disabled
server-template pool_4_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_4_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_5
balance roundrobin
server-template pool_5_ 10 0.0.0.0:0 check disabled
server-template pool_5_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_5_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_6
balance roundrobin
server-template pool_6_ 10 0.0.0.0:0 check disabled
server-template pool_6_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_6_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_7
balance roundrobin
server-template pool_7_ 10 0.0.0.0:0 check disabled
server-template pool_7_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_7_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_8
balance roundrobin
server-template pool_8_ 10 0.0.0.0:0 check disabled
server-template pool_8_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_8_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_9
balance roundrobin
server-template pool_9_ 10 0.0.0.0:0 check disabled
server-template pool_9_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_9_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_10
balance roundrobin
server-template pool_10_ 10 0.0.0.0:0 check disabled
server-template pool_10_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_10_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
# ACME Backend (for certbot)
backend acme_backend
@@ -147,539 +127,359 @@ backend acme_backend
backend pool_11
balance roundrobin
server-template pool_11_ 10 0.0.0.0:0 check disabled
server-template pool_11_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_11_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_12
balance roundrobin
server-template pool_12_ 10 0.0.0.0:0 check disabled
server-template pool_12_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_12_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_13
balance roundrobin
server-template pool_13_ 10 0.0.0.0:0 check disabled
server-template pool_13_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_13_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_14
balance roundrobin
server-template pool_14_ 10 0.0.0.0:0 check disabled
server-template pool_14_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_14_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_15
balance roundrobin
server-template pool_15_ 10 0.0.0.0:0 check disabled
server-template pool_15_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_15_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_16
balance roundrobin
server-template pool_16_ 10 0.0.0.0:0 check disabled
server-template pool_16_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_16_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_17
balance roundrobin
server-template pool_17_ 10 0.0.0.0:0 check disabled
server-template pool_17_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_17_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_18
balance roundrobin
server-template pool_18_ 10 0.0.0.0:0 check disabled
server-template pool_18_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_18_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_19
balance roundrobin
server-template pool_19_ 10 0.0.0.0:0 check disabled
server-template pool_19_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_19_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_20
balance roundrobin
server-template pool_20_ 10 0.0.0.0:0 check disabled
server-template pool_20_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_20_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_21
balance roundrobin
server-template pool_21_ 10 0.0.0.0:0 check disabled
server-template pool_21_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_21_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_22
balance roundrobin
server-template pool_22_ 10 0.0.0.0:0 check disabled
server-template pool_22_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_22_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_23
balance roundrobin
server-template pool_23_ 10 0.0.0.0:0 check disabled
server-template pool_23_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_23_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_24
balance roundrobin
server-template pool_24_ 10 0.0.0.0:0 check disabled
server-template pool_24_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_24_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_25
balance roundrobin
server-template pool_25_ 10 0.0.0.0:0 check disabled
server-template pool_25_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_25_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_26
balance roundrobin
server-template pool_26_ 10 0.0.0.0:0 check disabled
server-template pool_26_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_26_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_27
balance roundrobin
server-template pool_27_ 10 0.0.0.0:0 check disabled
server-template pool_27_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_27_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_28
balance roundrobin
server-template pool_28_ 10 0.0.0.0:0 check disabled
server-template pool_28_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_28_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_29
balance roundrobin
server-template pool_29_ 10 0.0.0.0:0 check disabled
server-template pool_29_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_29_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_30
balance roundrobin
server-template pool_30_ 10 0.0.0.0:0 check disabled
server-template pool_30_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_30_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_31
balance roundrobin
server-template pool_31_ 10 0.0.0.0:0 check disabled
server-template pool_31_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_31_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_32
balance roundrobin
server-template pool_32_ 10 0.0.0.0:0 check disabled
server-template pool_32_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_32_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_33
balance roundrobin
server-template pool_33_ 10 0.0.0.0:0 check disabled
server-template pool_33_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_33_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_34
balance roundrobin
server-template pool_34_ 10 0.0.0.0:0 check disabled
server-template pool_34_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_34_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_35
balance roundrobin
server-template pool_35_ 10 0.0.0.0:0 check disabled
server-template pool_35_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_35_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_36
balance roundrobin
server-template pool_36_ 10 0.0.0.0:0 check disabled
server-template pool_36_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_36_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_37
balance roundrobin
server-template pool_37_ 10 0.0.0.0:0 check disabled
server-template pool_37_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_37_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_38
balance roundrobin
server-template pool_38_ 10 0.0.0.0:0 check disabled
server-template pool_38_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_38_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_39
balance roundrobin
server-template pool_39_ 10 0.0.0.0:0 check disabled
server-template pool_39_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_39_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_40
balance roundrobin
server-template pool_40_ 10 0.0.0.0:0 check disabled
server-template pool_40_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_40_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_41
balance roundrobin
server-template pool_41_ 10 0.0.0.0:0 check disabled
server-template pool_41_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_41_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_42
balance roundrobin
server-template pool_42_ 10 0.0.0.0:0 check disabled
server-template pool_42_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_42_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_43
balance roundrobin
server-template pool_43_ 10 0.0.0.0:0 check disabled
server-template pool_43_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_43_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_44
balance roundrobin
server-template pool_44_ 10 0.0.0.0:0 check disabled
server-template pool_44_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_44_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_45
balance roundrobin
server-template pool_45_ 10 0.0.0.0:0 check disabled
server-template pool_45_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_45_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_46
balance roundrobin
server-template pool_46_ 10 0.0.0.0:0 check disabled
server-template pool_46_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_46_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_47
balance roundrobin
server-template pool_47_ 10 0.0.0.0:0 check disabled
server-template pool_47_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_47_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_48
balance roundrobin
server-template pool_48_ 10 0.0.0.0:0 check disabled
server-template pool_48_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_48_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_49
balance roundrobin
server-template pool_49_ 10 0.0.0.0:0 check disabled
server-template pool_49_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_49_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_50
balance roundrobin
server-template pool_50_ 10 0.0.0.0:0 check disabled
server-template pool_50_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_50_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_51
balance roundrobin
server-template pool_51_ 10 0.0.0.0:0 check disabled
server-template pool_51_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_51_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_52
balance roundrobin
server-template pool_52_ 10 0.0.0.0:0 check disabled
server-template pool_52_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_52_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_53
balance roundrobin
server-template pool_53_ 10 0.0.0.0:0 check disabled
server-template pool_53_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_53_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_54
balance roundrobin
server-template pool_54_ 10 0.0.0.0:0 check disabled
server-template pool_54_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_54_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_55
balance roundrobin
server-template pool_55_ 10 0.0.0.0:0 check disabled
server-template pool_55_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_55_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_56
balance roundrobin
server-template pool_56_ 10 0.0.0.0:0 check disabled
server-template pool_56_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_56_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_57
balance roundrobin
server-template pool_57_ 10 0.0.0.0:0 check disabled
server-template pool_57_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_57_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_58
balance roundrobin
server-template pool_58_ 10 0.0.0.0:0 check disabled
server-template pool_58_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_58_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_59
balance roundrobin
server-template pool_59_ 10 0.0.0.0:0 check disabled
server-template pool_59_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_59_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_60
balance roundrobin
server-template pool_60_ 10 0.0.0.0:0 check disabled
server-template pool_60_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_60_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_61
balance roundrobin
server-template pool_61_ 10 0.0.0.0:0 check disabled
server-template pool_61_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_61_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_62
balance roundrobin
server-template pool_62_ 10 0.0.0.0:0 check disabled
server-template pool_62_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_62_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_63
balance roundrobin
server-template pool_63_ 10 0.0.0.0:0 check disabled
server-template pool_63_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_63_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_64
balance roundrobin
server-template pool_64_ 10 0.0.0.0:0 check disabled
server-template pool_64_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_64_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_65
balance roundrobin
server-template pool_65_ 10 0.0.0.0:0 check disabled
server-template pool_65_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_65_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_66
balance roundrobin
server-template pool_66_ 10 0.0.0.0:0 check disabled
server-template pool_66_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_66_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_67
balance roundrobin
server-template pool_67_ 10 0.0.0.0:0 check disabled
server-template pool_67_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_67_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_68
balance roundrobin
server-template pool_68_ 10 0.0.0.0:0 check disabled
server-template pool_68_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_68_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_69
balance roundrobin
server-template pool_69_ 10 0.0.0.0:0 check disabled
server-template pool_69_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_69_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_70
balance roundrobin
server-template pool_70_ 10 0.0.0.0:0 check disabled
server-template pool_70_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_70_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_71
balance roundrobin
server-template pool_71_ 10 0.0.0.0:0 check disabled
server-template pool_71_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_71_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_72
balance roundrobin
server-template pool_72_ 10 0.0.0.0:0 check disabled
server-template pool_72_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_72_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_73
balance roundrobin
server-template pool_73_ 10 0.0.0.0:0 check disabled
server-template pool_73_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_73_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_74
balance roundrobin
server-template pool_74_ 10 0.0.0.0:0 check disabled
server-template pool_74_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_74_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_75
balance roundrobin
server-template pool_75_ 10 0.0.0.0:0 check disabled
server-template pool_75_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_75_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_76
balance roundrobin
server-template pool_76_ 10 0.0.0.0:0 check disabled
server-template pool_76_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_76_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_77
balance roundrobin
server-template pool_77_ 10 0.0.0.0:0 check disabled
server-template pool_77_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_77_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_78
balance roundrobin
server-template pool_78_ 10 0.0.0.0:0 check disabled
server-template pool_78_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_78_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_79
balance roundrobin
server-template pool_79_ 10 0.0.0.0:0 check disabled
server-template pool_79_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_79_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_80
balance roundrobin
server-template pool_80_ 10 0.0.0.0:0 check disabled
server-template pool_80_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_80_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_81
balance roundrobin
server-template pool_81_ 10 0.0.0.0:0 check disabled
server-template pool_81_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_81_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_82
balance roundrobin
server-template pool_82_ 10 0.0.0.0:0 check disabled
server-template pool_82_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_82_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_83
balance roundrobin
server-template pool_83_ 10 0.0.0.0:0 check disabled
server-template pool_83_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_83_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_84
balance roundrobin
server-template pool_84_ 10 0.0.0.0:0 check disabled
server-template pool_84_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_84_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_85
balance roundrobin
server-template pool_85_ 10 0.0.0.0:0 check disabled
server-template pool_85_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_85_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_86
balance roundrobin
server-template pool_86_ 10 0.0.0.0:0 check disabled
server-template pool_86_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_86_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_87
balance roundrobin
server-template pool_87_ 10 0.0.0.0:0 check disabled
server-template pool_87_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_87_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_88
balance roundrobin
server-template pool_88_ 10 0.0.0.0:0 check disabled
server-template pool_88_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_88_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_89
balance roundrobin
server-template pool_89_ 10 0.0.0.0:0 check disabled
server-template pool_89_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_89_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_90
balance roundrobin
server-template pool_90_ 10 0.0.0.0:0 check disabled
server-template pool_90_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_90_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_91
balance roundrobin
server-template pool_91_ 10 0.0.0.0:0 check disabled
server-template pool_91_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_91_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_92
balance roundrobin
server-template pool_92_ 10 0.0.0.0:0 check disabled
server-template pool_92_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_92_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_93
balance roundrobin
server-template pool_93_ 10 0.0.0.0:0 check disabled
server-template pool_93_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_93_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_94
balance roundrobin
server-template pool_94_ 10 0.0.0.0:0 check disabled
server-template pool_94_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_94_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_95
balance roundrobin
server-template pool_95_ 10 0.0.0.0:0 check disabled
server-template pool_95_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_95_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_96
balance roundrobin
server-template pool_96_ 10 0.0.0.0:0 check disabled
server-template pool_96_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_96_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_97
balance roundrobin
server-template pool_97_ 10 0.0.0.0:0 check disabled
server-template pool_97_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_97_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_98
balance roundrobin
server-template pool_98_ 10 0.0.0.0:0 check disabled
server-template pool_98_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_98_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_99
balance roundrobin
server-template pool_99_ 10 0.0.0.0:0 check disabled
server-template pool_99_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_99_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3
backend pool_100
balance roundrobin
server-template pool_100_ 10 0.0.0.0:0 check disabled
server-template pool_100_ssl_ 10 0.0.0.0:0 check disabled ssl verify none
server-template pool_100_h3_ 10 quic4@0.0.0.0:0 check disabled ssl verify none alpn h3

View File

@@ -3,7 +3,7 @@
This module provides an MCP (Model Context Protocol) server for managing HAProxy
configuration and runtime state. It supports dynamic domain/server management
with HTTP, HTTPS, and HTTP/3 (QUIC) protocols.
with HTTP backends (SSL termination at HAProxy frontend).
"""
import socket
@@ -395,7 +395,7 @@ def save_servers_config(config: Dict) -> None:
pass
def add_server_to_config(domain: str, slot: int, ip: str, http_port: int, https_port: int) -> None:
def add_server_to_config(domain: str, slot: int, ip: str, http_port: int) -> None:
"""Add server configuration to persistent storage.
Args:
@@ -403,15 +403,13 @@ def add_server_to_config(domain: str, slot: int, ip: str, http_port: int, https_
slot: Server slot (1 to MAX_SLOTS)
ip: Server IP address
http_port: HTTP port
https_port: HTTPS port
"""
config = load_servers_config()
if domain not in config:
config[domain] = {}
config[domain][str(slot)] = {
"ip": ip,
"http_port": http_port,
"https_port": https_port
"http_port": http_port
}
save_servers_config(config)
@@ -443,21 +441,15 @@ def remove_domain_from_config(domain: str) -> None:
save_servers_config(config)
def get_server_suffixes(http_port: int, https_port: int) -> List[Tuple[str, int]]:
def get_server_suffixes(http_port: int) -> List[Tuple[str, int]]:
"""Get server suffixes and ports based on port configuration.
Args:
http_port: HTTP port
https_port: HTTPS port
http_port: HTTP port for backend
Returns:
List of (suffix, port) tuples
List of (suffix, port) tuples - always HTTP only
"""
if http_port == 80 and https_port == 443:
# Default ports: HTTP + HTTPS + HTTP/3
return [("", 80), ("_ssl", 443), ("_h3", 443)]
else:
# Custom port: HTTP only
return [("", http_port)]
@@ -497,13 +489,12 @@ def restore_servers_from_config() -> int:
try:
http_port = int(server_info.get("http_port", 80))
https_port = int(server_info.get("https_port", 443))
except (ValueError, TypeError):
print(f"Warning: Invalid port for {domain} slot {slot}, skipping", file=sys.stderr)
continue
try:
for suffix, port in get_server_suffixes(http_port, https_port):
for suffix, port in get_server_suffixes(http_port):
server = f"{server_prefix}{suffix}_{slot}"
haproxy_cmd(f"set server {backend}/{server} addr {ip} port {port}")
haproxy_cmd(f"set server {backend}/{server} state ready")
@@ -553,14 +544,13 @@ def haproxy_list_domains() -> str:
@mcp.tool()
def haproxy_add_domain(domain: str, ip: str = "", http_port: int = 80, https_port: int = 443) -> str:
def haproxy_add_domain(domain: str, ip: str = "", http_port: int = 80) -> str:
"""Add a new domain to HAProxy using map-based routing (no reload required).
Args:
domain: The domain name to add (e.g., api.example.com)
ip: Optional IP address for initial server; if provided, adds to slot 1
http_port: HTTP port for the backend server (default: 80)
https_port: HTTPS port for the backend server (default: 443)
Returns:
Success message or error description
@@ -570,7 +560,7 @@ def haproxy_add_domain(domain: str, ip: str = "", http_port: int = 80, https_por
return "Error: Invalid domain format"
if not validate_ip(ip, allow_empty=True):
return "Error: Invalid IP address format"
if not (1 <= http_port <= 65535) or not (1 <= https_port <= 65535):
if not (1 <= http_port <= 65535):
return "Error: Port must be between 1 and 65535"
# Check if domain already exists
@@ -596,18 +586,15 @@ def haproxy_add_domain(domain: str, ip: str = "", http_port: int = 80, https_por
# If IP provided, add server to slot 1
if ip:
suffixes = get_server_suffixes(http_port, https_port)
for suffix, port in suffixes:
for suffix, port in get_server_suffixes(http_port):
server = f"{pool}{suffix}_1"
haproxy_cmd(f"set server {pool}/{server} addr {ip} port {port}")
haproxy_cmd(f"set server {pool}/{server} state ready")
# Save to persistent config
add_server_to_config(domain, 1, ip, http_port, https_port)
add_server_to_config(domain, 1, ip, http_port)
if len(suffixes) == 1:
return f"Domain {domain} added to {pool} with server {ip}:{http_port} (HTTP only)"
return f"Domain {domain} added to {pool} with server {ip}:{http_port}/{https_port}"
return f"Domain {domain} added to {pool} with server {ip}:{http_port}"
return f"Domain {domain} added to {pool} (no servers configured)"
@@ -651,8 +638,7 @@ def haproxy_remove_domain(domain: str) -> str:
# Disable all servers in the pool (reset to 0.0.0.0:0)
for slot in range(1, MAX_SLOTS + 1):
for suffix in ["", "_ssl", "_h3"]:
server = f"{backend}{suffix}_{slot}"
server = f"{backend}_{slot}"
try:
haproxy_cmd(f"set server {backend}/{server} state maint")
haproxy_cmd(f"set server {backend}/{server} addr 0.0.0.0 port 0")
@@ -708,7 +694,7 @@ def haproxy_list_servers(domain: str) -> str:
@mcp.tool()
def haproxy_add_server(domain: str, slot: int, ip: str, http_port: int = 80, https_port: int = 443) -> str:
def haproxy_add_server(domain: str, slot: int, ip: str, http_port: int = 80) -> str:
"""Add a server to a domain's backend at specified slot.
Args:
@@ -716,7 +702,6 @@ def haproxy_add_server(domain: str, slot: int, ip: str, http_port: int = 80, htt
slot: Server slot number (1 to MAX_SLOTS)
ip: IP address of the server (required)
http_port: HTTP port (default: 80)
https_port: HTTPS port (default: 443)
Returns:
Success message or error description
@@ -729,7 +714,7 @@ def haproxy_add_server(domain: str, slot: int, ip: str, http_port: int = 80, htt
return "Error: Invalid IP address format"
if not (1 <= slot <= MAX_SLOTS):
return f"Error: Slot must be between 1 and {MAX_SLOTS}"
if not (1 <= http_port <= 65535) or not (1 <= https_port <= 65535):
if not (1 <= http_port <= 65535):
return "Error: Port must be between 1 and 65535"
try:
@@ -748,14 +733,14 @@ def haproxy_add_server(domain: str, slot: int, ip: str, http_port: int = 80, htt
server_prefix = domain_to_backend(domain)
results = []
for suffix, port in get_server_suffixes(http_port, https_port):
for suffix, port in get_server_suffixes(http_port):
server = f"{server_prefix}{suffix}_{slot}"
haproxy_cmd(f"set server {backend}/{server} addr {ip} port {port}")
haproxy_cmd(f"set server {backend}/{server} state ready")
results.append(f"{server}{ip}:{port}")
# Save to persistent config
add_server_to_config(domain, slot, ip, http_port, https_port)
add_server_to_config(domain, slot, ip, http_port)
return f"Added to {domain} ({backend}) slot {slot}:\n" + "\n".join(results)
except (HaproxyError, ValueError) as e:
@@ -793,20 +778,8 @@ def haproxy_remove_server(domain: str, slot: int) -> str:
# Legacy backends use domain-based naming
server_prefix = domain_to_backend(domain)
# Get server config to determine which suffixes to remove
config = load_servers_config()
suffixes = ["", "_ssl", "_h3"] # Default: remove all
if domain in config and str(slot) in config[domain]:
server_info = config[domain][str(slot)]
try:
http_port = int(server_info.get("http_port", 80))
https_port = int(server_info.get("https_port", 443))
suffixes = [s for s, _ in get_server_suffixes(http_port, https_port)]
except (ValueError, TypeError):
pass # Use default suffixes
for suffix in suffixes:
server = f"{server_prefix}{suffix}_{slot}"
# HTTP only - single server per slot
server = f"{server_prefix}_{slot}"
haproxy_cmd(f"set server {backend}/{server} state maint")
haproxy_cmd(f"set server {backend}/{server} addr 0.0.0.0 port 0")