Nginx Config for .netcore Blazor WebAssembly

I recently finished a few Blazor WebAssembly projects which was both fun and challenging.  With a Blazor WebAssembly SPA app you end up creating a static html site that is interactive or dynamic based on the API calls. This means you can actually host the site on a static file system or something like S3 / CloudFront CDN and then the calling API functions can be on a traditional web server or container system. 

However during development or a quick deployment, you may want to simply load it on the web-server, which is what I did.  I used Ngnix to serve up both the static site  (WebAssembly) and the web-api section.  The following configuration was used and it worked like a charm.

# typically 1 per core
# determine cores
# --- linux: grep processor /proc/cpuinfo | wc -l
# --- mac: sysctl -n hw.ncpu
worker_processes 1;

error_log /var/log/nginx/error.log info;

events {
# check limit
# --- mac/linux: ulimit -n
worker_connections 1024;

http {

sendfile on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
large_client_header_buffers 4 16k;

upstream app_servers {
# this must be the same name as the docker container name
# it's how it maps to the service
# you can actually add more than one here if you want to
# unless its in ECS then it's localhost
server web-api:5000;

server {
listen 80;
#listen [::]:80;
server_name $hostname;
client_max_body_size 10M; # upload size

# root handle blazor spa app
location / {
# location of the app (html files) in the container
# this is defined in the Dockerfile for the spa app
# or in the local file system if you have it published here
root /app/www;
# with a spa app we should redirect to /index.html on any not found pages
try_files $uri $uri/ /index.html =404;

include /etc/nginx/mime.types;
types {
application/wasm wasm;
default_type application/octet-stream;

# allow for gziped items in the framework path
location /_framework/ {
gzip_static on;

# cache buster
add_header Last-Modified __CACHE_BUSTER_EXPIRE_DATE_TIME; # this should be replaced by a shell script
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;


# handle api requests which is in a different docker container
location /api {
proxy_pass http://app_servers; # references the upstream app_servers above
proxy_redirect off;
proxy_set_header Connection keep-alive;
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 X-NginX-Proxy true;
Image Credit:
Jens - Saturday, 20 March 2021

Getting Nginx to work with dotnet is not hard but it does require some tinkering. I run a Piranha-based little site myself with Nginx (on an RPi actually) and boy do I have to revisit my Nginx config from time to time. :) Nice site you got here, I'll be back for sure!