Skip to content

Container URLs are functional but not memorable. Proxy aliases transform cryptographic URLs into clean, production-ready domains.

After understanding how the Hoody Proxy works, you need to understand how to create memorable URLs for production use.


Official Technical Reference:

This Foundation page explains alias concepts and usage patterns. For complete endpoint documentation:

Alias Management:

Related:


When you spawn a container, you get automatic service URLs:

https://67e89abc123def456789abcd-890abcdef12345678901cdef-exec-1.node-us.containers.hoody.icu

These URLs are:

  • ✅ Automatic (zero configuration)
  • ✅ Unique (cryptographic IDs)
  • ✅ Secure (effectively unguessable)
  • ✅ Functional (everything just works)
  • Not memorable (impossible to type or remember)
  • Not safe to leak (if accidentally shared without permissions configured, anyone can access)
  • Not brandable (can’t put this on business cards)

Create an alias to get a memorable URL:

Terminal window
POST /api/v1/proxy/aliases
{
"container_id": "890abcdef12345678901cdef",
"alias": "my-api",
"program": "http",
"index": 1
}

Result:

https://my-api.node-us.containers.hoody.icu

Same container. Same service. Memorable URL.


When you run a web server or API in a container, you have two choices:

Option 1: Use Cryptographic URL (Development)

Section titled “Option 1: Use Cryptographic URL (Development)”
https://67e89abc123def456789abcd-890abcdef12345678901cdef-http-8080.node-us.containers.hoody.icu

Problems for production:

  • ❌ Exposes project and container IDs (48 characters of sensitive data)
  • ❌ Impossible to remember or type
  • ❌ Unprofessional for customers/users
  • ❌ Can’t put on business cards, marketing materials, documentation
https://api.node-us.containers.hoody.icu

Benefits:

  • ✅ Hides internal IDs (no sensitive data exposed)
  • ✅ Memorable and professional
  • ✅ Ideal for public APIs and web services
  • ✅ Ready for custom domain mapping

Then connect your domain:

api.mycompany.com CNAME api.node-us.containers.hoody.icu

Final result: https://api.mycompany.com routes to your container with zero ID exposure.

When you run a web server or API in a container, use program: "http":

Terminal window
POST /api/v1/proxy/aliases
{
"container_id": "890abcdef12345678901cdef",
"alias": "my-api",
"program": "http", // Routes to container's HTTP service
"index": 1 // First HTTP service instance
}

This maps to your container’s web server (running on any port internally—8080, 3000, 5000, etc.). The proxy automatically routes https://my-api.node-us.containers.hoody.icu to your HTTP service.

Typical production workflow:

  1. Deploy your Node.js/Python/Go API in container
  2. Create alias with program: "http"
  3. Point your domain to the alias
  4. Configure authentication via proxy permissions
  5. Production-ready

Aliases follow this pattern:

https://{alias}.{serverName}.containers.hoody.icu
└──┬──┘ └────┬────┘
Your Your Server
Choice (where container runs)

Important: Aliases are server-specific because the proxy runs on each server independently.

Example:

  • Container on node-us → Alias becomes my-app.node-us.containers.hoody.icu
  • Container on node-eu → Alias becomes my-app.node-eu.containers.hoody.icu

An alias points to a specific PROGRAM in a container:

Terminal window
POST /api/v1/proxy/aliases
{
"container_id": "890abcdef12345678901cdef",
"alias": "my-api",
"program": "http", // Which program
"index": 1, // Which instance (if multiple)
"target_path": "/api/v1", // Optional: base path
"allow_path_override": true
}

Common programs:

  • http - Web servers (HTTP service in container)
  • exec - hoody-exec scripts as APIs
  • terminal - Web terminal interface
  • display - Desktop environment
  • files - File browser interface
  • ssh - SSH access
  • Plus: browser, sqlite, agent, code, curl, daemon, notifications

Each container can have multiple aliases pointing to different programs or the same program with different configurations.


Terminal window
# Create a basic proxy alias for your container
hoody proxy create --container-id $CONTAINER_ID --alias my-app --program http --index 1
POST Create a basic proxy alias for your container
/api/v1/proxy/aliases
Click "Run" to execute the request

Now accessible at:

https://my-app.node-us.containers.hoody.icu

Omit the alias parameter to get an auto-generated name:

