![]() |
VOOZH | about |
dotnet add package AppPipe.Hosting --version 2.0.5
NuGet\Install-Package AppPipe.Hosting -Version 2.0.5
<PackageReference Include="AppPipe.Hosting" Version="2.0.5" />
<PackageVersion Include="AppPipe.Hosting" Version="2.0.5" />Directory.Packages.props
<PackageReference Include="AppPipe.Hosting" />Project file
paket add AppPipe.Hosting --version 2.0.5
#r "nuget: AppPipe.Hosting, 2.0.5"
#:package AppPipe.Hosting@2.0.5
#addin nuget:?package=AppPipe.Hosting&version=2.0.5Install as a Cake Addin
#tool nuget:?package=AppPipe.Hosting&version=2.0.5Install as a Cake Tool
👁 NuGet Version
👁 NuGet Downloads
👁 License
AppPipe is a lightweight, zero-container-dependency alternative to the .NET Aspire dashboard and gateway runner.
While .NET Aspire is highly optimized for cloud-first deployments and relies heavily on local Docker/container runtimes, AppPipe is built specifically for traditional virtual machines, bare-metal servers, and on-premises environments across Windows (IIS / Windows Services), Linux (systemd / Nginx / Caddy), and macOS.
With AppPipe, you get a beautiful, unified developer dashboard, OpenTelemetry (OTLP) collection, and service discovery routing without the container dependencies or cloud-only overhead.
ModularPipelines to automate publishing, creating Windows AppPools, registering IIS sub-applications, setting up Linux systemd units, and generating Nginx/Caddy configurations.For an in-depth dive into how AppPipe works under the hood and how to configure it for production deployment, refer to the .
It covers:
.WithEndpoint(), .WithAppPool(), .WithServiceAccount(), .WithReference(), and other builder methods.--prepublished-dir to deploy pre-compiled DLLs directly via GitHub Actions or Azure DevOps pipelines without requiring the .NET SDK on the target server.graph LR
%% Styles
classDef client fill:#f97316,stroke:#ea580c,stroke-width:2px,color:#fff;
classDef gateway fill:#0284c7,stroke:#0369a1,stroke-width:2px,color:#fff;
classDef service fill:#10b981,stroke:#047857,stroke-width:2px,color:#fff;
classDef telemetry fill:#8b5cf6,stroke:#6d28d9,stroke-width:2px,color:#fff;
classDef store fill:#6366f1,stroke:#4f46e5,stroke-width:2px,color:#fff;
classDef dashboard fill:#ec4899,stroke:#db2777,stroke-width:2px,color:#fff;
Client[Browser / API Client]:::client
subgraph AppPipeHost ["AppPipe Host Application"]
Gateway[YARP Gateway Proxy]:::gateway
TelemetryPort[Telemetry gRPC Port]:::telemetry
Store[(In-Memory Store)]:::store
Dashboard[Dashboard UI]:::dashboard
TelemetryPort -->|Write| Store
Store -->|Read| Dashboard
end
subgraph Microservices ["User Microservices Space"]
ServiceA[Microservice A]:::service
ServiceB[Microservice B]:::service
end
%% Request Routing Flow
Client -->|1. HTTP Request| Gateway
Gateway -->|2. Route proxy| ServiceA
Gateway -->|2. Route proxy| ServiceB
%% Telemetry Flow
ServiceA -.->|3. OTLP Traces/Logs/Metrics| TelemetryPort
ServiceB -.->|3. OTLP Traces/Logs/Metrics| TelemetryPort
To add the library to an existing project:
dotnet add package AppPipe.Hosting
AppPipe provides a custom .NET template pack that scaffolds a fully working multi-project solution structure out of the box (including the AppHost orchestrator, an ApiService backend, and a Web frontend):
dotnet new install AppPipe.Hosting.Templates
Create a new directory for your microservices solution and run:
dotnet new app-pipe -n MySystem
This generates:
MySystem.sln: The Visual Studio solution file.MySystem.AppHost: The AppPipe orchestrator and gateway dashboard.MySystem.ApiService: A backend REST API configured with OpenTelemetry.MySystem.Web: A frontend web application that calls the backend using dynamic service discovery.When scaffolding with dotnet new app-pipe, you can customize your architecture, frontend, database, auth, and caching options:
| Parameter | Choice Option | Default | Description |
|---|---|---|---|
-ar, --architecture |
simple, clean-cqrs |
simple |
Choose simple for a Minimal API structure, or clean-cqrs for a Clean Architecture layered solution. |
-da, --database |
none, sqlite, postgresql, sqlserver |
none |
Configures Entity Framework Core DB context persistence. |
-f, --frontend |
blazor, htmx |
blazor |
Scaffolds either a Blazor Server SSR UI or Razor Pages + HTMX UI, styled with a premium Outfit theme. |
-au, --auth |
none, jwt |
none |
Configures JWT Bearer authentication validation middleware and token generation endpoints. |
-c, --caching |
none, redis |
none |
Configures Redis distributed caching in command/query handlers. |
For example, to scaffold a full production CQRS architecture with a Blazor frontend, SQLite database, secure JWT authorization, and Redis caching:
dotnet new app-pipe -n MySystem --architecture clean-cqrs --database sqlite --auth jwt --caching redis
If you already have an existing .NET microservices solution and want to add AppPipe orchestration, dashboarding, and telemetry, follow these steps:
Add a new empty .NET Console or Web application project named YourSolution.AppHost to your existing solution:
dotnet new web -n YourSolution.AppHost
AppPipe.Hosting package to the new AppHost project:
dotnet add YourSolution.AppHost/YourSolution.AppHost.csproj package AppPipe.Hosting
dotnet add YourSolution.AppHost/YourSolution.AppHost.csproj reference YourExisting.Backend/YourExisting.Backend.csproj
dotnet add YourSolution.AppHost/YourSolution.AppHost.csproj reference YourExisting.Frontend/YourExisting.Frontend.csproj
Replace the contents of Program.cs in the YourSolution.AppHost project with:
using AppPipe.Hosting;
var builder = AppPipeHostingApp.CreateBuilder(args);
// Register your referenced projects:
// Note: AppPipe automatically generates compile-safe constants for your projects
// (e.g. AppPipeProjects.YourExisting_Backend) during compilation!
var backend = builder.AddProject(AppPipeProjects.YourExisting_Backend)
.WithEndpoint(5001); // Assign an entry endpoint port
var frontend = builder.AddProject(AppPipeProjects.YourExisting_Frontend)
.WithEndpoint(5002)
.WithReference(backend); // Automatically injects discovery environment variables
var app = builder.Build();
// Run the local orchestrator and OTLP collector
var runner = new AppPipeDevHostRunner(app);
await runner.RunAsync();
In each of your child microservices, add OpenTelemetry OTLP exporters. AppPipe automatically injects the OTLP telemetry ports and service discovery variables as environment values into your processes at run-time:
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
Program.cs:
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddAspNetCoreInstrumentation()
.AddOtlpExporter()) // Automatically picks up AppPipe gRPC port
.WithMetrics(metrics => metrics
.AddAspNetCoreInstrumentation()
.AddOtlpExporter()); // Automatically picks up AppPipe gRPC port
Configure your services and their relationships in your entry point:
using AppPipe.Hosting;
var builder = AppPipeHostingApp.CreateBuilder(args);
// Define a backend worker microservice using compile-safe generated constant
var backend = builder.AddProject(AppPipeProjects.BackendWorker);
// Or register directly using raw string name:
// var backend = builder.AddProject("BackendWorker");
// Define a frontend API that communicates with the backend
var frontend = builder.AddProject(AppPipeProjects.FrontendApi)
.WithReference(backend); // Injects service discovery variables automatically
var app = builder.Build();
// Run the host using AppPipeDevHostRunner
var runner = new AppPipeDevHostRunner(app);
await runner.RunAsync();
In your microservices, register the standard OpenTelemetry exporter. They will automatically detect the telemetry endpoints exposed by the AppPipe Gateway.
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter()) // Exports to AppPipe telemetry port
.WithMetrics(metrics => metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter());
You must start the AppHost project (e.g. MySystem.AppHost) — not one of your individual microservices.
Once the AppHost is running, open your browser and navigate to:
http://localhost:7001/dashboard
The dashboard port 7001 is the default gateway port. If you have changed it in your appsettings.json, use the port you configured instead.
| Page | URL | Description |
|---|---|---|
| Resources | /dashboard |
Service health, latency percentiles (P50/P95/P99), error rates, and data retention |
| Console Logs | /logs |
Structured logs grouped by service with severity filters, full-text search, and CSV export |
| Traces | /traces |
Distributed traces with waterfall timeline, correlated logs, and slow-trace detection |
| Metrics | /metrics |
Live metric charts grouped by service with min/max/avg aggregation |
| Service Map | /service-map |
SVG dependency graph showing service-to-service call flows |
If you used the AppPipe template:
# In Visual Studio — set the AppHost project as the startup project and press F5
# Or via CLI:
cd MySystem.AppHost
dotnet run
Then open http://localhost:7001/dashboard in your browser.
You can customize the dashboard, security, and persistence behavior in your appsettings.json or environment variables:
{
"Dashboard": {
"UseWebSockets": false,
"BasicAuth": {
"Enabled": true,
"Username": "admin",
"Password": "MySecretPassword"
}
},
"Telemetry": {
"PersistenceEnabled": true,
"DatabasePath": "telemetry.db",
"MaxDbRecords": 2000
}
}
| Key | Type | Default | Description |
|---|---|---|---|
Dashboard:UseWebSockets |
bool |
false |
Controls live push-updates: when true, the dashboard subscribes to OnTelemetryReceived events and updates in real time without polling. The dashboard is always fully interactive regardless of this setting. |
Dashboard:BasicAuth:Enabled |
bool |
false |
Set to true to enable Basic Authentication protection for the dashboard and diagnostics. |
Dashboard:BasicAuth:Username |
string |
null |
The username required to log in when Basic Authentication is enabled. |
Dashboard:BasicAuth:Password |
string |
null |
The password required to log in when Basic Authentication is enabled. |
Telemetry:PersistenceEnabled |
bool |
true |
Set to true to enable SQLite telemetry database persistence. Set to false for purely in-memory buffer. |
Telemetry:DatabasePath |
string |
telemetry.db |
The path to the persistent SQLite database file. |
Telemetry:MaxDbRecords |
int |
2000 |
Limits database rows retained per telemetry type. |
AppPipe:UseGatewayUrls |
bool |
null |
If true, the dashboard displays links routed through the reverse proxy gateway. If false, displays direct process port links. When null, automatically defaults to true in production/staging environments, and false in development environments. |
AppPipe:Endpoints:{Resource} |
string |
null |
Explicitly overrides a specific resource's dashboard link to use a manual URL (e.g. AppPipe:Endpoints:BackendWorker = "http://backend.internal:5001"). |
AppPipe's gateway binds natively to standard .NET configuration under the "ReverseProxy" section. You can define custom routes, clusters, HTTP request properties, rate-limiting, and transforms inside your appsettings.json, or programmatically configure them using .ConfigureGateway() in Program.cs.
For a complete guide, step-by-step code samples, and auto-generated routing details, see the .
To support various environments and multi-server topologies, the dashboard dynamically computes absolute URLs for registered microservices on the server side:
Development or LocalDev as local debugging sessions, outputting direct Kestrel ports (e.g., http://localhost:5001) to bypass gateways."Default Web Site"), resolving sub-application paths automatically: scheme://Request.Host{AppPath}.scheme://Request.Host.Host:{AssignedPort}.AppPipe:Endpoints:{Resource}) or force gateway URLs using AppPipe:UseGatewayUrls.For detailed information, see the .
By default, AppPipe persists logs, traces, and metrics in a local SQLite database (). This provides zero-configuration persistence out of the box.
However, SQLite is strictly a default option. AppPipe is fully database-agnostic. You can easily configure it to run entirely in-memory (using a ring buffer) or persist to enterprise databases like PostgreSQL, ClickHouse, SQL Server, MySQL, or Elasticsearch by implementing the interface and registering it:
builder.ConfigureGateway(gatewayBuilder =>
{
// Override the default SQLite persistence with your custom store
gatewayBuilder.Services.AddSingleton<ITelemetryStore, ClickHouseTelemetryStore>();
});
To run purely in-memory, set Telemetry:PersistenceEnabled to false in your appsettings.json.
For details and step-by-step code examples, see the .
AppPipe includes a built-in deployment module utilizing ModularPipelines to automate publishing and deployments directly to IIS, Windows Services, or Linux systemd.
You can configure environment-specific settings (such as custom IIS AppPools, sites, display names, startup accounts, and hosting models) directly in your orchestrator topology configuration:
var backend = builder.AddProject("BackendWorker")
// IIS & Linux Reverse Proxy Settings
.WithAppPool("CustomBackendPool")
.WithIISSite("Default Web Site")
.WithAppPath("/backend") // Custom path (IIS virtual path, Nginx location, or Caddy handle_path)
.WithHostingModel("OutOfProcess") // "InProcess" or "OutOfProcess"
// Windows Service / systemd Settings
.WithServiceDisplayName("AppPipe Backend Worker Service")
.WithServiceDescription("AppPipe backend processing service runs tasks.")
.WithServiceStartType("auto") // "auto", "demand", or "disabled"
.WithServiceAccount(@"DOMAIN\user")
.WithServicePassword("secret_password");
The dashboard itself is represented as builder.HostProject (an instance of AppPipeHostingProjectResource) and can be named and configured just like any other microservice:
// Set a custom dashboard application name (used for SCM Service name)
builder.HostProject = new AppPipeHostingProjectResource("AppPipeDashboard", "");
// Configure the dashboard options fluently
builder.HostProject.WithEndpoint(7001)
.WithIISSite("Default Web Site")
.WithAppPath("/") // Deployed directly at the root '/' of the site/proxy
.WithAppPool("AppPipeDashboardPool")
.WithServiceDisplayName("AppPipe Dashboard Orchestrator")
.WithServiceDescription("AppPipe gateway and diagnostic telemetry UI.");
To deploy the gateway and microservices directly from your development machine:
# Deploy to IIS under a custom sub-path
dotnet run --project YourDevHost.csproj -- --deploy iis /app-pipe-host-test
# Deploy as Windows Services
dotnet run --project YourDevHost.csproj -- --deploy windows-service
In a typical CI/CD pipeline, the build agent compiles the code (creating DLL artifacts), and the release agent downloads the pre-compiled files onto the target environment where no source code or .csproj files exist.
AppPipe supports this via the --prepublished-dir flag and configuration binding.
Compile and publish your projects into a target directory (e.g. ./publish):
# Publish DevHost (Orchestrator) and child projects
dotnet publish samples/AppPipe.DevHost/AppPipe.DevHost.csproj -c Release -o ./publish/AppPipe.DevHost
dotnet publish samples/BackendWorker/BackendWorker.csproj -c Release -o ./publish/BackendWorker
dotnet publish samples/FrontendApi/FrontendApi.csproj -c Release -o ./publish/FrontendApi
Upload the ./publish directory as a build artifact.
Download the published artifact to the target server and execute the orchestrator pointing to the pre-compiled folder. This completely bypasses source code compilation and .csproj file searches:
dotnet C:\inetpub\apps\AppPipe\AppPipe.DevHost.dll --deploy iis --prepublished-dir C:\inetpub\apps\AppPipe
To avoid hardcoding values (like AppPool names, Service Accounts, or database passwords) in Program.cs, bind your orchestrator to .NET configuration (IConfiguration):
// Program.cs
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddEnvironmentVariables(prefix: "APPIPE__")
.AddCommandLine(args)
.Build();
var appPool = config["BackendWorker:AppPoolName"] ?? "DefaultPool";
var password = config["BackendWorker:ServicePassword"]; // Read securely
builder.AddProject("BackendWorker")
.WithAppPool(appPool)
.WithServiceAccount(@"DOMAIN\ServiceAccount")
.WithServicePassword(password);
APPIPE__:
APPIPE__BackendWorker__AppPoolName $\rightarrow$ ProductionPoolAPPIPE__BackendWorker__ServicePassword $\rightarrow$ $(SecretServicePasswordValue)dotnet AppPipe.DevHost.dll --deploy iis --prepublished-dir C:\inetpub\apps\AppPipe --BackendWorker:AppPoolName "ProductionPool" --BackendWorker:ServicePassword "$(SecretServicePasswordValue)"
This section guides developers on how to work inside the AppPipe.Hosting repository, compile the projects, run sample environments, and package/test NuGet templates.
AppPipe.Hosting/: Core library (Razor Pages pages, YARP configuration, OTLP listener, SQLite store, process manager).templates/AppPipeSystemTemplate/: Scaffolding source code packaged as .NET templates.samples/: Test projects (AppPipe.DevHost, BackendWorker, FrontendApi) used to test the gateway runner and telemetry collection.tests/: Unit and integration test suites.To launch the developer sample environment locally (runs on Windows, Linux, and macOS):
# Navigate to the DevHost project
cd samples/AppPipe.DevHost
# Start the DevHost orchestrator
dotnet run
This command compiles and launches the gateway proxy, boots the microservices on dynamic local ports, registers them, and configures OTLP telemetry back to the dashboard at http://localhost:7001/dashboard.
You can pack the AppPipe gateway library and its templates pack locally using the standard .NET CLI:
# Build the solution in Release mode
dotnet build -c Release
# Pack the core hosting library (generates AppPipe.Hosting.<version>.nupkg in bin/Release)
dotnet pack AppPipe.Hosting/AppPipe.Hosting.csproj -c Release
# Pack the template pack (generates AppPipe.Hosting.Templates.<version>.nupkg)
dotnet pack AppPipe.Hosting.Templates.csproj -c Release
To verify template edits locally before uploading to NuGet:
# Register the templates pack from the local folder
dotnet new install templates/AppPipeSystemTemplate
# Check that app-pipe template is listed
dotnet new list app-pipe
# Test scaffolding in a clean folder
mkdir MyTestSystem
cd MyTestSystem
dotnet new app-pipe -n MyTestSystem
This project is licensed under the MIT License - see the file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.5 | 40 | 6/28/2026 |
| 2.0.4 | 45 | 6/28/2026 |
| 2.0.3 | 50 | 6/28/2026 |
| 2.0.2 | 37 | 6/28/2026 |
| 2.0.1 | 39 | 6/28/2026 |
| 2.0.0 | 41 | 6/28/2026 |
| 1.7.0 | 46 | 6/27/2026 |
| 1.6.9 | 45 | 6/27/2026 |
| 1.6.7 | 46 | 6/27/2026 |
| 1.6.6 | 41 | 6/27/2026 |
| 1.6.5 | 51 | 6/27/2026 |
| 1.6.4 | 44 | 6/27/2026 |
| 1.6.3 | 46 | 6/27/2026 |
| 1.6.2 | 51 | 6/27/2026 |
| 1.6.1 | 45 | 6/27/2026 |
| 1.6.0 | 42 | 6/27/2026 |
| 1.5.8 | 44 | 6/27/2026 |
| 1.5.7 | 47 | 6/27/2026 |
| 1.5.4 | 46 | 6/27/2026 |
| 1.5.3 | 52 | 6/27/2026 |