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
| Feature | How Temps handles it |
|---|---|
| Detection | Not detected; choose the Autopack (C# / .NET) preset |
| Build | dotnet publish with the .NET SDK, run on the ASP.NET Core runtime image |
| HTTPS | Let's Encrypt certificate, auto-renewed |
| Port | The PORT Temps sets (3000 unless you change the project's port), passed to --urls |
| Health checks | HTTP check on / at deploy time, or the path set in .temps.yaml |
| Zero-downtime deploys | New 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:
health:
path: /healthOnly path is used. Other health fields (status, interval, timeout, retries) are accepted but currently have no effect.
/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:
| Variable | Value | Description |
|---|---|---|
PORT | Resolved port | The port your app must listen on |
HOST | 0.0.0.0 | Bind address |
SENTRY_DSN | Auto-generated | Error tracking endpoint |
TEMPS_API_URL | Your Temps URL | Platform API endpoint |
TEMPS_API_TOKEN | Deployment token | Authentication for Temps SDKs |
OTEL_EXPORTER_OTLP_ENDPOINT | Your Temps OTLP URL | OpenTelemetry trace collection |
OTEL_SERVICE_NAME | Project name | Service 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.