Skip to content

Install a key on hosts and import hosts from CSV

Two ways to get many hosts ready at once: install one of your keys on servers you can already sign in to, and import a list of hosts kept in a spreadsheet.

Install on hosts… adds a key’s public key to the ~/.ssh/authorized_keys of the account each host signs in with, on as many hosts as you pick, the way ssh-copy-id does. Each host then says whether the key was added, was there already, or was not added and why.

It works on phones and computers.

To swap a key that is already on your hosts for a new one, use Replace on all 3 hosts… on the key instead (it names how many hosts use the key; Replace on its host… for one): it puts the new key on each host, checks that it signs in, and only then takes the old one off. See Key management.

  • Each host must already let you sign in another way, for example with a password: ZestSSH signs in to it as a session to it would, then adds the key.
  • The key needs a public key. ZestSSH uses the one kept with the key, or makes it from the private key. If it can make none, the dialog says “There is no public key to export.”
  • The hosts must run Linux, BSD or macOS.
  1. Open the key:
    • On a computer: open Keys and select the key.
    • On a phone: open Manage > Keys and open the key.
  2. Choose Install on hosts… (on a phone, the server icon at the top of the key).
  3. Tick the hosts. You can search by name, address or group, and a group’s box ticks every host in it.
  4. Choose the button that names how many hosts, for example Install on 3 hosts.

ZestSSH signs in to a few hosts at a time and shows each host’s result as it comes:

ResultWhat it means
Added for deployThe key was added to the authorized keys of the account deploy.
Already there for deployThat account’s authorized keys held the key already. The file was left as it was.
Not addedThe command ran and did not add the key. Open the row for what the host printed.
FailedZestSSH could not sign in, or the command had not ended after 2 minutes. Open the row for why, with Copy details.
StoppedYou stopped the install before this host’s turn.

The line at the top says how many have it and how many do not. Copy all results copies every host’s result, with what a host printed as errors where the key was not added. Install again where it failed tries again on the hosts where it did not work. Stop ends an install that is still going: hosts whose turn has not come are not installed on.

ZestSSH runs ssh-copy-id’s own steps under sh, whatever the account’s login shell is:

  • the key goes to the command on its standard input, never in the command line,
  • ~/.ssh and authorized_keys are made where they are missing, readable by the account alone,
  • a key that is already in the file, with whatever options or comment, is left as it is,
  • otherwise the key is added at the end of the file, after a line break where the file does not end with one,
  • where SELinux’s restorecon is there, it is run on both.

The key is installed for the account each host signs in as when you connect to it, and each row names that account.

  • Free plan: an install takes up to 4 hosts at once on a computer and 2 on a phone. Squeezed has no limit (see pricing).
  • SSH hosts only, running Linux, BSD or macOS: the command runs under sh.
  • One install at a time. Closing the dialog does not stop it; open it again to see where it stands.
  • Teams: a host whose team watches its sessions is not installed on. A host whose team logs its sessions has the install in its team’s log. See Teams overview.

Import hosts from a CSV file reads a spreadsheet’s hosts, one on each line, and shows what importing does with each before anything is written. It works on phones and computers.

  • On a computer: on the Hosts page open the arrow beside New host, choose Import hosts, then CSV file under From another app. It is also in the command palette as Import hosts from a CSV file.
  • On a phone: open More > Settings > Data > Import data and choose CSV file.
  1. Choose Choose a CSV file, or copy the text and choose Paste from clipboard.
  2. Check the list. Each host shows its name, address, how it signs in, its group and tags, and what importing does with it.
  3. Untick any host you do not want.
  4. Choose the import button, which names how many hosts it imports, for example Import 3 hosts.

ZestSSH then says how many hosts came from the file. Hosts that could not be written are listed, with Copy details. Another file goes back to choosing a file.

The first line names the columns. A host column is needed; the others are read where they are there, in any order. Column names are compared without capitals, spaces, dashes or underscores, so IP Address and ip_address are both the host column.

ColumnAlso calledWhat it sets
host (needed)hostname, address, ip, ip address, server, host addressThe host’s address. It may hold a user and a port too: deploy@web-01.example.com:2222, [2001:db8::10]:22.
namelabel, title, alias, hostname alias, display nameThe host’s name. Without one, the address is the name.
portssh portThe port, 1 to 65535. Without one, 22.
userusername, user name, loginWhom the host signs in as (see How hosts sign in).
groupgroups, folder, group nameThe group, found by its name in any case, or made.
tagstag, labelsTags, separated by ;, | or ,. Up to 12 for each host.
keyidentity, ssh key, key name, key labelThe name of a key that is already in ZestSSH, to sign in with.
protocoltypessh, mosh, et or telnet. Without one, ssh.
notenotes, description, comment, commentsThe host’s note.

