Skip to main content
Version: V3

Preview NetBox data in an existing Infrahub

Preview the sites and devices from your existing NetBox instance in an existing Infrahub. You will prepare two destination kinds, register a Sync configuration, and review a saved plan before importing inventory data. For a fresh local Infrahub and the public NetBox demo, follow the local demo tutorial instead.

Before you start​

  • Complete Start a Compose deployment and confirm READY.
  • Have NetBox and Infrahub running, with API tokens for each. The worker container must be able to reach both servers; the Docker host must also reach Infrahub to load its schema.
  • Have Python 3 with venv and pip on the Docker host for the separate Infrahub schema tool. The Sync CLI is already included in the deployment.
  • Choose an Infrahub branch where you can load the example schema. Loading the schema changes that branch's types; the later preview does not import data. If TestingSite or TestingDevice already exists there with a different definition, choose another suitable branch or adapt the schema and mapping together before continuing.

Run all commands from the extracted deployment directory on the Docker host. For Candidate 4, this is linux-amd64/infrahub-sync-compose-3.0.0a4 under the verified download.

The two YAML files have different purposes:

  • schema.yml defines the types and fields in Infrahub. Load it with infrahubctl.
  • package.yml declares the Sync source, destination, mappings, and credential references. Register it with ./infrahub-sync-compose cli.

Measured scenario​

The measured run used NetBox 4.6.10 and Infrahub 1.10.6. It does not establish compatibility with other server versions.

Set NetBox and Infrahub credentials​

Open operator.env, remove the leading #, and fill in the source and destination token entries:

NETBOX_TOKEN=<your NetBox token>
INFRAHUB_API_TOKEN=<your Infrahub token>

For NetBox 4.6, use a v2 API token. It starts with nbt_ and contains a dot; paste the complete string. For Infrahub, use an API token created under your account settings; a login password does not work here. Use source credentials that can read the mapped objects and an Infrahub token that can load schema and read those destination kinds on your chosen branch.

Do not change the generated Sync API credentials. The bundled CLI uses them to contact Sync; INFRAHUB_API_TOKEN authenticates to the destination Infrahub. Do not run source operator.env: that file also contains the deployment's internal credentials.

Prepare the destination schema​

Save the following as schema.yml in the deployment directory. Each device has a name, model, serial number, and a relationship to its site. This example requires unique site names and unique device names in the mapped data.

version: '1.0'
nodes:
- name: Site
namespace: Testing
human_friendly_id: [name__value]
uniqueness_constraints: [[name__value]]
attributes:
- name: name
kind: Text
optional: false
- name: Device
namespace: Testing
human_friendly_id: [name__value]
uniqueness_constraints: [[name__value]]
attributes:
- name: name
kind: Text
optional: false
- name: model
kind: Text
optional: false
- name: serial
kind: Text
optional: false
relationships:
- name: site
peer: TestingSite
kind: Attribute
cardinality: one
optional: false

Install the Infrahub SDK's schema tool in a host virtual environment:

python3 -m venv .schema-tools
.schema-tools/bin/python -m pip install 'infrahub-sdk[ctl]'
.schema-tools/bin/infrahubctl version

The version command must complete successfully before you continue. Replace https://infrahub.example.invalid below with the address the Docker host uses to reach Infrahub. The commands in parentheses read only the destination token from operator.env. These environment settings apply only inside the parentheses.

(
export INFRAHUB_ADDRESS="https://infrahub.example.invalid"
export INFRAHUB_API_TOKEN="$(sed -n 's/^INFRAHUB_API_TOKEN=//p' operator.env)"
.schema-tools/bin/infrahubctl branch list
)

Choose a branch from the list and replace BRANCH_NAME in every remaining command with its name. If you need a new branch, run .schema-tools/bin/infrahubctl branch create BRANCH_NAME inside the same scoped environment block before loading the schema.

