firebase-tools icon indicating copy to clipboard operation
firebase-tools copied to clipboard

Allow disabling IPv6 for emulators (e.g. for Codespaces port forwarding)

Open silviot opened this issue 3 years ago • 11 comments

Environment info

firebase-tools: 9.16.6

Platform: Linux

Test case

Install firebase-tools.

Steps to reproduce

Run the firebase emulators with npx firebase emulators:start

Expected behavior

All services would bind to 127.0.0.1 (and, optionally, also to [::ffff:127.0.0.1]). The codespaces port forwarding feature would work as expected.

Actual behavior

Some services (in particular the firestore emulator) only bind to IPV6 localhost:

State      Recv-Q     Send-Q              Local Address:Port          Peer Address:Port    Process                               
LISTEN   0        4096       [::ffff:127.0.0.1]:43299                  *:*       users:(("java",pid=19991,fd=78))                                               
LISTEN   0        4096       [::ffff:127.0.0.1]:8080                   *:*       users:(("java",pid=19991,fd=79))                                               
LISTEN   0        50         [::ffff:127.0.0.1]:36567                  *:*       users:(("java",pid=19991,fd=22))                                               
LISTEN   0        4096       [::ffff:127.0.0.1]:34265                  *:*       users:(("java",pid=19991,fd=53))                                               

and the codespaces port forwarding is not working.

silviot avatar Oct 19 '21 08:10 silviot

Does setting the host option to 1270.0.1 in firebase.json help? For example for Firestore (repeat for all emulators if needed):

  // ...
  "emulators": {
    "firestore": {
      "host": "127.0.0.1",
      "port": "8080"
    },
    // ...
  }
  // ...

yuchenshi avatar Nov 08 '21 22:11 yuchenshi

@yuchenshi It does help! The port is now bound to 127.0.0.1. It shows as being tcp6 though:

tcp6       0      0 127.0.0.1:8080          :::*                    LISTEN      4985/java           

and is not automatically picked up by the Codespaces port forwarding. Adding it manually there works, even though VSCode shows the message No running process: image

silviot avatar Nov 08 '21 22:11 silviot

@silviot Would you mind helping us to experiment a little bit more here? The behavior you're seeing is due to the IPv6 dual-stacking behavior in Java and can be disabled by the env var WSL_DISTRO_NAME (introduced for an unrelated issue). Would you mind trying to set that env var to any non-empty string before starting the emulators and see how it goes?

If that hack works, we can maybe change the CLI to also disable IPv6 when the env var CODESPACES is set or something.

yuchenshi avatar Nov 09 '21 19:11 yuchenshi

@yuchenshi It worked! Giving WSL_DISTRO_NAME a non-empty value made ipv6 to get skipped, and in turn the port forwarding from codespaces worked as expected.

silviot avatar Nov 10 '21 10:11 silviot

Okay, marking this as a feature request then now we have a workaround. +1 if you'd like even better support for disabling IPv6 (e.g. a better env var name or autodetect codespace) to help us prioritize! PRs welcome.

yuchenshi avatar Nov 10 '21 21:11 yuchenshi

@yuchenshi I'd like to help with this as I'm not able to get some emulators working

is there a place in the codebase where we've already established a pattern for automatically determining the environment?

In codespaces, there are env vars that exist like CODESPACES=true - so, just wondering where we could leverage this

markgoho avatar Jun 24 '22 13:06 markgoho

@markgoho we have a function that does check for that variable specifically isCloudEnvironment: https://github.com/firebase/firebase-tools/blob/master/src/utils.ts#L554-L559

(not sure how it's used throughout the codebase, but that seems like a good exercise for the reader 🙂 )

bkendall avatar Jun 24 '22 16:06 bkendall

I think the newest version no longer support this. I just upgraded to 11.14.2 and even though my firebase.json says:

 "emulators": {
    "hub": {
      "host": "127.0.0.1",
      "port": 4400
    },
    "functions": {
      "host": "127.0.0.1",
      "port": 5001
    },
    "firestore": {
      "host": "127.0.0.1",
      "port": 8080
    },
    "hosting": {
      "host": "127.0.0.1",
      "port": 5000
    },
    "auth": {
      "host": "127.0.0.1",
      "port": "9099"
    },
    "pubsub": {
      "host": "127.0.0.1",
      "port": "8085"
    }
  }

I get the following error inside of my firebase-debug.json and the emulator just shuts down immediately. I can no longer run the emulators in my circleci build.

[info] i  emulators: Shutting down emulators. {"metadata":{"emulator":{"name":"hub"},"message":"Shutting down emulators."}}
[debug] [2022-10-13T11:25:29.116Z] Error: listen EADDRNOTAVAIL: address not available ::1:4000
    at Server.setupListenHandle [as _listen2] (node:net:1415:21)
    at listenInCluster (node:net:1480:12)
    at doListen (node:net:1629:7)
    at processTicksAndRejections (node:internal/process/task_queues:84:21)

Should this be a new ticket or was this never resolved?

richtera avatar Oct 13 '22 11:10 richtera

I can add a definition for the ui port to make that particular error go away but then there is still a ipv6 listener for 4500 but that port number doesn't seem to be documented. Looking through the code.

richtera avatar Oct 13 '22 11:10 richtera

Ok to solve this you need to define more ports. There are some undocumented ones and the table inside of the docs doesn't have the names defined.

"logging": {
      "name": "logging",
      "host": "127.0.0.1",
      "port": 4500
    },
    "ui": {
      "name": "ui",
      "host": "127.0.0.1",
      "port": 4000
    },
    "hub": {
      "name": "hub",
      "host": "127.0.0.1",
      "port": 4400
    },
    "eventarc": {
      "name": "eventarc",
      "host": "127.0.0.1",
      "port": 9299
    },
    "database": {
      "name": "database",
      "host": "127.0.0.1",
      "port": 9000
    },
    "functions": {
      "name": "functions",
      "host": "127.0.0.1",
      "port": 5001
    },
    "firestore": {
      "name": "firestore",
      "host": "127.0.0.1",
      "port": 8080
    },
    "hosting": {
      "name": "hosting",
      "host": "127.0.0.1",
      "port": 5000
    },
    "auth": {
      "name": "auth",
      "host": "127.0.0.1",
      "port": "9099"
    },
    "pubsub": {
      "name": "pubsub",
      "host": "127.0.0.1",
      "port": "8085"
    }

I am not using all emulators so there might be some more in other use cases, but logging and eventarc were not easy to find (also ui was a guess as to the name of the port)

richtera avatar Oct 13 '22 11:10 richtera

v11.14.3 has better logic in it that should help with not binding to ipv6 if it's unavailable. Give that a whirl (without overriding all the things) and see if that helps?

bkendall avatar Oct 14 '22 16:10 bkendall