Hoody Proxy
Section titled “Hoody Proxy”The Hoody Proxy is the foundational infrastructure that makes “everything is a URL” possible.
It’s not just about web servers. Every single container feature—terminals, displays, files, databases, browsers, scripts—flows through this proxy. This unified approach transforms isolated containers into a web-native computing fabric.
API Endpoints Summary
Section titled “API Endpoints Summary”Official Technical Reference:
The Hoody Proxy is infrastructure (runs on your server), not API endpoints you call directly. However, you configure it via the Hoody API:
Proxy Configuration:
- Proxy Aliases - Create custom domains (
my-app.{serverName}.containers.hoody.icu) - Proxy Permissions (Project) - Project-level access control
- Proxy Permissions (Container) - Container-level overrides
Related Infrastructure:
- Container Network - Configure proxy/VPN routing
- Container Firewall - Network-level rules
- Container Operations - Start/stop containers
The proxy infrastructure automatically handles TLS, routing, and IP preservation—you just configure aliases and permissions via the API.
What the Hoody Proxy Actually Is
Section titled “What the Hoody Proxy Actually Is”Physical Reality: The Hoody Proxy runs as a container on YOUR bare metal server—the same machine hosting your containers.
What it does:
- ✅ Routes ALL traffic to container services (terminal, display, files, exec, sqlite, browser, workspaces, code, curl, notifications, daemon, cron, pipe, notes, watch, run)
- ✅ Terminates TLS for every connection (automatic HTTPS everywhere)
- ✅ Preserves real client IPs (no x-forwarded-for headers needed)
- ✅ Generates automatic URLs for all services
- ✅ Enforces authentication and permissions
- ✅ Handles modern protocols (HTTP/1.1, HTTP/2, HTTP/3, WebSocket)
What it runs on: A dedicated container on your server with access to:
- Host network stack (for IP preservation)
- Container networking (for service routing)
- TLS certificate management
- Permission configuration files
Universal Gateway to Everything
Section titled “Universal Gateway to Everything”Every container capability becomes a URL through the proxy:
- display-X — Your desktop in a browser
- http-X — Any HTTP server is proxified
- https-X — Any HTTPS server is proxified
- ssh-22 — Native SSH, works with any clients
- terminal-X — Your shell with multiplayer
- files-X — Your filesystem as HTTP
- exec-X — Any script becomes an API
- browser-X — Automated browser for AI & humans
- curl-X — Complex APIs made simple
- sqlite-X — Instant databases everywhere
- daemon-X — Long-running services
- notify-X — Native notifications from the web
- code-X — VSCode in your browser
- agent-X — AI with full system control
The breakthrough: You’re not just hosting websites. Your terminal sessions, desktop environments, file systems, databases—everything becomes web-native through automatic URL generation.
The Automatic URL Pattern
Section titled “The Automatic URL Pattern”When you spawn a container, it immediately gets URLs for all services:
https://{projectId}-{containerId}-{service}-{instance}.{serverName}.containers.hoody.icu └────┬────┘ └────┬─────┘ └───┬───┘ └───┬───┘ └─────┬─────┘ Project Container Service Instance Your Server (24-char) (24-char) Name Number LocationExample for one container:
Terminal: https://67e89abc123def456789abcd-890abcdef12345678901cdef-terminal-1.node-us.containers.hoody.icuDisplay: https://67e89abc123def456789abcd-890abcdef12345678901cdef-display-1.node-us.containers.hoody.icuFiles: https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.icuSQLite: https://67e89abc123def456789abcd-890abcdef12345678901cdef-sqlite-1.node-us.containers.hoody.icuExec: https://67e89abc123def456789abcd-890abcdef12345678901cdef-exec-1.node-us.containers.hoody.icuBrowser: https://67e89abc123def456789abcd-890abcdef12345678901cdef-browser-1.node-us.containers.hoody.icuWorkspaces: https://67e89abc123def456789abcd-890abcdef12345678901cdef-workspaces-1.node-us.containers.hoody.icuCode: https://67e89abc123def456789abcd-890abcdef12345678901cdef-code-1.node-us.containers.hoody.icucURL: https://67e89abc123def456789abcd-890abcdef12345678901cdef-curl-1.node-us.containers.hoody.icuNotify: https://67e89abc123def456789abcd-890abcdef12345678901cdef-n-1.node-us.containers.hoody.icuDaemon: https://67e89abc123def456789abcd-890abcdef12345678901cdef-daemon-1.node-us.containers.hoody.icuCron: https://67e89abc123def456789abcd-890abcdef12345678901cdef-cron-1.node-us.containers.hoody.icuPipe: https://67e89abc123def456789abcd-890abcdef12345678901cdef-pipe-1.node-us.containers.hoody.icuNotes: https://67e89abc123def456789abcd-890abcdef12345678901cdef-notes-1.node-us.containers.hoody.icuWatch: https://67e89abc123def456789abcd-890abcdef12345678901cdef-watch-1.node-us.containers.hoody.icuRun: https://67e89abc123def456789abcd-890abcdef12345678901cdef-run-1.node-us.containers.hoody.icuNo DNS configuration needed. The proxy automatically makes services accessible.
How Routing Works
Section titled “How Routing Works”Request flow for every container service:
User/AI/Device ↓https://67e89abc...890abc-terminal-1.node-us.containers.hoody.icu/execute ↓Hoody Proxy Container (on your server) ├─ Terminates TLS (port 443) ├─ Parses URL: projectId, containerId, service=terminal, instance=1 ├─ Validates authentication (if permissions configured) ├─ Preserves real client IP └─ Routes to internal service ↓Container's terminal service (localhost:76) ↓Response (through proxy, back to client)Key insight: External world sees HTTPS on port 443. Internal services run on any port. Proxy handles the mapping automatically.
Reserved Ports & HTTP Service Access
Section titled “Reserved Ports & HTTP Service Access”The proxy reserves specific ports for Hoody Kit services. When you run your own web servers or applications, use any other port.
Reserved Ports (Do Not Use)
Section titled “Reserved Ports (Do Not Use)”These internal ports are reserved for Hoody Kit services (defaults; operator-configurable via container env vars):
76 - Hoody Terminal (ttyd)75 - Hoody Exec5 - Hoody SQLite4 - Hoody cURL3998 - Hoody Display (Xpra HTML server; per-display from 4000)3999 - Hoody Notifications3971 - Hoody Code (code-server; instances from 60000)23333 - Hoody Browser+ Several others for run, cron, watch, pipe, notes, tunnel, daemon, agentUse any other port for your applications: 3000, 5000, 8000, 8888, 9000, etc. — none of these collide with the Hoody Kit defaults above.
Accessing Your Web Servers (http Program)
Section titled “Accessing Your Web Servers (http Program)”When you run a web server in a container, access it via the http program:
Example: Apache2 on port 80
# Install Apache2 in containerapt-get install apache2
# Apache runs on port 80 by default# Access via http programhttps://67e89abc...890abc-http-80.node-us.containers.hoody.icuExample: Node.js API on port 3000
# Your Node.js appapp.listen(3000, () => { console.log('API running on port 3000');});
# Access via http programhttps://67e89abc...890abc-http-3000.node-us.containers.hoody.icuExample: Multiple web services in one container
# Frontend on port 3000# Backend on port 5000# Admin panel on port 8000
# Access each separatelyhttps://67e89abc...890abc-http-3000.node-us.containers.hoody.icu (frontend)https://67e89abc...890abc-http-5000.node-us.containers.hoody.icu (backend)https://67e89abc...890abc-http-8000.node-us.containers.hoody.icu (admin)The pattern: http-{port} in the URL routes to your service on that port.
All accessed via HTTPS (port 443) externally. The proxy translates to your internal port automatically.
Always-On HTTPS
Section titled “Always-On HTTPS”Every connection is encrypted. Zero configuration required.
Automatic TLS
Section titled “Automatic TLS”- ✅ Wildcard certificates (
*.containers.hoody.icu) protect all service URLs - ✅ Automatic provisioning - certificates managed by Hoody
- ✅ Automatic renewal - no manual intervention
- ✅ TLS 1.2+ - modern encryption standards
- ✅ HTTPS enforcement - HTTP automatically redirects to HTTPS
Private Endpoints
Section titled “Private Endpoints”Your container URLs never appear in public Certificate Transparency logs.
Standard Let’s Encrypt certificates are public—anyone can see what domains you’re hosting. Hoody uses wildcard certificates (*.containers.hoody.icu), so your specific container URLs remain private.
Unguessable URLs, not a permission boundary:
- 24-character hex container IDs = 2^96 possible combinations
- Even knowing your project ID, guessing a container ID: billions of years at 1B attempts/second
- URLs are effectively unguessable
The default proxy permission for a newly created container is allow — the URL is the only access gate until you add proxy permissions. Treat the URL like a bearer credential: anyone it leaks to (browser history, chat logs, referer headers, screenshots) can hit the container directly. For real access control, set proxy permissions instead of relying on URL secrecy.
Real Client IPs, Zero Configuration
Section titled “Real Client IPs, Zero Configuration”This is unique to Hoody: Applications see the real client IP address directly in remoteAddr—no special configuration, no header parsing.
How It Works
Section titled “How It Works”Most proxies hide the client IP behind the proxy’s IP, requiring applications to parse X-Forwarded-For headers. This breaks:
- Legacy applications (don’t know about proxy headers)
- Standard firewalls (can’t filter by real IP)
- Analytics tools (see proxy IP instead of user IP)
Hoody solves this at the infrastructure level:
We run a TPROXY-based edge on the host that preserves the original client connection information end-to-end. When traffic reaches your container, it sees the true client IP as if there were no proxy at all.
What this means:
// Any application, any languageapp.get('/', (req, res) => { const clientIP = req.connection.remoteAddress; console.log(`Request from: ${clientIP}`); // Shows: 203.0.113.50 (real client) // NOT: 10.0.0.1 (proxy IP)});# Use iptables with real client IPsiptables -A INPUT -s 203.0.113.0/24 -j ACCEPTiptables -A INPUT -s 198.51.100.0/24 -j DROP
# Works perfectly - sees real IPs// Old PHP code (no proxy awareness)<?php$client_ip = $_SERVER['REMOTE_ADDR'];// Works correctly - real client IP?>It just works. No configuration. No code changes. No proxy headers.
Modern Protocol Support
Section titled “Modern Protocol Support”The proxy handles modern web protocols automatically:
HTTP/2 & HTTP/3
Section titled “HTTP/2 & HTTP/3”- ✅ HTTP/1.1 - Universal compatibility
- ✅ HTTP/2 - Multiplexing for faster connections
- ✅ HTTP/3 (QUIC) - Low-latency over UDP
- ✅ Automatic negotiation - Client gets best protocol it supports
WebSocket
Section titled “WebSocket”- ✅ WebSocket - For terminal sessions, real-time updates, live displays
- ✅ Bi-directional - Full-duplex communication
- ✅ Multiplayer support - Multiple WebSocket connections to same service
Example: Hoody Terminal uses WebSocket through the proxy for real-time command execution. Multiple users can connect to the same terminal URL, each with their own WebSocket—multiplayer by default.
Protocol Limitations
Section titled “Protocol Limitations”Service Instance Support
Section titled “Service Instance Support”Containers can run multiple instances of each service:
One Container, Multiple Service Instances:
https://67e89abc...890abc-terminal-1.node-us.containers.hoody.icuhttps://67e89abc...890abc-terminal-2.node-us.containers.hoody.icuhttps://67e89abc...890abc-terminal-3.node-us.containers.hoody.icu
https://67e89abc...890abc-display-1.node-us.containers.hoody.icuhttps://67e89abc...890abc-display-2.node-us.containers.hoody.icu
https://67e89abc...890abc-sqlite-1.node-us.containers.hoody.icuhttps://67e89abc...890abc-sqlite-2.node-us.containers.hoody.icuEach instance is isolated. Terminal-1 is a different session than Terminal-2. Display-1 is a separate desktop from Display-2.
The proxy routes to the correct instance automatically based on the instance number in the URL.
Authentication & Permissions
Section titled “Authentication & Permissions”The proxy enforces access control for container services:
Default: Open by Cryptographic URL
Section titled “Default: Open by Cryptographic URL”By default, anyone with the URL can access. But the URL contains:
- 24-char project ID (2^96 possibilities)
- 24-char container ID (2^96 possibilities)
Practically unguessable. But anyone the URL reaches — proxies, CI logs, browser history, screenshots, referer headers — can hit the container directly, so treat the URL like a bearer credential rather than a real access gate. For anything you wouldn’t paste into a public channel, add explicit proxy permissions before exposing it.
Configurable: Add Permissions When Ready
Section titled “Configurable: Add Permissions When Ready”Layer on authentication as needed:
$TOKENin the HTTP examples below refers to a Hoody API bearer token. Obtain one withhoody auth loginor create an automation token per the authentication guide, then export it asHOODY_TOKENbefore running the snippets.
# Project-level permissions (apply to all containers)hoody projects proxy permissions replace --project $PROJECT_ID \ --if-match file:v<N> \ --groups <name>='{...}' --permissions <name>='{...}' --default deny
# Container-level permissions (override project settings)hoody containers proxy permissions replace --container $CONTAINER_ID \ --if-match file:v<N> \ --groups <name>='{...}' --permissions <name>='{...}' --default deny// Project-level permissionsawait client.api.proxyPermissionsProject.replace(PROJECT_ID, config);
// Container-level permissions (override project)await client.api.proxyPermissionsContainer.replace(CONTAINER_ID, config);# The If-Match ETag (file:v<N>) comes from a prior GET of the permissions document.
# Project-level permissions (apply to all containers)curl -X PATCH "https://api.hoody.icu/api/v1/projects/$PROJECT_ID/proxy/permissions" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "If-Match: file:v<N>" \ -d '{...}'
# Container-level permissions (override project settings)curl -X PATCH "https://api.hoody.icu/api/v1/containers/$CONTAINER_ID/proxy/permissions" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "If-Match: file:v<N>" \ -d '{...}'Authentication methods:
- JWT - Token-based with claims validation
- Password - Username/password via HTTP Basic Auth
- IP-based - Allow/deny by IP address or CIDR range
- Bearer token - Custom token validation
Program-specific permissions:
- Terminal - Execute vs read-only
- Files - Read vs write vs delete
- Display - View vs control
- Database - Query vs modify
See: Proxy Permissions → for complete configuration.
Service Discovery
Section titled “Service Discovery”How do you know what URLs a container has?
Option 1: Construct URLs (Deterministic Pattern)
Section titled “Option 1: Construct URLs (Deterministic Pattern)”// You know: projectId, containerId, serverNameconst projectId = "67e89abc123def456789abcd";const containerId = "890abcdef12345678901cdef";const serverName = "node-us";
// Construct any service URLconst terminalUrl = `https://${projectId}-${containerId}-terminal-1.${serverName}.containers.hoody.icu`;const displayUrl = `https://${projectId}-${containerId}-display-1.${serverName}.containers.hoody.icu`;const sqliteUrl = `https://${projectId}-${containerId}-sqlite-1.${serverName}.containers.hoody.icu`;Option 2: Query via API
Section titled “Option 2: Query via API”# Get container details with live service informationhoody containers get $CONTAINER_ID --runtime trueconst container = await client.api.containers.get(CONTAINER_ID, { runtime: 'true' });console.log(container.data.runtime_info);curl "https://api.hoody.icu/api/v1/containers/$CONTAINER_ID?runtime=true" \ -H "Authorization: Bearer $TOKEN" Response includes live service information:
{ "data": { "id": "890abcdef12345678901cdef", "project_id": "67e89abc123def456789abcd", "server_name": "node-us", "runtime_info": { "terminals": [ { "id": "1", "display": 1, "username": "user" } ], "displays": [ { "display": 1, "pid": 12345, "connected_clients": 2 } ], "services": [ { "name": "hoody-sqlite", "status": "running", "pid": 23456 } ] } }}Then construct URLs for running services.
The Exception: Hoody API
Section titled “The Exception: Hoody API”The Hoody API does NOT use the container pattern:
Hoody API: https://api.hoody.icu (platform management, no project/container prefix)
Container: https://{project}-{container}-terminal-1.{server}.containers.hoody.icu (container service, includes project/container IDs)Why the difference:
- Hoody API manages the platform (create containers, configure networks, manage billing)
- Container services run inside containers (execute commands, access files, query databases)
One API spawns containers. Container URLs are what you spawned.
Proxy Capabilities
Section titled “Proxy Capabilities”1. Custom Aliases
Section titled “1. Custom Aliases”Create memorable URLs for production:
# Create a memorable alias instead of cryptographic URLshoody proxy create --container-id $CONTAINER_ID --alias my-api --program http --index 1const alias = await client.api.proxyAliases.create({ container_id: CONTAINER_ID, alias: 'my-api', program: 'http', index: 1});console.log(alias.data.url);// https://my-api.node-us.containers.hoody.icucurl -X POST "https://api.hoody.icu/api/v1/proxy/aliases" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "container_id": "'$CONTAINER_ID'", "alias": "my-api", "program": "http", "index": 1 }'Result: my-api.{serverName}.containers.hoody.icu routes to your container’s HTTP service.
See: Proxy Aliases →
2. Custom Domains
Section titled “2. Custom Domains”Point your own domain to container services:
# Create alias as CNAME targethoody proxy create --container-id $CONTAINER_ID --alias my-app --program http --index 1
# Then point your domain via DNS# api.mycompany.com CNAME my-app.node-us.containers.hoody.icu# SSL certificate provisioned automatically// Create alias as CNAME targetconst alias = await client.api.proxyAliases.create({ container_id: CONTAINER_ID, alias: 'my-app', program: 'http', index: 1});
// Then point your domain via DNS:// api.mycompany.com CNAME my-app.node-us.containers.hoody.icu// SSL certificate provisioned automatically# Create alias as CNAME targetcurl -X POST "https://api.hoody.icu/api/v1/proxy/aliases" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"container_id": "'$CONTAINER_ID'", "alias": "my-app", "program": "http", "index": 1}'
# Then point your domain via DNS# api.mycompany.com CNAME my-app.node-us.containers.hoody.icu# SSL certificate provisioned automaticallySee: Connect a Domain →
3. Path Routing
Section titled “3. Path Routing”Route different paths to different containers:
# Create alias with target path routinghoody proxy create --container-id $CONTAINER_ID \ --alias my-app --program http --index 1 \ --target-path /api/v1 --allow-path-overrideconst alias = await client.api.proxyAliases.create({ container_id: CONTAINER_ID, alias: 'my-app', program: 'http', index: 1, target_path: '/api/v1', allow_path_override: true});curl -X POST "https://api.hoody.icu/api/v1/proxy/aliases" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "container_id": "'$CONTAINER_ID'", "alias": "my-app", "program": "http", "target_path": "/api/v1", "allow_path_override": true }'Routing:
my-app.node-us.containers.hoody.icu/api/v1/users→ Container’s/api/v1/usersmy-app.node-us.containers.hoody.icu/api/v1/posts→ Container’s/api/v1/posts
4. Multi-Level Permissions
Section titled “4. Multi-Level Permissions”Configure who can access what:
Project level (applies to all containers):
# Set project-level proxy permissions (IP-restricted)hoody projects proxy permissions replace --project $PROJECT_ID \ --if-match file:v<N> \ --groups developers='{"type":"ip","range":"203.0.113.0/24"}' \ --permissions developers='{"terminal":true,"files":true}' \ --default denyawait client.api.proxyPermissionsProject.replace(PROJECT_ID, { groups: { developers: { type: 'ip', range: '203.0.113.0/24' } }, permissions: { developers: { terminal: true, files: true } }, default: 'deny'});# The If-Match ETag (file:v<N>) comes from a prior GET of the permissions document.curl -X PATCH "https://api.hoody.icu/api/v1/projects/$PROJECT_ID/proxy/permissions" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "If-Match: file:v<N>" \ -d '{ "groups": { "developers": { "type": "ip", "range": "203.0.113.0/24" } }, "permissions": { "developers": { "terminal": true, "files": true } }, "default": "deny" }'Container level (overrides project):
# Override permissions for a specific container (public HTTP only)hoody containers proxy permissions replace --container $CONTAINER_ID \ --if-match file:v<N> \ --groups public='{"type":"ip","range":"0.0.0.0/0"}' \ --permissions public='{"http":true,"files":false}' \ --default denyawait client.api.proxyPermissionsContainer.replace(CONTAINER_ID, { groups: { public: { type: 'ip', range: '0.0.0.0/0' } }, permissions: { public: { http: true, files: false } }, default: 'deny'});# The If-Match ETag (file:v<N>) comes from a prior GET of the permissions document.curl -X PATCH "https://api.hoody.icu/api/v1/containers/$CONTAINER_ID/proxy/permissions" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "If-Match: file:v<N>" \ -d '{ "groups": { "public": { "type": "ip", "range": "0.0.0.0/0" } }, "permissions": { "public": { "http": true, "files": false } }, "default": "deny" }'See: Proxy Permissions → for complete authentication configuration.
Why This Changes Computing
Section titled “Why This Changes Computing”HTTP Unlocks Everything
Section titled “HTTP Unlocks Everything”When every capability is HTTP:
-
Any device can control any container
- Phone → Terminal → Execute deployment
- Tablet → Display → Access full desktop
- Smart watch → Files → Read logs
- IoT device → Agent → Trigger workflow
-
Any service can call any other service
- hoody-exec calls hoody-terminal to run commands
- hoody-terminal calls hoody-sqlite to store results
- hoody-agent orchestrates everything via HTTP
- External APIs integrate via hoody-curl
-
Any AI can orchestrate everything
- LLMs already understand HTTP
- No SDK needed
- No custom training
- Just make HTTP requests
-
Everything is embeddable
- Terminals in documentation
- Desktops in dashboards
- Databases in spreadsheets
- All via
<iframe src="...hoody.icu">
The proxy makes this possible by transforming every container capability into a first-class web citizen.
The Proxy Is Per-Server
Section titled “The Proxy Is Per-Server”Important: Each of your bare metal servers runs its own Hoody Proxy container.
This means:
Server 1 (node-us): └─ Hoody Proxy Container ├─ Routes traffic to Server 1's containers └─ URLs: ...node-us.containers.hoody.icu
Server 2 (node-eu): └─ Hoody Proxy Container ├─ Routes traffic to Server 2's containers └─ URLs: ...node-eu.containers.hoody.icuContainer URLs include the server name (node-us, node-eu) so you know which proxy handles them.
Cross-server communication: Containers on different servers communicate via their public URLs (through their respective proxies). Use Realms for API isolation (token scoping and safety), not networking.
Technical Details
Section titled “Technical Details”Load Balancing
Section titled “Load Balancing”Proxy handles concurrent connections:
- ✅ Thousands of WebSocket connections per service
- ✅ HTTP keep-alive for efficiency
- ✅ Connection pooling to backend services
- ✅ Graceful degradation under load
Caching
Section titled “Caching”Proxy can cache responses:
- Static files from hoody-files
- API responses from hoody-exec
- Database query results from hoody-sqlite
- Configurable via Cache-Control headers
Request Size Limits
Section titled “Request Size Limits”Per-service limits are set by the individual Kit services (hoody-files, hoody-exec, hoody-sqlite, etc.); the proxy streams request and response bodies without imposing its own size ceiling. Check each service’s OpenAPI spec for the exact limits — there is no single global “request body: X MB” ceiling enforced at the proxy layer today.
Proxy vs Container Services
Section titled “Proxy vs Container Services”Clear distinction:
Hoody Proxy (Infrastructure)
Location: Container on your server
Responsibilities:
- TLS termination
- URL routing
- IP preservation
- Authentication enforcement
- Protocol handling
- Certificate management
You configure: Aliases, permissions, routing rules
Container Services (Capabilities)
Location: Inside your containers
Responsibilities:
- Actual functionality
- Command execution
- File operations
- Database queries
- Display rendering
You use: The HTTP endpoints they expose
The proxy routes TO services. Services provide capabilities.
Useful Questions
Section titled “Useful Questions”Does the Hoody Proxy run on Hoody’s servers or mine?
Section titled “Does the Hoody Proxy run on Hoody’s servers or mine?”Your server. The Hoody Proxy runs as a container on YOUR bare metal. All container traffic routes through this proxy on your infrastructure—Hoody never sees your container data. We only see platform management operations via the Hoody API.
Why can’t I access UDP services through the proxy?
Section titled “Why can’t I access UDP services through the proxy?”The Hoody Proxy is HTTP-based and only supports TCP protocols (HTTP, HTTPS, WebSocket). For UDP applications, you need to either use Container Firewall to configure direct access, or bring an IPv4 address to the container via IPv4 Management.
Do I need to manage SSL certificates for container services?
Section titled “Do I need to manage SSL certificates for container services?”No. All *.containers.hoody.icu URLs use wildcard certificates automatically managed by Hoody. For custom domains (via CNAME), SSL is provisioned automatically via Let’s Encrypt when your DNS points to an alias. You never touch certificates.
Can I run my own reverse proxy inside a container?
Section titled “Can I run my own reverse proxy inside a container?”Yes! You can install nginx, Caddy, Traefik, or any proxy inside containers. The Hoody Proxy routes to your container’s exposed port, then your internal proxy handles further routing. Common pattern: Hoody Proxy → nginx in container → multiple backend services.
What happens if I run multiple HTTP servers in one container?
Section titled “What happens if I run multiple HTTP servers in one container?”Access them via different ports: http-3000, http-5000, http-8000 in the URL. The Hoody Proxy routes each to the correct internal port automatically. Alternatively, use one internal nginx proxy and route through http-80.
Does the proxy add latency to my applications?
Section titled “Does the proxy add latency to my applications?”Minimal. The proxy runs on the same physical server as your containers (localhost routing). TLS termination and IP preservation add <1ms overhead. Your application’s response time dominates—proxy latency is negligible.
Can clients access containers without going through the proxy?
Section titled “Can clients access containers without going through the proxy?”Not by default. All traffic flows through the proxy for security and observability. However, you can configure direct access via IPv4 addresses or SSH which bypass the proxy completely.
Why does my application see the real client IP without proxy headers?
Section titled “Why does my application see the real client IP without proxy headers?”Hoody uses custom netfilter hooks at the kernel level to preserve the original client connection information. Your container sees the real client IP in remoteAddr as if there were no proxy—no X-Forwarded-For parsing needed.
Can I disable the proxy for a specific container?
Section titled “Can I disable the proxy for a specific container?”Yes. Use CLI: hoody containers proxy state --container $CONTAINER_ID --if-match file:v<N> (omit --enable-proxy to disable), SDK: client.api.proxyPermissionsContainer.updateState(id, { enable_proxy: false }), or HTTP: PATCH /api/v1/containers/{id}/proxy/permissions/state with {"enable_proxy": false} and an If-Match: file:v<N> header (the ETag from a prior GET). All service URLs will return 503. Useful for maintenance or complete lockdown. The container keeps running, just becomes inaccessible via proxy URLs.
Do I need different proxies for different containers?
Section titled “Do I need different proxies for different containers?”No. One Hoody Proxy per server handles ALL containers on that server. The proxy routes based on the projectId-containerId pattern in URLs. Each server runs its own proxy instance, but you don’t manage multiple proxies manually.
Troubleshooting
Section titled “Troubleshooting”Container Service URLs Not Working
Section titled “Container Service URLs Not Working”Problem: Service URLs return connection errors or timeouts
Check container status:
Verify:
- status: “running” (not stopped or error)
- runtime_info shows services are running
Common causes:
-
Container not running:
POST Start the container/api/v1/containers/{container_id}/startClick "Run" to execute the request -
Service not started in container:
Terminal window # SSH into container and check# Or use terminal URL to verify service is running -
Wrong service name in URL:
Terminal window # ❌ Wrong: ...terminal... (service doesn't exist)# ✅ Correct: Check container's runtime_info for available services
401/403 Errors on Container URLs
Section titled “401/403 Errors on Container URLs”Problem: Cryptographic or alias URLs return authentication errors
Cause: Proxy permissions configured, but you don’t match any group
Check permissions:
Solutions:
-
If IP-based auth: Verify you’re connecting from whitelisted IP
Terminal window curl https://ifconfig.me # Check your current IP -
If JWT/password auth: Ensure credentials are correct
-
Temporarily remove permissions for testing:
DELETE Remove container permissions (reverts to open access)/api/v1/containers/{container_id}/proxy/permissionsClick "Run" to execute the request
Proxy Disabled Errors
Section titled “Proxy Disabled Errors”Problem: All container URLs return 503 Service Unavailable
Check proxy state:
Solution:
Re-enable proxy at project level:
Or at container level:
TLS/SSL Certificate Errors
Section titled “TLS/SSL Certificate Errors”Problem: Browser shows certificate warnings for container URLs
Reality: This shouldn’t happen - all *.containers.hoody.icu URLs have valid wildcard certificates
If it occurs:
- Clear browser cache - Old cached certificates might cause issues
- Try different browser - Isolate if browser-specific
- Check system time - Wrong time causes certificate validation failures
- Verify URL: Ensure you’re accessing
*.containers.hoody.icunot a typo
Can’t Access HTTP Service
Section titled “Can’t Access HTTP Service”Problem: https://...http-3000.node-us.containers.hoody.icu returns connection error
Solutions:
-
Verify service is running on that port in container:
Terminal window # SSH or use terminal URL to checknetstat -tlnp | grep 3000# Should show service listening on port 3000 -
Check it’s the correct port number:
Terminal window # If your app runs on 5000, use:# https://...http-5000.node-us.containers.hoody.icu -
Ensure service binds to 0.0.0.0 not localhost:
// ❌ Wrong (localhost only)app.listen(3000, 'localhost');// ✅ Correct (accessible from proxy)app.listen(3000, '0.0.0.0');
Real Client IP Not Showing
Section titled “Real Client IP Not Showing”Problem: Application sees proxy IP instead of real client IP
This shouldn’t happen - Hoody preserves real IPs via netfilter hooks
If it occurs:
-
Verify you’re reading
remoteAddrcorrectly:Node.js const clientIP = req.connection.remoteAddress;// or req.socket.remoteAddress -
Contact support - This indicates infrastructure issue
What’s Next
Section titled “What’s Next”Understand proxy features:
- Create Aliases → - Clean URLs:
my-app.node-us.containers.hoody.icu - Connect a Domain → - Point
api.mycompany.comto containers - Configure Permissions → - Authentication and access control
Explore container services:
- 🛠️ The Hoody Kit → - All 18 services the proxy routes to
- 📚 API Reference → - Complete endpoint documentation
The Hoody Proxy is the gateway to everything.
It runs on your server. You control it.
Every container capability becomes a URL.
Real client IPs. Automatic HTTPS. Zero configuration.
This is the infrastructure that enables infinite HTTP computers.