Skip to content
Hoody.com

Point a domain you own, such as api.mycompany.com, at a container’s HTTP service with a single DNS record. The proxy issues and renews the TLS certificate for it.

Custom domains build on proxy aliases: the alias URL is what your CNAME record points at.


A custom domain reaches a container through a DNS CNAME to a proxy alias, so the DNS side involves no API call at all. The alias itself is managed through these endpoints:

Alias management (CNAME targets):

SSL and domains:

  • The proxy requests a certificate on its own once it sees a CNAME pointing at your alias
  • No API call is involved in that step; you only add the DNS record
  • Let’s Encrypt certificates are valid for 90 days and renewed automatically once 30 days remain

1. Create a proxy alias → my-app.node-us.containers.hoody.com
2. CNAME your domain to the alias → api.mycompany.com → my-app.node-us.containers.hoody.com
3. SSL certificate automatically provisioned → https://api.mycompany.com (live)

Your side of it is one DNS record. The proxy issues and renews the certificate; there is no certificate, port, or reverse-proxy step on your side.


A custom domain points at a proxy alias, never at a container URL directly.

Step 1: Create the alias (CNAME target)

Terminal window
# Create alias as CNAME target for your custom domain
hoody proxy create --container-id $CONTAINER_ID --alias myapp-prod --program http --port 3000
POST Create alias as CNAME target
/api/v1/proxy/aliases
Click "Run" to execute the request

Gives you: https://myapp-prod.node-us.containers.hoody.com

Step 2: Add CNAME record at your DNS provider

api.mycompany.com CNAME myapp-prod.node-us.containers.hoody.com

Step 3: Automatic SSL

Hoody detects the CNAME, provisions a Let’s Encrypt certificate for api.mycompany.com, and routes traffic:

User requests:
https://api.mycompany.com
↓ (DNS CNAME)
https://myapp-prod.node-us.containers.hoody.com
↓ (Hoody Proxy routes)
Container's HTTP service

Within 5-10 minutes: the domain serves your container over HTTPS.


You need:

  • A proxy alias (create via POST /api/v1/proxy/aliases)
  • Access to your domain’s DNS settings
  • Your server name (e.g., node-us, node-eu)

A custom domain must be a subdomain with a genuine CNAME. Root domains are not supported.

Terminal window
# Create the CNAME target alias
hoody proxy create --container-id $CONTAINER_ID \
--alias production-api --program http --port 3000 \
--target-path /api/v1 --allow-path-override
POST Create the CNAME target alias
/api/v1/proxy/aliases
Click "Run" to execute the request

Result: production-api.node-us.containers.hoody.com

Verify it works:

Terminal window
curl https://production-api.node-us.containers.hoody.com
# Should return your service response

The domain now routes to your container over HTTPS.


An alias can point your domain at a specific path inside the container, not only at the root.

Traditional hosting:

Your domain points to server root only:
api.mycompany.com → /
Problem: Your API is at /api/v1/, but domain points to /

You’d need:

  • Reverse proxy setup (nginx/Apache configuration)
  • URL rewrite rules
  • Server restarts
  • Complex routing logic
  • Configuration file management

With Hoody:

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

Then CNAME your domain:

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

Result:

User requests: https://api.mycompany.com/users
Proxy routes: Container's /api/v1/users
The alias setting does the rewriting; no server config, no reverse proxy.

Use case 1: microservices on one container

Terminal window
# One container serves:
# - Frontend at /
# - API at /api/v1
# - Admin panel at /admin
# Create 3 aliases, each targeting different path
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "app-frontend", "program": "http", "port": 3000, "target_path": "/", "allow_path_override": false }
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "app-api", "program": "http", "port": 3000, "target_path": "/api/v1", "allow_path_override": false }
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "app-admin", "program": "http", "port": 3000, "target_path": "/admin", "allow_path_override": false }
# Point 3 domains to same container
www.mycompany.com CNAME app-frontend.node-us.containers.hoody.com
api.mycompany.com CNAME app-api.node-us.containers.hoody.com
admin.mycompany.com CNAME app-admin.node-us.containers.hoody.com

