rehansaeed.github.io
rehansaeed.github.io copied to clipboard
[Comment] NGINX for ASP.NET Core In-Depth
https://rehansaeed.com/nginx-asp-net-core-depth/
Johan commented on 2016-09-13 16:40:45
Not often that I comment on a post like this but this is good. I'm sold on Nginx and trying to figure out .Net Core. The only missing part here, is Charting, with live data (SignalR + DependencyCache, OnChange).
By the way, thanks for sharing.
Os1r1s110 commented on 2016-11-18 16:43:44
Really nice article with in-depth details about nginx configuration. Gives much better configuration than default files found in ASP.NET Core tutorials.
What would you think about adding pagespeed module in the pipeline, would it be a good idea/worth it? I know some of the features are redundant but I wonder if it could get an even further performance boost. What do you think?
Muhammad Rehan Saeed commented on 2016-11-27 07:49:49
Really nice article with in-depth details about nginx configuration. Gives much better configuration than default files found in ASP.NET Core tutorials.
What would you think about adding pagespeed module in the pipeline, would it be a good idea/worth it? I know some of the features are redundant but I wonder if it could get an even further performance boost. What do you think?
Ideally you should build your site so it is optimized in the first place, so you shouldn't need to run a tool like this which adds it's own performance penalty. You can see what this tool is doing and replicate that in your app. That said, I'm not very familiar with this tool. Best thing to do is try it and see when it comes to performance.
Tim commented on 2017-05-05 09:08:08
Great article thanks - very helpful. Do you separate the server blocks into the sites-available folder? And do you know if this configuration works with Fail2Ban? I know I need to make sure the log file locations match - but I wasn't sure how custom log_format might affect Fail2Ban - any idea? Regards Tim
Muhammad Rehan Saeed commented on 2017-05-05 14:41:03
Great article thanks - very helpful. Do you separate the server blocks into the sites-available folder? And do you know if this configuration works with Fail2Ban? I know I need to make sure the log file locations match - but I wasn't sure how custom log_format might affect Fail2Ban - any idea? Regards Tim
Not sure what you mean about separating the server blocks. I've never used Fail2Ban either (I'd recommend using Cloudflare as well or perhaps instead if you worry about bad traffic).
Tim commented on 2017-05-06 01:39:59
Not sure what you mean about separating the server blocks. I've never used Fail2Ban either (I'd recommend using Cloudflare as well or perhaps instead if you worry about bad traffic).
Thanks Rehan
FYI - regarding splitting out the content of nginx.conf
into site-specifc and other config-specific files take a look here.
"...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
:
For open source NGINX 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 open source NGINX builds distributed with Ubuntu, the directory is /etc/nginx/sites-enabled
, and the default file for HTTP virtual servers is default
.
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:
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
After a fresh install of Nginx on Ubuntu it has these include's within the http block. So using your config, I would split out the server blocks into a site-specific file within the sites-available directory, then create a symbolic link to it within the sites-enabled directory (sites-available and sites-enabled directories are created as part of the Nginx install). The net effect at run time is the same as your config, except you can more easily manage multiple websites this way. Unfortunately this is not documented well in the Nginx docs - but mentioned in plenty of other articles around the web.
Vasko Mihailov commented on 2017-05-29 12:56:39
Thanks for sharing ur knowledge!
Is it possible to host multiple asp.net core web apps on a single nginx server? If so can you please provide some tips and tricks.
Thanks a lot.
Muhammad Rehan Saeed commented on 2017-05-29 13:26:20
Thanks for sharing ur knowledge!
Is it possible to host multiple asp.net core web apps on a single nginx server? If so can you please provide some tips and tricks.
Thanks a lot.
Yes that's possible. You just need a server
element in your config for each app.
Vasko Mihailov commented on 2017-05-30 18:22:00
Yes that's possible. You just need a
server
element in your config for each app.
Thank you for your advice.
My confusion comes from this article.
Somewhere before the end of the article the author claims this:
First and foremost, if you want to have multiple applications running on a single server that all share port 80 and port 443 you can't run Kestrel directly. Kestrel doesn't support host header routing which is required to allow multiple port 80 bindings on a single IP address. Without IIS (or http.sys actually) you currently can't do this using Kestrel alone (and I think this is not planned either).
I am sorry if it is not allowed to quote other authors in your posts. If so it is OK with me to delete it.
Thanks again.
Muhammad Rehan Saeed commented on 2017-05-31 09:18:50
Thank you for your advice.
My confusion comes from this article.
Somewhere before the end of the article the author claims this:
First and foremost, if you want to have multiple applications running on a single server that all share port 80 and port 443 you can't run Kestrel directly. Kestrel doesn't support host header routing which is required to allow multiple port 80 bindings on a single IP address. Without IIS (or http.sys actually) you currently can't do this using Kestrel alone (and I think this is not planned either).
I am sorry if it is not allowed to quote other authors in your posts. If so it is OK with me to delete it.
Thanks again.
The Kestrel web server does not support SNI which lets you run multiple sites on the same port (usually port 80 and/or 443 on a production site). If you want SNI, use the WebListener (Now renamed HttpSysServer) web server instead.
Vasko Mihailov commented on 2017-06-01 20:16:31
The Kestrel web server does not support SNI which lets you run multiple sites on the same port (usually port 80 and/or 443 on a production site). If you want SNI, use the WebListener (Now renamed HttpSysServer) web server instead.
Thanks. That will do the trick I hope. By the way, do you have any clues about performance comparison between IIS and Linux+Nginx? There are a lot talks on the net that can be found but it will be great to have your personal opinion.
Thanks.
Muhammad Rehan Saeed commented on 2017-06-02 12:04:56
Thanks. That will do the trick I hope. By the way, do you have any clues about performance comparison between IIS and Linux+Nginx? There are a lot talks on the net that can be found but it will be great to have your personal opinion.
Thanks.
NGINX is faster than IIS.
Karnesh Kumar commented on 2017-07-12 10:46:06
Hi, Is it possible to host asp.net website at NGINX server with below requirement. Developed in
- ASP.NET Website (not a MVC)
- Targeted framework 4.5.6
- SQL Server 2014
Please help me.
Muhammad Rehan Saeed commented on 2017-07-23 12:32:13
Hi, Is it possible to host asp.net website at NGINX server with below requirement. Developed in
- ASP.NET Website (not a MVC)
- Targeted framework 4.5.6
- SQL Server 2014
Please help me.
Not unless you use IIS too.
elbarto commented on 2017-09-18 23:59:59
Hello,
could you also explain how to use a subdirectory instead of /
? For example:
http://localhost/test
I don't get that running, it just happens nothing at all when you browse.
Thanks!
Muhammad Rehan Saeed commented on 2017-09-19 09:12:07
Hello,
could you also explain how to use a subdirectory instead of
/
? For example:http://localhost/test
I don't get that running, it just happens nothing at all when you browse.
Thanks!
You can just use the sub-directory name i.e. /test
.
Nathan commented on 2018-01-13 10:20:01
Hi, wonderful post.I am just starting out using Nginx and .NET Core.I have set it up on a Linux Ubuntu server.However I am facing problems with loading the images, js and css files, it gives me a 404.And also whilst I can see the home page, other paths like http://somewhere.com/About gives a 404 as well.Do I need to configure any forwarding rules in Nginx for this to work?
Joe Castro commented on 2018-02-11 22:05:45
Thanks for the article!!!! Good stuff !!! I modified it using nginx-rtmp-module sample code below on CentoOS :)
For Compiling Nginx
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --build=CentOS --builddir=nginx-1.13.3 --with-select_module --with-poll_module --with-threads --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-stream_ssl_preread_module --with-compat --with-pcre=../pcre-8.40 --with-pcre-jit --with-zlib=../zlib-1.2.11 --with-openssl=../openssl-1.1.0f --with-openssl-opt=../no-nextprotoneg --add-module=../nginx-rtmp-module --with-debug
Mime Types
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/png png;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
image/svg+xml svg svgz;
image/webp webp;
application/font-woff woff;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.wap.wmlc wmlc;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}
Update nginx.conf
Configure the Nginx web server to run your ASP.NET Core site efficiently.
See https://docs.asp.net/en/latest/publishing/linuxproduction.html
See http://nginx.org/en/docs/ and https://www.nginx.com/resources/wiki/
Set another default user than root for security reasons.
user nginx;
The maximum number of connections for Nginx is calculated by:
max_clients = worker_processes * worker_c
worker_processes 1;
Maximum file descriptors that can be opened per process
This should be > worker_connections
worker_rlimit_nofile 8192;
Log errors to the following location. Feel free to change these.
error_log logs/error.log;
Log NXingx process errors to the following location. Feel free to change these.
pid logs/nginx.pid;
events {
# When you need > 8000 * cpu_cores connections, you start optimizing
# your OS, and this is probably the point at where you hire people
# who are smarter than you, this is *a lot* of requests.
worker_connections 8000;
# This sets up some smart queueing for accept(2)'ing requests
# Set it to "on" if you have > worker_processes
accept_mutex off;
# These settings are OS specific, by defualt Nginx uses select(2),
# however, for a large number of requests epoll(2) and kqueue(2)
# are generally faster than the default (select(2))
# use epoll; # enable for Linux 2.6+
# use kqueue; # enable for *BSD (FreeBSD, OS X, ..)
}
http {
# Include MIME type to file extension mappings list.
include mime.types;
# The default fallback MIME type.
default_type application/octet-stream;
# Format for our log files.
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# Log requests to the following location. Feel free to change this.
access_log logs/access.log main;
# The number of seconds to keep a connection open.
keepalive_timeout 29;
# Defines a timeout for reading client request body.
client_body_timeout 10;
# Defines a timeout for reading client request header.
client_header_timeout 10;
# Sets a timeout for transmitting a response to the client.
send_timeout 10;
# Limit requests from an IP address to five requests per second.
# See http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone
limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
# Disables emitting Nginx version in error messages and in the 'Server' HTTP response header.
server_tokens off;
# To serve static files using Nginx efficiently.
sendfile on;
tcp_nopush on;
tcp_nodelay off;
# Enable GZIP compression.
gzip on;
# Enable GZIP maximum compression level. Ranges from 1 to 9.
gzip_comp_level 9;
# Enable GZIP over HTTP 1.0 (The default is HTTP 1.1).
gzip_http_version 1.0;
# Disable GZIP compression for IE 1 to 6.
gzip_disable "MSIE [1-6]\."
# Enable GZIP compression for the following MIME types (text/html is included by default).
gzip_types # Plain Text
text/plain
text/css
text/mathml
application/rtf
# JSON
application/javascript
application/json
application/manifest+json
application/x-web-app-manifest+json
text/cache-manifest
# XML
application/atom+xml
application/rss+xml
application/xslt+xml
application/xml
# Fonts
font/opentype
font/otf
font/truetype
application/font-woff
application/vnd.ms-fontobject
application/x-font-ttf
# Images
image/svg+xml
image/x-icon;
# Video
application/vnd.apple.mpegurl;
video/mp2t;
video/3gpp;
video/mp2t;
video/mp4;
video/mpeg;
video/quicktime;
video/webm;
video/x-flv;
video/x-m4v;
video/x-mng;
video/x-ms-asf;
video/x-ms-wmv;
video/x-msvideo;
# Enables inserting the 'Vary: Accept-Encoding' response header.
gzip_vary on;
# Configuration Use for Virtual Sites
# mkdir -p /etc/nginx/sites-available/
# mkdir -p /etc/nginx/sites-enabled/
# mkdir -p /var/www/example.com/logs/
# Create Symbolic Link
# ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf
include /etc/nginx/sites-enabled/*.conf;
server_names_hash_bucket_size 64;
# Sets configuration for a virtual server. You can have multiple virtual servers.
# See http://nginx.org/en/docs/http/ngx_http_core_module.html#server
server {
# Listen for requests on specified port including support for HTTP 2.0.
# See http://nginx.org/en/docs/http/ngx_http_core_module.html#listen
listen 80 http2 default;
# Or, if using HTTPS, use this:
listen 443 http2 ssl default;
# Configure SSL/TLS
# See http://nginx.org/en/docs/http/configuring_https_servers.html
ssl_certificate /etc/ssl/certs/*.crt;
ssl_certificate_key /etc/ssl/certs/*.key;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Ensure your cert is capable before turning on SSL Stapling.
ssl_stapling on;
ssl_stapling_verify on;
# The name of the virtual server where you can specify one or more domains that you own.
server_name localhost;
# server_name example.com www.example.com *.example.com www.example.*;
# Match incoming requests with the following path and forward them to the specified location.
# See http://nginx.org/en/docs/http/ngx_http_core_module.html#location
location / {
proxy_pass http://localhost:1025;
proxy_pass https://localhost:1025;
# The default minimum configuration required for ASP.NET Core
# See https://docs.asp.net/en/latest/publishing/linuxproduction.html?highlight=nginx#configure-a-reverse-proxy-server
proxy_cache_bypass $http_upgrade;
# Turn off changing the URL's in headers like the 'Location' HTTP header.
proxy_redirect off;
# Forwards the Host HTTP header.
proxy_set_header Host $host;
# The Kestrel web server we are forwarding requests to only speaks HTTP 1.1.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
# Adds the 'Connection: keep-alive' HTTP header.
proxy_set_header Connection keep-alive;
# Sets the maximum allowed size of the client request body.
client_max_body_size 10m;
# Sets buffer size for reading client request body.
client_body_buffer_size 128k;
# Defines a timeout for establishing a connection with a proxied server.
proxy_connect_timeout 90;
# Sets a timeout for transmitting a request to the proxied server.
proxy_send_timeout 90;
# Defines a timeout for reading a response from the proxied server.
proxy_read_timeout 90;
# Sets the number and size of the buffers used for reading a response from the proxied server.
proxy_buffers 32 4k;
}
}
}
Swapnil commented on 2018-04-06 06:45:13
Hi Friend.
i need to host my ASP.NET Core 2.1 with angular5 app in nginx. i am using MongoDB database.
Please help.
Muhammad Rehan Saeed commented on 2018-04-16 09:14:05
Hi Friend.
i need to host my ASP.NET Core 2.1 with angular5 app in nginx. i am using MongoDB database.
Please help.
Please learn to use StackOverflow like everybody else.
Andrew Simpson commented on 2019-08-06 12:03:20
Hi, I have been trying to configure this to use websockets. I have searched for quite some time, Plenty of examples using node.js but I just want to use Javascript as the client and asp.net c# as the 'other-end'. I believe it is NGINX that is stopping things working as it works under IIS
Anuj Garg commented on 2019-10-21 06:28:04
Hi Rehan, Nice article! I am trying to use nginx with ASP.NET Core and it works fine except OIDC path. When it goes to signin-oidc path, it give me 504 gateway timeout. I am wondering if it is due to header length or i need to specify port to open in asp.net specifically. I have it running it in docker and it works in my Machine but not on Fargate. Any clue would help. Thanks!
How do you allow nginx 'localhost' CORS access from a remote browser to web page ajax call via http://localhost or https://localhost:5001. It works in curl, but browser (Firefox, Chrome, Safari) all block localhost, even when listed as trusted by aspnetcore 6 middleware.
How do you allow nginx 'localhost' CORS access from a remote browser to web page ajax call via http://localhost or https://localhost:5001. It works in curl, but browser (Firefox, Chrome, Safari) all block localhost, even when listed as trusted by aspnetcore 6 middleware.
This sounds like a good question to ask on StackOverflow.