When something breaks
How to set environment variables without a .env file
In short
You can set environment variables without a .env file. Your code reads them straight from the environment (os.environ in Python, process.env in Node.js), and whatever runs the app fills that environment in. A .env file is only a local convenience: libraries like python-dotenv or dotenv read it and put the values into those same variables. On a server the values should come from the platform instead, so in Netrun you enter them during project setup, they are stored encrypted, and you can change a key later without touching the code.
A .env file is great right up to the moment your project leaves your laptop. In production the same file starts working against you. It travels inside the archive or the folder you push to GitHub and takes your tokens along; people forget to update it, so the host keeps running with a key you rotated a month ago; and when the file simply is not there, the app dies with a vague error about an empty value. Hence the usual question: how to set environment variables without a .env file once the code leaves your machine.
The good news is that your code never needed the file. Dotenv libraries do nothing magic: they open the file and load its contents into ordinary environment variables, the same ones your code already reads. The usual way to handle this is to create that file on the server by hand in a terminal and then be afraid to touch it. Netrun asks for the values when you set the project up, keeps them encrypted and injects them into the environment at start: no file, same code.
Read values from the environment, not from a file#
Your code should not care where a value came from. Use os.environ or os.getenv in Python, process.env in Node.js, os.Getenv in Go, and every language has the same call. Then the exact same app runs both on your machine, where .env fills the variables in, and on a server, where the platform does.
Keep .env out of the archive and out of the repository#
Add a .env line to .gitignore so the file never reaches GitHub, and check that it is not inside the ZIP you upload. This is the most common way keys leak: the file sits in the code folder and travels with it. It also kills the second classic problem, a forgotten .env on the server holding an outdated key.
Ship a .env.example with names only#
Keep a .env.example next to your code that lists variable names with no values. It is safe to commit and it answers the question of what this project needs in order to start. Six months from now that list is mostly for you, not just for whoever inherits the code.
Enter the values during setup and change them in the same place#
When you upload code to Netrun, the platform looks at which variables the project expects and asks for the values right in the form: a bot token, an API key, a database connection string. They are stored encrypted and injected into the environment at start. You can change a value at any time in your dashboard: type the new one, save, and the project restarts with it, so the code stays as it is and you do not upload the archive again.
Rotate any key that has already reached the repository#
If a .env file or a hard-coded key has ever been pushed to GitHub, treat it as compromised, even in a private repository. Deleting the file and committing again is not enough: the old value stays in the history and is readable by anyone with access to the code. There is only one real fix — revoke the key in the service that issued it, create a new one and put it into the project settings.
Do not treat build-time frontend variables as secrets#
Variables your bundler inlines at build time — the ones prefixed with VITE_, NEXT_PUBLIC_ or REACT_APP_ — end up inside the files the browser downloads, so any visitor can read them in developer tools. An API base URL or a deliberately public identifier is fine there; a paid service key or a database password is not. Anything that must stay secret belongs to the server side, and the frontend calls that server.
The rule is simple: .env stays a local convenience, and on a server the values live apart from the code, in one place where you can see and change them. They do not ride along in your archive and they do not get lost on the next update. If the app still cannot see a variable after that, the host is usually not the problem: either the name differs from the one in your code, or the code still reads a file instead of the environment. That is fixed in the project itself and works the same way anywhere you run it.
If you would rather not move keys around by hand, you can type the values in during project setup and let the platform inject them into the environment at start, with no terminal and no files on the server. Try Netrun.
Common questions
Should I include a .env file in the uploaded archive?
No, and it is better not to. Values are entered during project setup and injected into environment variables at start, while a file in the archive only increases the chance that a key leaks with the folder. If a .env did make it into the archive, treat the keys inside as compromised and issue new ones.
Why does my app not see an environment variable?
Most often it is the name: case matters, so API_KEY and Api_Key are different variables. The second reason is code that reads a file instead of the environment, and that file is not there. The third is a value added after the app started — it needs a restart or a new deploy to apply. The project logs in your dashboard show which of the three it is.
What do I do if a key is already committed to GitHub?
Treat it as compromised and issue a new one in the service that gave it to you. Deleting the file and committing again does not clean the history: the old value stays in earlier versions and is readable by anyone with access to the code. A private repository does not save you either, since collaborators had access and the repo may have been public at some point.
How do I change a value without re-uploading the code?
Open the project in your dashboard, type the new value in the settings and save — the project rebuilds and starts with it. The code and the archive stay untouched and the project link does not change. This is also the easy way to switch a test key for a production one.
Are VITE_ and NEXT_PUBLIC_ variables actually secret?
No. Those are inlined into the site files the browser downloads, so every visitor can read them. That is fine for an API base URL or a public identifier, but not for a paid service key or database credentials, which belong on the server side.
Can I keep a database connection string in an environment variable?
Yes, that is the normal way to do it: the app reads the host, user and password from the environment and uses them when connecting. In Netrun the connection string is asked for during setup and stored encrypted. If the database runs next to the app in your own docker-compose, the address of that service is also passed as a variable rather than written into the code.
Where do I set tokens and other secret values?
Every project has a Secrets tab where you set the values from your code — for example the token from BotFather. We store them encrypted: you can see the variable names, but the values are shown to no one, including you.
Are my tokens and secrets safe?
Yes. Tokens, access keys and values from your code are stored encrypted and are never shown in plain text.
How do I update the code of a project that is already published?
Open the project and upload a new version or update it from GitHub. The link stays the same, and your data is kept as long as it lives in persistent storage — the /data folder or a volume from your compose file.