Binding server to local IP or 0.0.0.0 does not work

Allow me to explain what I mean by «does not work»:

Everything works just fine when I run hugo server without any optional parameters. My website is available on http://localhost:1313 just as you would expect.

However, I’d also like to test my website from my phone (I know I can resize my browser window, but it’s not the same), so I run the server with the following command:

hugo server --bind=10.0.10.117 --baseURL=http://10.0.10.117:1313

With the following result:

Web Server is available at http://10.0.10.117:1313/ (bind address 10.0.10.117)

Using lsof and netstat, I can confirm that Hugo is running and listening to 10.0.10.117:113:

$ lsof -nP -i4TCP:1313
COMMAND   PID  USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
hugo    54512 runar   47u  IPv4 0xcb0fb61723a1db43      0t0  TCP 10.0.10.117:1313 (LISTEN)

$ netstat -an -ptcp | grep LISTEN
tcp4       0      0  10.0.10.117.1313       *.*                    LISTEN

However, opening http://10.0.10.117:1313 in any browser simply does not work. The error message is in Norwegian, so I’ll show you the output from curl instead:

$ curl -v -I http://10.0.10.117:1313
* Rebuilt URL to: http://10.0.10.117:1313/
*   Trying 10.0.10.117...
* TCP_NODELAY set
* Connected to 10.0.10.117 (10.0.10.117) port 1313 (#0)
> HEAD / HTTP/1.1
> Host: 10.0.10.117:1313
> User-Agent: curl/7.54.0
> Accept: */*
>
* Empty reply from server
* Connection #0 to host 10.0.10.117 left intact
curl: (52) Empty reply from server

There are no firewalls or network settings blocking Hugo, as running a simple Python server on the same port works just fine:

$ python -m SimpleHTTPServer 1313
Serving HTTP on 0.0.0.0 port 1313 …
$ curl -I http://10.0.10.117:1313
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.7.10
Date: Sat, 01 Jun 2019 11:48:29 GMT
Content-type: text/html
Content-Length: 263
Last-Modified: Thu, 23 May 2019 18:58:43 GMT

I don’t know how to debug this any further, and I have not been able to find any relevant posts here or on GitHub, so any help is highly appreciated!

Edit: Binding to 0.0.0.0 makes the website available on localhost and 0.0.0.0, but not on the local IP.

Hugo version: Hugo Static Site Generator v0.55.6/extended darwin/amd64 BuildDate: unknown

Can you somehow reach the mobile from 10.0.10.117?

Thought 1: There might be a firewall on either device that blocks connections from other IPs on port 1313. darwin/amd64 sounds like Mac?

Thought 2: Your mobile is on Wifi, your station is on cable network. Both are in the same router, but their network access is limited to their respective networks. If the mobile doesn’t start with 10.0.10. then in most cases it’s not in the same network.

But that’s going to be some network mumbo jumbo that you better solve on stackexchange.

0.0.0.0 is not an “official” IP, so that will probably not work in your network.

1 Like

Maybe try --port 1313 in addition to those other switches. Not sure if it can successfully work with the port specified on the baseurl. Untested but:

hugo server --bind=10.0.10.117 --baseURL=http://10.0.10.117 --port=1313
1 Like

@davidsneighbour:

Thank you for your reply!

Thought 1: I can successfully ping my phone from my MacBook. And when running the Python server on port 1313, my phone can successfully reach my MacBook.

Yes, I forgot to add that I’m running macOS 10.14.4.

Thought 2: Both my MacBook and my phone are on the same network, and both their IP-adresses are in the same subnet (10.0.10.1/24), so I am pretty confident that this is not a network issue.

Regarding 0.0.0.0: Other posts here and elsewhere suggested binding to 0.0.0.0 in order to listen to «all» interfaces.

@RickCogley:

Thank you for your reply and suggestion! However, adding the --port parameter made no difference. :frowning:

I learned something new today :wink: (about the 0.0.0.0 thing)

So, let’s concentrate on what happens when you curl the IP. -v -I basically says that it loads only the HEAD so it might be correct that the reply is “empty” because the headers are not part of the reply content. So that on closer inspection is NOT an error message but one of success.

The -I responds with content length 263, so SOMETHING is returned.

What is the output of curl http://10.0.10.117:1313? That one should at least show the 263 bytes that were delivered.

And what exactly is the error message that you get on the phone in Norwegian? Does it say “server response empty” or “server did not respond” or “server response not parsed/understandable”?

What is configured as default serveraddress in config.toml when you try? It should be 10.0.10.117 if you curl 10.0.10.117 - otherwise there is a loop of redirects.

Can you reach the website from another device in your network?

1 Like

try curl http://10.0.10.117:1313/index.html or any other direct URL on the server.

The interesting thing here is that your Python test curls don’t show this line, the Hugo one does. Maybe the Hugo server is running with some strange parameters? Maybe enabling logging so that all requests to Hugo server are logged will bring something to enlighten us.

I googled TCP_NODELAY and to my understanding it basically sends out content as soon as it is created as opposed to waiting for a certain amount of content to be collected before sending (like ob_flush in PHP).

1 Like

I apologize, I should have been clearer in my first post. I ran curl against Hugo and the Python server using different arguments, and both servers served different content. Also, the content length of 263 was actually a random file being served by the Python server, it had nothing to do with Hugo.

So I ran the commands again, with the same arguments, to make the results actually mean something.

Hugo, with the bind and baseURL params:

$ hugo server --bind=10.0.10.117 --baseURL=http://10.0.10.117
Web Server is available at http://10.0.10.117:1313/ (bind address 10.0.10.117)

Curl, with the verbose flag:

$ curl -v http://10.0.10.117:1313/index.html
*   Trying 10.0.10.117...
* TCP_NODELAY set
* Connected to 10.0.10.117 (10.0.10.117) port 1313 (#0)
> GET /index.html HTTP/1.1
> Host: 10.0.10.117:1313
> User-Agent: curl/7.54.0
> Accept: */*
>
* Empty reply from server
* Connection #0 to host 10.0.10.117 left intact
curl: (52) Empty reply from server

Note that binding to 0.0.0.0 gives the same result.

Python, serving an empty index.html file:

$ python -m SimpleHTTPServer 1313
Serving HTTP on 0.0.0.0 port 1313 …

Curl, with the verbose flag:

$ curl -v http://10.0.10.117:1313/index.html
*   Trying 10.0.10.117...
* TCP_NODELAY set
* Connected to 10.0.10.117 (10.0.10.117) port 1313 (#0)
> GET /index.html HTTP/1.1
> Host: 10.0.10.117:1313
> User-Agent: curl/7.54.0
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/2.7.10
< Date: Sat, 01 Jun 2019 19:03:34 GMT
< Content-type: text/html
< Content-Length: 0
< Last-Modified: Sat, 01 Jun 2019 19:02:47 GMT
<
* Closing connection 0

I cannot see anywhere to set the default «server address» in config.toml, the only relevant variable seems to be baseURL.

I enabled logging (hugo server --bind=10.0.10.117 --baseURL=http://10.0.10.117 --verboseLog --logFile=hugo.log), but I cannot see any trace of requests actually hitting Hugo. That is, nothing appears in the log after «Watching for config changes in …». Does that mean anything to you?

If it helps, here’s how I do it.

In short, if my laptop IP is 192.168.3.3 then I run this command:

hugo server --bind 0.0.0.0 --baseURL http://192.168.3.3:1313

And on my phone I navigate to:

http://192.168.3.3:1313/
7 Likes

Thank you, I’ve already read that post several times, so it’s nice of you to stop by! :slight_smile:

I managed to solve the problem, though, and it’s a bit embarrassing. I haven’t figured out the details yet, but it seems Little Snitch (a firewall application) blocked incoming connections, ignoring me telling it to not block anything. I’m looking into why Hugo was blocked, so I can make sure it doesn’t happen again.

Thank you all for your time and assistance!

1 Like

Ah, there you go. Little Snitch was an interesting concept for me, but I ended up uninstalling because it was just too time consuming to use. I was forever fiddling with it and trying to figure out what was connecting to what.

1 Like

Little Snitch indeed takes quite some time setting up and getting used to, but for me it’s crucial, as I’m above average paranoid about what leaves and connects to my Mac.

Enjoy the rest of your weekends! I sure will, now that I can access my local Hugo server from my phone!