Other columns are left out, and the list says which (“Columns left out: …”).

An example, with a comma between fields:

name,host,port,user,group,tags,key,protocol,note
web-01,web-01.example.com,22,deploy,Production,web;nginx,,ssh,Front end
db-01,192.168.10.31,2222,postgres,Production,db,Robin's key,ssh,"Primary, read and write"
lab-pi,192.0.2.40,,pi,Lab,,,mosh,

ZestSSH reads files the way spreadsheets write them:

  • Separators: a comma, a semicolon or a tab, whichever the first line uses.
  • Quotes: a field in double quotes may hold the separator and line breaks, and "" for a quote.
  • Text encodings: UTF-8 (with or without a byte order mark), UTF-16 with a byte order mark (a spreadsheet’s “Unicode text”), and otherwise Latin-1.
  • Empty lines are skipped.

Before anything is written, each line gets one of these:

StatusWhat importing does
NewAdds it. Ticked to begin with.
Already hereA host with the same address and port is here already (the address in any case). Left out.
Twice in the fileA line before it names the same address and port. Left out.
No hostThe line names no host. Left out.
Not an addressThe host holds spaces, slashes, backslashes or control characters, or is longer than 253 characters. Left out.
Port not 1 to 65535Left out.
Not ssh, mosh, et or telnetThe protocol is none of those. Left out.

The line above the list counts them: “Hosts in the file: 40. Already here: 3. With a problem: 1.”

A whole file is refused when it is larger than 5 MB, holds nothing, or has no host column. Only the first 5000 hosts are read, and the list says so.

Everything in a file is cleaned like text from any other source: control and direction characters are removed, names, users, groups and keys are cut to 255 characters and notes to 4096.

For each host, ZestSSH looks, in this order, for:

  1. The key the file names, by its name in any case. If no key has that name, or two do, the row says so (“No key here is named …” or “Two keys here are named …”), and the user is used instead.
  2. The user the file names, in the user column or in the address. ZestSSH makes one key for each user, named like deploy (imported), which asks for the password when you connect. Importing again reuses it.
  3. Nothing: ZestSSH asks when you connect.

The hosts go into your personal space. In a team, the list also offers the vaults where you may add hosts; a key a host names is then looked for in that vault first. See Teams overview.

Import hosts (the Import button on a computer’s Hosts page, also in the File menu on a Mac and in the command palette) lists every source in one place. On a phone, More > Settings > Data > Import data has SSH config file, CSV file and Hosts from a cloud, which opens the same list.

Under From another app:

SourceWhat it reads
SSH config fileHosts from ~/.ssh/config, or a file you choose.
PuTTY sessionsSaved sessions from this PC’s registry (Windows only).
MobaXtermIts sessions export (.mxtsessions) or its MobaXterm.ini: SSH and Telnet sessions, folders as groups. Passwords stay in MobaXterm.
SecureCRTIts exported settings (.xml, from Tools > Export Settings) or a session’s own .ini file: SSH and Telnet sessions, folders as groups. Passwords stay in SecureCRT.
TermiusTermius has no export. ZestSSH explains how to use termius-export, a free, open-source tool that is not part of ZestSSH, to write an SSH config file, then choose that file. Delete the exported files when you are done: the keys in them are not encrypted.
CSV fileA spreadsheet, as described above.
ZestSSH host fileA host someone shared from ZestSSH, as a .zest file.
Paste a listOne host on each line, for an app with no export: host, user@host, host:port, user@host:port, or an IPv6 address in brackets ([2001:db8::1]:2222). Blank lines and lines starting with # are left out.

MobaXterm, SecureCRT and a pasted list show the same preview as a CSV file before anything is written.

Under Cloud and infrastructure: AWS, DigitalOcean, Hetzner, Azure, Tailscale and Proxmox. See Import hosts from a cloud.

On a computer, when the hosts in an SSH config file name private keys (IdentityFile) that ZestSSH can read, the import offers Import the key these hosts use (or Import the {count} keys these hosts use). The box starts unticked: nothing but the hosts comes in unless you tick it. Ticked, a copy of each private key goes into your encrypted vault with its host (and syncs end-to-end encrypted if sync is on); the key files themselves are not changed. A key that is left out, or could not be read, stays named in the host’s note as IdentityFile: <path>.

ZestSSH reads only a regular file of a private key, up to 64 KB, by the path the config gives (a ~ is your home folder, a relative path is next to the config file), and never a network path.