KOSHI0.6.0
Remote sessions
v0.6remotefield manual

Saved servers

Keep the machines this koshi dials — names, addresses, certificate fingerprints, and secrets — and reconnect when a remote link drops.

A saved server is one record on the machine you sit at: a name, an address, the fingerprint of the certificate that machine presents, and a secret. The store is readable only by its owner, and koshi remote list never prints a secret.

CommandResult
koshi remote newSave a server, asking for its name, address, certificate fingerprint and secret
koshi remote edit <SERVER>Change one saved server's name, address, certificate fingerprint or secret
koshi remote list [--format table|json]List the servers this machine has saved
koshi remote forget <SERVER>Drop one saved server
koshi remote set-secret <SERVER>Replace the secret of one saved server

Naming a server

--remote takes either the host:port a machine listens on or the name it was saved under. The first connection names the address and the certificate fingerprint, and --save-as gives it a short name:

koshi attach --remote laptop.local:7654 --certificate-fingerprint sha256:3f6a0c2e9b8d4f17a5c3e1d0b9f8a7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0 --save-as work S-quiet-heron

After that the name stands in for the address and the fingerprint:

koshi attach --remote work S-quiet-heron

A first connection from any command that takes --remote, koshi list-sessions included, saves the address, the fingerprint, and the secret. Without --save-as the server is saved with no name, and koshi remote list prints - for it. A later koshi attach --remote <address> --save-as <NAME> names it. A saved server refuses a --save-as name other than the one it has; koshi remote edit renames it.

koshi remote new saves a server without attaching to one of its sessions. See the setup walkthrough.

Certificate fingerprints

The fingerprint is the sha256 of the server's certificate, written as sha256: followed by 64 lowercase hex characters. koshi share grant and koshi share open on the server print it in each connect command, and koshi remote list prints it for each saved server.

An address that is not saved needs --certificate-fingerprint; without it the connection is refused and nothing is dialled:

koshi: invalid arguments: laptop.local:7654 is not saved, so the fingerprint of its certificate is needed: add `--certificate-fingerprint <FINGERPRINT>` with the fingerprint `koshi share grant` printed on that machine

koshi compares the fingerprint during the TLS handshake, before the secret is sent. A server that presents another certificate is refused, the secret is not sent, and the refusal names the address and both fingerprints.

A saved server accepts --certificate-fingerprint only when it matches the saved one. To change the fingerprint a saved server expects, for example after the server's certificate changed on purpose, run koshi share open on the server to print the new one, then:

koshi remote edit work

A changed fingerprint means the machine answering that address may not be the one you saved. Change the saved fingerprint only when you know why the certificate changed.

A saved server that holds no fingerprint is never dialled. The sweep leaves it out and names it on standard error with the command that fixes it:

koshi: desk holds no certificate fingerprint, so it is not dialled; run `koshi remote edit desk` and give the fingerprint `koshi share grant` printed on that machine

Editing a saved server

koshi remote edit work

It asks the same four questions with the saved values in brackets. An empty answer keeps the value in brackets, and an empty secret keeps the saved secret, so only what changes is typed:

$ koshi remote edit work
press Enter to keep the value in brackets. An empty secret keeps the saved one. Ctrl-C stops without saving.
name [work]:
address [laptop.local:7654]: laptop.local:7655
fingerprint [sha256:3f6a0c2e9b8d4f17a5c3e1d0b9f8a7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0]:
secret:
checking laptop.local:7655 …
updated work at laptop.local:7655.

The check dials the server with the fingerprint the answers settled on. When it does not pass, the last question is save the change anyway? [y/N].

Nothing is written until every answer has settled. Ctrl-C at any question, and input that ends before an answer arrives, leave the saved server unchanged.

Rotating a secret

Once the serving machine grants a fresh secret:

koshi remote set-secret work

It reads the new secret the way a connection does — from KOSHI_REMOTE_SECRET, or asked for at the terminal.

A --remote connection to a saved server presents the saved secret. If KOSHI_REMOTE_SECRET holds a secret no saved server holds, the connection is refused before it opens and names koshi remote set-secret. A bare koshi list-sessions and a bare koshi attach present each saved server's own secret and do not read KOSHI_REMOTE_SECRET.

Two koshi processes at once

The store is read again at the moment the record is written, and the read and the write are held against every other koshi by a lock on remote/servers.lock beside the store.

  • A server another koshi saved while the questions were open is still saved, and a name or address that another record took meanwhile is refused with nothing written.
  • Every command that changes a saved server takes that lock, koshi attach included, which stamps the record it dialled.
  • A lock another koshi still holds after five seconds reads koshi: IPC unavailable: another koshi is changing the saved servers; try again. The operating system releases the lock if the koshi holding it dies.
  • The lock is never held while a question waits for an answer.

An edit re-reads its record at that same moment. A record whose name, address, secret, or fingerprint another koshi changed while the questions were open is refused, and the older values are not written:

koshi: invalid arguments: work changed while the questions were open, so nothing was saved; run `koshi remote edit work` again

The sweep

A bare koshi list-sessions and a bare koshi attach sweep every saved server and append what answered. The sweep waits two seconds in total, not two seconds per server. A server not heard from inside that wait is left out:

koshi: work did not answer; its sessions are not listed

A server whose connection fails is left out too, and its line carries the same sentence koshi attach --remote work prints for that failure, naming what to do.

Reconnecting

remote-reconnect is on by default and belongs to the terminal you sit at. It applies only to a terminal viewing a session on another machine.

A link drops when it breaks, or when no byte arrives over it for remote-link-timeout-ms (30 seconds by default). A dropped link dials that machine again — after 1 second, then 2, 4, 8, and 8 before every dial after that — for up to 120 seconds. While it waits, the tab strip reads a tag shaped like:

RECONNECTING (attempt 4, retry in 8s)

The first number is the dial it is about to make; the second is the seconds left before that dial. While a dial runs, the tag reads RECONNECTING (attempt 4, dialing).

Joining again puts back the tab you were on, the focused pane of each tab, the fullscreened pane of each tab, the scroll offset of each pane, and your floating panes. Keys and pastes typed while the link is down are dropped. The quit keybinding leaves at once while the link is down; koshi prints the commands that list and rejoin the session, and exits 0.

Each dial reads the saved server as it is at that moment, so a koshi remote edit or koshi remote set-secret made while attached takes effect at the next dial.

A refusal no dial can change stops the dialing at once: a certificate that is not the expected one, a token the server does not admit, a token that does not reach the session, two builds sharing no protocol version, or no saved server at that address any more. koshi then puts your terminal back the way it found it, prints the cause, the session continues without you, and the commands that list and rejoin the session, and exits with a non-zero status.

Off, a dropped link ends the terminal, printing how to attach again by hand. A link to a session on this machine ends the terminal either way.

koshi.kdl
version 2
remote-reconnect #true

On this page