Vue-cli: Vue thinks local IP address is global, causing several issues

Created on 19 Jun 2018  Β·  28Comments  Β·  Source: vuejs/vue-cli

Version

3.0.0-rc.2

Reproduction link

https://github.com/kissge/vue-cli-bug

Steps to reproduce

  1. Using vue create to start a project, on a remote machine (say, AWS EC2 instance)
  2. Run npm run serve

What is expected?

What is actually happening?

  • Local IP address is shown in console
  • HMR fails because sockjs tries to connect to local IP address
  • App cannot be accessed from outside the network, so I have to use tricks like ssh port forwarding

I also tried tweaking webpack config from vue.config.js, with no luck.

question

Most helpful comment

the devServer options have their own options property in vue.config.js because we process them internally before handing them to the devserver:

module.exports = {
  configureWebpack: {
    // other webpack options to merge in ...
  },
  // devServer Options don't belong into `configureWebpack`
  devServer: {
    host: '0.0.0.0',
    hot: true,
    disableHostCheck: true,
  },
};

All 28 comments

The devserver is meant for local development and is not accessible from outside by default.

However, you can adjust this behaviour in vue.config.js with the devServer option.

https://cli.vuejs.org/config/#devserver

Options to look into:

https://webpack.js.org/configuration/dev-server/#devserver-disablehostcheck

https://webpack.js.org/configuration/dev-server/#devserver-host

Thanks for you reply.
Yes, I read that and have already tried; if my understanding is correct, that means putting this file?
It was not effective.
App cannot be accessed via domain (Invalid Host header), and even if I somehow connect (e.g. using global IP address) HMR fails because vue-cli-service thinks local address as global.
Also the console shows "App running at: Local: localhost:8080 Network: xxx.xxx.xxx.xxx:8080" where xxx.xxx.xxx.xxx is local IP address (I think this is meaningless).

the devServer options have their own options property in vue.config.js because we process them internally before handing them to the devserver:

module.exports = {
  configureWebpack: {
    // other webpack options to merge in ...
  },
  // devServer Options don't belong into `configureWebpack`
  devServer: {
    host: '0.0.0.0',
    hot: true,
    disableHostCheck: true,
  },
};

Oops, my fault... thanks for pointing out.
But still, two other problems persist.
I think address.ip() used here is something meant to get local IP address, unlike other things like this and this?

  • Local IP address is shown in console
  • HMR fails because sockjs tries to connect to local IP address
  • ~App cannot be accessed from outside the network, so I have to use tricks like ssh port forwarding~

The code you mention should not be running if I set the host option (to your external IP)

So you mean the right configuration is not host: '0.0.0.0', but host: 'ggg.ggg.ggg.ggg', where ggg.ggg.ggg.ggg is my global IP address, right?
It also didn't work (of course no other process is listening to 8080, just to make it clear):

$ npm run serve

> [email protected] serve /***/***/***/***
> vue-cli-service serve

 INFO  Starting development server...
Starting type checking service...
Using 1 worker with 2048MB memory limit
 10% building modules 1/1 modules 0 activeevents.js:183                            
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRNOTAVAIL ggg.ggg.ggg.ggg:8080
    at Object._errnoException (util.js:992:11)
    at _exceptionWithHostPort (util.js:1014:20)
    at Server.setupListenHandle [as _listen2] (net.js:1338:19)
    at listenInCluster (net.js:1396:12)
    at GetAddrInfoReqWrap.doListen [as callback] (net.js:1505:7)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:97:10)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] serve: `vue-cli-service serve`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] serve script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/ec2-user/.npm/_logs/2018-06-21T07_43_06_386Z-debug.log

Hm, I see...

Side question: why do you want to run the development server on a remote machine?

Well, I thought that occurs everywhere... at least in the companies I have been at :)
Manager gives an EC2 instance to each developer, and they do their development on that machine.
This way provisioning is easy and you can destroy and rebuild machines at any time.
Plus you can limit resource access (e.g. RDB) within the network (on the cloud).
Another good point is I usually use my Windows PC but can develop on Linux.