(
export INFRAHUB_ADDRESS="https://infrahub.example.invalid"
export INFRAHUB_API_TOKEN="$(sed -n 's/^INFRAHUB_API_TOKEN=//p' operator.env)"
.schema-tools/bin/infrahubctl schema load schema.yml --branch BRANCH_NAME
)

Continue only after the schema load succeeds. In Infrahub, select that branch and inspect its schema: TestingSite and TestingDevice must exist, with TestingDevice.site referencing TestingSite. Resolve schema errors before continuing. Registering a Sync package does not load this schema.

Create and edit package.yml​

For an agent-assisted draft, follow Use Infrahub Sync with an AI agent, then review the package here before registration. That guide uses unreleased source skills.

Candidate 4 includes a NetBox example at linux-amd64/example-package.yml. It is beside the extracted infrahub-sync-compose-3.0.0a4 directory:

linux-amd64/
├── example-package.yml
└── infrahub-sync-compose-3.0.0a4/
├── infrahub-sync-compose
└── operator.env

From inside infrahub-sync-compose-3.0.0a4, copy it:

cp ../example-package.yml package.yml

The copied file contains the mapping below. It maps NetBox sites and devices to the TestingSite and TestingDevice kinds you loaded:

---
# Map NetBox sites and devices to TestingSite and TestingDevice in Infrahub.
# Replace both URLs and provide the matching destination schema before registration.
# Set NETBOX_TOKEN and INFRAHUB_API_TOKEN in the generated operator.env file.
format_version: 1
configuration:
name: my-netbox-evaluation
source:
name: netbox
settings:
url: https://netbox.example.invalid
token: {$credential: netbox-token}
destination:
name: infrahub
settings:
url: https://infrahub.example.invalid
token: {$credential: infrahub-token}
schema_mapping:
- name: TestingSite
mapping: dcim.sites
identifiers: [name]
fields:
- name: name
mapping: name
- name: TestingDevice
mapping: dcim.devices
identifiers: [name]
fields:
- name: name
mapping: name
- name: model
mapping: device_type.model
- name: serial
mapping: serial
- name: site
mapping: site
reference: TestingSite
credentials:
netbox-token: {provider: env, identifier: NETBOX_TOKEN}
infrahub-token: {provider: env, identifier: INFRAHUB_API_TOKEN}

Before registering package.yml:

  • Replace both URLs with addresses the worker container can reach. localhost and 127.0.0.1 inside the worker refer to that container. The destination must be the same Infrahub instance where you loaded the schema, even if the host uses a different address to reach it.
  • Keep the {$credential: ...} references in YAML; token values belong in operator.env.
  • Keep the mapping's destination kinds and fields consistent with schema.yml.

The mapping includes sites and devices only. It does not import IP addressing or interfaces. Source devices need the mapped name, model, serial, and site relationship; review source data before expecting a complete preview.

Reload credentials and register the package​

Recreate services whose environment changed, then check readiness:

./infrahub-sync-compose start
./infrahub-sync-compose status

Continue only when status reports READY and exits with status 0. start reloads the changed environment; restart retains the environment from when the containers were created.

Register your package with the included Sync CLI:

./infrahub-sync-compose cli --package ./package.yml -- \
configs register /input/package.yaml --reason 'register NetBox first preview'

With --package, the wrapper copies the host file into a temporary read-only container mount at /input/package.yaml. The wrapper removes that copy after the command. Sync stores the declared package, and the CLI prints config_id and registry_version. Record both; replace CONFIG_ID and VERSION below with those values.

Validate the configuration​

./infrahub-sync-compose cli configs validate CONFIG_ID VERSION

Read total_findings and every finding line. If next_offset is not <none>, repeat with --offset set to that value to read the remaining findings. Resolve findings with severity=error before planning; a zero command exit alone does not mean the report contains no errors.

This checks the registered package's declared content. It does not test source credentials, connectivity, or the live destination schema. The preview below performs the reads against both servers.

If you edit package.yml after registration, register a new immutable version:

./infrahub-sync-compose cli --package ./package.yml -- \
configs version CONFIG_ID /input/package.yaml --reason 'correct first-preview package'

Use the returned registry_version as VERSION, then validate it again.

Preview and review the changes​

Use the same BRANCH_NAME where you loaded the schema:

./infrahub-sync-compose cli diff --config-id CONFIG_ID --version VERSION \
--branch BRANCH_NAME --reason 'preview NetBox sites and devices'

The worker reads NetBox and Infrahub and saves a plan. The CLI waits by default, then prints run_id, plan_checksum, checksum_ok, and operation counts. Record the run ID and inspect the complete plan:

./infrahub-sync-compose cli runs plan RUN_ID --detail

Expect checksum_ok: true and operations for TestingSite and TestingDevice. On a destination with no objects of those kinds, expect creates for the mapped source records. Counts depend on your source data. Check device names, model and serial values, and each device's site relationship. An empty plan can mean the source is empty or the destination already matches it; confirm which case applies.

The preview does not create, update, or delete inventory objects in Infrahub. Against an existing destination, the plan can include updates and recorded deletes as well as creates; review every unexpected operation before proceeding.

If the run fails, inspect its record:

./infrahub-sync-compose cli runs show RUN_ID
./infrahub-sync-compose cli runs results RUN_ID

runs show reports the run's status and Prefect execution ID (flow_run_id). runs results prints saved failure evidence, including the stage and error types. The saved evidence omits exception messages. For more detail, inspect the worker logs:

./infrahub-sync-compose logs sync-worker

Find the flow_run_id from runs show in the logs to identify the Prefect flow-run name. Read the messages for that name. If they report a source connection failure, check the source URL and reachability from the worker container. Correct the cause before creating another preview. After credential edits, run start again; after package edits, register and validate the new version.

Continue​

You now have a registered configuration and a saved preview to review. For later approved writes and deployment maintenance, see the Compose operator sequence and day 2 operations.

The following notes concern larger mappings beyond this first preview.

If you map NetBox IP addressing​

For NetBox prefixes or IP addresses, the example uses the VRF name as the Infrahub namespace name. Differently named VRFs can therefore keep overlapping networks separate.

Repeated VRF names do not merge. The name-based mapping tries to load two namespace records with the same identity, so Sync refuses the run before it produces a plan or writes to Infrahub. This can happen even when the VRFs have different prefixes and addresses.

You do not have to rename VRFs in NetBox. The ID-derived namespace recipe derives distinct namespace names from NetBox VRF IDs and uses the same rule for every related prefix and address. It covers namespace, prefix, and address mappings only; copying only its namespace transform into the full NetBox example is insufficient because that example also loads VRF objects by name.

With the default name-based mapping, no-VRF data and data in a VRF literally named default use Infrahub's built-in default namespace. With the ID-derived recipe, a VRF named default gets its own ID-derived namespace; no-VRF data still uses the built-in namespace. Neither recipe merges duplicate prefixes or addresses within one namespace.

NetBox IDs belong to one source instance. Recreating a VRF or changing the naming rule changes destination identities; it does not rename an existing import. Review a migration before applying a changed recipe to existing data.

Recorded deletes when mapping namespaces​

A saved plan records destination objects absent from the mapped source, including Infrahub's built-in default namespace when no source VRF maps to that name. Apply never executes those deletes. In the measured run, the scoped name-based mapping planned eight creates and one recorded delete; after apply, the next plan contained only that delete and the ID, name, and description were unchanged. Adding a source VRF named default with matching attributes removed the delete without a configuration change. Under the ID-derived recipe it remained recorded, because every source VRF maps to its own derived name.

Review exact identities in the full plan and query the destination after apply. Expect zero remaining creates or updates after a successful unchanged mapping; do not mistake a recurring recorded delete for an executed deletion or an empty plan. Investigate any other difference before another apply.