nuxt icon indicating copy to clipboard operation
nuxt copied to clipboard

document running nuxt dev server behind nginx + SSL + proxy

Open quartze opened this issue 4 years ago • 36 comments

Environment


  • Operating System: Linux
  • Node Version: v16.11.1
  • Nuxt Version: 3-3.0.0-27235451.ece0e01
  • Package Manager: Yarn
  • Bundler: Webpack
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Describe the bug

Trying to start development server for people on nginx engine. When i'm starting with cli nuxt, i'm getting infinite reloads on page with error WebSocket connection to wss://example.com:24678/_nuxt/ failed`. Is there any chance to start nuxt with proxy on nginx?

Reproduction

Just cloned default project.

Additional context

No response

Logs

Nothing in nuxt3

quartze avatar Oct 14 '21 11:10 quartze

I think it can be prevented if we change connections from domain to ip address. Anyway, can i modify it now in nuxt.config.js?

quartze avatar Oct 14 '21 11:10 quartze

How does your nginx config look like?

lustremedia avatar Oct 14 '21 12:10 lustremedia

@lustremedia

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

events {
	worker_connections 768;
}

http {

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;


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


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

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

	gzip on;

server {                                                                                                         
        listen 80;
        listen 443 ssl;
        server_name dev.domainname.pl;

        gzip on;
        gzip_types	text/plain application/xml;
        gzip_proxied    no-cache no-store private expired auth;
        gzip_min_length 1000;

        # This is a cache for SSL connections
        ssl_session_cache shared:le_nginx_SSL:1m;
        ssl_session_timeout 1440m;

        rewrite ^/(.*)/$ /$1 permanent;

        location / {
                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-Proto $scheme;
                proxy_redirect          off;
                proxy_buffering         on;
                proxy_cache_valid	200 1d;
                proxy_cache_use_stale   error timeout invalid_header updating http_500 http_502 http_503 http_504;

                proxy_pass              http://localhost:3000;
                proxy_read_timeout	1m;
                proxy_connect_timeout   1m;
        }
}
	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}

quartze avatar Oct 14 '21 15:10 quartze

@quartze A few changes have to be made to allow development to run smoothly as expected behind your NGINX Proxy with SSL.

Everything below was tested and works properly, so let me know if you encounter any issues.

  1. Modify your nuxt config to set vite's hmr clientPort to 443(default https / ssl port) and path to "hmr/". Explanation: The vite server uses port 24678 for HMR by default, we are not going to change this. Setting clientPort to 443 will allow us to then use NGINX to proxy the request back to vite.
import { defineNuxtConfig } from "nuxt3";

export default defineNuxtConfig({
  vite: {
    server: {
      hmr: {
        protocol: "wss",
        clientPort: 443,
        path: "hmr/",
      },
    },
  },
});
  1. Modify the NGINX conf for you site Firstly, web sockets require HTTP/1.1, so the following is required in either your server or location block
proxy_http_version 1.1; # required
proxy_set_header Upgrade $http_upgrade; # required
proxy_set_header Connection "upgrade"; # required

Add location block to match the hmr path /hmr that we set in step 1.

location /_nuxt/hmr/ {
        proxy_pass http://localhost:24678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
}

@quartze I went ahead and modified your server block as needed: ps: I also made substantial improvements to your gzip compression, you should now get much faster load times ⚡️.

