Deploy .NET on Temps

Choose the Autopack (C# / .NET) preset (nixpacks-csharp) and run up: Temps publishes your web project with the .NET SDK and runs it on the ASP.NET Core runtime image, listening on $PORT behind automatic HTTPS. No Dockerfile is needed.

This guide describes how the nightly release channel builds your app, using the Autopack builder. Beta (v0.1.0-beta.56) also builds with Autopack, but some details below may differ. Earlier releases and the stable channel build with Nixpacks and behave differently. To run nightly, see Release channels.

Every framework and the preset it needs is listed under Supported platforms. The Java and Go guides cover the other compiled backends.


Quickstart

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

npx @temps-sdk/cli up --preset nixpacks-csharp

Temps doesn't detect .NET projects from a .csproj, so choose the Autopack (C# / .NET) preset (nixpacks-csharp), as above or under Project → Settings → Build & deploy → Build → Framework. Your app is live with HTTPS in a few minutes.

Temps runs dotnet restore and dotnet publish -c Release on mcr.microsoft.com/dotnet/sdk, then starts the app with dotnet <assembly>.dll --urls http://0.0.0.0:$PORT on mcr.microsoft.com/dotnet/aspnet. The image tag comes from <TargetFramework> in your project file (net10.0 uses 10.0), and defaults to 8.0 when it can't be read. .NET 8 and .NET 9 reach end of support on 10 November 2026, so target net10.0 (LTS, supported until November 2028) for new apps. A web: line in a Procfile replaces the start command.

If the repository has several .csproj or .fsproj files, exactly one of them must be a web project (Sdk="Microsoft.NET.Sdk.Web"). That's the one Temps publishes; otherwise the build stops and asks you to choose.


What Temps handles automatically

FeatureHow Temps handles it
DetectionNot detected; choose the Autopack (C# / .NET) preset
Builddotnet publish with the .NET SDK, run on the ASP.NET Core runtime image
HTTPSLet's Encrypt certificate, auto-renewed
PortThe PORT Temps sets (3000 unless you change the project's port), passed to --urls
Health checksHTTP check on / at deploy time, or the path set in .temps.yaml
Zero-downtime deploysNew container starts before old one stops

Minimal API

A minimal ASP.NET Core application. With the Autopack preset, the --urls argument already makes it listen on PORT; the UseUrls line keeps it working when you run it another way, such as from your own Dockerfile:

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>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

Managed PostgreSQL

Create a PostgreSQL service under Databases → Create database and link it from your project's Databases page. Temps injects POSTGRES_URL as a postgresql:// URL, which Npgsql doesn't accept as a connection string, so build the connection string from the individual variables Temps also injects:

Program.cs

var connectionString =
    $"Host={Environment.GetEnvironmentVariable("POSTGRES_HOST")};" +
    $"Port={Environment.GetEnvironmentVariable("POSTGRES_PORT")};" +
    $"Database={Environment.GetEnvironmentVariable("POSTGRES_DB")};" +
    $"Username={Environment.GetEnvironmentVariable("POSTGRES_USER")};" +
    $"Password={Environment.GetEnvironmentVariable("POSTGRES_PASSWORD")}";

builder.Services.AddDbContext<AppDbContext>(options => options.UseNpgsql(connectionString));

Temps doesn't run EF Core migrations for you. Apply them as a one-off step after a deploy that changes the schema, not in the start command, where several replicas could run them at once. See Deploy with a Database.


Custom Dockerfile

A custom Dockerfile gives you full control over the build and runtime images. The multi-stage build below compiles with the SDK image and runs on the smaller aspnet runtime image.

Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:10.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:10.0-alpine
WORKDIR /app
COPY --from=build /out .

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

This Dockerfile's app listens on 8080, so set the project's port to 8080 under Project → Settings → Build & deploy → Deploy. Temps then sets PORT to 8080 as well. 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) by default
  • Success: 2 consecutive responses with a 2xx, 3xx, 404 or 405 status code
  • Timeout: 300 seconds (5 minutes) for the app to become healthy, fixed in v0.1.0-beta.56. If the app answers with error responses (other 4xx, or 5xx) for 60 seconds in a row, the deployment fails sooner. From the next release the timeout is configurable from 30 to 3600 seconds under Project → Settings → Build & deploy
  • Retry interval: 2 seconds between successful checks, 5 seconds after an error response or a failed connection

Connection errors and other 4xx or 5xx responses are retried until the timeout; if the app hasn't passed by then, the deployment fails. The check runs once, at deploy time. To check a different path, add a .temps.yaml to your repository root:

.temps.yaml
health:
  path: /health

Only path is used. Other health fields (status, interval, timeout, retries) are accepted but currently have no effect.

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

Last updated

Was this page helpful?