Webhook and Documentation Isolation Strategy
This document explains how DocBuilder prevents webhook endpoints from colliding with documentation content.
Architecture: Multi-Server Design
DocBuilder uses a defense-in-depth approach with multiple isolated HTTP servers:
Port Allocation
| Server | Default Port | Purpose | Collision Risk |
|---|---|---|---|
| Docs | 8080 | Serves Hugo-generated documentation | ❌ None - separate server |
| Webhook | 8081 | Receives forge webhooks | ❌ None - separate server |
| Admin | 8082 | Administrative API, health checks | ❌ None - separate server |
| LiveReload | 8083 | Server-Sent Events for live reload | ❌ None - separate server |
Defense-in-Depth Layers
Layer 1: Port Isolation (Primary Defense)
Each server runs on a separate TCP port with its own http.Server instance and request multiplexer (http.ServeMux). This provides complete isolation:
Collision Probability: 0% - Requests to different ports go to completely different HTTP servers.
Layer 2: Path Prefixing (Secondary Defense)
Even if servers were combined (they’re not), webhook paths use reserved prefixes:
/webhooks/github/webhooks/gitlab/webhooks/forgejo/webhook(generic)
These paths are unlikely to exist in Hugo documentation because:
- Hugo content typically lives in
/docs/,/blog/, etc. - The
/webhooks/prefix is API-specific, not documentation content - Hugo wouldn’t generate these exact paths without explicit configuration
Layer 3: HTTP Method Filtering (Tertiary Defense)
Webhook handlers only accept POST requests:
Documentation requests use GET, so even if a collision occurred:
GET /webhooks/github→ Documentation server (404 or docs file)POST /webhooks/github→ Webhook server (webhook handler)
Layer 4: Configuration Validation (Preventive)
Port binding validation happens at startup:
If any port is already in use or if two services try to use the same port, the daemon fails to start with a clear error message.
Additional Safeguards
1. Port Conflict Detection
DocBuilder validates that all configured ports are unique:
If you accidentally configure the same port twice, the daemon will fail to start.
2. Firewall Recommendations
For production deployments, use firewall rules to restrict access:
3. Reverse Proxy Path Segregation
When using a reverse proxy (nginx, Traefik, Caddy), use different subdomains or paths:
Option A: Subdomain Separation
Option B: Path Separation (Less Recommended)
4. Content Security Policy
For defense in depth, the docs server could set CSP headers to prevent accidental form submissions to webhook paths:
This prevents JavaScript on the docs site from submitting forms to webhook endpoints.
Attack Vectors (and Why They’re Mitigated)
❌ Path Traversal Attack
Scenario: Attacker tries GET /webhooks/../../../etc/passwd
Mitigation:
- HTTP path normalization happens before routing
- Webhook server only handles
/webhooks/*, not arbitrary paths - Different port means request wouldn’t reach docs server anyway
❌ Documentation Collision
Scenario: Hugo generates a page at /webhooks/github.html
Mitigation:
- Webhook server is on port 8081, docs on 8080
- Even if page exists on docs server, webhook POST goes to webhook server
- HTTP method differs (GET vs POST)
❌ Port Confusion
Scenario: User configures same port for docs and webhooks
Mitigation:
- Startup validation fails with clear error
- Daemon refuses to start
- Operator must fix configuration
❌ Webhook Forgery via Docs
Scenario: Attacker embeds JavaScript in docs to forge webhooks
Mitigation:
- Different origins (port 8080 vs 8081) trigger CORS
- Webhook signature validation prevents unsigned requests
- Same-origin policy blocks cross-port requests
Testing Collision Prevention
Manual Testing
Port Conflict Testing
Configuration Best Practices
✅ Recommended: Default Ports
✅ Recommended: Custom Ports with Separation
❌ Never: Same Ports
⚠️ Caution: Non-Sequential Ports
Monitoring and Validation
Startup Validation
Watch daemon logs for port binding confirmation:
If you see errors:
This indicates a port conflict that must be resolved before the daemon can start.
Runtime Health Checks
Summary
DocBuilder prevents webhook/documentation collisions through:
- ✅ Port Isolation - Separate HTTP servers on different ports (primary defense)
- ✅ Path Prefixing - Reserved
/webhooks/*prefix (secondary defense) - ✅ Method Filtering - POST-only webhooks vs GET documentation (tertiary defense)
- ✅ Startup Validation - Fail fast if ports conflict (preventive)
- ✅ Firewall Rules - Network-level access control (optional)
- ✅ Reverse Proxy - Subdomain/path segregation (optional)
Collision Risk: Effectively 0% with default configuration.
Related Documentation
- Configure Webhooks - Webhook setup guide
- Daemon Mode - Running DocBuilder as a service
- HTTP Server Architecture - Multi-server design