microsoft / microsoft/aspire

HostUrl doesn't handle 0.0.0.0 or * bind addresses, causing incorrect container endpoint URLs

Open
#13,311 4 comments 0 reactions 0 assignees View on GitHub
area-app-model
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

When configuring the Aspire dashboard to bind to `0.0.0.0` (to listen on all network interfaces), the `HostUrl` record doesn't recognize `0.0.0.0` or `*` as host addresses that need translation to container-appropriate hostnames. This causes container resources to receive invalid endpoint URLs like `https://0.0.0.0:21186` instead of `https://host.containers.internal:21186`.

The root cause is in `HostUrl.cs` line 42, which only checks for:
```csharp
if (uri.Host is "localhost" or "127.0.0.1" or "[::1]")
```

This doesn't include `0.0.0.0` or `*`, which are valid and commonly used bind addresses for listening on all network interfaces.

**Impact:** This particularly affects Podman users on Linux who need to bind the dashboard to `0.0.0.0` because the dashboard binding to `127.0.0.1` only is unreachable from containers. Using `WithOtlpExporter()` or any code path through `HostUrl` results in broken endpoint URLs that containers cannot connect to.

### Expected Behavior

When `ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL=https://0.0.0.0:21186` is set:
- The dashboard should bind to all interfaces (`0.0.0.0:21186`) ✅ This works
- `HostUrl` should recognize `0.0.0.0` as a host address and translate it to `host.containers.internal` ❌ This fails
- Container resources should receive `OTEL_EXPORTER_OTLP_ENDPOINT=https://host.containers.internal:21186`

### Steps To Reproduce

**Prerequisites:** Podman on Linux (tested on Linux Mint 22.2 with Podman 4.9.3)

1. Create a new Aspire AppHost project:
```bash
dotnet new aspire-apphost -n ReproAppHost
cd ReproAppHost
```

2. Create `otel-config.yaml` in the project directory:
```yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317

exporters:
otlp/aspire:
endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
tls:
insecure: false
insecure_skip_verify: true

service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp/aspire]
```

3. Update `AppHost/Properties/launchSettings.json`:
```json
{
"profiles": {
"https": {
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://0.0.0.0:21186"
}
}
}
}
```

4. Update `Program.cs`:
```csharp
var builder = DistributedApplication.CreateBuilder(args);

var collector = builder.AddContainer("otel-collector", "otel/opentelemetry-collector-contrib", "0.141.0")
.WithBindMount("./otel-config.yaml", "/etc/otel/config.yaml")
.WithArgs("--config=/etc/otel/config.yaml")
.WithHttpEndpoint(targetPort: 4317, name: "grpc")
.WithOtlpExporter(OtlpProtocol.Grpc);

builder.Build().Run();
```

5. Run the application:
```bash
dotnet run
```

6. In another terminal, inspect the container:
```bash
podman ps
podman inspect otel-collector- --format '{{.Config.Env}}' | grep OTEL_EXPORTER_OTLP_ENDPOINT
```

7. Check the container logs:
```bash
podman logs otel-collector-
```

**Actual result:**
```bash
# Environment variable shows:
OTEL_EXPORTER_OTLP_ENDPOINT=https://0.0.0.0:21186

# Container logs show connection errors:
grpc: addrConn.createTransport failed to connect to {Addr: "0.0.0.0:21186", ServerName: "0.0.0.0:21186", }.
Err: connection error: desc = "transport: Error while dialing: dial tcp 0.0.0.0:21186: connect: connection refused"
```

**Expected result:**
```bash
OTEL_EXPORTER_OTLP_ENDPOINT=https://host.containers.internal:21186
```

And no connection errors in logs.

### Exceptions (if any)

No exceptions thrown, but containers fail to connect with gRPC dial errors as shown above.

### .NET Version

```
.NET SDK:
Version: 10.0.100

Runtime Environment:
OS Name: Linux
OS Version: Linux Mint 22.2
OS Platform: Linux
RID: linux-x64

.NET SDKs installed:
10.0.100

.NET runtimes installed:
Microsoft.AspNetCore.App 10.0.0
Microsoft.NETCore.App 10.0.0
```

**Additional version info:**
- Aspire: 13.0.1
- Podman: 4.9.3
- Container Runtime: Podman on Linux
- OS: Linux Mint 22.2

### Anything else?

**Current Workaround:**

```csharp
var otelCollectorUrl = builder.Configuration["ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL"];
// Replace 0.0.0.0 with localhost for HostUrl to properly convert to host.containers.internal
var otelCollectorUrlForContainer = otelCollectorUrl?.Replace("0.0.0.0", "localhost");

var collector = builder.AddContainer("otel-collector", "otel/opentelemetry-collector-contrib", "0.141.0")
.WithBindMount("./otel-config.yaml", "/etc/otel/config.yaml")
.WithArgs("--config=/etc/otel/config.yaml")
.WithHttpEndpoint(targetPort: 4317, name: "grpc")
.WithEnvironment("OTEL_EXPORTER_OTLP_ENDPOINT", new HostUrl(otelCollectorUrlForContainer))
.WithContainerRuntimeArgs("--add-host=host.containers.internal:host-gateway");
// Note: Cannot use WithOtlpExporter() due to this bug
```

**Proposed Fix:**

Update `HostUrl.cs` line 42 to include `0.0.0.0` and `*`:

```csharp
if (uri.Host is "localhost" or "127.0.0.1" or "[::1]" or "0.0.0.0" or "*")
```

And update the string replacement fallback at lines 116-118:
```csharp
retval = retval.Replace(KnownHostNames.Localhost, replacementHost, StringComparison.OrdinalIgnoreCase)
.Replace("127.0.0.1", replacementHost)
.Replace("[::1]", replacementHost)
.Replace("0.0.0.0", replacementHost)
.Replace("*", replacementHost);
```

**Related:**
- #5587 and PR #5588 added support for `*` in `applicationUrl`, but `HostUrl` still doesn't handle these addresses

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.