Out of curiosity, when you develop on localhost, then I wonder why HMR wants to connect to the server via local network address, not localhost.

So first, a small update. the devServer.public setting should allow you to set the public host to 0.0.0.0:8080

 devServer: {
    // setting host should not be necessary
    // host: '0.0.0.0:8080'
    public: '0.0.0.0:8080'
    disableHostCheck: true,
  },

Out of curiosity, when you develop on localhost, then I wonder why HMR wants to connect to the server via local network address, not localhost.

It doesn't do that for me. An that's a different scenario that yours, where you do access from an external host, right?

I think setting devServer.public to 0.0.0.0 is a misconfiguration. The linked docs say:

When using inline mode and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on window.location, but if that fails you'll need to use this.

Based on my testing, the address given for devServer.public is what the (browser) client will use when attempting to open a websocket connection for HMR. So if you set it to 0.0.0.0 it won't be able to open the websocket because that's not a routable IP.

Something that can be confusing is the auto-detection can end up using an IP from a purely local network adapter. For example, the yarn serve defaults give me:

App running at:
  - Local:   http://localhost:8080/
  - Network: http://10.0.75.1:8080/

That 10.0.75.1 IP is for DockerNAT. It's only accessible from my machine. I've always thought you can bind to localhost and 0.0.0.0 reliably and beyond that you need user specific config. Where does the 10.0.75.1 get detected?

The Network IP (10.0.75.1) is the same IP that is used (by default) for the HMR websocket for me. Where is that default getting set? If vue-cli-service serve is setting it, I don't think it should. The window.location strategy described in the Webpack docs seems like the most reliable way to do it. If that doesn't work, I can't think of a way you'd be able to figure it out (reliably) without having the user specify it. Is there another way?

What exactly is the Network address being reported? When I set devServer.public to an alternate IP, the HMR websocket connection uses the newly set IP (as expected), but yarn serve still reports Network: http://10.0.75.1:8080/.

It also seems like the server binds to 0.0.0.0 even though the above App running at message gives the impression it bound to 2 specific interfaces. By default, I can access the server from another PC on my LAN. If I set devServer.host to 0.0.0.0, there's no change:

// vue.config.js
module.exports = {
    devServer: {
        host: '0.0.0.0',
    },
}

gives:

App running at:
  - Local:   http://localhost:8080/
  - Network: http://10.0.75.1:8080/

The app is still accessible from my LAN. If I set devServer.host to localhost something doesn't like it:

App running at:
  - Local:   http://localhost:8080/
  - Network: undefined

However, the app is only accessible at localhost which makes sense since I set host to localhost.

Is the goal to avoid giving the user http://0.0.0.0:8080 as an address? If so, maybe you could do something like this (ignoring https options):

Server listening at:
- Host: devServer.host
- Port: devServer.port

Then, if devServer.host is 0.0.0.0 (this always includes localhost):

App available at:
- Local:  http://localhost:devServer.port
- Public: devServer.public or 'None'
See: https://webpack.js.org/configuration/dev-server/#devserver-public

Otherwise:

App available at:
- Local:  http://devServer.host:devServer.port
- Public: devServer.public or 'None'
See: https://webpack.js.org/configuration/dev-server/#devserver-public

The --public option described in the Webpack Docs doesn't seem to pass through on the CLI. Is it supposed to? Ideally the OPs case would be solved by (note: this does not work currently):

yarn serve --host "0.0.0.0" --port "8080" --public "mydomain.example.com:8080"

with the output:

Server listening at:
- Host: 0.0.0.0
- Port: 8080

App available at:
- Local:  http://localhost:8080
- Public: http://mydomain.example.com:8080
See: https://webpack.js.org/configuration/dev-server/#devserver-public

@kissge Try this vue.config.js:

// vue.config.js
module.exports = {
    devServer: {
        host: '0.0.0.0',
        port: '8080',
        public: 'mydomain.example.com:8080',
    },
}

