Skip to content

Bulk import

Create customers, servers, users, groups, policies and memberships from a CSV, JSON or ZIP file, with a preview and a decision on every duplicate before anything is written.

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 typeTo createTo overwrite an existing record
Customercustomers.createcustomers.update
Serverservers.createservers.update
Userusers.inviteusers.update
Groupgroups.managegroups.manage
Policypolicies.managepolicies.manage
Membershipgroups.managegroups.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 ​

  1. Open Bulk import.
  2. 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).
  3. Choose the file and select Upload & preview. The limit is 25 MB.
  4. Review the preview. Each entity shows a count of new rows, duplicates and errors, and every row shows its action.
  5. For duplicates, choose Overwrite all or Skip all, or decide row by row. Duplicates are skipped unless you say otherwise.
  6. 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 ​

FormatUse it for
CSVOne entity per file. Tell Shellius which with File type.
JSONEither 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.
ZIPSeveral 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 ​

ColumnNotes
hostnameRequired. Also how the row is matched against existing servers.
displayNameFriendly name.
ipAddressRequired unless dynamicIp is true.
dynamicIptrue for a host whose public IP can change.
customerSlug or name of the customer.
environmentdemo, dev, staging or prod.
onboardDefaults to true. Set false to add the server to the inventory without bootstrapping it.
protocolssh, rdp or both.
osType, osVersionFor example linux, Ubuntu 22.04.
sshUserThe account Shellius connects as to onboard the host.
password, keyFile, passphraseHow to log in for onboarding. A host can need a key and a password; give both. keyFile is a path inside the ZIP.
sudoPasswordIf sshUser needs a password for sudo.
rdpUsername, rdpPasswordFor RDP servers.
labelskey:value pairs, for example team:web;tier:frontend.
cloudProvider, cloudInstanceId, cloudRegionDescriptive only. See Cloud hosts.

A minimal servers file:

txt
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.

EntityColumns
Customersname, slug, description
Usersemail, name, role, manager, sendInvite
Groupsname, description
Membershipsgroup, user
Policiesname, 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.

Next steps ​

Was this page helpful?No, tell us why