Saltar al contenido principal

.NET

Kubiy ejecuta aplicaciones .NET usando systemd como process manager. El proceso de deploy compila y publica la aplicación en el servidor, o ejecuta una DLL o binario ya compilado.

Presets disponibles

auto/publish (recomendado)

Kubiy detecta automáticamente el archivo .csproj en el proyecto, ejecuta dotnet publish y luego inicia la aplicación publicada.

ParámetroValor
startModeauto
TargetDetectado automáticamente
Build por defectodotnet publish automático

Este preset es el recomendado para la mayoría de proyectos. No requiere que conozcas el nombre exacto del .csproj o la DLL resultante.

Ejemplo de configuración:

Preset: auto/publish

dotnet [dll]

Ejecuta una DLL ya compilada. Úsalo si haces el build en CI/CD y subes el output ya compilado al repositorio, o si publicas manualmente.

ParámetroValor
startModedll
TargetRuta a la DLL (ej: publish/MiApp.dll)

Ejemplo de configuración:

Preset: dotnet [dll]
Target: bin/Release/net8.0/MiApp.dll
aviso

Si usas este modo y subes código fuente (no el binario compilado), debes compilar primero usando el Build Command. Ver Build Command.

dotnet run

Modo de desarrollo. Compila y ejecuta la aplicación directamente desde el código fuente con dotnet run.

ParámetroValor
startModedotnetrun
TargetDirectorio del proyecto (por defecto la raíz)

:::warning Uso en producción dotnet run no está optimizado para producción. Tarda más en iniciar y no aplica las optimizaciones de dotnet publish. Úsalo solo para testing o demos. :::

bin (binario self-contained)

Ejecuta un binario self-contained publicado con --self-contained true. No requiere que el runtime de .NET esté instalado en el servidor.

ParámetroValor
startModebin
TargetRuta al binario ejecutable

Ejemplo de configuración:

Preset: bin
Target: publish/MiApp
Build Command: dotnet publish -c Release --self-contained true -r linux-x64 -o publish

Puerto

Kubiy configura automáticamente la variable ASPNETCORE_URLS con el valor:

http://127.0.0.1:{PORT}

Tu aplicación ASP.NET Core usará esta variable automáticamente para saber en qué puerto y dirección escuchar. No necesitas configurarlo explícitamente.

El puerto por defecto es 5000.

consejo

Si tu app usa app.UseHttpsRedirection() y el health check falla, verifica que la app no intenta redirigir la petición HTTP a HTTPS. Kubiy usa HTTP para el health check interno.

ASPNETCORE_URLS y configuración

Para aplicaciones que no usan la detección automática de ASPNETCORE_URLS, puedes leer el puerto explícitamente:

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

O en appsettings.json (no recomendado para producción — usa variables de entorno):

{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://0.0.0.0:5000"
}
}
}
}

Build Command

El campo Build Command en .NET funciona como un pre-build hook: se ejecuta antes del dotnet publish automático.

Esto significa que puedes usarlo para:

  • Restaurar paquetes NuGet adicionales
  • Generar código (Entity Framework migrations, OpenAPI clients, etc.)
  • Ejecutar scripts de preparación
# Restaurar herramientas dotnet
dotnet tool restore

# Generar migrations de EF Core antes del publish
dotnet ef migrations bundle --self-contained -r linux-x64

# Instalar herramientas y generar código
dotnet tool restore && dotnet ef dbcontext scaffold ...

:::warning Diferencia con otros runtimes En .NET, el Build Command es un hook previo al publish, no un reemplazo. El dotnet publish siempre se ejecuta después. Si quieres controlar completamente el proceso de build, usa el preset dotnet [dll] o bin y haz el publish explícitamente en el Build Command. :::

Ver la referencia completa de Build Command.

Casos de uso comunes

ASP.NET Core Web API

// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();

var app = builder.Build();
app.MapControllers();

// Health check endpoint
app.MapGet("/health", () => Results.Ok(new { status = "ok" }));

app.Run();

Configuración en Kubiy:

Preset: auto/publish
Health: /health

Minimal API

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/health", () => new { status = "ok" });
app.MapGet("/api/hello", () => new { message = "Hello World" });

app.Run();

Configuración en Kubiy:

Preset: auto/publish
Health: /health

Con Entity Framework Core migrations

Si necesitas aplicar migrations antes de que la app inicie, puedes hacerlo en el Build Command o en el startup de la app. El enfoque más robusto es aplicar migrations en el startup:

// Program.cs
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await db.Database.MigrateAsync();
}

Monorepo con múltiples proyectos

Si tu repositorio tiene varios proyectos .NET y quieres desplegar uno específico:

.
├── src/
│ ├── Api/
│ │ ├── Api.csproj
│ │ └── Program.cs
│ └── Worker/
│ └── Worker.csproj
└── MiSolucion.sln

Configuración en Kubiy:

Subdirectorio: src/Api
Preset: auto/publish

Proyecto con múltiples .csproj

Si tu proyecto tiene múltiples .csproj en el mismo directorio y la detección automática elige el equivocado, especifica el proyecto explícitamente en el Build Command:

dotnet publish src/Api/Api.csproj -c Release

Y usa el preset dotnet [dll]:

Preset: dotnet [dll]
Target: src/Api/bin/Release/net8.0/publish/Api.dll
Build Command: dotnet publish src/Api/Api.csproj -c Release

Variables de entorno disponibles

VariableDescripción
PORTPuerto asignado (default 5000)
APP_PORTAlias de PORT
ASPNETCORE_URLSConfigurado automáticamente a http://127.0.0.1:{PORT}
ASPNETCORE_ENVIRONMENTNo se configura automáticamente — agrégala si necesitas Production
KUBIY_DEPLOY_IDID del deploy actual
KUBIY_APP_IDID de la aplicación
consejo

Agrega ASPNETCORE_ENVIRONMENT=Production en las variables de entorno de tu app para activar los comportamientos de producción de ASP.NET Core (sin developer exception page, sin hot reload, etc.).

Lectura de variables en C#:

var dbUrl = Environment.GetEnvironmentVariable("DATABASE_URL");
var apiKey = builder.Configuration["API_KEY"]; // también accesible vía IConfiguration

Health Check recomendado

ASP.NET Core tiene soporte nativo para health checks:

// Program.cs
builder.Services.AddHealthChecks();

// ...

app.MapHealthChecks("/health");

O con un endpoint simple:

app.MapGet("/health", () => Results.Ok(new { status = "ok", timestamp = DateTime.UtcNow }));

Configura en Kubiy:

Health Check Path: /health

Troubleshooting

La detección automática de .csproj falla

Si tienes múltiples .csproj en el directorio o la estructura no es estándar, usa el subdirectorio para apuntar al directorio correcto, o usa el preset dotnet [dll] con un Build Command explícito.

"Could not find a part of the path" al publicar

El directorio de output del publish no existe. El dotnet publish lo crea automáticamente, pero si usas un Build Command que mueve archivos, asegúrate de que el directorio destino exista.

La app inicia pero no acepta conexiones externas

Verifica que la app no está escuchando solo en localhost. Con el preset auto/publish, Kubiy configura ASPNETCORE_URLS=http://127.0.0.1:{PORT} — esto es suficiente porque el proxy inverso de Kubiy está en el mismo host.

Si la app tiene configuración hardcodeada de URLs, puede estar sobreescribiendo ASPNETCORE_URLS. Revisa launchSettings.json y appsettings.json.

Redirección HTTPS hace fallar el health check

Si app.UseHttpsRedirection() está activo, el health check de Kubiy (HTTP) recibirá un redirect 301/302 y no lo considerará exitoso. Opciones:

  1. Desactiva UseHttpsRedirection() para el endpoint de health (configura la redirección solo para rutas específicas)
  2. O usa un middleware que excluya el path de health del redirect:
app.Use(async (context, next) =>
{
if (context.Request.Path.StartsWithSegments("/health"))
{
await next();
return;
}
// resto del pipeline
await next();
});

app.UseHttpsRedirection();

Timeout en publish para proyectos grandes

Si el dotnet publish tarda mucho, considera:

  1. Usar .dockerignore o .gitignore para no subir archivos innecesarios al repo
  2. Compilar en modo --no-restore si las dependencias NuGet no cambian frecuentemente (agrega dotnet restore en el Build Command primero)