alembic
the connective tissue of your network automation layer.
alembic moves your network data from the system that holds it to the one that needs it. your dcim or ipam holds the truth about your network; alembic reads it, reshapes it into a vendor-neutral model you define, and writes it back out, to another system or to the fabric. you set the shape once, and it runs the same way every time.
under the hood it is a data-model-first converger and loader: you describe your own model, and an engine validates, plans, and applies changes across one or more backends. the open core ships adapters for netbox, nautobot, infrahub, generic rest apis, and peeringdb (read-only). a commercial layer, alembic-ops, carries that same model onto the fabric and into ops, the actual automation: config and deployment, monitoring, dns, and access.
how it works
alembic is data-model-first: you describe the model once, and the same four steps run every time.
- describe: the shape your data takes as it moves. vendor-neutral, set once.
- pull: read straight from a system you already run, through its adapter.
- map: reshape each source to fit the model, with the transformation made explicit.
- apply: see the plan, then write. pull, map, and plan are read-only; apply is the only step that writes, so nothing changes by surprise.
when not to use alembic
alembic is built to converge a vendor-neutral data model onto one or more dcim/ipam backends, and to migrate between them. it is probably the wrong tool when:
- you have a single backend and a simple one-off load. a pynetbox script or csv import is less machinery for the same result.
- your infrastructure is ephemeral or event-driven. alembic reconciles batches against a known desired state; it is not an event processor or a real-time sync daemon.
- you need built-in approval, rbac, or audit workflows. alembic is a cli that emits deterministic plans; wrap it in your own ci/review process, or use a platform that bundles those.
how it compares
most tools manage the boxes in your infrastructure graph: the state inside a single system. alembic works on the edges, the correspondence between systems. it transforms data from a source of truth into a vendor-neutral model, validates it, and converges that model onto one or more backends. each alternative below owns a box; alembic connects them:
- terraform + netbox provider: covers the apply segment for a single backend, with hand-written hcl resources. alembic builds the desired state by transforming your source of truth into the data model, then applies it to multiple backends from that one model.
- nautobot ssot / netbox diode: cover ingestion into one system. alembic does the same source-to-infra load, but through a backend-neutral model with an explicit plan/diff, and can target several backends from it.
- infrahub native sync: infrahub is itself a source of truth with its own transform/sync into infrahub. alembic keeps the data model outside any single backend, so infrahub is one destination among several.
- ansible (netbox.netbox collection): connects source data to a backend imperatively, task by task. alembic covers the same path with a typed data model, schema validation, and a deterministic create/update/delete plan.
- pynetbox / custom scripts: the same source-to-infra glue, hand-rolled. alembic provides the transformation, validation, stable uids across renames, and reproducible plans so you do not rebuild that each time.
concepts
- ir objects: typed objects with stable
uid(uuid), atype, a humankey, andattrs. - relationships: references are always by
uid, never backend ids. - plan: a deterministic list of operations (create/update/delete) generated by diffing desired ir against observed backend state.
- state store: maps
uidto backend ids (integers or uuids) per type to keep renames stable; defaults to.alembic/state.jsonand can use postgres.
quickstart
-
create an inventory file (yaml) describing your desired state. see
examples/inventory.yaml. -
validate:
- plan (writes a json plan file):
# netbox
NETBOX_URL=https://netbox.example.com NETBOX_TOKEN=... \
# nautobot
NAUTOBOT_URL=https://nautobot.example.com NAUTOBOT_TOKEN=... \
# infrahub
INFRAHUB_URL=https://infrahub.example.com INFRAHUB_TOKEN=... \
- apply:
NETBOX_URL=https://netbox.example.com NETBOX_TOKEN=... \
adapters (frontends and backends)
alembic works like a compiler: many frontends, many backends, and some adapters are both. an adapter reads (a frontend), writes (a backend), or does both, and the unifying part in the middle is the data model, the ir, the types. so the same backend is an input one day and an output the next, and supporting a new system means adding an adapter, not touching the engine.
netbox and nautobot adapters are schema-driven and resolve types dynamically via their content type/object type APIs.
the infrahub adapter uses graphql and can optionally provision missing types/fields by generating
an infrahub schema file and applying it during apply.
- any
typewith a REST endpoint can be observed and applied attrsare passed through using backend field namesref/list_reffields are resolved via state mappings during apply- custom fields and tags are mapped by adapters when supported by the backend
- netbox custom object types can be provisioned on apply when the netbox custom objects plugin is installed
relationships are validated strictly by schema and uid references.
workspace layout
crates/alembic-core: ir types, serde, validation primitivescrates/alembic-engine: loader, graph validation, planning, state storecrates/alembic-adapter-registry: adapter config + registry for the clicrates/alembic-adapter-netbox: netbox adaptercrates/alembic-adapter-nautobot: nautobot adaptercrates/alembic-adapter-infrahub: infrahub graphql adaptercrates/alembic-adapter-generic: generic rest adaptercrates/alembic-adapter-peeringdb: peeringdb adaptercrates/alembic-cli: cli binary
notes
- input files never contain backend ids.
- plans are deterministic and stable-sorted.
- deletes are gated behind
--allow-delete.
documentation
docs/index.mddocs/ir.mddocs/inventory.mddocs/map.mddocs/engine.mddocs/plan.mddocs/state.mddocs/cli.mddocs/netbox.mddocs/nautobot.mddocs/infrahub.mddocs/external-adapters.mddocs/development.mddocs/case-studies/