A command-line utility for interacting with NETCONF devices, like curl but for NETCONF. Written in Acton, ncurl provides a simple interface for common NETCONF operations.
ncurl currently supports the following NETCONF operations:
- hello: Print server capabilities received during NETCONF hello exchange
- get: Retrieve operational + configuration data with optional filtering
- get-config: Retrieve configuration from a NETCONF datastore with optional filtering
- edit-config: Edit configuration in a NETCONF datastore
- rpc: Send raw NETCONF RPC XML and print the raw reply
- commit: Commit the candidate configuration to the running configuration
- discard-changes: Discard changes in the candidate configuration
- list-schemas: List all available schemas from a NETCONF server
- get-schema: Download individual or all schemas from a NETCONF server
There are pre-built binary releases for MacOS and Linux on x86_64 and aarch64 that you can download. ncurl is a single binary with no external dependencies.
curl -L -o ncurl https://github.com/stratoweave/ncurl/releases/download/tip/ncurl-macos-aarch64(or one of the other platforms / arch)chmod a+x ncurl./ncurl --help
You can build ncurl yourself from source. First ensure you have the Acton programming language installed, see the install guide.
acton buildThe easiest way to test ncurl is using notconf, a NETCONF server for testing. The published NETCONF server port (42830) and default credentials (admin/admin) align with ncurl defaults:
# Start a notconf server
docker run -td --name notconf --rm --publish 42830:830 ghcr.io/notconf/notconf
# List available schemas (--insecure skips SSH host key verification for testing)
./ncurl --insecure list-schemas
# Get running configuration
./ncurl --insecure get-config
# Get operational + configuration data
./ncurl --insecure getYou can run ncurl directly from its container image and pass command arguments
after the image name:
docker run -it --rm ghcr.io/stratoweave/ncurl:latest --helpTo use it as a sidecar with another NETCONF container (for example notconf),
share the target container network namespace:
# Start notconf without publishing a host port
docker run -td --name notconf --rm ghcr.io/notconf/notconf
# Run ncurl in the same network namespace as notconf
docker run -it --rm --network container:notconf ghcr.io/stratoweave/ncurl:latest \
--insecure --host localhost --port 830 list-schemas./ncurl [global-options] <command> [command-options]--host <hostname>: NETCONF server hostname (default: localhost)--port <port>: NETCONF server port (default: 42830)--username <username>: Username for authentication (default: admin)--password <password>: Password for authentication (default: admin)--insecure: Skip SSH host key verification (useful for testing/development)--no-fixups: Disable built-in NETCONF client fixups/workarounds--verbose: Enable verbose logging for SSH/NETCONF client debugging
Note: All examples use the --insecure flag to skip SSH host key verification. This is convenient for testing and development environments where devices may have self-signed certificates or changing host keys because of container restarts.
Print NETCONF server capabilities from the hello exchange:
./ncurl --insecure --host router.example.com helloList all available schemas from a NETCONF server:
./ncurl --insecure --host router.example.com list-schemasRetrieve configuration from a NETCONF datastore:
# Get entire running configuration
./ncurl --insecure --host router.example.com get-config
# Get startup configuration
./ncurl --insecure --host router.example.com get-config --source startup
# Apply subtree filter
./ncurl --insecure --host router.example.com get-config \
--filter-subtree '<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>'
# Apply XPath filter with namespaces
./ncurl --insecure --host router.example.com get-config \
--filter-xpath '/if:interfaces/if:interface[if:name="eth0"]' \
--xpath-namespaces 'if=urn:ietf:params:xml:ns:yang:ietf-interfaces'
# Save configuration to file
./ncurl --insecure --host router.example.com get-config --output config.xml
# Get configuration in JSON format
./ncurl --insecure --host router.example.com get-config --format json
# Get configuration as Acton GData
./ncurl --insecure --host router.example.com get-config --format acton-gdata
# Get configuration as a tree view
./ncurl --insecure --host router.example.com get-config --format treeOptions:
--source <datastore>: Configuration datastore (running, startup, candidate) (default: running)--filter-subtree <xml>: XML subtree filter--filter-xpath <expression>: XPath expression for filtering--xpath-namespaces <prefix=uri>: Namespace declarations for XPath filtering (can be specified multiple times)--format <format>: Output format (raw-xml, tree, xml, json, acton-gdata, acton-adata) (default: raw-xml)--output <file>: Output file (if not specified, prints to stdout) Tree output uses indentation, aligns leaf values across the full tree, and colorizes values on terminal output.
Example tree output:
interfaces
interface SC-1-3-C1
config type : ianaift:ethernetCsmacd
config enabled : true
state type : ianaift:ethernetCsmacd
state admin-status : UP
state oper-status : UP
interface SC-1-3-C2
config type : ianaift:ethernetCsmacd
config enabled : false
Retrieve operational + configuration data from the NETCONF server:
# Get all available data
./ncurl --insecure --host router.example.com get
# Apply subtree filter
./ncurl --insecure --host router.example.com get \
--filter-subtree '<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>'
# Apply XPath filter with namespaces
./ncurl --insecure --host router.example.com get \
--filter-xpath '/if:interfaces-state/if:interface[if:name="eth0"]' \
--xpath-namespaces 'if=urn:ietf:params:xml:ns:yang:ietf-interfaces'
# Save returned data to file
./ncurl --insecure --host router.example.com get --output data.xml
# Convert data to JSON
./ncurl --insecure --host router.example.com get --format json
# Render data as a tree view
./ncurl --insecure --host router.example.com get --format treeOptions:
--filter-subtree <xml>: XML subtree filter--filter-xpath <expression>: XPath expression for filtering--xpath-namespaces <prefix=uri>: Namespace declarations for XPath filtering (can be specified multiple times)--format <format>: Output format (raw-xml, tree, xml, json, acton-gdata, acton-adata) (default: raw-xml)--output <file>: Output file (if not specified, prints to stdout) Tree output uses indentation, aligns leaf values across the full tree, and colorizes values on terminal output.
Edit configuration in a NETCONF datastore:
# Edit candidate configuration with XML from file (no implicit commit to running)
./ncurl --insecure --host router.example.com edit-config config.xml
# Edit running configuration directly
./ncurl --insecure --host router.example.com edit-config --target running config.xml
# Read configuration from stdin (end with two empty lines or Ctrl+D)
./ncurl --insecure --host router.example.com edit-config -
# Use replace operation instead of merge
./ncurl --insecure --host router.example.com edit-config --default-operation replace config.xml
# Edit candidate and commit the changes
./ncurl --insecure --host router.example.com edit-config --commit config.xmlArguments:
config: Configuration XML file path, or-to read from stdin
Options:
--target <datastore>: Configuration datastore to edit (running, startup, candidate) (default: candidate)--default-operation <operation>: Default operation for config elements (merge, replace, none) (default: merge)--commit: Commit changes after editing (only applies when target is candidate)
Example Configuration XML:
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>eth1</name>
<description>Updated via ncurl</description>
<enabled>true</enabled>
</interface>
</interfaces>Send an arbitrary NETCONF RPC operation and print the raw <rpc-reply>:
# Send an operation element from a file
./ncurl --insecure --host router.example.com rpc get-system-time.xml
# Read RPC XML from stdin
./ncurl --insecure --host router.example.com rpc -
# Save the raw rpc-reply to a file
./ncurl --insecure --host router.example.com rpc --output reply.xml get-system-time.xmlArguments:
request: RPC XML file path, or-to read from stdin
Options:
--output <file>: Output file (if not specified, prints the raw<rpc-reply>to stdout)
ncurl manages the NETCONF message framing and outer <rpc> envelope. The
input should usually be the operation element itself, but if you provide a full
<rpc> document ncurl will unwrap and send its single child operation.
Commit the candidate configuration to the running configuration:
# Commit candidate configuration changes
./ncurl --insecure --host router.example.com commitThis command commits any pending changes in the candidate datastore to the running configuration.
Discard uncommitted changes in the candidate configuration:
# Discard all changes in candidate configuration
./ncurl --insecure --host router.example.com discard-changesThis command discards all uncommitted changes in the candidate datastore.
Download schema(s) from a NETCONF server:
# Download a specific schema
./ncurl --insecure --host router.example.com get-schema ietf-interfaces
# Download a specific version
./ncurl --insecure --host router.example.com get-schema ietf-interfaces --version 2018-02-20
# Download all available schemas
./ncurl --insecure --host router.example.com get-schema all
# Specify output directory
./ncurl --insecure --host router.example.com get-schema all --output-dir yang-models
# Download in YIN format instead of YANG
./ncurl --insecure --host router.example.com get-schema ietf-interfaces --format yinArguments:
identifier: Schema identifier or 'all' to download all schemas
Options:
--version <version>: Schema version--format <format>: Schema format (yang or yin) (default: yang)--output-dir <directory>: Output directory for downloaded schemas (default: schemas)
./ncurl --host 192.168.1.1 --username cisco --password secret \
get-config --filter-xpath '/interfaces/interface' \
--output interfaces.xml./ncurl --host 192.168.1.1 --username admin --password admin \
get-schema all --output-dir device-models./ncurl --host 192.168.1.1 --verbose list-schemasncurl is built using the following Acton libraries: