Check list to verify that your application is ready for deployment behind NGINX reverse proxy.
Here is the list of points to check when you hosting web site behind reverse proxy:
- You use everywhere
Url.Content("~/...")
in your Razor pages - You enabled using of forwarded headers
- If you’re deploying to sub-folder, you need to specify base path in the application
- You need to configure NGINX
Relative URLs in razor pages and Sub-folders
Usage of the class UrlHelper
will utilize the base path which may be configured for your website. If your website is located under a sub-folder, than any link which starts with /...
is referencing its root. For example, if you need to have your website be accessible using this URL http://common.com/app/...
then all links to images, css, scripts should be relative to /app/
folder. If you use just /images
browser will understand that you want to load a resource from the root (http://common.com/images/
) instead of the sub-folder (http://common.com/app/images/
). So that you need explicitly to tell browser where to look for resources. Using of the Url helper and specifying links with ~
solves this.
If you’re deploying th web site under a sub-folder, you may want to specify this in Startup.cs
file. Use this middleware for that purpose.
app.UsePathBase("/folder");
Utilization of forwarded HTTP headers
In order to work behind reverse proxy, your web site should know a bit about outside internet to correctly build references and request correct resources. The web server (NGINX in our case) sends special HTTP headers to say to the web site about this host and other connection parameters. Your application in its turn should react and do some stuff when it gets those headers.
Starting from .NET Core 3.0 it’s possible to enable usage of HTTP forwarded header just specifying environment variable ASPNETCORE_FORWARDEDHEADERS_ENABLED
to true
. The default hosting configuration of ASP.NET will configure Kestler to use them. In older version you had to add a middleware which enables usage of those headers. More about that is written here.
NGINX and SignalR
The NGINX configuration for the website which has SignalR enabled should include configuration for hub endpoint. If it’s missing then you can have such error message in DevTools:
Error during WebSocket handshake: Unexpected response code: 204
Additional configuration should specify to use header Connection with the value “upgrade”. And the sample configuration may look as follows (assuming, that the web site is deployed to a sub-folder /app
):
worker_processes 4;
events { worker_connections 1024; }
http {
sendfile on;
upstream app_servers {
server http://x.x.x.x:5050;
}
server {
listen 80;
location /app {
proxy_pass http://app_servers;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_cache_bypass $http_upgrade;
}
location /app/notifications {
proxy_pass http://app_servers/notifications;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_cache_bypass $http_upgrade;
}
}
}
SignalR is using the endpoint /notifications
. If you need to use TCP port inside the configuration you can do this via $server_port
. But it will be equal to the one which NGINX listens to (80 in the example). If you need another port, for example 8888, you can modify setting for Host header and use something like this:
proxy_set_header Host $host:8888;