Date: 2025-07-15 Goal: Find the best Microsoft-ecosystem-aligned HTTPS proxy for AgentBox Context: Ephemeral dev containers on Azure Container Instances (ACI), accessed via code-server + ttyd + SSH. Needs TLS termination, Entra ID auth, WebSocket support, wildcard routing, low cost.
| Option | Est. Cost/mo | Auto TLS | Entra ID Auth | WebSocket | Complexity | Microsoft-native |
|---|---|---|---|---|---|---|
| 1. Container Apps (direct) | ~$5–15 | ✅ Free managed certs | ✅ Built-in Easy Auth | ✅ Native | ⭐ Low | ✅ Yes |
| 2. Container Apps as proxy | ~$5–10 | ✅ Free managed certs | ✅ Built-in Easy Auth | ✅ Native | ⭐⭐ Low-Med | ✅ Yes |
| 3. Application Gateway | ~$20–40+ | ✅ (bring cert or Key Vault) | ✅ Native | ⭐⭐⭐ High | ✅ Yes | |
| 4. Azure Front Door | ~$35–50+ | ✅ Auto-managed | ✅ Yes | ⭐⭐⭐ High | ✅ Yes | |
| 5. Azure API Management | ~$0–5 (Consumption) | ✅ Managed | ✅ Entra ID policies | ✅ (not on Consumption tier) | ⭐⭐⭐ High | ✅ Yes |
| 6. Caddy on Container Apps | ~$5–10 | ✅ Let's Encrypt via Caddy | ✅ Easy Auth + forward_auth | ✅ Native | ⭐⭐ Medium | |
| 7. Traefik on Container Apps | ~$5–10 | ✅ Let's Encrypt via Traefik | ✅ Easy Auth + ForwardAuth | ✅ Native | ⭐⭐ Medium | |
| 8. YARP on Container Apps | ~$5–10 | ✅ Via Container Apps | ✅ Easy Auth or middleware | ✅ Yes (.NET) | ⭐⭐ Medium | ✅ Yes (Microsoft) |
| 9. Static Web Apps + Functions | ~$0–9 | ✅ Auto-managed | ✅ Built-in | ❌ No WebSocket proxy | ⭐⭐ Medium | ✅ Yes |
| 10. ACI direct (no proxy) | ~$0 | ❌ Self-signed only | ❌ None | N/A | ⭐ Low | ✅ Yes |
Concept: Skip ACI entirely. Run each AgentBox container as a Container App with built-in ingress, TLS, and Easy Auth.
Findings:
- Container Apps provides built-in HTTP ingress with automatic TLS termination using free managed certificates (via DigiCert). Supports custom domains and wildcard subdomains via CNAME records. (Source)
- WebSocket support is native — the ingress explicitly supports "HTTP/1.1, HTTP/2, WebSocket, and gRPC". (Source)
- Built-in Entra ID authentication (Easy Auth) runs as a sidecar container that intercepts all requests before they reach the app. Supports Microsoft Entra ID, GitHub, Google, and custom OIDC. Can be set to "Require authentication" to block unauthenticated traffic. (Source)
- Free managed certificates are available for custom domains. Requirement: CNAME must point directly to the Container App (no intermediate CNAME like Cloudflare). Certificates auto-renew. (Source)
- Custom domains: Supports wildcard DNS via CNAME. Each subdomain (e.g.,
project1.agentbox.networg.com) can be routed to a different Container App, or a single proxy app can route by hostname.
Cost (Consumption Plan):
- Free tier: 180,000 vCPU-seconds, 360,000 GiB-seconds, 2M requests/month per subscription.
- Beyond free tier: ~$0.000024/vCPU-second active, ~$0.000003/GiB-second active.
- Scale to zero — no charge when idle.
- For a proxy container (0.25 vCPU, 0.5 GiB) running 24/7: ~$5–8/mo.
- (Source)
Wildcard routing limitation: Container Apps free managed certs require per-subdomain CNAME validation — no wildcard certificates. You'd need to add each subdomain programmatically via az containerapp hostname bind. Alternatively, use a bring-your-own wildcard certificate.
AgentBox containers on Container Apps directly?
- Possible but suboptimal. Each AgentBox container runs code-server (port 8080), ttyd (port 7681), and sshd (port 2222). Container Apps supports additional TCP ports (up to 5 per app), so multi-port is feasible.
- Concern: Container Apps is optimized for HTTP microservices that scale on demand. AgentBox containers are long-running, stateful dev environments. ACI is a better fit for this workload pattern.
- Verdict: Use Container Apps for the proxy layer, keep ACI for workload containers.
Concept: Run a lightweight reverse proxy container on Container Apps. Container Apps handles TLS + Easy Auth. The proxy routes authenticated requests to ACI containers.
This is the recommended architecture pattern. It combines:
- Container Apps free managed TLS (or bring-your-own wildcard cert)
- Container Apps built-in Easy Auth for Entra ID login
- A simple proxy container (nginx, Caddy, YARP, or custom) that routes to ACI backends
- Container Apps native WebSocket pass-through
How it works:
- User visits
https://project1.agentbox.networg.com - Container Apps terminates TLS (free managed cert)
- Easy Auth sidecar authenticates user via Entra ID, injects
X-MS-CLIENT-PRINCIPALheaders - Request reaches the proxy container
- Proxy checks authorization (does this user own this container?) and routes to the ACI container's IP/FQDN
- WebSocket connections pass through transparently
Cost: ~$5–10/mo for a single always-on proxy container (0.25 vCPU, 0.5 GiB).
Concept: Azure-native L7 load balancer with TLS termination.
Findings:
- Full L7 load balancer with SSL/TLS termination, URL-based routing, cookie-based session affinity. (Source)
- WebSocket: Native support, no configuration needed. Standard HTTP listeners handle WebSocket upgrade transparently. Timeout values must be set higher than ping intervals. (Source)
- TLS: Supports certificates from Azure Key Vault. No free auto-managed certs — you must provide your own or integrate with Let's Encrypt externally.
- Entra ID auth: Not built-in. Application Gateway is a network appliance, not an application platform. You'd need to add authentication at the app level or chain with another service. Can integrate with Azure AD via custom WAF rules or by pairing with APIM, but it's not turnkey.
- Wildcard routing: Supports multi-site listeners with wildcard hostnames (
*.agentbox.networg.com).
Cost:
- V2 SKU: ~$0.246/gateway-hour fixed + ~$0.008/capacity-unit-hour.
- Minimum ~$18/mo just for the fixed gateway cost (running 24/7).
- With light traffic: ~$20–30/mo.
- (Source)
Verdict: Overkill and expensive for this use case. No built-in auth. Better suited for enterprise production workloads.
Concept: Global CDN + L7 load balancer with WAF and auto-TLS.
Findings:
- Global edge network with 118+ PoPs, auto-TLS with free managed certificates, WAF integration. (Source)
- WebSocket: Supported (proxies WebSocket traffic after HTTP upgrade).
- TLS: Free auto-rotating managed SSL certificates included.
- Entra ID auth: Not built-in as Easy Auth. Front Door is a CDN/edge service. Auth must be handled at the origin (app layer) or via WAF rules that inspect JWT tokens. No turnkey Entra ID login flow.
- Wildcard routing: Supports wildcard custom domains.
Cost:
- Standard tier: $35/mo base fee + $0.083/GB data transfer + $0.009/10K requests.
- Premium tier: $330/mo base fee (includes WAF).
- For our low-traffic scenario: $35–40/mo minimum on Standard.
- (Source)
Verdict: Way too expensive for 5-10 users. Designed for global-scale applications. No built-in auth flow.
Concept: API gateway with built-in auth policies.
Findings:
- Comprehensive API gateway with Entra ID integration, JWT validation policies, rate limiting. (Source)
- WebSocket: Supported via WebSocket passthrough API, BUT not on the Consumption tier. Requires Developer, Basic, Standard, or Premium tier. (Source)
- Entra ID auth: Built-in JWT validation policy (
validate-jwt). Can validate Entra ID tokens on every request. Very powerful for API scenarios. - TLS: Managed TLS on the gateway endpoint.
Cost:
- Consumption tier: First 1M calls free, then $0.035/10K calls. But no WebSocket support.
- Developer tier: ~$50/mo (not production-grade, no SLA).
- Basic v2: Pricing not fully public yet, estimated ~$150+/mo.
- (Source)
Verdict: WebSocket limitation on Consumption tier is a dealbreaker. Other tiers are far too expensive. APIM is designed for API management, not reverse proxying dev containers.
Concept: Caddy reverse proxy running on Container Apps with Easy Auth.
Findings:
- Caddy provides automatic HTTPS via Let's Encrypt, simple configuration, built-in
forward_authdirective for delegating auth decisions. - When deployed on Container Apps, you get double TLS options: Container Apps manages the external TLS cert, Caddy handles internal routing.
forward_authintegrates well with Easy Auth's/.auth/meendpoint for authorization checks.- WebSocket: Caddy handles WebSocket pass-through natively.
- Caddy is written in Go, lightweight (~30MB binary).
Why the user is hesitant: Caddy is an open-source project by a small company (Dapperware). Not a "Microsoft choice." However, it's production-grade and widely used.
Cost: Same as option 2 — ~$5–10/mo on Container Apps.
Verdict: Technically excellent, but the user wants something more Microsoft-aligned.
Concept: Traefik reverse proxy as a replacement for Caddy.
Findings:
- Cloud-native reverse proxy with 3.3B+ downloads and 55K+ GitHub stars. (Source)
- Has
ForwardAuthmiddleware (equivalent to Caddy'sforward_auth). - Built-in Let's Encrypt support with multiple ACME challenge providers.
- Native Docker, Kubernetes, and file-based service discovery.
- WebSocket: Full WebSocket support (pass-through).
- More complex configuration than Caddy (YAML/TOML vs Caddyfile).
Microsoft alignment: Traefik is an open-source project by Traefik Labs (French company). No more "Microsoft" than Caddy. Used by many enterprises but not a Microsoft product.
Cost: Same as Caddy — ~$5–10/mo on Container Apps.
Verdict: Powerful but more complex than Caddy, with no Microsoft alignment advantage. Not recommended over Caddy for this use case.
Concept: Microsoft's own .NET reverse proxy library, running as a small ASP.NET app on Container Apps.
Findings:
- YARP is a Microsoft-built reverse proxy library for .NET, developed by the ASP.NET team. Used internally at Microsoft for Azure services. (Source)
- Not a standalone binary — it's a NuGet package (
Yarp.ReverseProxy) that you embed in an ASP.NET Core application. You write a small C# program that configures routes and clusters. - TLS termination: When deployed on Container Apps, TLS is handled by Container Apps (not YARP). YARP handles HTTP-level routing internally.
- WebSocket: Fully supported. YARP proxies WebSocket connections as part of standard HTTP upgrade handling. It's built on ASP.NET Core's Kestrel server which has excellent WebSocket support.
- Entra ID auth: Two approaches:
- Use Container Apps Easy Auth (recommended) — YARP sees pre-authenticated requests with identity headers.
- Use ASP.NET Core's built-in
Microsoft.Identity.Webpackage for Entra ID authentication directly in the YARP app. This gives you fine-grained authorization middleware in C# — e.g., check if the user owns the container before proxying.
- Dynamic routing: YARP supports programmatic route configuration. You can dynamically add/remove routes as containers are created/destroyed via an API or config store.
- Maturity: Production-grade. Version 2.x. Used in Azure App Service, Azure Active Directory, and other Microsoft services.
Architecture with YARP:
User → Container Apps (TLS + Easy Auth) → YARP (.NET app)
→ Reads X-MS-CLIENT-PRINCIPAL headers
→ Checks authorization (user owns container?)
→ Proxies to ACI container IP:port
→ WebSocket pass-through works natively
Sample YARP proxy (minimal):
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddReverseProxy()
.LoadFromMemory(routes, clusters); // dynamic config
var app = builder.Build();
app.MapReverseProxy();
app.Run();Cost: Same as other Container Apps options — ~$5–10/mo.
Verdict: Best Microsoft-native option. Gives you C# authorization logic, native .NET ecosystem, and Microsoft's own engineering. Slightly more code than Caddy's Caddyfile, but much more flexible for per-container authorization.
Concept: Use SWA for the dashboard, Azure Functions to proxy traffic to ACI.
Findings:
- Static Web Apps has built-in Entra ID auth (Microsoft identity platform). Pre-configured, no setup needed. (Source)
- Azure Functions linked to SWA can serve as API endpoints.
- WebSocket: Dealbreaker. Azure Functions does not support WebSocket connections. Functions are HTTP request/response only (triggers and bindings limited to HTTP). There is no way to proxy a long-lived WebSocket connection through a Function. (Source)
- SWA + Functions is great for the management dashboard but cannot proxy code-server/ttyd traffic.
Cost: Free tier for SWA. Functions consumption: effectively free for low volume.
Verdict: Use for the dashboard/management UI, not for the container proxy. WebSocket support is completely absent.
Concept: Each ACI container gets a public IP with a DNS label. Terminate TLS directly in the container.
Findings:
- ACI assigns public IPs with FQDN labels like
my-project.westeurope.azurecontainer.io. (Source) - ACI does NOT support managed TLS certificates. You must handle TLS yourself.
- Microsoft documents a sidecar pattern where an nginx container handles TLS within the ACI container group, using self-signed or manually-provided certificates. (Source)
- No wildcard DNS — each container gets its own
*.azurecontainer.iosubdomain. - No built-in auth — you'd have to implement authentication in each container.
- Let's Encrypt in ACI: Technically possible with Caddy or certbot as a sidecar, but operationally painful (certificate storage, DNS challenges, renewal coordination).
Cost: $0 additional (already paying for ACI compute).
Verdict: Not viable. No auth, no managed TLS, no unified domain. Every container is its own island.
WebSocket support is non-negotiable for AgentBox. Both code-server and ttyd rely on persistent WebSocket connections for their IDE and terminal interfaces.
| Option | WebSocket Support | Notes |
|---|---|---|
| Container Apps ingress | ✅ Full | Explicitly listed as supported. HTTP/1.1 and HTTP/2. |
| Application Gateway | ✅ Full | Native support, all sizes. Set timeout > 20s for ping/pong. |
| Azure Front Door | ✅ Full | Proxies WebSocket after HTTP upgrade. |
| APIM Consumption | ❌ No | WebSocket API not available on Consumption tier. |
| APIM Developer+ | ✅ Full | WebSocket passthrough API. One-to-one client-backend mapping. |
| Caddy | ✅ Full | Transparent proxy of WebSocket connections. |
| Traefik | ✅ Full | Transparent proxy of WebSocket connections. |
| YARP (.NET) | ✅ Full | Built on Kestrel; handles HTTP upgrade natively. |
| Azure Functions | ❌ No | HTTP triggers only. No persistent connections. |
| ACI sidecar (nginx) | ✅ Full | Nginx/Caddy in sidecar handles WebSocket. |
Winner: Any option except APIM Consumption and Azure Functions.
Scenario: 5–10 users, ~20 containers active at peak, light traffic (dev tool access, not high-throughput APIs).
| Option | Fixed Cost | Variable Cost | Estimated Total/mo |
|---|---|---|---|
| Container Apps proxy (Consumption) | ~$0 (free tier covers idle) | ~$5–8 for always-on proxy | $5–10 |
| Application Gateway V2 | ~$18 fixed gateway | ~$2–5 capacity units | $20–25 |
| Azure Front Door Standard | $35 base fee | ~$1–3 data/requests | $36–40 |
| APIM Consumption | $0 | ~$0–3 per-call charges | $0–3 (but no WS!) |
| APIM Developer | ~$50 fixed | $0 | $50 (no SLA) |
| SWA + Functions | $0–9 | ~$0 | $0–9 (no WS!) |
| ACI direct | $0 additional | $0 | $0 (no auth/TLS) |
Cheapest viable options: Container Apps proxy (Consumption plan) at ~$5–10/mo.
Why: Maximum Microsoft alignment + full control + low cost.
| Criterion | Score |
|---|---|
| Microsoft-native | ✅ YARP is a Microsoft product, .NET is Microsoft's platform |
| Entra ID auth | ✅ Easy Auth built-in + ASP.NET Microsoft.Identity.Web for fine-grained authZ |
| WebSocket | ✅ Full support via Kestrel |
| Cost | ✅ ~$5–10/mo on Container Apps Consumption |
| Complexity | ⭐⭐ Requires writing a small .NET app (~50–100 lines for basic proxy) |
| Dynamic routing | ✅ Programmatic route config — add/remove ACI backends via API |
| Authorization | ✅ Write C# middleware to check container ownership |
Architecture:
┌──────────────────────────────┐
│ Azure Container Apps │
Internet ──HTTPS──▶ │ ┌─────────┐ ┌────────────┐ │ ┌──────────┐
*.agentbox. │ │Easy Auth│→ │ YARP (.NET)│─┼────▶│ ACI #1 │
networg.com │ │(sidecar)│ │ Proxy App │ │ │code-server│
│ └─────────┘ └────────────┘ │ └──────────┘
│ TLS + Entra ID │ ┌──────────┐
│ Free managed certs │────▶│ ACI #2 │
└──────────────────────────────┘ └──────────┘
Pros:
- 100% Microsoft stack (Azure + .NET + YARP)
- Easy Auth handles Entra ID login — zero auth code for the login flow
- YARP gives you C# authorization middleware for per-container access control
- Dynamic routing — programmatically update routes as containers are created/destroyed
- Can integrate with Azure SDK to query ACI state, verify container ownership
- Container Apps handles TLS certificates automatically
Cons:
- Must maintain a small .NET application (vs. Caddy's config-only approach)
- Slightly steeper learning curve if team is not .NET-familiar
Why: Simplest possible architecture. Zero proxy code.
Concept: Run each AgentBox container as a Container App (not ACI). Let Container Apps handle everything — ingress, TLS, auth, routing.
| Criterion | Score |
|---|---|
| Microsoft-native | ✅ Fully Azure-managed |
| Entra ID auth | ✅ Built-in Easy Auth |
| WebSocket | ✅ Native |
| Cost | |
| Complexity | ⭐ Minimal — pure Azure config, no custom code |
| Dynamic routing | |
| Authorization |
Trade-offs:
- Moving workloads from ACI to Container Apps changes the operational model.
- Each AgentBox instance is a separate Container App with its own custom domain binding.
- Per-container authorization still requires custom logic (could be a small middleware).
- Managed cert provisioning per subdomain (no wildcard) adds operational overhead.
- ACI may be more cost-effective for long-running stateful containers.
Why: Battle-tested, simple config, proven WebSocket support.
| Criterion | Score |
|---|---|
| Microsoft-native | |
| Entra ID auth | ✅ Easy Auth + forward_auth directive |
| WebSocket | ✅ Full |
| Cost | ✅ ~$5–10/mo |
| Complexity | ⭐ Very simple Caddyfile config |
| Dynamic routing |
Why it's still good: If the team values simplicity over Microsoft purity, Caddy is the fastest path to a working system. The "not Microsoft" concern is only about Caddy itself — the hosting (Container Apps), auth (Easy Auth), and TLS (Azure managed certs) are all Microsoft.
YARP is the Microsoft-native answer. It's built by the ASP.NET team, used internally at Microsoft, and gives you:
- Microsoft ecosystem alignment — .NET + Azure Container Apps + Easy Auth + Azure SDK
- Cost — ~$5–10/mo on Container Apps Consumption plan (same as Caddy)
- WebSocket — Full support via Kestrel
- Entra ID — Easy Auth for login + C# middleware for per-container authorization
- Dynamic routing — Programmatically configure routes as containers are created/destroyed
- Authorization power — Write real C# logic to check container ownership, shared access, admin roles
What this means for the architecture:
| Component | Before (Caddy plan) | After (YARP plan) |
|---|---|---|
| Proxy runtime | Caddy (Go) | YARP ASP.NET app (C#) |
| Hosting | Container Apps | Container Apps (no change) |
| TLS | Container Apps managed certs | Container Apps managed certs (no change) |
| Auth (login) | Easy Auth | Easy Auth (no change) |
| Auth (per-container) | Caddy forward_auth + custom API | YARP middleware (built-in) |
| Routing config | Caddyfile / Caddy API | YARP in-memory config / IConfiguration |
| WebSocket | Caddy pass-through | YARP/Kestrel pass-through |
| Backend containers | ACI | ACI (no change) |
The only thing that changes is the proxy process itself — from a Caddy binary with a Caddyfile to a small .NET app with YARP. Everything else in the architecture stays the same.
| Option | Reason for elimination |
|---|---|
| Application Gateway | Too expensive (~$20+/mo), no built-in auth, high complexity |
| Azure Front Door | Way too expensive ($35+/mo base), designed for global scale |
| APIM Consumption | No WebSocket support on Consumption tier |
| APIM Developer+ | Too expensive ($50+/mo), wrong tool for this job |
| Azure Functions proxy | No WebSocket support — dealbreaker |
| ACI direct | No managed TLS, no auth, no unified domain |
| Traefik | No advantage over Caddy, more complex config, also not Microsoft |
- Container Apps Ingress Overview
- Container Apps Authentication
- Container Apps Entra ID Setup
- Container Apps Managed Certificates
- Container Apps Custom Domains
- Container Apps Pricing
- Application Gateway Overview
- Application Gateway WebSocket Support
- Application Gateway Pricing
- Azure Front Door Overview
- Azure Front Door Pricing
- API Management Overview
- APIM WebSocket API
- API Management Pricing
- YARP (Microsoft Reverse Proxy)
- Traefik Documentation
- Static Web Apps Auth
- SWA Functions Limitations
- ACI TLS Sidecar Pattern
- ACI Overview