POST Create alias with auto-generated name (omit alias parameter)
/api/v1/proxy/aliases
Click "Run" to execute the request

Returns: A 48-character hexadecimal alias (auto-generated, unique), e.g. a3f9b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3

Valid alias names:

  • 3-61 characters
  • Lowercase letters (a-z)
  • Numbers (0-9)
  • Hyphens (-)
  • Must start with letter or number
  • Must end with letter or number
  • Pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$

Examples:

  • my-api
  • staging-frontend
  • app-v2
  • prod
  • -myapp (starts with hyphen)
  • my_api (underscore not allowed)
  • MY-APP (uppercase not allowed)

Route requests to specific base paths in your container:

POST Create alias with target path routing to /api/v1
/api/v1/proxy/aliases
Click "Run" to execute the request

Routing behavior:

Incoming Request:
https://my-api.node-us.containers.hoody.icu/users
Routed To Container:
/api/v1/users
(target_path prepended)

The allow_path_override flag controls whether requests can access paths outside target_path:

# All paths allowed
https://my-api.hoody.icu/api/v1/users → /api/v1/users ✅
https://my-api.hoody.icu/admin → /admin ✅
https://my-api.hoody.icu/anything → /anything ✅

Use when: You want flexible routing

Example use case: Expose your API (/api/v1/*) publicly but hide admin routes (/admin/*):

Terminal window
POST /api/v1/proxy/aliases
{
"alias": "public-api",
"program": "http",
"target_path": "/api/v1",
"allow_path_override": false
}

One container can have multiple aliases for different services:

POST Create alias for HTTP service
/api/v1/proxy/aliases
Click "Run" to execute the request

Result:

https://my-api.node-us.containers.hoody.icu → HTTP service
https://my-scripts.node-us.containers.hoody.icu → Exec scripts
https://my-terminal.node-us.containers.hoody.icu → Terminal

Same container, different entry points.


Terminal window
# List all aliases
hoody proxy list
# Filter by project
hoody proxy list --project-id $PROJECT_ID
# Filter by container
hoody proxy list --container-id $CONTAINER_ID
# Find expired aliases
hoody proxy list --expired true
GET List all your aliases
/api/v1/proxy/aliases
Click "Run" to execute the request
Terminal window
# Change alias target service
hoody proxy update $ALIAS_ID --program exec --index 2 --target-path /v2
# Update expiration
hoody proxy update $ALIAS_ID --expires-at "2026-12-31T23:59:59Z"
PATCH Change alias target service (replace {id} with actual alias ID)
/api/v1/proxy/aliases/{id}
Click "Run" to execute the request

Temporarily disable without deleting:

Terminal window
# Disable alias (stops routing, keeps configuration)
hoody proxy set-state $ALIAS_ID --enabled false
# Re-enable alias
hoody proxy set-state $ALIAS_ID --enabled true
PATCH Disable alias (stops routing, keeps configuration)
/api/v1/proxy/aliases/{id}/state
Click "Run" to execute the request

Use case: Temporarily take an API offline for maintenance without losing the alias configuration.

Terminal window
# Permanently remove alias
hoody proxy delete $ALIAS_ID
DELETE Permanently remove alias (replace {id} with actual alias ID)
/api/v1/proxy/aliases/{id}
Click "Run" to execute the request

The alias name becomes available for reuse immediately.


Aliases can automatically expire:

POST Create alias with automatic expiration (ISO 8601 timestamp)
/api/v1/proxy/aliases
Click "Run" to execute the request

After expiration:

  • Alias stops routing traffic automatically
  • Returns 404 for all requests
  • Configuration preserved (can re-enable by removing expiration)

Expiration formats:

On create (POST), expires_at must be an ISO 8601 string (or null for no expiration). On update (PATCH), the route schema additionally accepts a numeric Unix timestamp (seconds or milliseconds) alongside the ISO string and null. Prefer ISO 8601 everywhere for consistency.

{ "expires_at": "2026-07-12T00:00:00.000Z" }
{ "expires_at": "2026-12-31T23:59:59.000Z" }

Use cases:

  • Demo environments - Auto-expire after customer trial
  • Temporary access - Event-specific URLs
  • Staged rollouts - Beta URLs that expire when moving to prod

Clean URL for your API service:

POST Create permanent production API alias with path restrictions
/api/v1/proxy/aliases
Click "Run" to execute the request

Access:

https://prod-api.node-us.containers.hoody.icu/users
→ Routes to container's /api/v1/users

Different aliases for same container’s different programs:

POST Production HTTP service
/api/v1/proxy/aliases
Click "Run" to execute the request

Result:

https://app.node-us.containers.hoody.icu → Web service
https://app-terminal.node-us.containers.hoody.icu → Terminal
https://app-scripts.node-us.containers.hoody.icu → Exec scripts

Manage API versions with aliases:

POST Current production version
/api/v1/proxy/aliases
Click "Run" to execute the request

Clients can choose:

https://api-v1.node-us.containers.hoody.icu → Old version
https://api-v2.node-us.containers.hoody.icu → New version
https://api-beta.node-us.containers.hoody.icu → Beta (same as v2)

When ready: Delete api-v1, rename api-v2api-v1, or update client references.

Pattern 4: Staging → Production Promotion

Section titled “Pattern 4: Staging → Production Promotion”

Typical deployment workflow:

Terminal window
# 1. Develop in container with crypto URL
https://67e89abc...890abc-exec-1.node-us.containers.hoody.icu
# 2. Create staging alias when ready for testing
POST /api/v1/proxy/aliases
{ "alias": "staging-app", "container_id": "890abcdef...", "program": "http" }
# → https://staging-app.node-us.containers.hoody.icu
# 3. Test with team, clients, QA
# 4. Snapshot tested container
POST /api/v1/containers/890abcdef.../snapshots
{ "alias": "pre-prod-2025-11-09" }
# 5. Create production alias
POST /api/v1/proxy/aliases
{ "alias": "prod-app", "container_id": "890abcdef...", "program": "http" }
# → https://prod-app.node-us.containers.hoody.icu
# 6. If issues, instant rollback via snapshot
PATCH /api/v1/containers/890abcdef.../snapshots/pre-prod-2025-11-09

GET Find all aliases for a specific project (replace project_id)
/api/v1/proxy/aliases?project_id=67e89abc123def456789abcd
Click "Run" to execute the request

Update multiple aliases programmatically:

// Example: Update all staging aliases to point to new containers
const stagingAliases = await fetch(
'https://api.hoody.icu/api/v1/proxy/aliases?project_id=staging-project'
).then(r => r.json());
for (const alias of stagingAliases.data.aliases) {
await fetch(`https://api.hoody.icu/api/v1/proxy/aliases/${alias.id}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${process.env.HOODY_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
container_id: newContainerId,
target_path: '/v2'
})
});
}

The exec program has special routing capabilities:

When you create an alias for program: "exec", you can use subdomain-based routing to access specific scripts:

POST Create exec alias for subdomain-based script routing
/api/v1/proxy/aliases
Click "Run" to execute the request

Your scripts in container:

/api/users.ts
/api/posts.ts
/webhooks/stripe.ts

Access via subdomains:

https://api.my-scripts.node-us.containers.hoody.icu/users
→ Executes /api/users.ts, route: /users
https://webhooks.my-scripts.node-us.containers.hoody.icu/stripe
→ Executes /webhooks/stripe.ts, route: /stripe

The subdomain maps to the directory, the path maps to the route.

See: Hoody Exec → for complete script routing documentation.

Target different instances of the same program:

POST Alias to first HTTP service instance
/api/v1/proxy/aliases
Click "Run" to execute the request

Result:

https://frontend.node-us.containers.hoody.icu → HTTP service instance 1
https://backend.node-us.containers.hoody.icu → HTTP service instance 2

Aliases serve as CNAME targets for custom domains:

Step 1: Create alias

POST Create alias for custom domain CNAME target
/api/v1/proxy/aliases
Click "Run" to execute the request

Step 2: Point your domain to the alias

# DNS configuration at your domain provider
api.mycompany.com CNAME myapp-prod.node-us.containers.hoody.icu

Step 3: Automatic SSL

Hoody automatically provisions a Let’s Encrypt certificate for api.mycompany.com. Within minutes, your custom domain is live with HTTPS.

Result:

https://api.mycompany.com
→ CNAME →
https://myapp-prod.node-us.containers.hoody.icu
→ Routes to →
Container's HTTP service

See: Connect a Domain → for complete custom domain setup.


Aliases must be globally unique per server:

If someone else has claimed my-app on node-us, you cannot use it. The API will return 422 Unprocessable Entity during creation.

Solution: Choose descriptive, unique aliases:

  • Add your company name: acme-api
  • Add identifier: my-app-prod
  • Use generated names when uniqueness is uncertain

Cryptographic URLs (Default)

https://67e89abc...890abc-exec-1.
node-us.containers.hoody.icu

Security:

  • ✅ Unguessable (2^96 combinations)
  • ✅ Share URL = grant access
  • ✅ Don’t share = private
  • ✅ Perfect for development/collaboration

Usability:

  • ❌ Impossible to remember
  • ❌ Can’t type manually
  • ❌ Not brandable

Aliases (Production)

https://my-api.node-us.
containers.hoody.icu

Security:

  • ⚠️ Guessable (if known pattern)
  • ⚠️ Discoverable (enumeration possible)
  • ✅ IP whitelist recommended
  • ✅ Add authentication via permissions

Usability:

  • ✅ Memorable
  • ✅ Typeable
  • ✅ Brandable
  • ✅ Professional

Best practice:

  • Development: Use cryptographic URLs (secure by obscurity)
  • Production: Use aliases + permissions (secure by authentication)

Aliases work with proxy permissions:

POST Create public API alias (then configure permissions separately)
/api/v1/proxy/aliases
Click "Run" to execute the request

Then configure permissions (separate endpoint):

Terminal window
PUT /api/v1/containers/{id}/proxy/permissions
{
"groups": {
"authenticated": {
"type": "jwt",
"secret": "your-jwt-secret",
"sources": ["header:Authorization"]
}
},
"permissions": {
"authenticated": { "http": true }
},
"default": "deny"
}

Now both URLs require authentication:

https://67e89abc...890abc-exec-1.node-us.containers.hoody.icu → Requires JWT
https://public-api.node-us.containers.hoody.icu → Requires JWT

The alias and cryptographic URL apply the same permissions.


Complete workflow from development to production:

1. Develop in container (use crypto URL)

https://67e89abc123def456789abcd-890abcdef12345678901cdef-exec-1.node-us.containers.hoody.icu

2. Create staging alias for team testing

POST Create staging alias for team testing
/api/v1/proxy/aliases
Click "Run" to execute the request

Result: https://staging-myapp.node-us.containers.hoody.icu

3. Configure staging with IP whitelist (office only)

Terminal window
curl -X PUT "https://api.hoody.icu/api/v1/containers/890abcdef.../proxy/permissions" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"groups": {
"office": { "type": "ip", "range": "203.0.113.0/24" }
},
"permissions": {
"office": { "http": true }
},
"default": "deny"
}'

4. Team tests on staging-myapp.node-us.containers.hoody.icu

5. Snapshot when ready

POST Create snapshot before production deployment
/api/v1/containers/{container_id}/snapshots
Click "Run" to execute the request

6. Create production alias

POST Create production alias
/api/v1/proxy/aliases
Click "Run" to execute the request

Result: https://myapp.node-us.containers.hoody.icu

7. Point custom domain

DNS: api.mycompany.com CNAME myapp.node-us.containers.hoody.icu

Result: https://api.mycompany.com (automatic SSL)

8. Configure production permissions (JWT auth)

Terminal window
curl -X PUT "https://api.hoody.icu/api/v1/containers/890abcdef.../proxy/permissions" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"groups": {
"customers": {
"type": "jwt",
"secret": "production-jwt-secret",
"sources": ["header:Authorization"]
}
},
"permissions": {
"customers": { "http": true }
},
"default": "deny"
}'

9. Production is live

Development: https://67e89abc...890abc-exec-1.node-us.containers.hoody.icu (crypto URL)
Staging: https://staging-myapp.node-us.containers.hoody.icu (IP-restricted)
Production: https://api.mycompany.com (JWT auth, custom domain)

Same container. Different URLs. Different access policies. Complete control.


Can I use the same alias name on different servers?

Section titled “Can I use the same alias name on different servers?”

Yes! Aliases are server-specific. my-app on node-us becomes my-app.node-us.containers.hoody.icu, while my-app on node-eu becomes my-app.node-eu.containers.hoody.icu. Different full URLs, no conflict.

What happens if I delete a container that has aliases?

Section titled “What happens if I delete a container that has aliases?”

The aliases remain configured but return errors (container not found) until you either delete the aliases or update them to point to a different container. Best practice: delete aliases before deleting containers.

Can I point multiple aliases to the same container service?

Section titled “Can I point multiple aliases to the same container service?”

Absolutely. Create multiple aliases with different names, all pointing to the same container_id and program. Useful for versioning (api-v1, api-v2 both pointing to same container initially) or multi-brand domains.

Yes. When you configure proxy permissions for a container, they apply to BOTH the cryptographic URL and all aliases pointing to that container. One permission configuration protects all entry points.

Can I create an alias before the container is running?

Section titled “Can I create an alias before the container is running?”

Yes. You can create aliases for stopped containers. The alias exists, but requests will fail until you start the container. Useful for pre-configuring production URLs before deployment.

What’s the difference between target_path and allow_path_override?

Section titled “What’s the difference between target_path and allow_path_override?”

target_path prepends a base path to all requests (e.g., /api/v1). allow_path_override: false restricts access to ONLY that base path—requests to other paths are blocked. Use false to expose only specific API routes while hiding admin endpoints.

How do I prevent someone from guessing my alias names?

Section titled “How do I prevent someone from guessing my alias names?”

Use complex, unique aliases (acme-prod-api-v2-us-2025) instead of generic ones (api, app). Even better: combine aliases with proxy permissions for authentication—then guessing the name doesn’t grant access.

Can I have an alias without specifying program or index?

Section titled “Can I have an alias without specifying program or index?”

No. Aliases must target a specific program (http, exec, terminal, etc.) and instance number. This is because one container runs multiple services—the alias needs to know which one to route to.

Do aliases persist if I snapshot and restore a container?

Section titled “Do aliases persist if I snapshot and restore a container?”

Aliases are stored separately, not in the container. If you snapshot container A with alias my-app, then restore to container B, the alias still points to container A. You must update the alias to point to container B’s ID.

Can I see which custom domains point to my aliases?

Section titled “Can I see which custom domains point to my aliases?”

The GET /api/v1/proxy/aliases/{id} endpoint shows alias configuration, but not which custom domains CNAME to it (that’s in your DNS provider). Best practice: document your CNAME mappings externally (spreadsheet, wiki, infrastructure-as-code).


Error:

{
"statusCode": 422,
"error": "Validation Error",
"message": "Alias is already in use on this server"
}

Solutions:

  1. Choose a different alias name
  2. Use a suffix: my-app-v2, my-app-prod
  3. Check existing aliases: GET /api/v1/proxy/aliases?project_id={id}

Check:

  1. Enabled status: GET /api/v1/proxy/aliases/{id} → Check enabled: true
  2. Container running: GET /api/v1/containers/{id} → Check status: "running"
  3. Service running: Check container’s service is actually started
  4. Permissions: Verify you can access via cryptographic URL first

When using custom domains:

  • CNAME changes take 5-60 minutes to propagate globally
  • Test from multiple locations or wait before troubleshooting
  • Use dig api.mycompany.com to verify DNS points to alias

Both remain active:

When you create an alias, the original cryptographic URL still works:

Alias:
https://my-api.node-us.containers.hoody.icu
Original (still works):
https://67e89abc123def456789abcd-890abcdef12345678901cdef-exec-1.node-us.containers.hoody.icu

Both route to the same container service. Same permissions apply.

Use case:

  • Share aliases publicly (clean URLs)
  • Keep cryptographic URLs for internal tools (unguessable security)

Configure your aliases:

  1. Connect a Domain → - Point your custom domain to an alias
  2. Set Permissions → - Add authentication to protect aliases

Understanding gained:

  • ✅ Aliases create memorable URLs: my-app.{serverName}.containers.hoody.icu
  • ✅ Map to specific container programs (http, exec, terminal, etc.)
  • ✅ Support path routing and access control
  • ✅ Serve as CNAME targets for custom domains
  • ✅ Can be temporary (expiration) or permanent

Cryptographic URLs for development.
Aliases for production.
Custom domains for your brand.
All routing through the same Hoody Proxy on your server.

Clean URLs don’t change the HTTP power underneath. They just make it memorable.