Note that you must be able to connect to mydomain.example.com on port 8080.

@LinusBorg A decent use case for wanting to do this is to have a site / app running on an alternate device during development. For example, at the moment I'm playing around with an app on a Raspberry Pi. The screen is fairly low resolution (800x480), the color reproduction isn't comparable to the monitor I use for development, and I want to test the touch input. It's useful to have it plugged in beside me auto-reloading as I make changes.

@ryanjaeb You can use my patch/workarround to solve this issue, look here #1905

So, the inference for public network API has its limitations, but you can always explicitly specify the public URL to use with devServer.public in vue.config.js.

In ccc90c98 I've also added:

  • allow specifying devServer public url via vue-cli-service serve --public your/url:port
  • made the console message prioritize this value.

I think vue create my_project_name should also generate a vue.config.js file at the root of the project with the default configuration (and maybe hostCheckoption set to true)

@lux-lth yeah, that was my confusion here too. It took quite a bit of research over GH issues and webpack questions to find out that one can just create a vue.config.js in the root of the project, with the contents that Linus suggested above. Thanks!

I've found this issue looking for a solution where a device connected through Chrome's port forwarding was trying to connect to the hot reloading module in my local IP address (192.168.0.250) instead of localhost (Chrome port forwarding only works on localhost), causing the hot reloading module not to work on mobile.

Based on what is written in this issue, my vue.config.js:

const fs = require("fs");
const path = require("path");
const port = 18001; // Easy to change the port here

function resolvePath(dir)
{
    return path.join(__dirname, "certificates", dir); // c:\project\certificates contains my self-signed HTTPs certificates
}

module.exports =
    {
        lintOnSave: false,
        baseUrl: `https://localhost:${port}/`,
        devServer:
        {
            https: // Only needed if you want https (I need them for location and web notifications)
            {
                key: fs.readFileSync(resolvePath("server.key")),
                cert: fs.readFileSync(resolvePath("server.crt")),
                ca: fs.readFileSync(resolvePath("server.pem.key"))
            },

            headers:
            {
                "Access-Control-Allow-Origin": "*"
            },

            overlay: true,
            port, // This will take care of desktop machine
            public: `0.0.0.0:${port}`, // This will take care of mobile device
            disableHostCheck: true,
        }
    };

