What is the best practice to build firmware for IoT nodes with node specific credentials

You may get some ideas by reading Access upload verbose info.

The most time-efficient way to build those firmwares is to exactly not recompile the firmware for every new node. (Okay for 15 nodes this might be feasible, but beyond that quickly not). The linked topic describes ideas on how e.g. setup a global array where the keys are stored, or by using EEPROM / the end of flash they’re stored and read from constant addresses, then the firmware is compiled once, and through the address information in the ELF file one can just manipulate the once-created .bin file at the right spots to change the keys. This is especially usefull for your LoRaWAN systems where the stuff you have to overwrite is fixed-length, in the ABP case two 128-bit AES keys and a 4-byte device address, for OTAA equivalently some EUIDs etc… Such a “read address of key arrays from ELF (or know constant address beforehand), iterate through 15 sets of keys from a csv file or wherever, duplicate original firmware.bin and inject keys in the right places” script in e.g. Python is a million times faster than having to go through the build system over and over again. This scales.

Of course you can still go through the build system, but expect the appropriate recompilation and relinking times then. Advanced scripting or environment variables should be your starting point there. For the simplest case, you can have your platformio.ini do something like

build_flags = -I${sysenv.LORAWAN_KEYS_DIR}

and then write a small wrapper script in batch, shell or Python that sets the LORAWAN_KEYS_DIR variable to the directory where the appropriate access key is stored and executes pio run to kick of compilation – this assumes that you have a folder structure like

lorawan_keys
  | - node_01
       | - access_keys.h
  | - node_02
       | - access_keys.h

and the code doing a #include <access_keys.h> to load them in – then depending on which -I flag is given to add a certain directory to the path (e.g., -Ilorawan_keys/node_01), it will find the access_keys.h file in that specific folder.

There are of course many different ways to solve that.