Routing:

  • www.mycompany.com/about → Container’s /about
  • api.mycompany.com/users → Container’s /api/v1/users
  • admin.mycompany.com/dashboard → Container’s /admin/dashboard

One container, three domains, three isolated path spaces, and no nginx config.

Use case 2: API versioning

Terminal window
# Container serves both v1 and v2 at different paths:
# /api/v1/*
# /api/v2/*
# Create version-specific aliases
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "api-v1", "program": "http", "port": 3000, "target_path": "/api/v1", "allow_path_override": false }
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "api-v2", "program": "http", "port": 3000, "target_path": "/api/v2", "allow_path_override": false }
# Point domains
v1.api.mycompany.com CNAME api-v1.node-us.containers.hoody.com
v2.api.mycompany.com CNAME api-v2.node-us.containers.hoody.com

Users call:

  • v1.api.mycompany.com/endpoint/api/v1/endpoint
  • v2.api.mycompany.com/endpoint/api/v2/endpoint

One container serves both versions, each on its own domain.

Use case 3: multi-tenant SaaS

Terminal window
# Container organized by tenant:
# /tenant/acme/*
# /tenant/globex/*
# /tenant/initech/*
# Alias per customer
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "acme", "program": "http", "port": 3000, "target_path": "/tenant/acme", "allow_path_override": false }
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "globex", "program": "http", "port": 3000, "target_path": "/tenant/globex", "allow_path_override": false }
# Customer domains
acme.myapp.com CNAME acme.node-us.containers.hoody.com
globex.myapp.com CNAME globex.node-us.containers.hoody.com

Each customer gets a domain that routes to their tenant path, and one container serves all of them.

Traditional routing (nginx/Apache):

# Write config file
server {
server_name api.mycompany.com;
location / {
proxy_pass http://localhost:3000/api/v1;
rewrite rules...
header manipulation...
}
}
# Test config
nginx -t
# Restart server (downtime risk)
systemctl restart nginx
# Verify production still serves traffic

Hoody routing (one API call):

Terminal window
# Create alias with path routing; live immediately, no restart
hoody proxy create --container-id $CONTAINER_ID \
--alias my-api --program http --port 3000 --target-path /api/v1
POST Create alias with path routing
/api/v1/proxy/aliases
Click "Run" to execute the request

The alias takes effect immediately, with no restart and no downtime.


Root domains (like mycompany.com without a subdomain) cannot be connected, because CNAME records aren’t allowed at the DNS root by RFC standards and Hoody’s SSL provisioning is CNAME-only.

Hoody’s automatic SSL resolves your domain by following a real CNAME record to <alias>.<serverName>.containers.hoody.com. ALIAS and ANAME records are flattened to A records by your DNS provider, so Hoody’s resolvers never see a CNAME, no certificate is issued, and the root domain never comes up over HTTPS.

Point a subdomain at the alias instead, such as www.mycompany.com or app.mycompany.com:

Type: CNAME
Name: www
Value: production-api.node-us.containers.hoody.com

Then add a redirect from root to subdomain at your DNS provider.


Several domains can share one alias:

Terminal window
# 1. Create one alias
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "prod-api", "program": "http", "port": 3000 }
# 2. CNAME multiple domains to it
api.mycompany.com CNAME prod-api.node-us.containers.hoody.com
api.mybrand.com CNAME prod-api.node-us.containers.hoody.com
api-v2.oldcompany.com CNAME prod-api.node-us.containers.hoody.com

All three domains route to the same container service, and Hoody provisions a certificate for each one automatically.

Use cases:

  • Multiple brand domains pointing to the same backend
  • API versioning (api-v1.com, api-v2.com)
  • Regional domains (api.mycompany.eu, api.mycompany.com)

Move an existing domain to Hoody without taking it offline:

Terminal window
# Deploy your app to Hoody container
# Create alias
POST /api/v1/proxy/aliases
{ "container_id": "CONTAINER_ID", "alias": "myapp-prod", "program": "http", "port": 3000 }
# Test via alias URL first
curl https://myapp-prod.node-us.containers.hoody.com
# Verify everything works