server {                                                                                                         
    listen 80;
    listen 443 ssl;
    server_name dev.domainname.pl;

	gzip on;
	gzip_disable "msie6";
	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 6;
	gzip_buffers 16 8k;
	gzip_http_version 1.1;
	gzip_min_length 256;

	gzip_types
		application/atom+xml
		application/geo+json
		application/javascript
		application/x-javascript
		application/json
		application/ld+json
		application/manifest+json
		application/rdf+xml
		application/rss+xml
		application/xhtml+xml
		application/xml
		font/eot
		font/otf
		font/ttf
		image/svg+xml
		text/css
		text/javascript
		text/plain
		text/xml;

    # This is a cache for SSL connections
    # ssl_session_cache shared:le_nginx_SSL:1m;
    # ssl_session_timeout 1440m;

    rewrite ^/(.*) /$1 break;

    location / {
        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-Proto $scheme;
        proxy_redirect          off;
        proxy_buffering         on;
        proxy_cache_valid	200 1d;
        proxy_cache_use_stale   error timeout invalid_header updating http_500 http_502 http_503 http_504;

        proxy_pass              http://localhost:3000;
        proxy_read_timeout	1m;
        proxy_connect_timeout   1m;
    }

    location /_nuxt/hmr/ {
        proxy_pass http://localhost:24678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Diizzayy avatar Oct 19 '21 21:10 Diizzayy

@Diizzayy working perfectly. Thanks for rewriting my code. Can you add this to docs?

quartze avatar Oct 20 '21 09:10 quartze

Hey, I had the same issue and this helped me. Makes sense to create a guide page with this setup similar to the previous version.

bubooon avatar Dec 19 '21 10:12 bubooon

@quartze @bubooon having this setup added to the docs is a good idea. I'll get started on a PR.

Diizzayy avatar Dec 19 '21 13:12 Diizzayy

Trying to start production server.The nuxt throw an error when i let http redirect to https on nginx. 1648804090(1)

wstee avatar Apr 01 '22 09:04 wstee

Hi, I had the same issue with docker. I have nginx as proxy for https here is my nginx config (I am not the author, my colleague made it) port 80 is served by default so I have proxy for 443 and 24678 (WS) if you forced ws protocol on https, then browser throws error due to trying communicate to unsecured endpoint from secured

https-proxy.conf

server {
    listen 443 ssl http2;
    server_name _;

    location / {
        proxy_pass http://app:80;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    ssl_protocols TLSv1.2;

    ssl_certificate     /var/https-proxy-cert.cert;
    ssl_certificate_key /var/https-proxy-cert.key;

    access_log /dev/stdout;
    error_log /dev/stderr;
}

server {
    listen 24678 ssl http2;
    server_name _;

    location / {
        proxy_pass http://app:24678;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    ssl_protocols TLSv1.2;

    ssl_certificate     /var/https-proxy-cert.cert;
    ssl_certificate_key /var/https-proxy-cert.key;

    access_log /dev/stdout;
    error_log /dev/stderr;
}

and nuxt.config.js

export default defineNuxtConfig({
  vite: {
    server: {
      hmr: {
        protocol: 'wss',
      },
    },
  }
});

ivan-mihalic avatar Apr 18 '22 18:04 ivan-mihalic

I have added ssl to my server name and nuxt3 was a blank page when using npm run dev. In nuxt config i did what @Diizzayy commented.

vite: {
    server: {
      hmr: {
        clientPort: 443,
        path: "hmr/",
        protocol: "wss",
      },
    },
  }

And also added the " location /_nuxt/hmr/ " in nginx. After all that it worked. @Diizzayy Saved the day. Huge thx.

jamesallan93 avatar May 29 '22 01:05 jamesallan93

The config that @Diizzayy and @jamesallan93 mentioned was working perfect until RC-7 :( Let me know guys if you have another workaround please!

kosmeln avatar Aug 11 '22 15:08 kosmeln

@kosmeln I'll have another look at the setup and update you guys accordingly on what changes may need to be made here

Diizzayy avatar Aug 11 '22 16:08 Diizzayy

Thank you in advance @Diizzayy !

kosmeln avatar Aug 11 '22 16:08 kosmeln

@kosmeln I just got around to checking this out, and the setup I mentioned above works just fine still.

Perhaps you can give me more details about your exact setup and what's not working properly

Diizzayy avatar Aug 12 '22 12:08 Diizzayy

Sorry for late response @Diizzayy . Before upgrading the hmr requests (if looking at dev tools) showed Request URL: ws://localhost: 24678/_nuxt/hmr/

After upgrade the url changed to Request URL: https://localhost/hmr/

So I had to tune vite server.hmr.path setting from

hmr: {
    protocol: 'wss',
    host: 'localhost',
    clientPort: 443,
    path: 'hmr/',
}

as you suggested earlier to

hmr: {
    protocol: 'wss',
    host: 'localhost',
    path: '_nuxt/hmr/',
}

Still not sure if this is correct and what has changed with the upgrade. Please let me know if you have any insights or what I can check further. Thanks in advance.

kosmeln avatar Aug 15 '22 17:08 kosmeln

Hi guys. It work for me: Nuxt 3 \ vite proxy. I generate key and sert with mkcert. Change package script to: "dev": "nuxt dev --https --ssl-key key.pem --ssl-cert cert.pem"

https:localhost:3000 work nice. vite proxy work too.

cwe-dev avatar Aug 17 '22 10:08 cwe-dev

Waiting for a good answer🤖

wangrongding avatar Nov 10 '22 15:11 wangrongding

The final solution: open your mind and reflect on what you really need

After a week spent trying to get Nuxt3 working with SSL with Nginx for development.... I realized that I have no need of Nginx !!! My goal is to get Nuxt3 working in a domain with SSL. It was my principle that it should work behind the reverse proxy, but, after all, it is just a whim. so:

package.json

"scripts": {
    ...
    "dev": "nuxi dev --port YOUR_PORT --host YOUR_IP --https",  <-- use IP and --https !!
   ...
}

In your Unbound conf or hosts file add reference to your domain and your YOUR_IP

now open the browser on https://yourdomain.tld:YOUR_PORT :

  • no hmr problems
  • no wss problems
  • no crazy Nginx configuration
  • no infinite console errors
  • no problem of any kind
  • hot reloading work, all work as expected.

giovannimanzoni avatar Jan 21 '23 14:01 giovannimanzoni

So as I see, there is a reasonable solution for this — should we maybe close this and add a small PR to add some docs to the "Going further" part in the nuxt docs?

madebyfabian avatar Feb 06 '23 21:02 madebyfabian

Better replace node args with nuxt.conifg.ts configuration.

Is it possible to fix it ?

❗ Code below isn't working!

// nuxt.config.ts
devServer: {
    host: "0.0.0.0",
    port: 3000,
    https: {
        key: fileURLToPath(new URL("./stage.key", import.meta.url)),
        cert: fileURLToPath(new URL("./stage.crt", import.meta.url)),
    },
    url: process.env.APP_URL,
},

ccxdev avatar Feb 07 '23 15:02 ccxdev

So as I see, there is a reasonable solution for this — should we maybe close this and add a small PR to add some docs to the "Going further" part in the nuxt docs?

It is reasonable only in certain circumstances. We are using Docker and a reverse proxy container to make sure our development setup is as close to our production setup. The option to remove the reverse proxy and let Nuxt do the ssl would be a lot different from our production and therefore not reasonable for us.

(I read somewhere that letting Nuxt do ssl in production is not safe, am I right?)

HendrikJan avatar Apr 10 '23 09:04 HendrikJan

Hi, this is my definitive and working setup for Nuxt3 with vite and Nginx

nuxt.config.js

server: {
  hmr: {
    protocol: 'wss',
    clientPort: 443,
    path: 'hmr/',
  },
},

package.json

"dev": "nuxt dev --host localhost --port 3035"

domain.conf

map $sent_http_content_type $expires {
  "text/html"                 epoch;
  "text/html; charset=utf-8"  epoch;
  default                     7d;
}

upstream mydomain {
  zone upstreams 64K;
  server localhost:3035 max_fails=1 fail_timeout=2s;
  keepalive 2;
}

server{
  listen       443 ssl http2;
  server_name  mydomain.lan;
  ...
  rewrite ^/(.*) /$1 break;
  
  location /_nuxt/hmr/ {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_pass http://localhost:24678;
  }

  location / {
    expires $expires;
    sendfile on;
    sendfile_max_chunk 512k;        
    aio on;
    proxy_max_temp_file_size 0;
    proxy_pass http://mydomain;
    proxy_next_upstream error timeout http_500;
    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-Proto $scheme;  # PLEASE !! DO NOT ADD THIS !!!
    proxy_redirect          off;
    proxy_buffering         on;
    proxy_cache_valid       200 1d;
    proxy_cache_use_stale   error timeout invalid_header updating http_500 http_502 http_503 http_504;
    proxy_cache_key         $uri$is_args$args;
    proxy_read_timeout      1m;
    proxy_connect_timeout   1m;
  }
}

enjoy :)

giovannimanzoni avatar Aug 13 '23 11:08 giovannimanzoni

Just leaving a note for anyone who may be having issues with this solution after upgrading to [email protected], I was experiencing reload loops and WSS connection errors.

It seems like specifying a vite.server.hmr config along with a nginx proxy_pass directive is no longer required to get HMR working on a SSL dev server. Removing the HMR config from nuxt.config.ts and removing the location block for /_nuxt/hmr from the nginx config fixed the issue.

slavanossar avatar Sep 28 '23 03:09 slavanossar

App work when removing proxy_pass from nginx config and vite.server.hmr from nuxt.config.ts But HMR not work for me

Need to add this in server block on nginx config

location /_nuxt/ {
    proxy_pass http://{localhost or container name}:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

tibesyc avatar Sep 28 '23 19:09 tibesyc

We also had issues on 3.7.4 --- To clarify, we actually had issues just when we went to upgrade, not even necessarily related to 3.7.4 but its dependencies.. We had the same issues on at least 3.7.0-3.7.4. Had to add these two rules to our existing nginx proxy pass to get HMR to work as per @tibesyc comment. We didn't need the cache bypass, host rule, nor did we need the http_version change.

proxy_set_header 		Upgrade 		$http_upgrade;
proxy_set_header 		Connection 		"upgrade";

AverySJones avatar Oct 04 '23 16:10 AverySJones

For anyone trying to run nuxt dev server behind a reverse proxy using latest nuxi CLI:

  • HMR is now same port of the same server (3000)
  • vite.server.hmr config should be removed

see https://github.com/nuxt/cli/issues/241#issuecomment-1745113589 for a working (apache2) example and feel free to open any issues in nuxt/cli repository if still having for setup.

Also worth to note, modern Nuxi can terminate SSL and listen on single port (including 80/443) or even tunnel to an external URL with custom domain. You probably can simplify your whole workflow, however hacking is always welcome!

pi0 avatar Oct 04 '23 16:10 pi0

@JefferySJones's answer worked for me with [email protected].

fabkho avatar Nov 06 '23 15:11 fabkho

So glad to see others using Nuxt / SSL / Nginx Proxy, I was going crazy trying to find the error:

[Vue Router warn]: No match found for location with path "/_nuxt/"

@fabko reference to @JefferySJones solution worked, redeployed NGINX proxy with new settings and worked great. THANK YOU!

mgd216 avatar Nov 17 '23 15:11 mgd216

New problem in Nuxt 3.10.1, last config from 3.8.x do not work anymore.

my last problem after a lot configs was: SyntaxError: Failed to construct 'WebSocket': The URL 'wss://localhost:undefined/' is invalid

but now, I can not believe DevTools, hmr work !!:

[vite] connecting... [vite] connected.

so: nuxt.config.ts

vite: {
  // no server block !
},

package.json

"dev": "nuxt dev --host localhost --port 3035"

nginx.conf

map $sent_http_content_type $expires {
  "text/html"                 epoch;
  "text/html; charset=utf-8"  epoch;
  default                     7d;
}

domain.conf

upstream mydomain {
  zone upstreams 64K;
  server localhost:3035 max_fails=1 fail_timeout=2s;
  keepalive 2;
}

server{
  listen       443 ssl http2;
  server_name  mydomain.lan;
  ...
  rewrite ^/(.*) /$1 break;
  
  location /_nuxt/ {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_pass http://mydomain;
  }

  location / {
    expires $expires;
    sendfile on;
    sendfile_max_chunk 512k;        
    aio on;
    proxy_max_temp_file_size 0;
    proxy_pass http://mydomain;
    proxy_next_upstream error timeout http_500;
    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-Proto $scheme;  # PLEASE !! DO NOT ADD THIS !!!
    proxy_redirect          off;
    proxy_buffering         on;
    proxy_cache_valid       200 1d;
    proxy_cache_use_stale   error timeout invalid_header updating http_500 http_502 http_503 http_504;
    proxy_cache_key         $uri$is_args$args;
    proxy_read_timeout      1m;
    proxy_connect_timeout   1m;
  }
}

giovannimanzoni avatar Feb 12 '24 16:02 giovannimanzoni

Our configuration for dev:

(only nuxt specific settings) nginx:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    location ~ /_nuxt {
        proxy_redirect                      off;
        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_read_timeout                  1m;
        proxy_connect_timeout               1m;
        proxy_pass                          http://mydomain:3000
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_cache_bypass $http_upgrade;
    }

    location / {
        proxy_redirect                      off;
        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_read_timeout                  1m;
        proxy_connect_timeout               1m;
        proxy_pass                          http://mydomain:3000
    }
}

We have a seperate nginx config for our (nginx) proxy, that does the ssl. Here we have also map $http_upgrade: (whole file)

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;
    listen [::]:80;
    server_name _;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name _;

    ssl_certificate <path-server.crt>
    ssl_certificate_key <path-server.key>

    location / {
        proxy_pass http://<point to webserver>
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port 443;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

larsalbrecht avatar Feb 13 '24 12:02 larsalbrecht