Expose local HTTP, HTTPS, TCP, UDP, and other services to the internet through CloudPub — similar in spirit to ngrok-style tunnels, with a control WebSocket, protobuf protocol, and optional ASP.NET Core integration with fluent builder setup.
This repository ships two NuGet packages:
| Package | When to use |
|---|---|
| CloudPub.Client | Console apps, workers, or any .NET Standard 2.1+ library. |
| CloudPub.AspNet | ASP.NET Core apps on .NET 10+ that should auto-publish when the web host starts. |
Both packages share the root namespace CloudPub (types such as CloudPubClient, CloudPub.Options.CloudPubClientOptions).
dotnet add package CloudPub.ClientFor ASP.NET Core integration:
dotnet add package CloudPub.AspNet(CloudPub.AspNet references CloudPub.Client; you do not need to add the client package separately unless you want an explicit reference.)
The agent handshake accepts either:
- Token — set
CloudPubClientOptions.Token(e.g. from environment or user secrets), or - Email + password — set
EmailandPassword.
You can also point ServerUri at another control plane (default is https://cloudpub.ru).
using CloudPub;
using CloudPub.Options;
using CloudPub.Protocol;
CloudPubClientOptions options = new CloudPubClientOptions
{
Email = "you@example.com",
Password = "your-password",
// Or: Token = "your-token",
};
await using CloudPubClient client = new CloudPubClient(options, new CloudPubRules());
await client.ConnectAsync();
Endpoint endpoint = await client.PublishAsync(new CloudPubPublishOptions
{
Protocol = ProtocolType.Http,
Address = "8080", // localhost:8080 (or host:port, URL, etc.)
Name = "my-app",
Auth = AuthType.None,
});
Console.WriteLine($"Public URL: {endpoint.Url}");
// … keep running …
await client.UnpublishAsync(endpoint);After ConnectAsync, use the static extension methods on ICloudPubClient:
| Method | Purpose |
|---|---|
PublishAsync |
Register a new publication from CloudPubPublishOptions. |
UnpublishAsync |
Remove a publication and mark the endpoint offline. |
StopAsync |
Stop traffic without removing registration. |
CleanAsync |
Clear all publications on the account. |
ListAsync |
List current endpoints. |
| Property | Description |
|---|---|
ServerUri |
Control server (default https://cloudpub.ru). WebSocket URL is derived from this. |
Timeout |
Handshake / wait timeouts (default 30 seconds). |
ResumeEndpointsOnConnect |
When true, the transport may send EndpointStartAll after connect. |
Token |
Session token after login, or pre-provisioned token. |
Email / Password |
Account credentials for hello handshake. |
AgentId |
Stable agent id; a new GUID is used if empty. |
Hwid |
Optional hardware id string. |
ClientVersion |
Reported client version string. |
| Property | Description |
|---|---|
Protocol |
e.g. Http, Https, Tcp, Udp, Ssh, … |
Address |
Port only, host:port, path, or full URL — see XML docs on CreateCleintEndpoint. |
Name |
Friendly description stored on the endpoint. |
Auth |
Optional; defaults (e.g. Basic for WebDAV) apply when null. |
Acl, Headers, Rules |
Optional access lists, headers, and filter rules. |
The addon wires ICloudPubClient into DI and uses a fluent ICloudPubClientBuilder.
Startup and shutdown responsibilities are split:
HostedCloudPubLifetimeService: connect/publish on startup, unpublish on shutdown.HostedCloudPubLocalhostProxyService: localhost address projection intoIServerAddressesFeature.HostedCloudPubPipelineProxyService: HTTP request forwarding directly into ASP.NET pipeline.
Pick one style.
Option A — bind from configuration (recommended)
appsettings.json:
{
"CloudPub": {
"ServerUri": "https://cloudpub.ru",
"Email": "you@example.com",
"Password": "your-password"
}
}Program:
using CloudPub;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddCloudPub(builder.Configuration.GetSection("CloudPub"));Option B — inline options
builder.Services.AddCloudPub(new CloudPub.Options.CloudPubClientOptions
{
Token = builder.Configuration["CloudPub:Token"]!,
});Option C — custom factory
builder.Services.AddCloudPub(sp =>
{
CloudPub.Options.CloudPubClientOptions o = sp.GetRequiredService<IOptions<CloudPub.Options.CloudPubClientOptions>>().Value;
return new CloudPubClient(o, sp.GetRequiredService<ICloudPubRules>());
});Use the fluent builder returned by AddCloudPub(...):
builder.Services
.AddCloudPub(builder.Configuration.GetSection("CloudPub"))
.AddEndpoint(5000, "My API")
.AddEndpoint(new CloudPub.Options.CloudPubPublishOptions
{
Protocol = CloudPub.Protocol.ProtocolType.Https,
Address = "5001",
Name = "Secure API",
})
.WithLocalhostProxy();WithLocalhostProxy() and WithPipelineProxy() are mutually exclusive.
Use WebApplication extension method OnCloudPubStarted and OnCloudPubStopped
WebApplication app = builder.Build();
app.OnCloudPubStarted(ctx =>
{
Endpoint endpoint = ctx.PublishedEndpoints.FirstOrDefault()
?? throw new InvalidOperationException("No endpoints found");
telegramBotClient.RemapWebhook(endpoint.Url + "telegram/");
});
app.Run();using CloudPub;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services
.AddCloudPub(builder.Configuration.GetSection("CloudPub"))
.AddEndpoint(5000, "Sample site")
.WithPipelineProxy();
WebApplication app = builder.Build();
app.MapGet("/", () => "Hello from CloudPub!");
app.Run();Requirements: a server that exposes IServerAddressesFeature (Kestrel does). The hosted service throws at startup if the feature is missing.
The solution includes CloudPub.Example: a CLI-style app with argument parsing and commands:
listpublish --address <addr> --protocol <proto> [--name <text>] [--auth <mode>] [--wait]publish-http <port> [--wait](shortcut)stop --guid <guid>unpublish --guid <guid>clean
It reads auth settings from CLOUDPUB_* variables or explicit CLI options (--token, --email, --password, --server).
Examples:
set CLOUDPUB_EMAIL=you@example.com
set CLOUDPUB_PASSWORD=secret
dotnet run --project src/CloudPub.Example/CloudPub.Example.csproj -- list
dotnet run --project src/CloudPub.Example/CloudPub.Example.csproj -- publish --protocol tcp --address 127.0.0.1:25565 --name "Minecraft"
dotnet run --project src/CloudPub.Example/CloudPub.Example.csproj -- publish-http 8080 --wait(Use CLOUDPUB_TOKEN instead of email/password if you prefer.)
git clone <repository-url>
cd CloudPub.Client
dotnet build CloudPub.Sdk.slnx -c ReleasePackages are emitted under bin/Release/ when GeneratePackageOnBuild is enabled.
- Repository: see the package metadata (e.g.
RepositoryUrlin the.csprojfiles). - License: see the
LICENSEfile bundled with the package.
For API details, open the XML documentation shipped with each package or browse the /// comments in the source.