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

@@ -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,22 +441,16 @@ 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)]
return [("", http_port)]
def restore_servers_from_config() -> int:
@@ -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,13 +638,12 @@ 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}"
try:
haproxy_cmd(f"set server {backend}/{server} state maint")
haproxy_cmd(f"set server {backend}/{server} addr 0.0.0.0 port 0")
except HaproxyError:
pass # Ignore errors for individual servers
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")
except HaproxyError:
pass # Ignore errors for individual servers
# Remove from persistent config
remove_domain_from_config(domain)
@@ -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,22 +778,10 @@ 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}"
haproxy_cmd(f"set server {backend}/{server} state maint")
haproxy_cmd(f"set server {backend}/{server} addr 0.0.0.0 port 0")
# 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")
# Remove from persistent config
remove_server_from_config(domain, slot)