# Proxy Aliases

**Page:** foundation/proxy/aliases

[Download Raw Markdown](./foundation/proxy/aliases.md)

---

# Proxy Aliases

**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.

---

## API Endpoints Summary

**Official Technical Reference:**

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

**Alias Management:**
- **[POST /api/v1/proxy/aliases](/api/proxy-aliases/)** - Create new alias
- **[GET /api/v1/proxy/aliases](/api/proxy-aliases/)** - List all aliases (with filters)
- **[GET /api/v1/proxy/aliases/\{id\}](/api/proxy-aliases/)** - Get alias details
- **[PATCH /api/v1/proxy/aliases/\{id\}](/api/proxy-aliases/)** - Update alias configuration
- **[PATCH /api/v1/proxy/aliases/\{id\}/state](/api/proxy-aliases/)** - Enable/disable alias
- **[DELETE /api/v1/proxy/aliases/\{id\}](/api/proxy-aliases/)** - Delete alias

**Related:**
- **[Proxy Permissions](/api/proxy-permissions/)** - Control who can access aliases
- **[Container Operations](/api/container-operations/)** - Container lifecycle

---

## The Problem and Solution

### Default Container URLs Work, But...

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

<div style="
  background: #f8f8f8;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 12px 16px;
  font-family: var(--sl-font-mono);
  font-size: 0.75rem;
  margin: 1.5rem 0;
  overflow-x: auto;
">

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

</div>

**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)

### Proxy Aliases Create Clean URLs

**Create an alias to get a memorable URL:**

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

**Result:**

<div style="
  background: #f8f8f8;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 12px 16px;
  font-family: var(--sl-font-mono);
  font-size: 0.875rem;
  margin: 1.5rem 0;
">

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

</div>

**Same container. Same service. Memorable URL.**


**Production Usage:** Aliases are essential when running web servers or APIs in containers. They provide clean, memorable URLs that don't expose your project/container IDs—critical for public-facing services and professional deployments.


---

## Why Aliases Matter for Production

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

### 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

### Option 2: Create Alias (Production-Ready)

```
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.

### The `http` Program (Most Common)

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

```bash
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](./permissions/)
5. Production-ready

---

## How Aliases Work

### Alias Structure

**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`


The `{serverName}` component ensures aliases don't conflict across your servers. You can use the same alias name on different servers because they'll have different full URLs.


### What Aliases Map To

**An alias points to a specific PROGRAM in a container:**

```bash
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.

---

## Creating Aliases

### Basic Alias Creation


  
    ```bash
    # Create a basic proxy alias for your container
    hoody proxy create --container-id $CONTAINER_ID --alias my-app --program http --index 1
    ```
  
  
    ```typescript
    const alias = await client.api.proxyAliases.create({
      container_id: CONTAINER_ID,
      alias: 'my-app',
      program: 'http',
      index: 1
    });
    console.log(alias.data.url);
    // https://my-app.node-us.containers.hoody.icu
    ```
  
  
    ```bash
    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",
        "index": 1
      }'
    ```
  




**Now accessible at:**
```
https://my-app.node-us.containers.hoody.icu
```

### Auto-Generated Aliases

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



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

### Alias Naming Rules

**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)

---

## Path Routing

### Target Path Configuration

**Route requests to specific base paths in your container:**



**Routing behavior:**


  
    ```
    Incoming Request:
    https://my-api.node-us.containers.hoody.icu/users
    
    Routed To Container:
    /api/v1/users
    
    (target_path prepended)
    ```
  
  
    ```
    Incoming Request:
    https://my-api.node-us.containers.hoody.icu/users
    
    Routed To Container:
    /users
    
    (pass-through, no modification)
    ```
  


### Path Override Control

**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
  
  
    ```
    # Only target_path allowed
    https://my-api.hoody.icu/api/v1/users  → /api/v1/users ✅
    https://my-api.hoody.icu/admin         → Blocked ❌
    https://my-api.hoody.icu/anything      → Blocked ❌
    ```
    
    **Use when:** You want to restrict access to a specific API path
  


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

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

---

## Multi-Service Aliases

**One container can have multiple aliases for different services:**


  
    
  
  
    
  
  
    
  


**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.**

---

## Alias Lifecycle

### Listing Aliases


  
    ```bash
    # 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
    ```
  
  
    ```typescript
    // List all aliases
    const all = await client.api.proxyAliases.list();

    // Filter by project
    const byProject = await client.api.proxyAliases.list({ project_id: PROJECT_ID });

    // Filter by container
    const byContainer = await client.api.proxyAliases.list({ container_id: CONTAINER_ID });

    // Find expired aliases
    const expired = await client.api.proxyAliases.list({ expired: 'true' });
    ```
  
  
    ```bash
    # List all aliases
    curl "https://api.hoody.icu/api/v1/proxy/aliases" \
      -H "Authorization: Bearer $TOKEN"

    # Filter by project
    curl "https://api.hoody.icu/api/v1/proxy/aliases?project_id=$PROJECT_ID" \
      -H "Authorization: Bearer $TOKEN"

    # Filter by container
    curl "https://api.hoody.icu/api/v1/proxy/aliases?container_id=$CONTAINER_ID" \
      -H "Authorization: Bearer $TOKEN"
    ```
  



  
    
  
  
    
  
  
    
  
  
    
  


