OTA password in separate file

I would like to put the ota password in a separate file that is not uploaded to GitHub. So far I’ve managed to put the password in the code using a “pre” python script:

Import ("env")
import os

password = ""

with open("ota_password.txt") as f:
  password = f.readline()

env.Append(CPPDEFINES=[("OTA_PASSWORD", "\\\"" + password + "\\\"")])

But now the password should also be replaced in the platformio.ini upload_flags. I’ve read all the documentation I found but so far I found nothing that worked. Is there a way to access the CPPDEFINES variables in platformio.ini or is there another way to pass variables from the python script to the ini file?

Here is my platformio.ini file:

default_envs = release

platform = espressif32
board = featheresp32
framework = arduino
board_build.partitions = min_spiffs.csv
extra_scripts = pre:ota_password.py

upload_protocol = espota
upload_port =
upload_flags =


You are already telling PlatformIO to read the OTA_PASSWORD variable from the system environment variables here – have you tried doing a import os and os.environ["OTA_PASSWORD"] = password in your script?

You can also always fallback to a custom upload method as outlined in the docs. In the upload logic, you can basically duplicate the pre-existing logic and just add your --auth param.

1 Like

Yes I’ve already tried setting the environment variable with os.environ["OTA_PASSWORD"] = password, but for some reason this doesn’t work.

I also found the custom upload method, but I want to be able to easily switch from debug with usb upload to release with ota upload. Is this also somehow possible with this method?

I’ll try myself with the environment variable way… maybe it creates the variale in a different shell session than the one the uplaod takes place.

1 Like

I work with Visual Studio Code on a Mac. Maybe there is something different?

Is it maybe possible to read the parameters from the platformio.ini file in the python script? This way I would be able to get the default_envs config and only add the upload method if the release build is configured.

Just throwing this out there… extra_configs. Never used it myself, but it lets you define extra configurations in a seperate file. In a pinch, defining an env with your password as a build flag, and then importing that env via extendsand maybe some other glue might do the trick? Another possibility anyway.

I found a different solution in the meantime. I now simply check the PIOENV variable in the Python script to determine if debug or release is selected. Here is my Python script:

Import ("env")
import os.path


if os.path.isfile("ota.txt"):
  lines = open("ota.txt","r").read().splitlines()

  port = lines[0]
  password = lines[1]

  env.Append(CPPDEFINES=[("OTA_PASSWORD", "\\\"" + password + "\\\"")])

  if env["PIOENV"] == "release":
        UPLOAD_FLAGS=["--port=8266", "--auth=" + password],
  env.Append(CPPDEFINES=[("OTA_PASSWORD", "\\\"defaultPassword\\\"")])
1 Like

In case this is helpful to anyone in the future, my approach has been to read the environment variable directly from the platform.ini file.

The following assumes that you have a .env file at the project root with a variable named PW in the form of PW=yourPassword:

upload_flags =
	--auth=`awk '/^PW=/ {sub(/PW=/, ""); print;}' .env`

The /^PW=/ tells awk to only match lines that begin with PW=.

The sub(/PW=/, ""); tells awk to remove the text PW=, as it isn’t part of the password.

And finally, the print simply prints what remains (ie the actual password), so it gets set as the value for --auth.

I’m sure there are hundreds of ways to approach this, but I like that this is a simple one liner.