Deploy .NET on Your Own Server

Deploy ASP.NET Core and C# applications with automatic HTTPS and managed databases. A .csproj is not a detection signal, so select the nixpacks-csharp preset (or nixpacks) on the project — Nixpacks then builds it and runs it in a minimal runtime image.


Quickstart

From your project root, deploy with your preferred package manager:

npx @temps-sdk/cli up

With the nixpacks-csharp preset set on the project, Nixpacks recognises your .csproj files and builds the project. Your app is live with HTTPS in a few minutes. Without a preset the build stops with "Could not auto-detect project type from files", since .csproj is not one of the signals Temps scans for.


What Temps handles automatically

FeatureHow Temps handles it
Detection.csproj in the project directory
Build.NET SDK via Nixpacks
HTTPSLet's Encrypt certificate, auto-renewed
PortPORT env var injected, defaults to 8080
Health checksHTTP health check on /
Zero-downtime deploysNew container starts before old one stops

Minimal API

A minimal ASP.NET Core application that reads the port from the environment:

Program.cs

var builder = WebApplication.CreateBuilder(args);

var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
builder.WebHost.UseUrls($"http://0.0.0.0:{port}");

var app = builder.Build();

app.MapGet("/", () => new { message = "Hello from .NET", status = "healthy" });
app.MapGet("/health", () => new { status = "ok" });

app.Run();

MyApp.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

Custom Dockerfile

For production deployments, a custom Dockerfile gives you control over the SDK version and runtime image. The aspnet runtime image is much smaller than the sdk image, so the multi-stage build uses the SDK for compilation and the runtime for execution.

Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
WORKDIR /app
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /out

FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine
WORKDIR /app
COPY --from=build /out .

EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApp.dll"]

A Dockerfile in your repository root always takes priority over auto-detection. See the Custom Dockerfile guide for build args, caching, and more.


Platform behavior

These rules apply to every app deployed on Temps, regardless of framework.

The one requirement: your app must listen on the port in the PORT environment variable and bind to 0.0.0.0 — not localhost or 127.0.0.1. Temps runs your app in a container and routes traffic from the host, so an app bound to localhost only accepts connections from inside the container and will fail its health check.

Health checks

After your container starts, Temps sends HTTP GET requests to verify it is healthy before routing traffic to it.

  • Path: / (the root of your application)
  • Success: 2 consecutive responses with a 2xx or 3xx status code
  • Timeout: 300 seconds (5 minutes) for the app to become healthy
  • Retry interval: every 5 seconds

Connection errors while the app is still starting are retried without penalty. If the app returns 4xx or 5xx errors for 60 consecutive seconds, the deployment fails. Customize the check by adding a .temps.yaml to your repository root:

.temps.yaml
health:
  path: /health
  status: 200
  interval: 30
  timeout: 5
  retries: 3
Add a dedicated /health endpoint that returns a simple 200. This avoids issues where / requires authentication or returns a redirect.

Auto-injected environment variables

Temps injects these variables into every deployment automatically:

VariableValueDescription
PORTResolved portThe port your app must listen on
HOST0.0.0.0Bind address
SENTRY_DSNAuto-generatedError tracking endpoint
TEMPS_API_URLYour Temps URLPlatform API endpoint
TEMPS_API_TOKENDeployment tokenAuthentication for Temps SDKs
OTEL_EXPORTER_OTLP_ENDPOINTYour Temps OTLP URLOpenTelemetry trace collection
OTEL_SERVICE_NAMEProject nameService identifier for traces

You do not need to configure these manually. They are available in process.env (Node.js), os.environ (Python), os.Getenv (Go), and the equivalent in other languages.


Next Steps

Was this page helpful?