KubeMQ
Integrations.NET AspireHow-to guides

Client Configuration and TLS

Configure the KubeMQ client through appsettings.json or delegates, including TLS, gRPC tuning, keepalive, and reconnect.

The KubeMQ.Aspire.Client package exposes every client setting through two configuration surfaces that you can mix freely: a JSON section in appsettings.json and inline delegates on the registration call. This guide walks through the connection string resolution order, the core SDK passthrough settings, enabling TLS, the startup TLS warnings, and the gRPC, keepalive, and reconnect tuning knobs — all grounded in the actual settings type and binding logic.

Prerequisites

  • An Aspire AppHost project with the KubeMQ resource added, and a service project referencing KubeMQ.Aspire.Client (see Getting Started with .NET Aspire)
  • builder.AddKubeMQClient(...) (or AddKeyedKubeMQClient) already called in the service's Program.cs

Two Configuration Surfaces

Settings live in the Aspire:KubeMQ:Client section of appsettings.json. At startup AddKubeMQClient binds that section into a KubeMQClientSettings instance, then invokes the optional configureSettings delegate so code can override or supplement what came from configuration. A second configureOptions delegate runs last and operates on the raw SDK KubeMQClientOptions, giving you an escape hatch for anything the Aspire settings layer does not surface.

Program.cs
var builder = WebApplication.CreateBuilder(args);

// 1. binds Aspire:KubeMQ:Client from appsettings.json
// 2. configureSettings overrides bound values
// 3. configureOptions tweaks the SDK options directly (runs last)
builder.AddKubeMQClient(
    "messaging",
    configureSettings: settings => settings.ClientId = "order-service",
    configureOptions: options => { /* low-level SDK options */ });

var app = builder.Build();
app.Run();

The signature is the same for the keyed overload, which binds from a per-name subsection (Aspire:KubeMQ:Client:<name>) instead of the top-level section:

Keyed registration
builder.AddKeyedKubeMQClient("orders");
builder.AddKeyedKubeMQClient("notifications");

The binding order is fixed: appsettings.json first, then configureSettings, then configureOptions. A value set in a later step always wins over an earlier one.

Connection String Resolution

You normally do not set a connection string in the client at all — when the AppHost wires WithReference(messaging), Aspire injects the resource's endpoint as a connection string named after the connection (messaging). The client resolves it in this order:

  1. If settings.ConnectionString is set explicitly, that value wins.
  2. Otherwise the client reads Aspire's injected connection string for the connection name via GetConnectionString(connectionName).

The resolved value must be a plain host:port string with no scheme. The parser rejects anything containing ://, and IPv6 literals must be bracketed as [host]:port.

appsettings.json — explicit override
{
  "Aspire": {
    "KubeMQ": {
      "Client": {
        "ConnectionString": "kubemq.prod.internal:50000"
      }
    }
  }
}
InputValid?Notes
localhost:50000YesStandard IPv4 / hostname form
[::1]:50000YesIPv6 must be bracketed
grpc://localhost:50000NoScheme prefix rejected
::1:50000NoUnbracketed IPv6 rejected
localhostNoPort is required

In a typical Aspire solution you let the AppHost supply the connection string. Set ConnectionString explicitly only when connecting to a broker that Aspire does not provision (for example a staging cluster).

Core Settings

These four settings pass straight through to the SDK. When left unset (null), the SDK applies its own documented defaults rather than the client forcing a value.

Prop

Type

appsettings.json — core settings
{
  "Aspire": {
    "KubeMQ": {
      "Client": {
        "AuthToken": null,
        "ClientId": "order-service",
        "DefaultTimeout": "00:00:05",
        "ConnectionTimeout": "00:00:10"
      }
    }
  }
}

Enabling TLS

TLS is off by default so dev containers work over plain HTTP. Set UseTls=true to switch the gRPC connection to TLS; when it is true the client builds the SDK TlsOptions from the matching Tls* properties. All certificate fields are optional — omit them to verify against the system trust store, or supply PEM paths for mutual TLS.

Prop

Type

appsettings.json — TLS with a CA file
{
  "Aspire": {
    "KubeMQ": {
      "Client": {
        "ConnectionString": "kubemq.prod.internal:50000",
        "UseTls": true,
        "TlsCaFile": "/etc/kubemq/certs/ca.pem"
      }
    }
  }
}

For mutual TLS, add the client certificate and key:

appsettings.json — mutual TLS
{
  "Aspire": {
    "KubeMQ": {
      "Client": {
        "UseTls": true,
        "TlsCaFile": "/etc/kubemq/certs/ca.pem",
        "TlsCertFile": "/etc/kubemq/certs/client.pem",
        "TlsKeyFile": "/etc/kubemq/certs/client-key.pem"
      }
    }
  }
}

TlsInsecureSkipVerify=true disables certificate verification entirely and exposes the connection to man-in-the-middle attacks. Use it only against a local development broker, never in production.

TLS Startup Warnings

A hosted service (KubeMQTlsWarningHostedService) runs at startup and inspects the resolved TLS configuration so a missing-TLS setup never goes unnoticed in the logs:

  • If UseTls is false, it logs a warning advising you to set UseTls=true for production.
  • If UseTls is false and an AuthToken is configured, it additionally logs a Critical message because the credentials would travel in plaintext.
Startup log — token without TLS
warn: KubeMQ.Aspire.Client
      KubeMQ client 'messaging' is configured without TLS. Set UseTls=true for production environments.
crit: KubeMQ.Aspire.Client
      KubeMQ client 'messaging' has an authentication token configured without TLS.
      Credentials will be transmitted in plaintext. Enable UseTls=true to secure the connection.

The check is purely advisory — it never blocks startup — but the Critical entry is your signal that an AuthToken is leaking over an unencrypted channel. The clean fix is to set UseTls=true alongside the token.

gRPC Tuning

These options shape the gRPC channel pool and message-size limits. Each is nullable; leaving it null keeps the SDK default.

Prop

Type

appsettings.json — gRPC tuning
{
  "Aspire": {
    "KubeMQ": {
      "Client": {
        "GrpcChannelCount": 8,
        "MaxSendSize": 209715200,
        "MaxReceiveSize": 209715200,
        "WaitForReady": true
      }
    }
  }
}

GrpcChannelCount is validated to the inclusive range 1–16 by ConfigurationSchema.json; the IDE flags out-of-range values before you ever run the app.

Keepalive

Keepalive pings keep idle gRPC connections healthy through load balancers and NAT timeouts. Both values are nullable and fall back to the SDK defaults.

Prop

Type

appsettings.json — keepalive
{
  "Aspire": {
    "KubeMQ": {
      "Client": {
        "KeepalivePingInterval": "00:00:10",
        "KeepalivePingTimeout": "00:00:05"
      }
    }
  }
}

Reconnect

The client auto-reconnects after a dropped connection. Tune the behavior with these nullable options.

Prop

Type

appsettings.json — reconnect
{
  "Aspire": {
    "KubeMQ": {
      "Client": {
        "ReconnectEnabled": true,
        "ReconnectMaxAttempts": 0,
        "ReconnectTimeout": "00:01:00"
      }
    }
  }
}

Configuring via Delegate

Anything you can set in appsettings.json you can also set in code through the configureSettings delegate. This is handy for values that come from secrets, feature flags, or environment-specific logic.

Program.cs — settings delegate
builder.AddKubeMQClient("messaging", settings =>
{
    settings.DisableHealthChecks = true;
    settings.AuthToken = "my-token";
});

Because the delegate runs after JSON binding, it overrides whatever was in the Aspire:KubeMQ:Client section. For multiple instances, pass a delegate to each keyed registration:

Program.cs — per-keyed settings
builder.AddKeyedKubeMQClient("orders", settings => settings.ClientId = "orders-consumer");
builder.AddKeyedKubeMQClient("notifications", settings => settings.UseTls = true);

Full appsettings.json Example

This example shows the default client section together with a keyed subsection. The keyed subsection name (orders) matches the service key passed to AddKeyedKubeMQClient. Because the package ships a ConfigurationSchema.json, your IDE provides IntelliSense, defaults, and range validation for every key below.

appsettings.json
{
  "Aspire": {
    "KubeMQ": {
      "Client": {
        "DisableHealthChecks": false,
        "DisableTracing": false,
        "DisableMetrics": false,
        "HealthCheckTimeout": "00:00:05",
        "ClientId": "default-service",
        "DefaultTimeout": "00:00:05",
        "ConnectionTimeout": "00:00:10",
        "UseTls": true,
        "TlsCaFile": "/etc/kubemq/certs/ca.pem",
        "GrpcChannelCount": 5,
        "KeepalivePingInterval": "00:00:10",
        "KeepalivePingTimeout": "00:00:05",
        "ReconnectEnabled": true,
        "ReconnectMaxAttempts": 0,
        "ReconnectTimeout": "00:01:00",

        "orders": {
          "ConnectionString": "orders-broker:50000",
          "ClientId": "orders-consumer",
          "UseTls": true,
          "TlsCaFile": "/etc/kubemq/certs/ca.pem",
          "GrpcChannelCount": 8
        }
      }
    }
  }
}

To exercise the configuration locally against a plain broker, run KubeMQ with the gRPC port published:

docker run -d \  --name kubemq \  -p 50000:50000 \  -p 9090:9090 \  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \  europe-docker.pkg.dev/kubemq/images/kubemq:next

License Key vs. AuthToken

These two tokens are easy to confuse but serve different roles:

TokenWhere it is setPurpose
License key (KUBEMQ_TOKEN)AppHost, via WithLicenseKey()Activates the KubeMQ server container. A server/deployment concern.
AuthTokenClient settings (Aspire:KubeMQ:Client)Authenticates the gRPC client connection to the broker.

The license key is not a client credential — set it on the server resource in the AppHost with WithLicenseKey(). The client AuthToken is the per-connection gRPC credential and belongs in the client settings. When you set an AuthToken, also enable UseTls=true so it is not sent in plaintext.

Was this page helpful?

On this page