# Koshi 0.6.0 — Saved servers (/docs/v0.6/remote/servers)



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.

| Command                                    | Result                                                                          |
| ------------------------------------------ | ------------------------------------------------------------------------------- |
| `koshi remote new`                         | Save 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 [#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:

```bash
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:

```bash
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](/docs/v0.6/remote/setup#client--6-save-the-server).

## Certificate fingerprints [#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:

```text
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:

```bash
koshi remote edit work
```

<Callout type="warn">
  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.
</Callout>

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:

```text
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 [#editing-a-saved-server]

```bash
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:

```text
$ 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 [#rotating-a-secret]

Once the serving machine grants a fresh secret:

```bash
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 [#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:

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

## The sweep [#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:

```text
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 [#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`](/docs/v0.6/configuration/koshi-kdl#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:

```text
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.

```kdl title="koshi.kdl"
version 2
remote-reconnect #true
```
