Overview
The toolkit has no way to reach a resource that should not be on the public internet. Existing tunnel-style integrations (Ngrok) hand out a public URL, which is the wrong shape when the thing you want is "my teammate, or a CI runner, or my phone, can reach this dev resource, and nobody else can."
Twingate fills that gap. Its Connector is a container that joins a Twingate network and makes selected resources reachable only to authenticated clients with a matching policy — no public URL, no inbound port. Running one alongside an app host would let an Aspire dev loop publish a database, an internal API, or a dashboard to exactly the people who should see it.
It is a natural fit for the toolkit specifically because the Connector is a plain container with a token-based configuration and no .NET-side protocol work — the integration is resource wiring, not a client library.
Usage example
var builder = DistributedApplication.CreateBuilder(args);
var accessToken = builder.AddParameter("twingate-access-token", secret: true);
var refreshToken = builder.AddParameter("twingate-refresh-token", secret: true);
var api = builder.AddProject<Projects.Api>("api");
var db = builder.AddPostgres("db");
builder.AddTwingateConnector("twingate", network: "my-company")
.WithTokens(accessToken, refreshToken)
.WithResource(api) // reachable inside the Twingate network
.WithResource(db);
builder.Build().Run();
A minimal form, for someone who has already defined their resources in the Twingate admin console and just needs the Connector running:
builder.AddTwingateConnector("twingate", network: "my-company")
.WithTokens(accessToken, refreshToken);
Additional context
The Connector ships as twingate/connector on Docker Hub (current tags 1.92.0, 1.92, 1). Its documented configuration is entirely environment variables:
| Variable |
Purpose |
TWINGATE_NETWORK |
Network slug, i.e. <name> for <name>.twingate.com |
TWINGATE_ACCESS_TOKEN |
Time-expiring access token from the admin console or API |
TWINGATE_REFRESH_TOKEN |
Time-expiring refresh token |
TWINGATE_DNS |
Optional custom resolver |
TWINGATE_LABEL_HOSTNAME |
Local hostname label |
TWINGATE_LOG_ANALYTICS |
Optional; v2 enables connection logs |
Two details worth designing around rather than discovering later:
- The documented
docker run passes --sysctl net.ipv4.ping_group_range="0 2147483647". Twingate notes that removing it is what lets clients on the same local network reach the Connector peer-to-peer, so this is a deliberate knob rather than boilerplate, and probably wants to be expressed in the API.
- Both tokens expire, so they belong in parameters marked
secret: true rather than anywhere they would be persisted into a manifest.
I have no affiliation with Twingate; I ran into the gap while building tunnel integrations of my own and concluded the ZTNA side belongs here rather than in a tunnel-shaped package.
Help us help you
No, just wanted to propose this.
Overview
The toolkit has no way to reach a resource that should not be on the public internet. Existing tunnel-style integrations (
Ngrok) hand out a public URL, which is the wrong shape when the thing you want is "my teammate, or a CI runner, or my phone, can reach this dev resource, and nobody else can."Twingate fills that gap. Its Connector is a container that joins a Twingate network and makes selected resources reachable only to authenticated clients with a matching policy — no public URL, no inbound port. Running one alongside an app host would let an Aspire dev loop publish a database, an internal API, or a dashboard to exactly the people who should see it.
It is a natural fit for the toolkit specifically because the Connector is a plain container with a token-based configuration and no .NET-side protocol work — the integration is resource wiring, not a client library.
Usage example
A minimal form, for someone who has already defined their resources in the Twingate admin console and just needs the Connector running:
Additional context
The Connector ships as
twingate/connectoron Docker Hub (current tags1.92.0,1.92,1). Its documented configuration is entirely environment variables:TWINGATE_NETWORK<name>for<name>.twingate.comTWINGATE_ACCESS_TOKENTWINGATE_REFRESH_TOKENTWINGATE_DNSTWINGATE_LABEL_HOSTNAMETWINGATE_LOG_ANALYTICSv2enables connection logsTwo details worth designing around rather than discovering later:
docker runpasses--sysctl net.ipv4.ping_group_range="0 2147483647". Twingate notes that removing it is what lets clients on the same local network reach the Connector peer-to-peer, so this is a deliberate knob rather than boilerplate, and probably wants to be expressed in the API.secret: truerather than anywhere they would be persisted into a manifest.I have no affiliation with Twingate; I ran into the gap while building tunnel integrations of my own and concluded the ZTNA side belongs here rather than in a tunnel-shaped package.
Help us help you
No, just wanted to propose this.