### Updating Aliases


  
    ```bash
    # 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"
    ```
  
  
    ```typescript
    // Change alias target service
    await client.api.proxyAliases.update(ALIAS_ID, {
      program: 'exec',
      index: 2,
      target_path: '/v2'
    });

    // Update expiration
    await client.api.proxyAliases.update(ALIAS_ID, {
      expires_at: '2026-12-31T23:59:59Z'
    });
    ```
  
  
    ```bash
    # Change alias target service
    curl -X PATCH "https://api.hoody.icu/api/v1/proxy/aliases/$ALIAS_ID" \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"program": "exec", "index": 2, "target_path": "/v2"}'

    # Update expiration
    curl -X PATCH "https://api.hoody.icu/api/v1/proxy/aliases/$ALIAS_ID" \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"expires_at": "2026-12-31T23:59:59Z"}'
    ```
  



  
    
  
  
    
  


### Enabling/Disabling Aliases

**Temporarily disable without deleting:**


  
    ```bash
    # 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
    ```
  
  
    ```typescript
    // Disable alias
    await client.api.proxyAliases.setState(ALIAS_ID, { enabled: false });

    // Re-enable alias
    await client.api.proxyAliases.setState(ALIAS_ID, { enabled: true });
    ```
  
  
    ```bash
    # Disable alias
    curl -X PATCH "https://api.hoody.icu/api/v1/proxy/aliases/$ALIAS_ID/state" \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"enabled": false}'

    # Re-enable alias
    curl -X PATCH "https://api.hoody.icu/api/v1/proxy/aliases/$ALIAS_ID/state" \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"enabled": true}'
    ```
  



  
    
  
  
    
  


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

### Deleting Aliases


  
    ```bash
    # Permanently remove alias
    hoody proxy delete $ALIAS_ID
    ```
  
  
    ```typescript
    await client.api.proxyAliases.delete(ALIAS_ID);
    ```
  
  
    ```bash
    curl -X DELETE "https://api.hoody.icu/api/v1/proxy/aliases/$ALIAS_ID" \
      -H "Authorization: Bearer $TOKEN"
    ```
  




**The alias name becomes available for reuse immediately.**

---

## Expiration

**Aliases can automatically expire:**



**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.


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


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

---

## Common Patterns

### Pattern 1: Production API Alias

**Clean URL for your API service:**



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

### Pattern 2: Multiple Environment Aliases

**Different aliases for same container's different programs:**


  
    
  
  
    
  
  
    
  


**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
```

### Pattern 3: Version-Based Aliases

**Manage API versions with aliases:**


  
    
  
  
    
  
  
    
  


**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-v2` → `api-v1`, or update client references.

### Pattern 4: Staging → Production Promotion

**Typical deployment workflow:**

```bash
# 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
```

---

## Alias Management

### Filtering and Discovery


  
    
  
  
    
  
  
    
  


### Bulk Operations

**Update multiple aliases programmatically:**

```javascript
// 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'
    })
  });
}
```

---

## Advanced Routing

### hoody-exec Subdomain Routing

**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:



**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 →](/kit/exec/) for complete script routing documentation.

### Multiple Instances

**Target different instances of the same program:**


  
    
  
  
    
  


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

---

## Alias + Custom Domain

**Aliases serve as CNAME targets for custom domains:**

**Step 1: Create alias**



**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 →](./connect-domain/) for complete custom domain setup.

---

## Security Considerations

### Alias Uniqueness

**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 vs Aliases

<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin: 1.5rem 0;">

<div style="padding: 1.25rem; background: #f8f8f8; border: 1px solid #ddd; border-radius: 4px;">

**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

</div>

<div style="padding: 1.25rem; background: #f8f8f8; border: 1px solid #ddd; border-radius: 4px;">

**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

</div>

</div>

**Best practice:**
- **Development:** Use cryptographic URLs (secure by obscurity)
- **Production:** Use aliases + [permissions](./permissions/) (secure by authentication)

### Permission Integration

**Aliases work with proxy permissions:**



**Then configure permissions** (separate endpoint):

```bash
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.**

---

## Real-World Example

**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**



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

**3. Configure staging with IP whitelist (office only)**

```bash
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**



**6. Create production alias**



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)**

```bash
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.**

---

## Useful Questions

### 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?

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?

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.

### Do aliases work with proxy permissions?

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?

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`?

`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?

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

### 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?

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?

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).

---

## Troubleshooting

### Alias Already Exists

**Error:**
```json
{
  "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}`

### Alias Not Routing

**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

### DNS Propagation Delay

**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

---

## Aliases vs Cryptographic URLs

**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)

---

## What's Next

**Configure your aliases:**

1. **[Connect a Domain →](./connect-domain/)** - Point your custom domain to an alias
2. **[Set Permissions →](./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.**