The ZTP server is where network devices fetch their firmware during ZTP — for new site bringup, for OS upgrades, and for NVLink firmware upgrades. Before any of those workflows can succeed, the right image has to be on the ZTP server for the device’s platform and version. This guide covers how to put it there.
The ZTP server reads from an object-storage backend configured at install time. The backend is either an S3 / Ceph bucket or a file-backed PersistentVolumeClaim; see TUI Wizard Reference - OS Images for which one your environment uses.
Either way, files are laid out as:
A manifest.json at the storage root tracks each entry’s SHA256 checksum and an optional firmware-image tag. The tag marks which file in a {platform}/{version}/ directory is the OS image the workflows should serve to devices — only one file per directory can hold the tag.
There are three ways to get an image onto the ZTP server. Pick whichever fits the situation.
Use the SHA256 published by the image’s download source (for example, the checksum listed alongside the image on enterprise.nvidia.com). The upload endpoint requires the SHA256 as a query parameter and the server stores it in manifest.json so devices and workflows can verify the file is intact.
If you do need to compute it locally as a sanity check against the published value:
Path: POST /v1/files/{platform}/{version}/{filename}
Set firmware_image=true for the actual OS / firmware image. Leave it false for supporting files (vendor pre-install scripts, signed metadata, anything else a device or workflow needs alongside the image). If you upload a different filename into a directory that already has a firmware-tagged image, the request is rejected — remove the previous file first, or upload with the same filename and overwrite=true.
The upload endpoint is an admin endpoint. There are two supported ways to authenticate.
OpenAPI UI (easiest). Open the ZTP service’s Swagger UI in a browser (https://ztp.<hostname>/docs). You will already be authenticated through the OIDC session that loaded the page, so the Try it out flow for POST /v1/files/{platform}/{version}/{filename} will pick up your session automatically. No extra header is needed.
Direct API call. Send the request to the svc-ztp.<hostname> JWT-only host and attach the OIDC access token as a bearer credential — the svc-* hostnames bypass the cookie/session path the browser uses and accept a JWT directly.
Get the bearer token using workflow-cli from the nv-config-manager checkout:
Tokens are short-lived. Re-run uv run workflow-cli login -H <hostname> --force to refresh; uv run workflow-cli auth-status reports the current cache state, and uv run workflow-cli logout clears it.
Unauthenticated requests (or requests sent to the cookie-gated hostname without a session) get 403 Forbidden.
If your environment is file-backed (ztp_storage.type: file in nv-config-manager-install.yaml) and you want the image set checked into the install config, add it to os_images:
Re-run:
The installer computes the SHA256, writes the image into {platform}/{version}/{filename} on the PVC, and updates manifest.json — tagging the entry as the firmware image. See Iterative Deployment → Add or Update OS Images.
If the PVC is NFS-backed and the API is not reachable, you can write the image straight into the mount and update manifest.json by hand:
Copy the file to {nfs-root}/{platform}/{version}/{filename}.
Use the SHA256 published by the image’s download source (e.g. enterprise.nvidia.com) — not one computed from the local copy — so the manifest matches what the vendor shipped.
Edit manifest.json at the PVC root, adding (or updating) an entry:
The tags.firmware-image field is what marks this file as the OS image for the directory. Omit it for supporting files.
Reach for this approach only when the API path is unavailable. The API and the installer keep the manifest consistent for you; hand edits are easy to get wrong.
List what is currently on the server for a platform / version:
Confirm the checksum the server recorded matches the file you uploaded:
For a global view, GET /v1/files/ lists every file with metadata and tags.
400 Bad Request — File already exists.
A file with that exact path is already on the server. Either upload with overwrite=true or pick a different version / filename.
400 Bad Request — A different firmware image already exists.
You tried to upload with firmware_image=true into a directory that already has a different filename tagged as the firmware image. Remove the previous file or re-upload using the existing filename with overwrite=true.
403 Forbidden.
The request did not arrive with an authenticated SSO identity. Confirm you are reaching the server through the Envoy gateway and that your credentials are current.
Devices fail to boot off the new image after upload.
Confirm the device’s intended-firmware.version in Nautobot matches the version segment you uploaded under, and that firmware_image=true was set on the upload — otherwise the workflow will not pick it as the OS image. See Switch OS Upgrade → Prerequisites for the pairing.