En esta guía vamos a instalar NGINX como proxy reverso y como server de core net el servicio kestrel; antes repasemos las piezas que vamos a usar:

Nginx ​es un servidor web/proxy inverso ligero de alto rendimiento y un proxy para protocolos de correo electrónico.​​ Es software libre y de código abierto, licenciado bajo la Licencia BSD simplificada. Nginx es ampliamente utilizado, por ser muy configurable, ligero en consumo de recursos y rápido.

Kestrel es el servidor web multi-plataforma que creo Microsoft y que sirve para albergar las aplicaciones web creadas con ASP.NET Core y dotarlas de manera sencilla de la infraestructura para poder ejecutarse.

Porque usamos Nginx? Kestrel es ideal para servir contenido dinámico desde ASP.NET Core. Sin embargo, las capacidades de servicio web no son tan ricas en características como servidores como IIS, Apache o Nginx (MS, ya posee IIS y no tiene interez en crear uno nuevo y libre). Un servidor proxy inverso puede servir contenido estático, solicitudes de almacenamiento en caché, solicitudes de compresión y conexión HTTPS desde el servidor HTTP.

Aquí una imagen que gráfica lo que antes intento explicar:

Image

Nginx me permite atender las solicitudes http de los clientes y este redirigirlas a los contenedores que van a servir la solución. Es deducible y cabe destacar que nginx puede manejar distintos contenedores de aplicaciones sean kestrel o no.

Ahora que conocemos cada pieza, lo que intentaremos es unirlas para crear un servidor de aplicaciones net core.

Pre requisitos

  • Servidor Debian/Ubuntu con una cuenta de usuario estándar con privilegio sudo.
  • Instalar el runtime de .NET Core en el servidor.
  • Una aplicación ASP.NET Core cualquiera.

1- Instalar Runtime net core:

$ wget https://packages.microsoft.com/config/ubuntu/19.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb

$ sudo apt-get update
$ sudo apt-get install apt-transport-https
$ sudo apt-get update
$ sudo apt-get install aspnetcore-runtime-3.1

2- Realizar un publish de una aplicación cualquiera

Crear una aplicación tipo webapp:

$ dotnet new webapp

Luego de que termine de crear la webapp vaciá, creamos una release:

$ dotnet publish --configuration Release

Esto nos va a crear un directorio, generalmente en bin/Release/<target_framework>/publish; esta es la aplicación que luego vamos a publicar en el server kestrel.

Creamos la carpeta que va a contener nuestra aplicaciones; generalmente en: /var/www. Este es el lugar donde generalmente se alojan los sitios.

$ mkdir /var/www

Copiamos el contenido del publish sobre una carpeta dentro de www:

$ sudo cp -a publish/. /var/www/webapp

Ahora probamos si nuestra release esta funcionando:

$ dotnet <app_assembly>.dll

Esto lanza en la consola algo como lo siguiente:

    info: Microsoft.Hosting.Lifetime[0]
        Now listening on: http://localhost:5000
    info: Microsoft.Hosting.Lifetime[0]
        Now listening on: https://localhost:5001
    info: Microsoft.Hosting.Lifetime[0]
        Application started. Press Ctrl+C to shut down.
    info: Microsoft.Hosting.Lifetime[0]
        Hosting environment: Production
    info: Microsoft.Hosting.Lifetime[0]
        Content root path: /var/www/webapp

Ahora deberías ingresar por un navegador a la url que indica y comprobar de que funciona todo bien, en mi caso https://localhost:5001

3- Configurar el proxy reverso

Instalar nginx:

$ sudo apt install nginx

Iniciar el servicio:

$ sudo service nginx start

Verifica que nginx esta corriendo: en un navegador http://127.0.0.1 y deberías ver la pagina de “Welcome to nginx” (también deberías verlo desde otra pc apuntando a la ip del server)

Modificaremos el archivo /etc/nginx/sites-available/default y agregamos o reemplazamos lo siguiente:

server 
{
    listen        80;
    server_name   example.com *.example.com;
    location / {
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

Asegurate de agregar a Startup.cs de tu proyecto lo siguiente

En el método Configuration:

using System.Net;

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.KnownProxies.Add(IPAddress.Parse("192.168.1.TU_IP"));
    };
}S

Si quieres agregar otros proxies de confianza:

En el método Configure:

using Microsoft.AspNetCore.HttpOverrides;

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

Creando el servicio de app

Ahora bien, ya tenemos un servidor nginx que redirige peticiones al server kestrel en el puerto 5000; ahorra queremos que este servicio funcione sin tener que darle al comando dotnet app.dll:

Para ello debemos crear un demonio que se ejecute automáticamente… vamos a usar a nuestro amigo system.d:

$ sudo nano /etc/systemd/system/kestrel-webapp.service

En el debemos ingresar lo siguiente:

    [Unit]
    Description=Example .NET Web API App running on Ubuntu

    [Service]
    WorkingDirectory=/var/www/webapp
    ExecStart=/usr/bin/dotnet /var/www/webapp/webapp.dll
    Restart=always
    # Restart service after 10 seconds if the dotnet service crashes:
    RestartSec=10
    KillSignal=SIGINT
    SyslogIdentifier=dotnet-example
    User=www-data
    Environment=ASPNETCORE_ENVIRONMENT=Development
    Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

    [Install]
    WantedBy=multi-user.target

Environment=ASPNETCORE_ENVIRONMENT=Development buscara el archivo appsettings.Development.json de la carpeta de release! User=www-data -> este es el usuario que ejecutara la aplicacion; debe existir y tener permisos de ejecucion sobre el directorio de release!

Paso siguiente, guardar el archivo y habilitar el servicio:

sudo systemctl enable kestrel-webapp.service

Iniciar el servicio y verificar que este funcionando:

sudo systemctl start kestrel-webapp.service
sudo systemctl status kestrel-webapp.service

kestrel-webapp.service - Example .NET Web API App running on Ubuntu
    Loaded: loaded (/etc/systemd/system/kestrel-webapp.service; enabled)
    Active: active (running) since Thu 2020-04-02 04:09:35 NZDT; 35s ago
Main PID: 9021 (dotnet)
    CGroup: /system.slice/kestrel-webapp.service
            └─9021 /usr/local/bin/dotnet /var/www/webapp/webapp.dll

Probando todo

Desde un navegador ya deberias tener funcionando tu sitio completamente configurado con nginx y kestrel; sirviendo la solucion en la direccion 127.0.0.1 y tambien en maquinas remotas dentro de tu LAN.

Puedes usar: curl -v 192.168.1.xxx

    HTTP/1.1 200 OK
    Server: Kestrel
    Keep-Alive: timeout=5, max=98
    Connection: Keep-Alive

Configurar un CRT para que funcione por SSL (HTTPS)

Es muy pobable que tu sitio este funcionando cuando lo probas por localhost, pero si intentas acceder desde otro equipo no funciona (conection refuse). Esto es debido a que “localhost” siempre es tomado como seguro para nginx, en cambio para otra pc esto no es asi. Lo que debemos hacer es configurar un certificado para que las conexiones sean seguras y nuestro server nginx pueda responder por https.

El proyecto core net creado por defecto usa Properties/launchSettings.json y es probable que applicationUrl este escuchando en https://localhost:5001;http://localhost:5000)… puedes editar esta configuracion para que todo funcione de una… pero lo que pretendemos aca es que funcione por https.

Mas data: Host ASP.NET Core on Linux with Nginx