Skip to content

Servers and SSH

On the home screen:

  • a adds a server, e edits the selected one, d deletes it. Deleting names the container settings that go with it.
  • ctrl+t in the form tests the connection by running docker version.
  • i imports servers from your ~/.ssh/config.

i on the home screen reads ~/.ssh/config and offers every concrete Host as a server, with its HostName, User, Port, the first IdentityFile that exists, and ProxyJump as the jump host. A jump through another Host of the file becomes that host’s address.

The file is read the way ssh reads it: the first value found wins, Host * and patterns with ! apply, Include files are read, and Match blocks are skipped.

Left out of the list:

  • hosts already configured, by the same name, or the same user, host and port;
  • aliases of a machine that is already in the list;
  • git hosts such as github.com, gitlab.com and bitbucket.org.

Every host in the list starts chosen.

Key Action
space Choose or unchoose a host
a All or none
enter Import the chosen hosts
esc Close without importing

A host that does not pass the checks of the server form is reported and skipped. The config is written once, with all the imported servers.

Field Description
name Shown in the server list, unique
type ssh for a remote server, local for this machine’s Docker
host, port, user The SSH connection. port defaults to 22
key Private key file. Empty: ssh-agent, then your default keys
jump_host [user@]host[:port] of an SSH bastion, like ssh -J. User defaults to the server’s, port to 22
jump_key Key for the bastion. Empty: the server’s key, then ssh-agent
docker_cmd How to run Docker there. Default: docker
root_path Default Laravel root for this server’s containers
read_only Refuse everything that would change the server. See Read-only servers

laraport tries, in this order:

  1. The key file from the config, with its passphrase if one is set.
  2. ssh-agent, through SSH_AUTH_SOCK.
  3. The standard key files: ~/.ssh/id_ed25519, ~/.ssh/id_rsa, ~/.ssh/id_ecdsa.

Passphrases cannot be entered in the UI. Load such keys into ssh-agent instead.

Host keys are checked against ~/.ssh/known_hosts, the file OpenSSH uses.

  • A server you have never connected to is trusted on first use and its key is recorded (accept-new). With host_key_check: strict it is refused instead, and the error shows the fingerprint and the ssh-keyscan command to add it.
  • A server whose key differs from the recorded one is refused with a “host key mismatch” error. That is what a man-in-the-middle attack looks like. If the server was reinstalled, remove the old entry with ssh-keygen -R <host>.

For servers reachable only through a bastion, set jump_host. laraport connects to the bastion, opens a tunnel from it to the server (what ssh -J does) and runs the session through it.

  • Both host keys are checked, each under its own name.
  • If the bastion or the tunnel drops, the chain is re-established on the next action.
  • The bastion must allow TCP forwarding (AllowTcpForwarding yes, the OpenSSH default).
  • The interactive shell uses your system ssh with -J, so it follows the same route.

If the SSH user is not in the docker group, set:

docker_cmd: "sudo -n docker"

This needs passwordless sudo for docker. Every docker call laraport makes on that server goes through it, the shell and logs included. The same field takes docker --context prod.

A dropped connection (a network change, a laptop going to sleep, a server restart) is noticed through SSH keepalives every 30 seconds, and the next action reconnects. There is no need to go back to the server list.

c on the home screen checks all servers at once. Each is checked on a connection of its own, in parallel, which is closed afterwards. A line under each server then shows its state:

  • ✓ 21/26 running when all is well;
  • or what is wrong: 2 down: shop-worker, mailpit, 1 unhealthy, the disk and the load, the warnings of the server panel, or why the server could not be reached.

“Down” counts only containers that should run. Left out are stopped containers you hid, old Swarm tasks a newer one replaced, and one-off containers that exited with 0. A Swarm service without a running task counts once.

To check every server each time laraport starts, switch on Check servers on start in Settings (check_servers_on_start: true).