Bulk import is for standing up an organisation quickly, or for moving an existing inventory into Shellius. You upload a file, Shellius shows you exactly what it would create and what already exists, you decide what to do about the duplicates, and only then does it write anything. Servers in the file can be bootstrapped automatically afterwards.
Required permissions
import.run opens the page and lets you upload. It is held by the Admin and Super admin roles by default. On top of it, each row needs the permission you would need to make that change by hand:
| Row type | To create | To overwrite an existing record |
|---|---|---|
| Customer | customers.create | customers.update |
| Server | servers.create | servers.update |
| User | users.invite | users.update |
| Group | groups.manage | groups.manage |
| Policy | policies.manage | policies.manage |
| Membership | groups.manage | groups.manage |
A row you lack the permission for fails on its own, with the missing permission named. The rest of the import carries on.
How an import runs
- Open Bulk import.
- Choose the File type. For a single CSV, pick the entity it contains — Customers, Servers, Users, Groups, Policies or Memberships. For a JSON object or a ZIP, leave it on Auto-detect (JSON object / ZIP).
- Choose the file and select Upload & preview. The limit is 25 MB.
- Review the preview. Each entity shows a count of new rows, duplicates and errors, and every row shows its action.
- For duplicates, choose Overwrite all or Skip all, or decide row by row. Duplicates are skipped unless you say otherwise.
- Select Commit import.
Rows with errors are never written. Nothing is written at all until you commit.
The Templates links on the page download a sample CSV for each entity, with the exact column names.
File formats
| Format | Use it for |
|---|---|
| CSV | One entity per file. Tell Shellius which with File type. |
| JSON | Either an array of rows for one entity (set the File type), or one object with a key per entity — customers, servers, users, groups, policies, memberships. |
| ZIP | Several entities at once, plus SSH key files. |
Inside a ZIP, a data file is matched to an entity by its name. An exact name works, and so does any name containing the entity as a word: servers.csv, servers-prod.csv and 01-servers.csv are all servers. A CSV or JSON file whose name matches nothing is reported as a warning, not silently dropped. Every other file in the ZIP, such as keys/web-01.pem, can be referenced from the keyFile column of a server row.
References use names, not IDs
Rows refer to each other by natural key: a customer by slug or name, a user by email, a server by hostname, a group or a policy by name. References are resolved against the file as well as the database, and rows are always applied in dependency order — groups, customers, users, servers, policies, then memberships — so the order of rows within your file does not matter.
Multi-value cells accept ;, , or | as a separator, or a JSON array. Boolean cells accept true, 1, yes, y or on.
Server columns
| Column | Notes |
|---|---|
hostname | Required. Also how the row is matched against existing servers. |
displayName | Friendly name. |
ipAddress | Required unless dynamicIp is true. |
dynamicIp | true for a host whose public IP can change. |
customer | Slug or name of the customer. |
environment | demo, dev, staging or prod. |
onboard | Defaults to true. Set false to add the server to the inventory without bootstrapping it. |
protocol | ssh, rdp or both. |
osType, osVersion | For example linux, Ubuntu 22.04. |
sshUser | The account Shellius connects as to onboard the host. |
password, keyFile, passphrase | How to log in for onboarding. A host can need a key and a password; give both. keyFile is a path inside the ZIP. |
sudoPassword | If sshUser needs a password for sudo. |
rdpUsername, rdpPassword | For RDP servers. |
labels | key:value pairs, for example team:web;tier:frontend. |
cloudProvider, cloudInstanceId, cloudRegion | Descriptive only. See Cloud hosts. |
A minimal servers file:
hostname,ipAddress,customer,environment,onboard,sshUser,keyFile
web-01,10.0.0.10,acme,prod,true,root,keys/web-01.pem
db-01,10.0.0.12,acme,prod,false,,Other entities
These are the columns in each downloadable template.
| Entity | Columns |
|---|---|
| Customers | name, slug, description |
| Users | email, name, role, manager, sendInvite |
| Groups | name, description |
| Memberships | group, user |
| Policies | name, effect, targetEnvironments, allowedPrincipals, maxSessionDuration, requireApproval, autoApprove, priority, subjectGroups, approverGroup, approverRoles |
Imported users are created in the invited state. An imported policy obeys the same rules as one made by hand, so autoApprove cannot grant unreviewed production access — see Access policies.
Onboarding after the import
For each server row with onboard left on and a password or key supplied, Shellius bootstraps the host in the background once the import is committed. The Onboarding table on the import page shows each server's status and its number of attempts. A host is tried up to three times; after that the server stays in the inventory with onboarding marked failed, and you can bootstrap it from its own page instead.
A server imported with onboard set to false, or with no credentials, is inventory only. If it uses certificate authentication, nobody can connect to it until it is bootstrapped.
What happens to the credentials in your file
Login secrets in the file are encrypted the moment it is uploaded, and are kept separately from the preview, which never contains them. They exist only to onboard the host. They are wiped once onboarding finishes, and a background job deletes any that are still left six hours after upload, whether or not the import was ever committed. RDP passwords are different: they are part of the server record, and are stored encrypted with it.
Treat the file itself with the same care as the secrets in it, and delete it once the import is done.
Troubleshooting
"0 rows parsed" from a ZIP. Shellius could not tell which entity a file holds. Rename it so that one word in the name is an entity, such as servers-prod.csv. The preview's warnings name the file.
A JSON array is rejected. An array has no entity name in it. Set the File type, or wrap it in an object: { "servers": [ ... ] }.
A row fails with "You don't have the … permission". You have import.run but not the permission for that row type. See the table at the top.
A key file is not found. The keyFile value is matched against the ZIP ignoring case, folder nesting and the direction of slashes, so a wrong path is rarely the cause. Check the file is actually in the ZIP.