Config Manager Render Service
Overview
The NVIDIA Config Manager Network Template Render Service is an event-driven microservice that automatically generates and versions network device configurations. The configured DCIM provider supplies device data and change events; the built-in nautobot-2x provider remains the default. Rendered configurations are stored in the Config Store.
Architecture
The service consists of three main components: the API, the event consumers, and the event dispatcher.
API endpoints
You can use the render service’s API endpoints to trigger the rendering of network device configurations.
POST /v1/render/{device_uuid}/render- Render the configuration for a single devicePOST /v1/render/all- Queue renders for all devices that are enabled for renderingPOST /v1/render/batch- Queue renders for a list of devices
Event Consumers
Two specialized pull-based consumers process NATS JetStream events:
The DCIM event consumer responds to provider-neutral change events for objects such as devices, interfaces, cables, and IP addresses. The consumer validates the event envelope, dispatches it to model-specific handlers, and queues device renders. The built-in Nautobot provider translates its legacy changelog payload at the provider boundary during the compatibility window.
The device change consumer responds to queued render requests from event handlers. It executes renders with distributed locking and updates the Config Store.
External NATS administration
External NATS deployments using password or JWT authentication must provide a tls:// or wss:// endpoint. Secure WebSockets (wss://) establish TLS before the NATS handshake and do not require the native NATS handshake_first setting. Native tls:// endpoints must enable TLS-first negotiation on the server. Add handshake_first: true to the server’s existing tls block, retaining the deployment’s certificate and verification settings:
For native tls:// endpoints, the password- or JWT-authenticated client performs TLS before reading the initial server INFO message and does not fall back to INFO-first negotiation. NATS defaults to sending INFO before TLS, so a server without this setting can cause a TLS error or connection timeout even when its certificates and credentials are valid. The Helm chart does not configure an externally managed server; coordinate this setting with its administrator before connecting.
TLS-first avoids relying on an unauthenticated INFO message to request encryption before sending credentials. This requirement applies to external password and JWT authentication; the bundled nats:// deployment retains its existing negotiation behavior.
The bundled NATS deployment creates the streams automatically. The application creates missing durable consumers at runtime in both bundled and externally managed deployments. When NATS is owned outside the Config Manager deployment, coordinate the streams, account imports, and user permissions with the NATS administrator. An administrator can own consumer provisioning instead by omitting create permission and provisioning the fixed durables described below.
The application uses three fixed durable names in every deployment:
Each stream also has an apiPrefix value. Its default, $JS.API, addresses JetStream in the connected account directly. Override it when the stream belongs to another NATS account and its JetStream API service export is imported under a different local subject prefix. For example:
The prefix is configured per stream because the Config Manager stream can remain local while the Nautobot event stream is imported from another account. It is a local routing prefix, not a stream or consumer name. The NATS user permissions and account service imports must refer to the selected prefix.
For each render pull-consumer <prefix>, <stream>, and <consumer> tuple, the application account needs these consumer subjects:
The account also needs the ordinary data-plane permissions for its configured subjects: subscribe access to request/delivery inboxes, permission to publish acknowledgements to the reply subjects supplied by JetStream, and publish access to any event subjects produced by the application. In an account-import design, the owning administrator must export the corresponding JetStream service subjects and the application account must import them at apiPrefix.
When temporal.archive.enabled=true, the archive service consumes archiveSubject through the fixed archiveConsumer.name and archiveConsumer.deliverySubject. It requires consumer INFO and durable CREATE for that exact stream and durable, subscribe access to the configured delivery subject, and publish access to JetStream acknowledgement subjects. The archive service creates the push durable when it is missing. An administrator can provision the same durable with deliver_policy=new, ack_policy=explicit, ack_wait=360s, max_deliver=-1, the configured filter and delivery subjects, and a delivery group matching the durable name.
Clients specify their stream explicitly and do not request STREAM.INFO for externally managed streams. Stream creation, mutation, and inspection therefore remain administrator operations. When externalServices.nats.local=true, the application retains its existing stream setup behavior for local development.
An administrator-provisioned consumer should use the configured stream and filter subject with the fixed durable name, deliver_policy=new, ack_policy=explicit, ack_wait=360s, and max_deliver=-1. The application validates operational settings but does not change an existing consumer or require its delivery policy to match; the owner can retain the delivery policy chosen for a migration boundary.
If create permission is omitted and the durable is absent, the consumer logs the exact provisioning request. If delete permission is omitted, the reset API returns instructions to delete and recreate the exact durable at the stream head. Configuration mismatches likewise produce an administrator-ready update request in the consumer log.
Event Dispatcher
The event dispatcher is a dynamic event routing system that maps normalized DCIM object types to handler functions. It maintains a dispatch table for supported render impacts and exposes Prometheus metrics for event processing.
Rendering Process
The rendering process is as follows:
- Fetch normalized
RenderDatafrom the selected DCIM provider. - Render the configuration using the
nv_config_manager_templates.Renderer. - Persist the rendered files using the Config Store client.
- Record intended-configuration metadata through the DCIM provider.
Template Version Management
Template updater: Runs as a Kubernetes job after Helm installs and upgrades.
It queries the selected DCIM provider for devices with a stale template_version
and renders those devices directly with bounded concurrency. Each update uses the
device’s Redis-backed render lock.
Version tracking: A successful render records the
nv_config_manager_templates version through the selected DCIM provider. The
next template-updater job skips devices that already have the current version.
Deployment
The service uses two consumer deployments (nautobot and device), a separate
template-updater job that runs after Helm installs and upgrades, and Redis for
distributed locking. It exposes Prometheus metrics on port 8000.
The service is configured using a configuration file (config.py). The configuration file contains the selected DCIM provider settings, NATS connection details (TLS, credentials), Redis connection for locking, Config Store client settings, and environment-specific aggregate management flags. External providers configure dcim_change_stream and dcim_change_subject; empty Helm values retain the historical Nautobot stream and subject.
Monitoring
Prometheus metrics:
Event processing:
nv_config_manager_events_received- Events received through NATS (by model, instance, namespace).nv_config_manager_events_processed- Events successfully processed.nv_config_manager_events_skipped- Events skipped (no handler, device not enabled).nv_config_manager_events_failed- Events that failed processing (by exception type).nv_config_manager_event_processing_time- Event processing duration histogram.
Legacy Nautobot change compatibility:
nv_config_manager_nautobot_change_messages_receivednv_config_manager_nautobot_change_messages_processednv_config_manager_nautobot_change_messages_failednv_config_manager_nautobot_change_message_processing_time- Render durationnv_config_manager_nautobot_change_message_end_to_end_time- Nautobot publish to Config Store persist
Error handling
Exception types:
DCIMError- DCIM provider API errors, retry on transient failuresRenderException- Template rendering failures, ACK (do not retry)DeviceNotEnabledError- Device not enabled for rendering, ACKEventParseError- Malformed event data, fail counter incrementedConfigStoreException- Config store persistence errors
Consumer behavior:
- ACK: Successful processing, render exceptions (will not succeed on retry), disabled devices
- NAK: Transient failures and lock acquisition failures (5s delay)
- Consumer recreation: Any fetch/heartbeat failure triggers automatic consumer rebuild
Key design patterns
Provider-owned handler registration: The event dispatcher exposes a registration surface; the selected provider registers its own object-type handlers and owns affected-device resolution.
Pull-based consumption: Consumers fetch messages on demand instead of using push-based subscriptions, which improves flow control and horizontal scaling.
Distributed locking: Redis-backed locks prevent concurrent renders for the same device across multiple consumer instances.
Version-aware processing: The template-updater job compares the current template package version with the version recorded by the selected DCIM provider. It renders stale devices directly with bounded concurrency and per-device locks.
Provider-backed data access: Render obtains normalized device data and managed-device state from the configured DCIM provider. Template rendering runs in a thread pool using asyncio.to_thread() to avoid blocking the event loop.
Connection sharing: NATSConnectionManager shares the NATS connection across components within a process.