When something breaks
Site works locally but not after deploy: localhost, 0.0.0.0 and PORT
In short
A site that works locally but will not open after deploying usually listens on localhost (127.0.0.1) instead of 0.0.0.0, or on its own hardcoded port instead of the one in the PORT environment variable. Localhost accepts connections only from inside the same machine, so the platform cannot reach the app from outside, even though the logs say it is running. The fix is two changes to the start command: bind to 0.0.0.0 and read the port from the PORT environment variable. On Netrun the platform sets PORT for you and tells you when the app listens only on localhost.
- The address 127.0.0.1, also called localhost, accepts connections only from programs on the same machine, so an app bound to it is unreachable from outside.
- The address 0.0.0.0 means accept connections on every network interface, and it is what hosting platforms and containers expect.
- A hosting platform tells the app which port to use through the PORT environment variable, and the app has to listen on exactly that port.
- Flask, uvicorn, gunicorn and the Django development server listen on 127.0.0.1 by default, so they need 0.0.0.0 set explicitly.
- Django also checks the site address against ALLOWED_HOSTS and returns 400 Bad Request when the address is not listed.
A familiar picture: on your computer the site opens at localhost:5000, you deploy it, the logs say Running on or Uvicorn running, and the link shows nothing, a 502 error or an endless spinner. The app really is running. It is just waiting for visitors at the wrong door: it listens on an address nobody outside can reach, or on a port nobody knocks on.
Here it is without networking jargon. Localhost, also known as 127.0.0.1, means insiders only: only programs on the same machine can connect to it, which is why everything works on your laptop. 0.0.0.0 means anyone who arrives over the network: the app accepts connections from everywhere, including from the platform that forwards visitors to it. The port is the number of the door the platform knocks on, and hosting platforms pass it to your app in the PORT variable.
| Framework | How to start it | Listens on by default |
|---|---|---|
| Flask | app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 8080))) or gunicorn --bind 0.0.0.0:$PORT app:app | 127.0.0.1:5000 |
| FastAPI (uvicorn) | uvicorn main:app --host 0.0.0.0 --port $PORT | 127.0.0.1:8000 |
| Django | gunicorn project.wsgi --bind 0.0.0.0:$PORT, and add the site address to ALLOWED_HOSTS | 127.0.0.1:8000 |
| Express (Node.js) | app.listen(process.env.PORT || 3000) with no host argument, or with 0.0.0.0 | all addresses when no host is given |
| Next.js | next start -H 0.0.0.0 -p $PORT (next start also reads PORT on its own) | port 3000 |
| Vite (preview) | vite preview --host 0.0.0.0 --port $PORT | localhost:4173 |
| Streamlit | streamlit run app.py --server.address 0.0.0.0 --server.port $PORT | port 8501 |
Check in the logs which address and port the app listens on#
Almost every web server prints where it waits for connections when it starts: Running on http://127.0.0.1:5000, Uvicorn running on http://127.0.0.1:8000, Listening on port 3000. Open the startup logs and find that line. If it says 127.0.0.1 or localhost, the address is the problem. If the address is 0.0.0.0 but the port is not the one the host provides, the port is the problem. If there is no such line at all, the app crashed earlier, so look at the error above it.
Replace localhost with 0.0.0.0#
Find the place in your code or start command where the address is set and change it to 0.0.0.0. In Flask that is the host argument of app.run, in uvicorn and Streamlit the --host and --server.address flags, in gunicorn the --bind flag with address and port joined by a colon. In Express you can simply leave the address out, and Node.js then listens on every address at once. If the code explicitly says localhost or 127.0.0.1, remove it.
Read the port from the PORT environment variable#
The host decides which port your app should use and passes it in the PORT environment variable. If 5000, 8000 or 3000 is hardcoded, the app starts, but the platform knocks on a different door. In Python read it as int(os.environ.get('PORT', 8080)), in Node.js as process.env.PORT, and in start commands as $PORT. The fallback value is only for running on your own computer. Netrun sets PORT for you, and for a project with its own Dockerfile the port is taken from the first EXPOSE line.
For Django, add the site address to ALLOWED_HOSTS#
Django has an extra check: it answers only requests to addresses listed in ALLOWED_HOSTS. If your site address is not there, the page returns 400 Bad Request even when the address and port are set correctly. Add the domain your site opens on, or better, read the list from an environment variable so you do not have to edit code when the domain changes. And run the site with gunicorn rather than runserver, because the built-in Django server is meant for development only.
Do not deploy the front-end development server#
The npm run dev command in Vite, React and Vue projects starts a development server that listens only on localhost by default and is not built for visitors. For production you need either the built site or the preview or start mode. If your front end is a plain one without its own server, upload the source code with package.json: on Netrun the build happens on the platform, and you do not have to set an address or port at all. If you need server mode, as with Next.js or Nuxt, run its start command with 0.0.0.0 and the port from PORT.
Deploy again and open the link#
After the changes, upload the new version and check the logs again: the startup line should now show 0.0.0.0 and the port from PORT. If the link still does not open, make sure the app does not crash right after starting, in which case the logs show an error and restarts in a loop. Keep in mind that a heavy app that loads a model or a large file at startup needs some time before it starts answering.
A site that will not open after deploying is fixed in most cases by two changes: 0.0.0.0 instead of localhost, and the port from the PORT variable instead of a hardcoded number. The rule is the same for every host and every container, so code you fix once works everywhere. On Netrun the PORT variable is set automatically, the link comes with HTTPS from the start, and if your app listens only on localhost the platform tells you what to change. Try Netrun.
Common questions
What is the difference between 127.0.0.1 and 0.0.0.0?
The address 127.0.0.1, or localhost, accepts connections only from programs on the same machine. The address 0.0.0.0 means accept connections from anywhere, including over the network. On your own computer you see no difference, but on a server an app bound to 127.0.0.1 is unreachable for visitors.
Why do the logs say the site is running while the link does not open?
Because it is running on an address or port the platform cannot reach. Look at the startup line in the logs: if it says 127.0.0.1 or localhost, change the address to 0.0.0.0, and if the port does not match the PORT variable, read the port from it.
Which port should I use if the host does not tell me?
Read it from the PORT environment variable: nearly every host works this way, and your code will run on any of them without changes. Keep a fallback such as 8080 for running on your own computer, where the variable is not set.
Is it safe to listen on 0.0.0.0?
On a hosting platform, yes: the app runs in its own isolated environment, and the only traffic that reaches it comes through the public link. For a website that is the whole point. Be more careful with 0.0.0.0 on your own laptop on a public network, where the app becomes visible to everyone on the same Wi-Fi.
Do I need to change anything for a bot without a website?
No, not if the bot uses polling: it goes to Telegram for messages itself and does not wait for incoming connections, so it needs no address or port. 0.0.0.0 and PORT matter only for something that accepts requests from outside, such as a website, an API or a bot on a webhook.
How do I put a website online?
Upload your site code as a ZIP archive or from GitHub — Netrun builds it and gives you a working link with HTTPS. A static site (HTML, CSS, JS), a React app or a Python site all work. There is no domain to buy and no server or certificates to set up.
My project will not open — what should I do?
Open the project page and check its status and logs. If you cannot figure it out, email us.
What about React, Vue, Next.js, Nuxt, Svelte or Astro?
Yes, all of them work. Upload the source code with your package.json — you do not need to build the project yourself or include the built output, the build happens on our side. If your framework can produce both static pages and a server build, either works: in server mode the app should listen on the port from the environment variable. One important detail: values baked into the built front-end are visible to any visitor, so keep real keys on the server side.