Every service is a URL. The proxy is how.
One container exposes every Hoody Kit service at its own HTTPS URL, plus an http-PORT slug for anything you bind yourself. Ports, auth, TLS, and real client IPs all resolve at the URL layer.
Proxy runs on your bare metal. Hoody sees management API calls — container traffic never leaves your server.
*.containers.hoody.com — wildcard TLS · no Certificate Transparency log exposure
One grammar, many patterns
Every Kit service resolves through the same proxy, but the URL slug reveals what it is. Same grammar, different shape per service.
| Service | URL slug | Notes |
|---|---|---|
| Terminal | terminal-N | Per-instance shell; maps to display-N |
| Display | display-N | GUI / X11 desktop per instance |
| Browser | browser-N | Remote Chrome instance |
| Code | code-N | VS Code instance per index |
| Files | files-N | File manager per instance |
| SQLite | sqlite-N | One slug per database service |
| Exec | exec-N | Scripts-as-APIs |
| Workspaces | workspaces-N | Per-agent LLM instance |
| cURL | curl-N | Outbound HTTP proxy |
| Daemon | daemon-N | Process manager |
| Cron | cron-N | Scheduled jobs per instance |
| Notifications | n-N · notification-server-N | Browser bridge + API |
| Pipe | pipe-N | Byte-stream relay per instance |
Project 24-hex × container 24-hex = 2^192 pair combinations. Infeasible to brute-force.
Run a server on any port. It gets a URL.
http-PORT prefixes route the proxy to your container's internal port. No nginx server block. No ingress YAML.
# listening sockets
$ ss -ltnp
https://PROJECT_ID-CONTAINER_ID-http-4000.containers.hoody.com
https://PROJECT_ID-CONTAINER_ID-http-5173.containers.hoody.com
https://PROJECT_ID-CONTAINER_ID-http-7070.containers.hoody.com
— Hoody-kit ports are reserved for the platform's own services; everything else is yours. App-side, bind on any port and expose it via http-PORT.
— Apps must bind to 0.0.0.0, not localhost — the socket has to be reachable from the proxy container.
— Proxies HTTP/1.1, HTTP/2, HTTP/3, and WebSocket end-to-end. Arbitrary user UDP is not routed — use a dedicated IPv4 if you need raw UDP.
Auth is a JSON policy, not application middleware.
The proxy validates JWT claims, password hashes, IP CIDR ranges, and bearer tokens before a request reaches your container. Your app stays vanilla.
{
"project": "abc123",
"container": "def456",
"enable_proxy": true,
"default": "deny",
"groups": {
"dashboard": {
"type": "jwt",
"algorithm": "HS256",
"sources": ["header:Authorization"],
"secret": "<hmac-secret>",
"claims": { "role": ["admin", "viewer"] }
},
"office-only": {
"type": "ip",
"range": "203.0.113.0/24"
}
},
"permissions": {
"dashboard": { "ui": true, "terminal": [1, 2] },
"office-only": { "ssh": true, "terminal": true }
}
}JWT
HS256 · RS256 · ES256 · header / cookie / query · claim validation
Password
HTTP Basic · SHA-256 + salt · URL-embeddable
IP
IPv4 CIDR match · real client IP at socket level
Bearer Token
Multiple tokens per group · API-friendly
Container-level permissions replace project-level permissions — they do not merge. Set both scopes explicitly if you rely on inheritance.
Memorable URLs on top of cryptographic URLs
One API call turns the long cryptographic URL into a memorable Hoody subdomain like myapp.node-us-1.containers.hoody.com — served under Hoody's wildcard *.containers.hoody.com TLS, with no certificate to provision.
https://abc123-def456-http-4000.node-us-1.containers.hoody.com
https://myapp.node-us-1.containers.hoody.com
Alias naming: 3–61 chars, lowercase alphanumeric plus hyphens, must start and end with a letter or number. Auto-generated aliases are 48-char hex.
What you would otherwise stitch together
The proxy replaces a stack most teams assemble from scratch: reverse proxy + cert manager + VPN or tunnel + per-app auth + audit log. The axioms the self-hosted column fails — URL-as-route, URL-as-auth-scope, URL-as-embeddable — are what the proxy supplies natively.
| Concern | Hoody Proxy | Self-hosted equivalent |
|---|---|---|
| Wildcard HTTPS | supported natively — Native | certbot + renewal cron + cert rotation |
| Routing to internal port | supported natively — Native | nginx server block per service |
| Real client IP | supported natively — Native | Parse X-Forwarded-For per app |
| JWT · Basic · IP · Token auth | supported natively — Native | Middleware per app + session libs |
| Custom domain + TLS | supported natively — Native | Cloudflare / DNS-01 / nginx reload |
| Centralized request audit | supported natively — Native | nginx logs + log shipper + index |
| Iframe-embeddable URLs | supported natively — Native | Manual CORS / CSP / TLS per app |
| Runs on your hardware | supported natively — Native | You run it yourself anyway |
If you're already on Kubernetes with an ingress controller, Cloudflare Tunnels for SSO to Okta, or Tailscale for L3 private access, those tools stay better for their specific niches. The proxy earns its place when you want URL-addressable container services as the primary abstraction.
Six workflows the URL-first model makes trivial
Drawn from patterns teams actually ship with the Hoody Proxy.
Ship an API with no reverse proxy
Bind to 0.0.0.0:4000. Get abc123-def456-http-4000.node-us-1.containers.hoody.com. Skip the nginx, cert, and DNS song.
Memorable subdomain, zero cert setup
POST /api/v1/proxy/aliases turns the crypto URL into a memorable subdomain like myapp.node-us-1.containers.hoody.com, served instantly under Hoody's wildcard TLS — no certificate to provision.
Blue/green via alias swap
Point myapp.node-us-1.containers.hoody.com at container B, test, swap the alias back. No config reload, no downtime.
Give an AI agent a container to drive
Agent gets a JWT, proxy validates per-request, agent writes files, runs commands, queries sqlite over HTTPS.
Multi-tenant SaaS subdomains
One container per tenant; alias each to tenant.node-us-1.containers.hoody.com. Tenant isolation enforced at the URL layer.
Instant revocation
One DELETE call to the Control Plane and the URL is dead within a second. No cache poisoning.
Your first URL is one API call away.
Create a project, create a container, and every service is already online. No infrastructure to stand up first.
See also — /platform/control-plane for proxy alias, permission, and log APIs.