Provisioning¶
Provisioning prepares a fresh ESP32 to join your fleet: it generates a device key, builds (or downloads) firmware, writes the encrypted configuration, flashes everything, and registers the device in the keystore. It is done from the Provision view in C3PO and implemented by the c3po/provision/ package (config.py, builder.py, nvs.py, flasher.py).
Copland is gone
Earlier versions used a standalone copland.py script. Provisioning is now fully integrated
into the C3PO UI. There is no external script to run.
The Provision view¶
Fill in the form and click Provision:
| Field | Notes |
|---|---|
| Port | Serial port (e.g. /dev/ttyACM0); use Scan to refresh |
| Chip | esp32c6, esp32s3, esp32s3-v0.2, esp32, esp32c3, esp32s2, esp32s3-cam-n16r8, esp32-cam-aithinker |
| Device ID | Unique id; auto-generated if left empty |
| Network | WiFi (SSID + password) or GPRS (APN, SIM PIN, board profile) |
| C2 Server | IP and port the device will connect to (default :2626) |
| Firmware | Path to a local Espilon-Firmware checkout to build, or empty to use a release |
| Keystore | Path to keys.json (default keys.json) |
| Erase flash | Recommended for first-time provisioning |
What provisioning does¶
flowchart TD
A["Generate 32-byte master_key"] --> B["Build firmware (idf.py)<br/>or fetch release"]
B --> C["Generate fctry NVS binary<br/>master_key + device_id + board pins"]
C --> D["Generate config NVS binary<br/>ChaCha20-Poly1305 encrypted<br/>WiFi + server, key = HKDF(master_key)"]
D --> E["esptool: flash all partitions"]
E --> F["Save device entry to keys.json"]
- Generate the key. A random 32-byte
master_keyis created. This is the root of the device's key hierarchy. - Build or fetch firmware. With a firmware path, C3PO auto-detects the chip target (
CONFIG_IDF_TARGET), generates ansdkconfigfrom your form values, and runsidf.py build. Otherwise it uses release binaries. - Generate the factory NVS (
fctry, offset 0x14000, 24 KB). Holds themaster_key(namespacecrypto, keymaster_key), the device id, and any board-specific modem or camera pins. - Generate the encrypted config NVS. WiFi SSID/password and the Management Protocol server address are encrypted with ChaCha20-Poly1305 under a key derived from
master_keyviaHKDF-SHA256(salt = device_id). - Flash.
esptoolwrites the bootloader, partition table, NVS, OTA data, factory partition, firmware, and config at the architecture-correct offsets (Xtensa bootloader at 0x1000, RISC-V at 0x0). - Register. The device id and key are written to
keys.json.
On the next boot the device decrypts its config, connects to the Management Protocol server, and appears in the Fleet view.
Per-device binding¶
Because the master_key is generated per device and written only to that device's immutable fctry partition, every device has a unique identity. The same key derives the transport, module-signing, and config-encryption keys, so a module signed for one device will not load on another. See the security model.
GPRS and camera boards¶
For cellular boards, choose GPRS and a board profile (t-call, t-sim7070g) to auto-fill the modem pins. Camera board profiles (esp32s3-cam-n16r8, esp32-cam-aithinker) write the camera pin map to NVS, but runtime camera support is not in the current version (see planned modules). See GPRS boards and ESP32-CAM.