Files
loader/_docs/02_document/deployment/provisioning_runbook.md
T
Oleksandr Bezdieniezhnykh d244799f02 [AZ-182][AZ-184][AZ-187] Batch 1
Made-with: Cursor
2026-04-15 07:23:47 +03:00

103 lines
5.5 KiB
Markdown

# Jetson device provisioning runbook
This runbook describes the end-to-end flow to fuse, flash, provision a device identity, and reach a state where the Azaion Loader can authenticate against the admin/resource APIs. It targets a Jetson Orin Nano class device; adapt paths and NVIDIA bundle versions to your manufacturing image.
## Prerequisites
- Provisioning workstation with bash, curl, openssl, python3, and USB/network access to the Jetson in recovery or mass-storage mode as required by your flash tools.
- Admin API reachable from the workstation (base URL, for example `https://admin.internal.example.com`).
- NVIDIA Jetson Linux Driver Package (L4T) and flash scripts for your SKU (for example `odmfuse.sh`, `flash.sh` from the board support package).
- Root filesystem staging directory on the workstation that will be merged into the image before `flash.sh` (often a `Linux_for_Tegra/rootfs/` tree or an extracted sample rootfs overlay).
## Admin API contract (provisioning)
The `scripts/provision_device.sh` script expects:
1. **POST** `{admin_base}/users` with JSON body `{"email":"<string>","password":"<string>","role":"CompanionPC"}`
- **201** or **200**: user created.
- **409**: user with this email already exists (idempotent re-run).
2. **PATCH** `{admin_base}/users/password` with JSON body `{"email":"<string>","password":"<string>"}`
- Used when POST returns **409** so the password in `device.conf` matches the account after re-provisioning.
- **200** or **204**: password updated.
Adjust URL paths or JSON field names in the script if your deployment uses a different but equivalent contract.
## Device identity and `device.conf`
For serial **AZJN-0042**, the script creates email **azaion-jetson-0042@azaion.com** (suffix is the segment after the last hyphen in the serial, lowercased). The password is 32 hexadecimal characters from `openssl rand -hex 16`.
The script writes:
`{rootfs_staging}/etc/azaion/device.conf`
On the flashed device this becomes **`/etc/azaion/device.conf`** with:
- `AZAION_DEVICE_EMAIL=...`
- `AZAION_DEVICE_PASSWORD=...`
File permissions on the staging file are set to **600**. Ensure your image build preserves ownership and permissions appropriate for the service user that runs the Loader.
## Step-by-step flow
### 1. Unbox and record the serial
Read the manufacturing label or use your factory barcode process. Example serial: `AZJN-0042`.
### 2. Fuse (if your product requires it)
Run your approved **fuse** workflow (for example NVIDIA `odmfuse.sh` or internal wrapper). This task does not replace secure boot or fTPM scripts; complete them per your security phase checklist before or after provisioning, according to your process.
### 3. Prepare the rootfs staging tree
Extract or sync the rootfs you will flash into a directory on the workstation, for example:
`/work/images/orin-nano/rootfs-staging/`
Ensure `etc/` exists or can be created under this tree.
### 4. Provision the CompanionPC user and embed credentials
From the Loader repository root (or using an absolute path to the script):
```bash
./scripts/provision_device.sh \
--serial AZJN-0042 \
--api-url "https://admin.internal.example.com" \
--rootfs-dir "/work/images/orin-nano/rootfs-staging"
```
Confirm the script prints success and that `rootfs-staging/etc/azaion/device.conf` exists.
Re-running the same command for the same serial must not create a duplicate user; the script updates the password via **PATCH** when POST returns **409**.
If the admin API requires authentication (Bearer token, mTLS), extend the script or shell wrapper to pass the required `curl` headers or use a local proxy; the stock script assumes network-restricted admin access without extra headers.
### 5. Flash the device
Run your normal **flash** procedure (for example `flash.sh` or SDK Manager) so the staged rootfs—including `etc/azaion/device.conf`—is written to the device storage.
### 6. First boot
Power the Jetson, complete first-boot configuration if any, and verify the Loader service starts. The Loader should read `AZAION_DEVICE_EMAIL` and `AZAION_DEVICE_PASSWORD` from `/etc/azaion/device.conf`, then use them when calling **POST /login** on the Loader HTTP API (which forwards credentials to the configured resource API per your deployment). After a successful login path, the device can request resources and unlock flows as designed.
### 7. Smoke verification
- From another host: Loader **GET /health** returns healthy.
- **POST /login** on the Loader with the same email and password as in `device.conf` returns success (for example `{"status":"ok"}` in the reference implementation).
- Optional: trigger your normal resource or unlock smoke test against a staging API.
## Troubleshooting
| Symptom | Check |
|--------|--------|
| curl fails to reach admin API | DNS, VPN, firewall, and `API_URL` trailing slash (script strips one trailing slash). |
| HTTP 4xx/5xx from POST /users | Admin logs; confirm role value **CompanionPC** and email uniqueness rules. |
| 409 then failure on PATCH | Implement or enable **PATCH /users/password** (or change script to match your upsert API). |
| Loader cannot log in | `device.conf` path, permissions, and that the password in the file matches the account after the last successful provision. |
## Security notes
- Treat `device.conf` as a secret at rest; restrict file permissions and disk encryption per your product policy.
- Prefer short-lived credentials or key rotation if the admin API supports it; this runbook describes the baseline manufacturing flow.