And it works (there is a huge warning on Android because of not trusted certificate, but that's another issue).

 DONE  Compiled successfully in 302ms                                                                                                                                                           16:30:24
                                                                                                                                                                          Type checking in progress...

  App running at:
  - Local:   https://localhost:18001/
  - Network: https://0.0.0.0:18001/

No type errors found
Version: typescript 3.1.6
Time: 609ms

I think this is a bug, because it occurs when creating the default template with all defaults settings too:

So I've run vue create hello-world --default:

vue create hello-world --default        


Vue CLI v3.2.1
✨  Creating project in /Users/piotrblazejewicz/git/pwa-builder-test/hello-world.
πŸ—ƒ  Initializing git repository...
βš™  Installing CLI plugins. This might take a while...


> [email protected] install /Users/piotrblazejewicz/git/pwa-builder-test/hello-world/node_modules/fsevents
> node install

[fsevents] Success: "/Users/piotrblazejewicz/git/pwa-builder-test/hello-world/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node" is installed via remote

> [email protected] install /Users/piotrblazejewicz/git/pwa-builder-test/hello-world/node_modules/yorkie
> node bin/install.js

setting up Git hooks
done

added 1177 packages from 761 contributors and audited 14846 packages in 41.504s
found 0 vulnerabilities

πŸš€  Invoking generators...
πŸ“¦  Installing additional dependencies...

added 26 packages from 23 contributors, updated 2 packages, moved 5 packages and audited 15136 packages in 13.117s
found 0 vulnerabilities

βš“  Running completion hooks...

πŸ“„  Generating README.md...

πŸŽ‰  Successfully created project hello-world.
πŸ‘‰  Get started with the following commands:

 $ cd hello-world
 $ npm run serve

and I've ended using Google to learn that I have to add vue.config.js with just single property to just remove those errors.

Thanks!

Not sure why yet, but after upgrade to @vue/cli-service to 3.5.3 start getting

GET http://localhost:8080/sockjs-node/info?t=1554912129403 net::ERR_CONNECTION_REFUSED

on 3.5.0 was working fine without touching vue.config.js

Same issue with @vue/[email protected]

Same issue here with an app inside VirtualBox

Cases like this happen if you are running another app (e.g. Laravel via the artisan CLI) concurrently on your network that uses the same port as your Vuejs app. So basically it is listening to both your local and network IP when running the app in your dev environment.

if you are working on Vue CLI, may not be able to configure webpack dev server directly.
instead, locate your vue.config.js file and use the sample below.

module.exports = {
  publicPath: '/',
  devServer: {
    host: 'localhost',
    port: 3000
  }
}

Maybe i don't get something essential but i think i encounter some behaviour with cli version4 that seems to be the same thing and nothing here on this page seems to completely help:

I do a standard vue create, without any vue.config.js file in the root dir, and npm run servetells me:
App running at:

Calling it in the browser the page gets loaded fine but the console gives me (cross-origin) warnings: xxx.xxx.xxx.xxx:8081/sockjs-node/info?t=1579649486458 could not be read, one by one, adding up.

Then, after adding a vue.config.js file in the root folder with the content suggested by phalconVee npm run servetells me:
App running at:

and the warnings are gone.
Still, _the browser now connects to http://localhost:8081 two times_ for each XHR:

[HMR] Waiting for update signal from WDS... log.js:24
XHRGEThttp://localhost:8081/sockjs-node/info?t=1579650320832
[HTTP/1.1 200 OK 1ms]

XHRGEThttp://localhost:8081/sockjs-node/info?t=1579650320833
[HTTP/1.1 200 OK 2ms]

What would i have to do to have no extra network participating at all?
Like with vue init webpack ...

In Ubuntu 18.04.03 Server Edition and with [email protected], I'm getting these error messages, when deploying my starting-page of webapp with vue.js: npm run serve

INFO Starting development server…
98% after emitting CopyPlugin

DONE Compiled successfully in 10220ms 3:02:16 PM

App running at:

    Local: http://192.168.1.7:8081/
    Network: http://192.168.1.7:8081/

GET https://192.168.1.7:8081/sockjs-node/info?t=1579780726858
net::ERR_SSL_PROTOCOL_ERROR
GET https://192.168.1.7/sockjs-node/info?t=1579780726857
net::ERR_CERT_COMMON_NAME_INVALID

sockejsError01

sockejsError02

sockejsError03

This is my vue.config.js file :

module.exports = {
  productionSourceMap: false,
  pluginOptions: {
    i18n: {
      enableInSFC: true
    }
  },
  devServer: {
    host: '192.168.1.7',
    hot: true,
    disableHostCheck: true
  }
}

How to solve the problem?

In my case I had HOST env variable in .env file. It was specified with production host which caused same error.

@alex700 in which file exactly you had HOST env variable set to production, which caused sockjs error?
I get these error messages: net::ERR_CONNECTION_REFUSED
sockejsError05
sockejsError06

@marcoippolito HOST env was specified in .env file during usage at local installation. For example if my production is example.com and local installation local.example.com and HOST=example.com is specified at local installation I have the same error in Vue.

Thanks @alex700 . I guess I miss something because I didn't specify any .env file

I think setting devServer.public to 0.0.0.0 is a misconfiguration. The linked docs say:

When using inline mode and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on window.location, but if that fails you'll need to use this.

Based on my testing, the address given for devServer.public is what the (browser) client will use when attempting to open a websocket connection for HMR. So if you set it to 0.0.0.0 it won't be able to open the websocket because that's not a routable IP.

Something that can be confusing is the auto-detection can end up using an IP from a purely local network adapter. For example, the yarn serve defaults give me:

App running at:
  - Local:   http://localhost:8080/
  - Network: http://10.0.75.1:8080/

That 10.0.75.1 IP is for DockerNAT. It's only accessible from my machine. I've always thought you can bind to localhost and 0.0.0.0 reliably and beyond that you need user specific config. Where does the 10.0.75.1 get detected?

The Network IP (10.0.75.1) is the same IP that is used (by default) for the HMR websocket for me. Where is that default getting set? If vue-cli-service serve is setting it, I don't think it should. The window.location strategy described in the Webpack docs seems like the most reliable way to do it. If that doesn't work, I can't think of a way you'd be able to figure it out (reliably) without having the user specify it. Is there another way?

What exactly is the Network address being reported? When I set devServer.public to an alternate IP, the HMR websocket connection uses the newly set IP (as expected), but yarn serve still reports Network: http://10.0.75.1:8080/.

It also seems like the server binds to 0.0.0.0 even though the above App running at message gives the impression it bound to 2 specific interfaces. By default, I can access the server from another PC on my LAN. If I set devServer.host to 0.0.0.0, there's no change:

// vue.config.js
module.exports = {
    devServer: {
        host: '0.0.0.0',
    },
}

gives:

App running at:
  - Local:   http://localhost:8080/
  - Network: http://10.0.75.1:8080/

The app is still accessible from my LAN. If I set devServer.host to localhost something doesn't like it:

App running at:
  - Local:   http://localhost:8080/
  - Network: undefined

However, the app is only accessible at localhost which makes sense since I set host to localhost.

Is the goal to avoid giving the user http://0.0.0.0:8080 as an address? If so, maybe you could do something like this (ignoring https options):

Server listening at:
- Host: devServer.host
- Port: devServer.port

Then, if devServer.host is 0.0.0.0 (this always includes localhost):

App available at:
- Local:  http://localhost:devServer.port
- Public: devServer.public or 'None'
See: https://webpack.js.org/configuration/dev-server/#devserver-public

Otherwise:

App available at:
- Local:  http://devServer.host:devServer.port
- Public: devServer.public or 'None'
See: https://webpack.js.org/configuration/dev-server/#devserver-public

The --public option described in the Webpack Docs doesn't seem to pass through on the CLI. Is it supposed to? Ideally the OPs case would be solved by (note: this does not work currently):

yarn serve --host "0.0.0.0" --port "8080" --public "mydomain.example.com:8080"

with the output:

Server listening at:
- Host: 0.0.0.0
- Port: 8080

App available at:
- Local:  http://localhost:8080
- Public: http://mydomain.example.com:8080
See: https://webpack.js.org/configuration/dev-server/#devserver-public

@kissge Try this vue.config.js:

// vue.config.js
module.exports = {
    devServer: {
        host: '0.0.0.0',
        port: '8080',
        public: 'mydomain.example.com:8080',
    },
}

Note that you must be able to connect to mydomain.example.com on port 8080.

@LinusBorg A decent use case for wanting to do this is to have a site / app running on an alternate device during development. For example, at the moment I'm playing around with an app on a Raspberry Pi. The screen is fairly low resolution (800x480), the color reproduction isn't comparable to the monitor I use for development, and I want to test the touch input. It's useful to have it plugged in beside me auto-reloading as I make changes.

Worked like magic for me :-)

Wanted to leave a comment here for folks arriving from Google looking to get this working with an ngrok tunnel. Ngrok configuration is standard http tunnel. The final working dev server config for us ended up being

devServer: {
  public: 'your-subdomain.ngrok.io',
  disableHostCheck: true,
  headers: {
    'Access-Control-Allow-Origin': '*',
  },
},

This ought to allow you to access via tunnel (including https) with hot reloading working and no CORS issues.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BusyHe picture BusyHe  Β·  3Comments

eladcandroid picture eladcandroid  Β·  3Comments

CodeApePro picture CodeApePro  Β·  3Comments

b-zee picture b-zee  Β·  3Comments

NathanKleekamp picture NathanKleekamp  Β·  3Comments