rek2
rek2

Reputation: 181

rust yew app working on local laptop/pc not behind nginx

This is prob very easy to solve(I hope) I never deployed wasm apps before and now I have a working frontend(rust yew) and backend(actix) working locally on my laptop and PC when I run it without nginx, just raw dev. Problem comes when I have:

server {
    listen 443 ssl; # IPv4
    listen [::]:443 ssl; # IPv6
    server_name my-portal.org;

    
    ssl_certificate /etc/letsencrypt/live/my-portal.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/my-portal.org/privkey.pem;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams-2048.pem;

   #this is temp until is running ok, is a simple way to not allow people to play with it. 
    auth_basic           "Invitation Token";
    auth_basic_user_file /etc/nginx/.htpasswd;


    location / {
      root /home/portal/my-portal/dist;
      try_files $uri $uri/ /index.html;
    }

What is not right: — I do not see my app ever talking to my backend, like I do on my dev environment, works fine with curl curl localhost:80000/test

I suspect this could be: — Web socket I just find out I am getting when I inspect the site and is trying to connect to: wss://my-portal.org/_trunk/ws

NS_ERROR_WEBSOCKET_CONNECTION_REFUSED

— somehow CORS is wrong? (even do I added as allowed origin the same I see on the headers like

# I have on my local only the localhost in deployement I add the domain, because it was not # working I added/changing this adding/removing diff options.

 HttpServer::new(move || {
        let cors = Cors::default()
            .allowed_origin("http://127.0.0.1:3000")
            .allowed_origin("http://127.0.0.1")
            .allowed_origin("https://my-portal.org")
            .allowed_methods(vec!["GET", "POST", "OPTIONS"])
            .allowed_headers(vec![
                header::CONTENT_TYPE,
                header::AUTHORIZATION,
                header::ACCEPT,
            ])

the only yew wasm example I found is this: https://www.workfall.com/learning/blog/deploy-a-yew-rust-application-on-an-aws-ec2-ubuntu-instance-nginx/ since is wasm it does not need to run on its own like the backen does, nginx can load its index.html and this loads the wasm binary that runs on the browser, so no need to reverse proxy is running now with nginx, I need websockets somehow to work tho. More info in WHY this should not be run on its own webserver, nginx should do that, is a frontend not a backend. https://github.com/yewstack/yew/issues/2376

Upvotes: 1

Views: 638

Answers (2)

rek2
rek2

Reputation: 181

ok so I was right, the issue was not in nginx,, rust yew is a webassembly site so runs completely on the browser/client side so does not need a nginx acting as reverse proxy at all to serve the wasm binary, just run it as a regular site, so I needed to do a couple steps:

  • websockets need to be under https/wss this is autofix when running as a regular site and not trin g to have proxy_pass for / location.
  • the main issue here was at first in my errors with cors but someone told me is not really cors the issue but that the browser needs access to the backend but the app was looking for localhost is why it was working on my laptop/PC.

Solution: expose the backend port, change the yew frontned to call by domain not localhost so clients know to contact the server, then nginx will reverse proxy only /api that is what I exposed on the backend

example:

server {
    listen 443 ssl; # IPv4
    listen [::]:443 ssl; # IPv6
    server_name my-portal.org;

    
    ssl_certificate /etc/letsencrypt/live/my-portal.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/my-portal.org/privkey.pem;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams-2048.pem;

    
    auth_basic           "Invitation Token";
    auth_basic_user_file /etc/nginx/.htpasswd;


    location / {
      root /home/portal/my-portal/dist;
      try_files $uri $uri/ /index.html;
      include /etc/nginx/mime.types;
      default_type application/octet-stream;
    }
 
    location /api {
        proxy_pass        http://localhost:8000;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  Host $http_host;

    }
}   

now is all working and frontend is working as intended 100% from nginx not its own dev web server that is wrong for a frontend, the backend yes, and only /api exposed to the frontend that is a wasm running on peoples browser.

Upvotes: 1

berkes
berkes

Reputation: 27603

This has little to do with Yew, but everything with your nginx config.

The config you shared, has no entry to actually connect to the running service on port 80000.

You'll need a line that configures nginx as a proxy. So that it passes requests along to the backend.

Typically, that will look something like:

server {
  listen 443 ssl;
  listen [::]:443;

  ## SSL cert stuff here.

  root /path/to/app/public/data;

  server_name example.com;

  try_files $uri/index.html $uri @app;

  location @app {
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header Host $http_host;
     proxy_set_header X-Forwarded-Proto https;
     proxy_redirect off;
     proxy_pass http://localhost:80000;
  }
}

Since you also need websockets, you'll need some additional nginx magic.

location /ws/ {
    proxy_pass http://localhost:80000; # Or whatever port yew has websockets exposed on.
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
}

This will upgrade any request to example.com/ws to a Websocket connection. You may need to finetune this further for production. As mentioned in the article linkeed, a.o. to properly close the connection.

Upvotes: 1

Related Questions