feat: Zero-downtime certificate management via Runtime API

Changes:
- Replace USR2 signal reload with HAProxy Runtime API for cert updates
  - new ssl cert → set ssl cert → commit ssl cert
  - No connection drops during certificate changes
- Add certificates.json for persistence (domain list only)
- Add haproxy_load_cert tool for manual certificate loading
- Auto-restore certificates on MCP startup
- Update startup sequence to load both servers and certificates

certificates.json format:
{
  "domains": ["inouter.com", "anvil.it.com"]
}

Paths derived from convention:
- Host: /opt/haproxy/certs/{domain}.pem
- Container: /etc/haproxy/certs/{domain}.pem

Total MCP tools: 28 → 29

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kaffa
2026-02-02 04:23:28 +00:00
parent 7ebe204f89
commit 79254835e9
4 changed files with 292 additions and 53 deletions

View File

@@ -241,7 +241,7 @@ Returns backend server status for a specific domain:
**Status values:** `healthy` (all UP), `degraded` (partial UP), `down` (all DOWN), `no_servers`
## MCP Tools (28 total)
## MCP Tools (29 total)
### Domain Management
| Tool | Description |
@@ -285,7 +285,7 @@ Returns backend server status for a specific domain:
| `haproxy_save_state` | Save server state to disk (legacy) |
| `haproxy_restore_state` | Restore state from disk (legacy) |
### Certificate Management
### Certificate Management (Zero-Downtime via Runtime API)
| Tool | Description |
|------|-------------|
| `haproxy_list_certs` | List all certificates with expiry info |
@@ -294,6 +294,7 @@ Returns backend server status for a specific domain:
| `haproxy_renew_cert` | Renew specific certificate (force option available) |
| `haproxy_renew_all_certs` | Renew all certificates due for renewal |
| `haproxy_delete_cert` | Delete certificate from acme.sh and HAProxy |
| `haproxy_load_cert` | Load/reload certificate into HAProxy (manual trigger) |
## Key Conventions
@@ -335,6 +336,13 @@ api.example.com → pool_6
- Startup restore: All servers restored in 1 connection (was 2×N for N servers)
- Example: 7 servers restored = 1 connection (was 14 connections)
### Zero-Downtime Certificate Management
- **Runtime API**: Certificates loaded/updated without HAProxy reload
- `new ssl cert``set ssl cert``commit ssl cert`
- No connection drops during certificate changes
- **Persistence**: `certificates.json` stores domain list
- **Auto-restore**: Certificates reloaded into HAProxy on MCP startup
## HAProxy Runtime API
```bash
@@ -369,17 +377,18 @@ echo "set server pool_1/pool_1_1 state ready" | nc localhost 9999
│ ├── haproxy_client.py # HAProxy Runtime API client
│ ├── file_ops.py # File I/O operations
│ ├── utils.py # Parsing utilities
│ └── tools/ # MCP tools (28 total)
│ └── tools/ # MCP tools (29 total)
│ ├── domains.py # Domain management (3 tools)
│ ├── servers.py # Server management (7 tools)
│ ├── health.py # Health checks (3 tools)
│ ├── monitoring.py # Monitoring (4 tools)
│ ├── configuration.py # Config management (4 tools)
│ └── certificates.py # Certificate management (6 tools)
│ └── certificates.py # Certificate management (7 tools)
├── conf/
│ ├── haproxy.cfg # Main HAProxy config (100 pool backends)
│ ├── domains.map # Domain → Pool mapping
│ ├── servers.json # Server persistence (auto-managed)
│ ├── certificates.json # Certificate domain list (auto-managed)
│ └── mcp-token.env # Bearer token for MCP auth
├── certs/ # SSL/TLS certificates (HAProxy PEM format)
├── data/ # Legacy state files
@@ -419,9 +428,11 @@ echo "set server pool_1/pool_1_1 state ready" | nc localhost 9999
4. systemd starts haproxy-mcp.service
5. MCP server reads servers.json
5. MCP server reads servers.json & certificates.json
6. MCP server restores servers via Runtime API
7. Ready to serve traffic
7. MCP server loads certificates via Runtime API (zero-downtime)
8. Ready to serve traffic
```