blazor-starter-kit icon indicating copy to clipboard operation
blazor-starter-kit copied to clipboard

[HELP] Deploying Blazor Hero to Linux with Nginx and SignalR support

Open RHaughton opened this issue 4 years ago • 29 comments

Hi everyone,

I'm trying to deploy this application to linux using NGINX as a reverse proxy. I managed to get access to the site using the IP Adress but when I connect to it, I recieve a signalR 404 connection error.

When I try to access https://MyIpAddress/signalRHub I get a 404 page. When I try to access https://localhost:5000/signalRHub on my local windows machine (in development) everything works as expected.

Could anyone help me deploy this project on a linux server using nginx?

RHaughton avatar Aug 12 '21 14:08 RHaughton

This is what I Find when debugging on my local computer image

this is in production image

It's like SignalR is not working on my linux server. I have no idea why

RHaughton avatar Aug 12 '21 15:08 RHaughton

Do you have Kestrel as web server behind NGINX? If it is so, take a look to this tutorial: https://www.nginx.com/blog/tutorial-proxy-net-core-kestrel-nginx-plus/

nbiada avatar Aug 12 '21 17:08 nbiada

Hi @nbiada, Thanks for your answer.

I already have a successful kestrel server working. image

I can access it with http://192.168.1.102 over the network and everything is working except for the signalRHub.

image

It's only when I try to access SignalR endpoint that I recieve a 404 not found page.

image

I believe that my Nginx server is working (at least for the website page) but not for the signalR part. I don't know how to activate signalR on the production server. When I run the project from my development computer on windows, SignalR is running and working as expected.

I think I'm going to have to remove signalR from the project since this is the only thing blocking me. I would of course prefer to make it work

RHaughton avatar Aug 13 '21 12:08 RHaughton

What is your nginx config? You have to add a few lines to a default nginx config. https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-5.0 https://docs.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-5.0#linux-with-nginx

jnalley20 avatar Aug 13 '21 17:08 jnalley20

Hello, Thanks for your answer and sorry for the late response, I didn't had access to my server during the weekend.

Here is my nginx.conf file.

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;


events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

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

	##
	# SSL Settings
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}


#mail {
#	# See sample authentication script at:
#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# 
#	# auth_http localhost/auth.php;
#	# pop3_capabilities "TOP" "USER";
#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
# 
#	server {
#		listen     localhost:110;
#		protocol   pop3;
#		proxy      on;
#	}
# 
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}

and my site-enable/default file:

server {
    listen        80;
    server_name   ppt-lab.com *.ppt-lab.com;
    location / {
        proxy_pass         http://127.0.0.1:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

RHaughton avatar Aug 16 '21 06:08 RHaughton

I tried following the guides on your links but with no success. I'm not sure if I have to add a second server with location /signalRHub. I tried everything with no success. I will, for now, sadly remove signalR from the project.

RHaughton avatar Aug 18 '21 07:08 RHaughton

Sorry, I did have this working at one time but it was done only for future planning and not current use. So, it has not been maintained. I had to redo my nginx setup and have made many project updates along the way. Now I'm not able to get it working.

I do not remember adding the additional location. My notes from when I previously did it referenced the guides previously referenced and sudo vi /etc/nginx/nginx.conf and add in http section proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; large_client_header_buffers 4 16k;

jnalley20 avatar Aug 18 '21 15:08 jnalley20

I got mine going. I made a change in my nginx.conf to enable debugging.
error_log /var/log/nginx/error.log debug; Then get your app to crash and go look at the logs. I found the follow error which helped me find the solution. [info] 143898#143898: *16 client exceeded http2_max_field_size limit while processing HTTP/2 connection I had to also add http2_max_field_size 64k; because of the version of nginx that I was using.

jnalley20 avatar Aug 25 '21 01:08 jnalley20

I added the debug to the error file. There doesn't seem to be an obvious error...

image

RHaughton avatar Aug 25 '21 16:08 RHaughton

I have now deployed a clean Blazor Hero application without any modification on my side. I still get the same 404 error. I have added to nginx.conf the following statements like @jnalley20 has suggested without any success.

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

http2_max_field_size 64k;

RHaughton avatar Aug 25 '21 16:08 RHaughton

Are you sure that your kestrel in Linux is working correctly? It seems an unreachable address. Have you followed every instruction reported here https://docs.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/server?view=aspnetcore-5.0#linux-with-nginx-1 ?

nbiada avatar Aug 25 '21 16:08 nbiada

Did you add a cors policy and forward the headers? I added a pull request to add these options. #290

jnalley20 avatar Aug 25 '21 19:08 jnalley20

@nbiada I believe I have yes. I've simplified my nginx.conf. image

As you can see everything reported in https://docs.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/server?view=aspnetcore-5.0#linux-with-nginx-1 is done.

I still get 404 not found exception on the signalR Endpoint.

RHaughton avatar Aug 26 '21 08:08 RHaughton

@jnalley20

would this be sufficient to enable forward headers?

image

RHaughton avatar Aug 26 '21 08:08 RHaughton

I don't understand the organisation. Probably my bad. If your nginx configuration point to localhost:5000 this endpoint needs to run on your Linux box. The question is: in your Linux box a telnet command to localhost port 5000 return an http 200 ?

nbiada avatar Aug 26 '21 08:08 nbiada

I can correctly telnet to localhost or 127.0.0.1 on port 5000 from the linux box.

image

Everything also works if I go to http://localhost:5000 with my browser from the linux box.

RHaughton avatar Aug 26 '21 13:08 RHaughton

In your Nginx.conf, you are hosting as example.com, does DNS resolve internally to the correct host?

jnalley20 avatar Aug 26 '21 13:08 jnalley20

@RHaughton I don't think that method of forwarding headers will work but I've never tried it that way so I can't say for sure... I've got the settings for forwarded headers and Cors in my Services section and then simply app.UseCors() and app.UseForwardedHeaders().

jnalley20 avatar Aug 26 '21 13:08 jnalley20

In your Nginx.conf, you are hosting as example.com, does DNS resolve internally to the correct host?

Yes, I directly go to the IpAddress and get access to the website. the only thing missing is http://localhost:5000/signalRHub

RHaughton avatar Aug 26 '21 13:08 RHaughton

In your Nginx.conf, you are hosting as example.com, does DNS resolve internally to the correct host?

Yes, I directly go to the IpAddress and get access to the website. the only thing missing is http://localhost:5000/signalRHub

I'm not sure I am following. Maybe if you explain to me what the end result would be. Why are you putting Nginx in between Kestrel? What is the Application's Url? Is that Application Url is the appsettings.json?

jnalley20 avatar Aug 26 '21 14:08 jnalley20

In your Nginx.conf, you are hosting as example.com, does DNS resolve internally to the correct host?

Yes, I directly go to the IpAddress and get access to the website. the only thing missing is http://localhost:5000/signalRHub

I'm not sure I am following. Maybe if you explain to me what the end result would be. Why are you putting Nginx in between Kestrel? What is the Application's Url? Is that Application Url is the appsettings.json?

My goal is to take a fresh Clean architecture template and publish/host it to a linux server with SignalRHub endpoint working.

Everything works except for the /signalRhub which is 404 not found. When I run my application in my development environement (on my windows machine), I get access to https://localhost:5001/signalRHub image

When I access my site from the server I get a 404 error for the same address image

So SignalR is 404 on my linux server

RHaughton avatar Aug 26 '21 14:08 RHaughton

So does 192.168.1.102 pull up the web page properly but just fails when connecting to signalR?

jnalley20 avatar Aug 26 '21 15:08 jnalley20

I have only ever used Nginx to route url's to a specific host:port and add SSL. I don't think Nginx would route it using the IP, I thought you had to access it with url example.com based on your last nginx.conf example. That's all I've ever done.

jnalley20 avatar Aug 26 '21 15:08 jnalley20

So does 192.168.1.102 pull up the web page properly but just fails when connecting to signalR?

Exactly!

RHaughton avatar Aug 26 '21 15:08 RHaughton

I added a domain name but I don't get access to it. image image

I only get access from the IP Address which is not an issue for me.

RHaughton avatar Aug 26 '21 15:08 RHaughton

So does 192.168.1.102 pull up the web page properly but just fails when connecting to signalR?

Exactly!

I don't think you can proxy from port 80 to https... At least I've never done it. And does DNS resolve that name properly. Is it in your ApplicationUrl appsettings.json file?

jnalley20 avatar Aug 26 '21 15:08 jnalley20

So does 192.168.1.102 pull up the web page properly but just fails when connecting to signalR?

Exactly!

I don't think you can proxy from port 80 to https... At least I've never done it.

So Should I just remove https://localhost:5001 from LaunchSettings and only leave http://localhost:5000 ?

RHaughton avatar Aug 26 '21 15:08 RHaughton

So does 192.168.1.102 pull up the web page properly but just fails when connecting to signalR?

Exactly!

I don't think you can proxy from port 80 to https... At least I've never done it.

So Should I just remove https://localhost:5001 from LaunchSettings and only leave http://localhost:5000 ?

That shouldn't even be in play here but yes, just http://localhost:5000 is what I would expect. If running in Linux, it should be controlled by Kestrel settings, not launchsettings.. Whatever Kestrel is hosting it is where the proxypass should point. https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-5.0 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/when-to-use-a-reverse-proxy?view=aspnetcore-5.0

jnalley20 avatar Aug 26 '21 15:08 jnalley20

Hi @RHaughton Did you already solve this issue?

unchase avatar May 17 '22 10:05 unchase