Tutorial: Proxying .NET Core and Kestrel with NGINX and NGINX Plus

NGINX | February 14, 2017

About two years ago Microsoft® announced .NET Core, a framework that allows you to develop and run .NET applications natively on Linux and Mac systems. ASP.NET Core includes Kestrel, an internal web server library.

As indicated in the documentation for Kestrel on the Microsoft website and the GitHub repository, you typically run Kestrel behind a production web server such as IIS or NGINX. In this tutorial, we’ll describe how to implement Kestrel behind NGINX and NGINX Plus.

In this tutorial you’ll learn how to:

When the installation and configuration are complete:

  • .NET Core and Kestrel:
    • Run the dynamic application code
    • Listen on a local IP address and respond to HTTP requests
  • NGINX or NGINX Plus, acting as a reverse proxy:
    • Accepts HTTP/2 traffic over IPv6 and IPv4
    • Provides SSL offload for the .NET application
    • Provides static file serving
    • Provides access logs
    • Adds caching
  • NGINX Plus:
    • Provides live activity monitoring and metrics
    • Ensures the app is working by means of active health checks

The .NET Core application deployment architecture is similar to the deployment architecture of Node.js or Go applications. NGINX provides .NET apps with traffic management features that simplify production deployment and scalability of the apps. You can run multiple .NET applications on the same or different machines, and NGINX or NGINX Plus performs load balancing and intelligent traffic routing between them.

Instructions

The following instructions explain how to quickly build a “Hello World” app using .NET Core, run it on Linux, and deploy it behind an NGINX or NGINX Plus reverse proxy with advanced traffic‑management functionality.

  1. Install .NET Core, NGINX, and NGINX Plus
  2. Run the “Hello World” App
  3. Run the Kestrel HTTP Server
  4. Configure NGINX or NGINX Plus to Reverse Proxy the .NET Application
  5. Configure NGINX Plus Live Activity Monitoring and Active Health Checks

Install .NET Core, NGINX, and NGINX Plus

  1. Install .NET Core using the instructions on the Microsoft website. In our example we’re using Ubuntu 16.04. The following commands were correct at the time of writing, but are subject to change because Kestrel is still under development. Consult the .NET Core documentation as necessary. [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
  2. Install NGINX: [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
  3. Install NGINX Plus if you want live activity monitoring, active health checks, or both. See the instructions in the NGINX Plus Admin Guide.
    1. Edit the ./project.json file to add Kestrel as a dependency to the project. [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
    2. Copy this code for a simple app to a new file called Program.cs. It returns the current date and time, running Kestrel on port 5000 on localhost. [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
    3. Run the dotnet run command to start the .NET Core server: [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
    4. Run the curl command to test connectivity and HTTP: [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
    5. Install an SSL certificate. There are several ways to obtain one: For the purposes of quickly spinning up a sample .NET Core app with SSL, we’re generating a self‑signed certificate and associated key with this openssl command. We’re installing the certificate and key in the standard location for NGINX, /etc/nginx, but you can choose a different location. [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
      • Buy it from a well‑known certificate authority (CA)
      • Have your corporate IT group or CA generate it
      • Export it from an existing IIS server
      • Use a free CA like Let’s Encrypt
      • Generate a self‑signed certificate directly
    6. Configure reverse proxy in the default NGINX and NGINX Plus configuration file for HTTP virtual servers. The main NGINX and NGINX Plus configuration file is /etc/nginx/nginx.conf. However, several NGINX distributions (as well as NGINX Plus) follow the convention that you do not place much actual configuration in the main file, but instead create smaller, function‑specific files in a subdirectory of /etc/nginx: The content of the function‑specific files in these directories is then read into the main (nginx.conf) file with an include directive, for example: [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop If you are not sure which is the default configuration file for HTTP virtual servers on your system, find the relevant include directive in /etc/nginx/nginx.conf. To configure NGINX or NGINX Plus as a reverse proxy, add the following three configuration blocks to the default configuration file for HTTP virtual servers: [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
      • For NGINX Open Source builds provided by nginx.org, and for NGINX Plus, the directory is /etc/nginx/conf.d, and the default file for HTTP virtual servers is default.conf.
      • For NGINX Open Source builds distributed with Ubuntu, the directory is /etc/nginx/sites-enabled, and the default file for HTTP virtual servers is default.
      • The first server block accepts HTTP requests on port 80 and redirects them to the virtual server for HTTPS requests.
      • The second server block accepts HTTPS requests on port 443 and proxies them to a group of one or more upstream (backend) servers, here called dotnet. (If in Step 1 you installed your self‑signed SSL certificate in a directory other than /etc/nginx, substitute the correct path in the ssl_certificate and ssl_certificate_key directives.)
      • The upstream block defines the dotnet group of backend servers. In Run the Kestrel HTTP Server, we configured Kestrel on localhost:5000, meaning that it listens for both IPv4 and IPv6 traffic on that port. (Configuring Kestrel for just one protocol can cause instability and potentially 502 errors.) Similarly, NGINX and NGINX Plus resolve localhost to both its IPv4 and its IPv6 address (127.0.0.1 and ::1). For the sake of simplicity, here we identify the upstream server as 127.0.0.1 instead of localhost, so it listens for IPv4 traffic only. You can use localhost if you are comfortable with a more advanced configuration that includes IPv6.
    7. Run this curl command to test connectivity to the .NET Core app via HTTPS. (You can also point your browser at your Linux server instead.) [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop Note: If you see 502 Bad Gateway errors, it means that NGINX or NGINX Plus cannot connect to your .NET application. Make sure it’s running and serving responses on port 5000. If you have installed the nghttp2 package, you can also run the following nghttp command to test connectivity over HTTP/2. Look for the line highlighted in orange in the following example, near the beginning of the rather lengthy output. [@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop
  • The response code is 200 OK
  • The app server is Kestrel and not some other software
  • The body of the response includes the words “Current date”
  • The app responds within a 1‑second timeout period

Run the “Hello World” App

Install and initialize a “Hello World” app in the parent directory of your choice:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

To check that the app is working, run the dotnet run command.

Run the Kestrel HTTP Server

At this point .NET Core is running on Linux and serving dynamic data using Kestrel as the HTTP server.

Configure NGINX or NGINX Plus to Reverse Proxy the .NET Application

With NGINX or NGINX Plus as a reverse proxy for the .NET application, you can easily configure security with SSL/TLS, HTTP/2 support, and many other features for fast application delivery on the same machine where the .NET Core application is running. The following instructions assume that NGINX and NGINX Plus are already installed on your system; if not, see Install .NET Core, NGINX, and NGINX Plus.

Configure NGINX Plus Live Activity Monitoring and Active Health Checks

At this point we’ve finished the basic configuration of NGINX or NGINX Plus with .NET Core. NGINX or NGINX Plus is providing HTTP handling, passive health checks, security with SSL/TLS, and HTTP/2 connectivity for our .NET Core app.

If you have installed NGINX Plus, you can configure two additional capabilities: live activity monitoring and active health checks.

Configure Live Activity Monitoring

[Editor – This section has been updated to refer to the NGINX Plus API, which replaces and deprecates the separate extended Status module originally discussed here.]

Add the following server block to the default NGINX configuration file for HTTP virtual servers. We strongly recommend that you restrict access to the statistics and metrics. Here we allow access only to users on localhost and a local network.

For more information on live activity monitoring, see Live Activity Monitoring of NGINX Plus in 3 Simple Steps on our blog and the NGINX Plus Admin Guide.

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Configure Active Health Checks

Active health checks guarantee that NGINX Plus sends traffic only to applications that are working correctly. You define the HTTP requests that NGINX Plus periodically sends to the app, and the type of response that the app must return to be considered healthy.

Here we require that the response from the app meets the following conditions:

In the default configuration file for HTTP virtual servers, add the following location block to the main server block (the block for HTTPS traffic defined in Step 2 of Configure NGINX or NGINX Plus to Reverse Proxy the .NET Application):

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Also add the following match block at the same level in the hierarchy as the server and upstream blocks:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

You can verify that your backend app is healthy on the Upstreams tab of the built‑in live activity monitoring dashboard (point your browser at //http://nginx-plus-server-address:8080/):

The NGINX Plus live activity monitoring dashboard reports the health of the backend .NET applications NGINX is proxying

For more NGINX configuration options, see the Microsoft documentation.

Conclusion

For production‑ready deployments of the apps you develop with ASP.NET, NGINX and NGINX Plus provide the traffic‑management features you need in a reverse proxy. NGINX and NGINX Plus provide security, scalability, authentication, traffic limiting, and intelligent routing of your HTTP requests to .NET Core applications.

To try NGINX Plus for yourself, start your free 30-day trial today or contact us to discuss your use cases.


Share

About the Author

Related Blog Posts

Automating Certificate Management in a Kubernetes Environment
NGINX | 10/05/2022

Automating Certificate Management in a Kubernetes Environment

Simplify cert management by providing unique, automatically renewed and updated certificates to your endpoints.

Secure Your API Gateway with NGINX App Protect WAF
NGINX | 05/26/2022

Secure Your API Gateway with NGINX App Protect WAF

As monoliths move to microservices, applications are developed faster than ever. Speed is necessary to stay competitive and APIs sit at the front of these rapid modernization efforts. But the popularity of APIs for application modernization has significant implications for app security.

How Do I Choose? API Gateway vs. Ingress Controller vs. Service Mesh
NGINX | 12/09/2021

How Do I Choose? API Gateway vs. Ingress Controller vs. Service Mesh

When you need an API gateway in Kubernetes, how do you choose among API gateway vs. Ingress controller vs. service mesh? We guide you through the decision, with sample scenarios for north-south and east-west API traffic, plus use cases where an API gateway is the right tool.

Deploying NGINX as an API Gateway, Part 2: Protecting Backend Services
NGINX | 01/20/2021

Deploying NGINX as an API Gateway, Part 2: Protecting Backend Services

In the second post in our API gateway series, Liam shows you how to batten down the hatches on your API services. You can use rate limiting, access restrictions, request size limits, and request body validation to frustrate illegitimate or overly burdensome requests.

New Joomla Exploit CVE-2015-8562
NGINX | 12/15/2015

New Joomla Exploit CVE-2015-8562

Read about the new zero day exploit in Joomla and see the NGINX configuration for how to apply a fix in NGINX or NGINX Plus.

Why Do I See “Welcome to nginx!” on My Favorite Website?
NGINX | 01/01/2014

Why Do I See “Welcome to nginx!” on My Favorite Website?

The ‘Welcome to NGINX!’ page is presented when NGINX web server software is installed on a computer but has not finished configuring

Deliver and Secure Every App
F5 application delivery and security solutions are built to ensure that every app and API deployed anywhere is fast, available, and secure. Learn how we can partner to deliver exceptional experiences every time.
Connect With Us