fullstackhero / blazor-starter-kit

Clean Architecture Template for Blazor WebAssembly Built with MudBlazor Components.
MIT License
3.48k stars 730 forks source link

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

Open RHaughton opened 3 years ago

RHaughton commented 3 years ago

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 commented 3 years ago

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

nbiada commented 3 years ago

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/

RHaughton commented 3 years ago

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

jnalley20 commented 3 years ago

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

RHaughton commented 3 years ago

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 commented 3 years ago

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.

jnalley20 commented 3 years ago

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 commented 3 years ago

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.

RHaughton commented 3 years ago

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

image

RHaughton commented 3 years ago

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;

nbiada commented 3 years ago

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 ?

jnalley20 commented 3 years ago

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

290

RHaughton commented 3 years ago

@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 commented 3 years ago

@jnalley20

would this be sufficient to enable forward headers?

image

nbiada commented 3 years ago

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 ?

RHaughton commented 3 years ago

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.

jnalley20 commented 3 years ago

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

jnalley20 commented 3 years ago

@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().

RHaughton commented 3 years ago

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

jnalley20 commented 3 years ago

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?

RHaughton commented 3 years ago

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

jnalley20 commented 3 years ago

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

jnalley20 commented 3 years ago

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.

RHaughton commented 3 years ago

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

Exactly!

RHaughton commented 3 years ago

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.

jnalley20 commented 3 years ago

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?

RHaughton commented 3 years ago

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 ?

jnalley20 commented 3 years ago

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

unchase commented 2 years ago

Hi @RHaughton Did you already solve this issue?