Downtime: Minimal (DNS TTL period, usually 5 minutes or less)

There are two ways to change which container a domain reaches.

Option A: Recreate the alias under the same name (points to different container)

The container_id of an existing alias is immutable: PATCH only updates program, port, index, target_path, allow_path_override, expires_at, enabled, and the alias name. To repoint to a different container, delete the alias and recreate it with the same alias name. The CNAME target is unchanged, so no DNS edit is required.

Terminal window
# Instant switch: delete, then recreate under the same alias name
hoody proxy delete $ALIAS_ID --yes
hoody proxy create --container-id $NEW_CONTAINER_ID \
--alias production-api --program http --port 3000
POST Recreate the alias under the same name on the new container
/api/v1/proxy/aliases
Click "Run" to execute the request

DNS is unchanged. Reusing the same alias name keeps the CNAME target valid, so the domain starts routing to the new container immediately.

Option B: Create new alias, update CNAME

Terminal window
# Create new alias for the new container
hoody proxy create --container-id $NEW_CONTAINER_ID --alias myapp-v2 --program http --port 3000
POST Create new alias for new container
/api/v1/proxy/aliases
Click "Run" to execute the request

Then update DNS:

api.mycompany.com CNAME myapp-v2.node-us.containers.hoody.com

This changes the CNAME target, so you wait out propagation again (5-60 minutes).

Recommendation: Use Option A (recreate under the same name) for instant switching.


The proxy handles issuance and renewal:

  1. Detection: Proxy sees request for your custom domain
  2. Challenge: Hoody responds to the ACME HTTP-01 challenge automatically
  3. Issuance: Certificate issued by Let’s Encrypt (30-60 seconds)
  4. Installation: Certificate installed and activated
  5. Renewal: Auto-renewed before expiry

Each issued certificate:

  • Certificate authority: Let’s Encrypt
  • Validation method: ACME HTTP-01 challenge (automatic)
  • Certificate type: Domain Validation (DV)
  • Validity: 90 days (auto-renews before expiry)
  • Coverage: Your exact domain (e.g., api.mycompany.com)

HTTPS enforcement:

  • HTTP requests for platform domains and custom domains with an issued certificate → Automatic redirect to HTTPS (301); unrecognized or not-yet-issued custom domains return 400, while ACME HTTP-01 challenge requests are served over HTTP
  • HSTS is not set by the proxy. Send Strict-Transport-Security from your own application if you want it

For wildcard subdomains (*.api.mycompany.com):


Type: CNAME
Name: api
Value: myapp-prod.node-us.containers.hoody.com
Proxy: OFF (DNS only, not proxied through Cloudflare)
TTL: Auto

Important: Turn off Cloudflare’s proxy (the orange cloud icon) so traffic reaches Hoody directly.

Type: CNAME
Name: api.mycompany.com
Value: myapp-prod.node-us.containers.hoody.com
TTL: 300
Routing Policy: Simple
Type: CNAME
Host: api
Data: myapp-prod.node-us.containers.hoody.com
TTL: 1h
Type: CNAME Record
Host: api
Value: myapp-prod.node-us.containers.hoody.com
TTL: Automatic

One container can serve several interfaces, each on its own domain:

Terminal window
# Create two aliases for different paths
POST /api/v1/proxy/aliases
{
"container_id": "CONTAINER_ID",
"alias": "api-backend",
"program": "http",
"port": 3000,
"target_path": "/api/v1",
"allow_path_override": false
}
POST /api/v1/proxy/aliases
{
"container_id": "CONTAINER_ID",
"alias": "admin-dashboard",
"program": "http",
"port": 3000,
"target_path": "/admin",
"allow_path_override": false
}
# CNAME different domains
api.mycompany.com CNAME api-backend.node-us.containers.hoody.com
admin.mycompany.com CNAME admin-dashboard.node-us.containers.hoody.com

Result:

  • api.mycompany.com → Container’s /api/v1/* only
  • admin.mycompany.com → Container’s /admin/* only
  • Same container, different domain access, isolated paths

Frontend and backend in separate containers

Section titled “Frontend and backend in separate containers”

Two containers, one domain each:

Terminal window
# Frontend container alias
POST /api/v1/proxy/aliases
{ "alias": "frontend", "container_id": "FRONTEND_ID", "program": "http", "port": 3000 }
# Backend container alias
POST /api/v1/proxy/aliases
{ "alias": "backend", "container_id": "BACKEND_ID", "program": "http", "port": 3000 }
# DNS configuration
www.mycompany.com CNAME frontend.node-us.containers.hoody.com
api.mycompany.com CNAME backend.node-us.containers.hoody.com

Each domain routes to a different container.

The same application in more than one region:

Terminal window
# US container
POST /api/v1/proxy/aliases
{ "alias": "app-us", "container_id": "US_CONTAINER", "program": "http", "port": 3000 }
# EU container
POST /api/v1/proxy/aliases
{ "alias": "app-eu", "container_id": "EU_CONTAINER", "program": "http", "port": 3000 }
# DNS with GeoDNS routing
api.mycompany.com (US users) → app-us.node-us.containers.hoody.com
api.mycompany.com (EU users) → app-eu.node-eu.containers.hoody.com

Use your DNS provider’s GeoDNS feature to route users to the nearest container.


Switch versions at the DNS layer, without downtime:

Terminal window
# Blue (current production)
POST /api/v1/proxy/aliases
{ "alias": "blue", "container_id": "CURRENT_CONTAINER", "program": "http", "port": 3000 }
# Deploy to green (new version)
POST /api/v1/projects/{id}/containers
{ "name": "green", ... }
# Create green alias
POST /api/v1/proxy/aliases
{ "alias": "green", "container_id": "NEW_CONTAINER", "program": "http", "port": 3000 }
# Test green environment
curl https://green.node-us.containers.hoody.com
# Switch production (update CNAME)
api.mycompany.com CNAME green.node-us.containers.hoody.com
# (was: blue.node-us.containers.hoody.com)
# After DNS propagation (5-10 min), all traffic on new version
# Keep blue for rollback
# If issues: Revert CNAME back to blue.node-us.containers.hoody.com

Use DNS weighting, if your provider supports it:

api.mycompany.com CNAME stable.node-us.containers.hoody.com (Weight: 90%)
api.mycompany.com CNAME canary.node-us.containers.hoody.com (Weight: 10%)

That sends 10% of users to the canary version. Monitor it, then shift the weight gradually.


Once the CNAME resolves:

Terminal window
# Check SSL certificate
openssl s_client -showcerts -connect api.mycompany.com:443 -servername api.mycompany.com
# Should show:
# issuer=C = US, O = Let's Encrypt, CN = R3
# subject=CN = api.mycompany.com

Or via browser:

  1. Visit https://api.mycompany.com
  2. Click padlock icon
  3. View certificate details
  4. Verify: Issued by Let’s Encrypt, Valid for your domain
  • Hoody scans certificates for expiry every 6 hours
  • Renewal triggers below the configured remaining-lifetime threshold, 30 days by default (out of 90)
  • New certificate issued and installed automatically
  • No downtime, no intervention needed

You never create or renew a certificate yourself.


Yes. A custom domain reaches a container through a proxy alias, so create the alias first, take its URL, and CNAME your domain to that URL. You cannot CNAME directly to cryptographic container URLs.

Typically 5-60 minutes globally, depending on your DNS provider’s TTL. A 300-second TTL means changes propagate in about 5 minutes; a 3600-second TTL means about 60. Use a tool like whatsmydns.net to check global propagation.

Yes. When Hoody’s proxy detects a CNAME pointing to an alias, it automatically requests a Let’s Encrypt certificate for your custom domain. The first HTTPS request may take 30-60 seconds (certificate issuance time), then it’s instant. Certificates are valid for 90 days and renewed automatically once 30 days remain.

Root domains are not supported. ALIAS/ANAME and A records both fail Hoody’s CNAME-only detection, so no certificate is ever issued. Use a subdomain (www.mycompany.com, app.mycompany.com) with a CNAME record, and redirect the root to it at your registrar.

What happens if my CNAME points to a deleted alias?

Section titled “What happens if my CNAME points to a deleted alias?”

The domain will return HTTP 404 because Hoody’s proxy no longer has a matching alias for that URL. Always verify the alias exists before updating DNS, and avoid deleting aliases that have active CNAMEs pointing to them.

Can multiple custom domains point to the same container?

Section titled “Can multiple custom domains point to the same container?”

Yes. Create one alias, then CNAME multiple domains to it. Hoody provisions separate SSL certificates for each domain. Common use case: www.mycompany.com and app.mycompany.com both pointing to the same HTTP service.

Does the container need any configuration?

Section titled “Does the container need any configuration?”

No. Your application binds to a port (e.g., 3000) and the proxy handles routing, SSL, and domain resolution. The app itself does not know about domains; it only responds to HTTP requests.

Can I use Cloudflare’s proxy (orange cloud) with Hoody?

Section titled “Can I use Cloudflare’s proxy (orange cloud) with Hoody?”

Turn it off. Cloudflare’s proxy interferes with Hoody’s SSL provisioning and IP preservation, so use DNS-only mode (gray cloud). Your traffic goes: Client → Hoody Proxy → Container, not through Cloudflare’s edge network.

How do I switch a domain from one container to another?

Section titled “How do I switch a domain from one container to another?”

Option A (instant): The alias container_id is immutable, so delete the alias and recreate it with the same name on the new container (DELETE then POST /api/v1/proxy/aliases). Here “name” refers to the alias field. The CNAME target is unchanged, so no DNS edit is needed. Option B (slower): Create a new alias pointing to the new container, then update CNAME to point to the new alias (requires DNS propagation).

What’s the maximum number of custom domains I can connect?

Section titled “What’s the maximum number of custom domains I can connect?”

No limit. Each alias can support unlimited CNAMEs (at your DNS provider level). One Hoody alias can have dozens of custom domains pointing to it, and each one gets automatic SSL and routes to the same container service.


1. Verify CNAME is correct

Terminal window
dig api.mycompany.com
# Should show CNAME record pointing to alias.node-us.containers.hoody.com
# If showing A record or different CNAME: DNS not updated yet

2. Check alias exists and is enabled

GET List aliases for project to verify configuration
/api/v1/proxy/aliases?project_id={id}
Click "Run" to execute the request

Verify:

  • Alias exists
  • enabled: true
  • container is running

3. Test alias URL directly

Terminal window
# Bypass custom domain, test alias
curl https://myapp-prod.node-us.containers.hoody.com
# If this works but custom domain doesn't:
# → DNS propagation still in progress
# → Wait 15-30 more minutes

Common causes:

  1. CNAME pointing to wrong target

    Terminal window
    # Wrong: CNAME to cryptographic URL
    api.mycompany.com CNAME 67e89abc...node-us.containers.hoody.com (wrong)
    # Correct: CNAME to alias
    api.mycompany.com CNAME myapp-prod.node-us.containers.hoody.com (correct)
  2. DNS not fully propagated

    • Let’s Encrypt validation fails until the record resolves worldwide
    • Wait for full propagation (up to 60 minutes)
  3. Cloudflare proxy enabled

    • Orange cloud icon in Cloudflare = Proxied through CF
    • Must be gray cloud (DNS only) for Hoody SSL
  4. Cert issuance blocked upstream

    • The HTTP-01 challenge is answered by Hoody’s edge, not by your container, so no firewall or port 80 change on your side is needed
    • If validation still fails, the cause is almost always DNS (item 2) or Cloudflare proxying (item 3)

Check Hoody status:

GET Get alias details to check certificate status
/api/v1/proxy/aliases/{id}
Click "Run" to execute the request

Contact support if the certificate keeps failing to issue.

  1. ACME rate limits exceeded
    • Let’s Encrypt enforces per-registered-domain rate limits (for example, the duplicate-certificate limit of 5 per week for the same exact set of names)
    • If you’ve been testing extensively with the same domain, you may hit one of these limits
    • If you hit a limit: there is no second certificate authority to fall back to, so issuance fails outright until the weekly window resets. Use a different subdomain in the meantime
    • Prevention: Use different subdomains for testing (test1.example.com, test2.example.com) instead of repeatedly recreating certificates for the same domain

Check if you hit rate limits:

Terminal window
# Visit Let's Encrypt rate limit checker
# https://crt.sh/?q=%.mycompany.com
# Shows all certificates issued for your domain
# If you see many recent certificates: likely hit the limit

Workaround while waiting:

  • Use a different subdomain temporarily
  • Or use the alias URL directly (already has SSL)
  • Rate limit resets 7 days after first certificate in the batch

Typical propagation windows by provider:

ProviderTypical TTLMax Wait
Cloudflare5 minutes10 minutes
Route535 minutes15 minutes
Google Domains1 hour2 hours
Namecheap30 minutes1 hour
GoDaddy1 hour2 hours

Check propagation:

Terminal window
# From your machine
dig api.mycompany.com @8.8.8.8
# From different DNS server
dig api.mycompany.com @1.1.1.1
# If different results: Still propagating

Exercise the alias URL before you point a domain at it:

Terminal window
# 1. Create alias
POST /api/v1/proxy/aliases
{ "alias": "myapp-test", ... }
# 2. Test thoroughly
curl https://myapp-test.node-us.containers.hoody.com
# Run full test suite, verify responses
# 3. Add custom domain only when alias works perfectly
api.mycompany.com CNAME myapp-test.node-us.containers.hoody.com

An alias name should say what it serves:

Good: production-api
Good: staging-frontend
Good: blue-deployment
Good: myapp-v2
Bad: app
Bad: test
Bad: api
Bad: x

Once you run 20 domains, the names are what keep them apart.

Keep a file tracking each domain and its target:

domains.yml
domains:
api.mycompany.com:
cname_target: production-api.node-us.containers.hoody.com
alias_id: 63a3e4b5c6d7e8f9a0b1c2d3
container_id: 890abcdef12345678901cdef
staging.mycompany.com:
cname_target: staging-api.node-us.containers.hoody.com
alias_id: 74b4f5c6d7e8f9a0b1c2d3e4
container_id: 901bcdef12345678901cdefa

That is what saves you from re-deriving which alias serves which domain months later.

If you use expiring aliases:

Terminal window
POST /api/v1/proxy/aliases
{
"alias": "beta-program",
"expires_at": "2026-08-16T00:00:00.000Z" # Absolute ISO 8601 timestamp
}

Set a calendar reminder 7 days before expiration if users depend on this URL.


The same services, under two sets of names:

Your branding:
https://api.acme.com
https://app.techstartup.io
https://platform.saas.com
Hoody infrastructure:
https://prod-acme.node-us.containers.hoody.com
https://startup-app.node-eu.containers.hoody.com
https://saas-platform.node-asia.containers.hoody.com

Visitors see your domain; Hoody’s hostname stays behind it as the CNAME target. The CNAME record is the only thing you maintain, and you do not manage certificates, renewals, or proxy configuration.


  • Create container with hoody-kit enabled
  • Verify container is running (GET /api/v1/containers/{id})
  • Create proxy alias (POST /api/v1/proxy/aliases)
  • Test alias URL ( curl https://alias.node-us.containers.hoody.com)
  • Add CNAME record at DNS provider
  • Wait for DNS propagation (5-60 minutes)
  • Test custom domain (curl https://api.mycompany.com)
  • Verify SSL certificate (browser padlock icon)
  • Configure permissions if needed
Type: CNAME
Name: [subdomain]
Value: [alias].[serverName].containers.hoody.com
TTL: 300-3600 (lower = faster updates, higher = better caching)

Example:

Type: CNAME
Name: api
Value: prod-api.node-us.containers.hoody.com
TTL: 3600

Secure your domains:

Explore related topics: