ctl: Bulk Import Commands
This article covers every "bulk import" command in ctl, the Xona command-line tool: adding many connections, users, groups, or relays at once instead of one at a time in the web UI.
Looking for bulk permission changes instead? (e.g. "give this group access to 50 connections at once")
ctldoesn't have a bulk permissions command today. Reach out to your Xona representative if that's what you need - this article only covers creating new connections, users, groups, and relays in bulk.
Getting ctl talking to your appliance
- Generate an API key first, in the web UI - you can't skip this. There's no plain username/password login in
ctl; it only supports API key or SSH key login. Sign intohttps://your-appliance.example.com/in a browser → your Profile → API Keys → create one. Keep the secret somewhere safe; it's only shown once. - Point
ctlat your appliance:ctl config set addr https://your-appliance.example.comThis creates
~/.ctland auto-detects whether you're talking to a CSG or an XCM. - Log in with the API key:
ctl login apikey your-usernameIt'll prompt
API Key Secret:with hidden input - paste the secret from step 1. - Confirm it worked:
ctl status getA real JSON response (CPU, memory, storage stats) means you're fully authenticated and talking to the appliance.
Before you start
- These commands need a CSV or JSON file as input. A CSV file is just a spreadsheet saved in plain-text form - Excel, Google Sheets, and Numbers can all save/export to
.csv. - Run
ctl <command> --helpat any time to see a command's exact options. - Try it on a small file first. A 2 or 3 row test file takes seconds to run and confirms your column names and formatting are right before you commit to a big import.
- If you're running
ctlon a CSG (Gateway) appliance directly, use the commands exactly as shown below. If you're runningctlon an XCM (Central Manager) that oversees multiple CSGs, most commands need one extra piece of information first: which CSG (Gateway) the new items belong to. That's called out separately under each command below.
At a glance
| I want to bulk-add... | Command | Input file type |
|---|---|---|
| Connections | ctl conn add-bulk-csv |
CSV |
| Users (optionally into groups) | ctl users add-bulk-csv |
CSV |
| Groups | ctl groups add-bulk-csv |
CSV |
| Relays | ctl relay add-bulk-csv |
CSV |
| X-Connections | ctl x-connect add-bulk |
JSON |
One important behavior difference between these, explained in full further down: for connections, if even one row in your file has a problem, none of the connections in that file get created. For users, groups, and relays, a problem row is skipped and everything else still goes through. See How a bad row is handled before running a large import.
Adding connections in bulk
ctl conn add-bulk-csv rdp my-connections.csv
The word right after add-bulk-csv is the connection type: rdp, ssh, telnet, vnc, or web.
On an XCM, add the CSG's name right before the connection type:
ctl conn add-bulk-csv MyGatewayName rdp my-connections.csv
Example: adding 3 RDP servers
name,showMonitorDialog,approvalLifetimeMin,domain,hostname,manualLogin,password,port,username
Finance Server,TRUE,120,corp.local,10.10.2.4,FALSE,MyPassword1!,3389,jsmith
HR Server,TRUE,120,corp.local,10.10.2.5,FALSE,MyPassword1!,3389,jsmith
IT Server,FALSE,60,corp.local,10.10.2.6,FALSE,MyPassword1!,3389,jsmith
Example: adding 2 SSH servers
name,showMonitorDialog,approvalLifetimeMin,hostname,manualLogin,password,port,username
PLC-01,TRUE,120,10.20.1.10,FALSE,SecurePass1!,22,admin
PLC-02,TRUE,120,10.20.1.11,FALSE,SecurePass1!,22,admin
Example: adding 2 web connections
name,showMonitorDialog,approvalLifetimeMin,appUrl
Vendor Portal,TRUE,120,https://vendor.example.com
Internal Wiki,FALSE,60,https://wiki.example.com
Column reference by connection type
Every connection type needs these three columns: name, showMonitorDialog (TRUE/FALSE), approvalLifetimeMin (a number, in minutes).
| Connection type | Extra columns needed |
|---|---|
rdp |
domain, hostname, manualLogin, password, port, username |
ssh |
hostname, manualLogin, password, port, username |
telnet |
hostname, manualLogin, password, port, username |
vnc |
hostname, manualLogin, password, port, username |
web |
appUrl only |
Tip: the built-in --help text for this command always shows the RDP column list, even when you're importing a different connection type. Use the table above instead - it's accurate for every type.
You can leave username blank if a connection doesn't need one - an empty cell is fine, just don't remove the column.
Any connection setting you don't include a column for will use Xona's standard default for that setting (for example, RDP connections default to having clipboard access turned on unless you say otherwise) - you only need to fill in what's different from the default.
Adding users in bulk (and putting them straight into groups)
ctl users add-bulk-csv my-users.csv
Example: adding 3 new employees, 2 of them into groups right away
email,fullName,initialPassword,organization,username,groups
jsmith@example.com,Jane Smith,Welcome2026!,Engineering,jsmith,"Engineers"
bwong@example.com,Bob Wong,Welcome2026!,Engineering,bwong,"Engineers,OnCall"
tclark@example.com,Tom Clark,Welcome2026!,Operations,tclark,
The groups column is optional per row - leave it blank (like Tom Clark above) to create the user without adding them to any group yet. If you're adding someone to more than one group, separate the group names with a comma and put quotes around the cell, like Bob Wong above.
Tip: if a group name in your groups column doesn't match an existing group exactly, that one group gets skipped - but the user still gets created. Double-check your group names match what's already set up before running a large import.
Adding groups in bulk
ctl groups add-bulk-csv my-groups.csv
Example: adding 2 groups, one of them tied to Active Directory and SSO names
name,adName,ssoName
Engineers,Engineering-AD-Group,engineers-sso
Contractors,,
adName and ssoName are optional - leave them blank if a group isn't tied to Active Directory or SSO (like Contractors above). name is required for every row.
Adding relays in bulk
ctl relay add-bulk-csv my-relays.csv
Example: adding 2 relays
name,host,srcPort,dstPort,maxDurationMinutes,protocol,allowListIPs
Historian Relay,historian.example.com,2020,1000,0,udp,10.0.0.5
Camera Relay,cameras.example.com,2001,1002,120,tcp,"10.0.0.5,10.0.0.6"
If you need to list more than one allowed IP address, put them all in the same allowListIPs cell separated by commas, with quotes around the whole thing: "10.0.0.5,10.0.0.6".
Adding X-Connections in bulk
ctl x-connect add-bulk my-xconnections.json
This one uses a JSON file instead of a CSV - ask your Xona representative for a template if you need one. There's no CSV option for X-Connections today.
How a bad row is handled (read this first)
This is the single most important thing to know before running a bulk import on a real, live system:
- Connections and X-Connections work all-or-nothing. If your file has 50 rows and even 1 has a problem - a duplicate name, a name that's already in use, a setting that's not allowed - none of the 50 get created. Fix the problem row and run the whole file again.
- Users, groups, and relays work row-by-row. If your file has 50 rows and 1 has a problem, that 1 is skipped and the other 49 are still created. The command will tell you in its output which rows succeeded and which were skipped and why - always check that output rather than assuming everything in the file was created just because the command finished.
Practical advice:
- Before a large connections import, double-check for duplicate or already-existing names yourself - one collision anywhere in the file stops the entire import.
- After a large user, group, or relay import, read through the command's output (or scroll back through your terminal) to confirm nothing was silently skipped.
Formatting tips that apply to every command above
- Column order doesn't matter - as long as your header row (the first row) has the right column names, you can arrange them in any order.
- TRUE/FALSE columns accept
TRUE,true,True,1for yes andFALSE,false,False,0for no. - Save your file as a standard
.csv(comma-separated) - if you're exporting from Excel or Google Sheets, use "CSV" as the file format, not "Excel Workbook" or similar. - If a cell needs to contain a comma (like a list of IPs or group names), wrap that whole cell in double quotes, e.g.
"10.0.0.5,10.0.0.6".