NGINX with Blazor Server-Side

If you do have a TLS certificate (strongly recommended) you can force each connecting client to switch from HTTP to HTTPS. There are various ways to do so, however, I find it pretty easy to apply the following config to each server configuration. Furthermore, the return value does not statically include any destination URL, but uses whatever the client originates from. E.g.: a Client browsing to http://dev.indie-dev.at will be redirected with a HTTP 301 return massage to https://dev.indie-dev.at

server {
    listen                              80;
    server_name                         _;
    return                              301 https://$host$request_uri;
}

The server config for our Blazor Server-Side application requires some additional parameters. proxy_read_timeout, proxy_connect_timeout, and proxy_send_timeout require to deviate from the default variant, as Blazor Server-Side has a steady Signal-R connection. Furthermore, we include X-Real-IP and X-Forwarded-For to pass through the client’s IP-Address. You could then read the client’s IP-Address, even though you are hiding behind a reverse-proxy. You may also spot the 443 ssl http2 config. Http2 is nowadays recommended, supports multiplexing, compresses the header,… In short, enable it. One could argue that HTTP2 is not supported by all browsers. Even though the argument is valid, neither is Blazor Server-Side. Hence, if your browser supports Blazor Server-Side, then it will also support HTTP2.

server {
        listen                          443 ssl http2;
        server_name                     indie-dev.at;

        location / {
                proxy_pass http://127.0.0.1:1234;

                proxy_read_timeout 1d;
                proxy_connect_timeout 4;
                proxy_send_timeout 1d;

                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $http_connection;

                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}
        /// <summary>
        /// Obtains the connected client's IP-Address.
        /// </summary>
        public string IpAddress
        {
            get
            {
                HttpContext httpContext = httpContextAccessor?.HttpContext;

                string ipAddress = httpContext?.Connection?.RemoteIpAddress?.ToString() ?? string.Empty;
                
                // check whether we are dealing with a reverse proxy.
                // if we deal with a reverse proxy, we require to pick the ipAddress
                // from a custom http header attribute (x-real-ip)
                if(!string.IsNullOrEmpty(ipAddress) && IPAddress.IsLoopback(IPAddress.Parse(ipAddress)))
                    ipAddress = httpContextAccessor?.HttpContext?.Request.Headers["X-Real-IP"].FirstOrDefault()?.Sanitize() ?? ipAddress;

                return ipAddress;
            }
        }

Performance does matter – Thus, we apply some additional optimizations to our NGINX configuration. First, we hide the fact that we use NGINX. On internal or external failures, we then do not expose our reverse-proxy setup. This does not relate to performance, although it does improve security. Enabling gzip on various file-types decreases bandwidth usage and leads to faster responses. Last but not least we drop TLSv1.0 and v1.1 support, because those versions are not considered secure anymore.


http {
        # hide server infos
        more_clear_headers Server;
        server_tokens off;
        more_set_headers 'Ass';


        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        client_max_body_size 10M;

        # TLS stuff
        ssl_certificate                 /fakepath/fullchain.cer;
        ssl_certificate_key             /fakepath/key.key;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;


        # Compression
        gzip on;
        # if a client doesn't support gzip, NGINX is able to decompress before sending
        gunzip on;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

...

}

With all of those settings applied, a Blazor Server-Side application is reachable and functional. The performance shows, as Google’s lighthouse reports a score between 85 and 95 on all of my Blazor web applications.

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments