msh CLI Reference

msh is the client CLI for Mezite. It lets an end user log in to a cluster, open SSH sessions, copy files, request access, manage their device-trust status, and join or moderate other sessions.

login

Authenticate to a Mezite cluster and receive short-lived SSH certificates. --user and --password are required for credential-style auth (local username/password and LDAP). Browser-mediated SSO connectors (OIDC, SAML, GitHub) are selected with --auth=<connector> and complete the login via the proxy callback.

Login flows bash
# Local username + password
msh login --proxy=mezite.example.com:3080 \
  --user=admin --password="$MEZITE_PASSWORD"

# LDAP / Active Directory (uses the same --user / --password)
msh login --proxy=mezite.example.com:3080 \
  --auth=corp-ldap --user=alice --password="$LDAP_PASSWORD"

# SSO (OIDC / SAML / GitHub) — opens the browser
msh login --proxy=mezite.example.com:3080 --auth=okta

# Custom certificate TTL (default 12h, hard cap 24h)
msh login --proxy=mezite.example.com:3080 \
  --user=alice --password="$MEZITE_PASSWORD" --ttl=30m

Identity-file export (--out)

Pass --out <path> to write the issued SSH key pair and certificate to disk in OpenSSH identity-file format instead of stashing them in the per-profile cache. This is what CI runners, scheduled jobs, and Machine-ID-style helpers consume.

Export an identity file for CI bash
msh login --proxy=mezite.example.com:443 \
  --auth=ci-machine-id \
  --user=ci-bot --password="$CI_BOT_PASSWORD" \
  --out=/tmp/mezite-identity

# Use it with native ssh
ssh -i /tmp/mezite-identity ubuntu@web-01.mezite

Hardware-key login (--hardware-key)

The --hardware-key flag is recognized by msh login, and roles with require_session_mfa: hardware-key are honoured by the proxy and auth service. However, real PIV hardware-key signing is not yet implemented — invoking the flag against a hardware token currently fails with no hardware key implementation available; real PIV support not yet built. The flag, RBAC policy hooks, and certificate extension are in place so that integration can land without churning the public surface; treat the feature itself as unimplemented today.


ssh

Open an interactive SSH session, or run a one-off remote command, against a registered node.

Open a session bash
# Connect by hostname
msh ssh ubuntu@web-01
msh ssh --login=ubuntu web-01

# Run a one-off command
msh ssh web-01 -- uptime

# Pre-approve a session-MFA challenge in the same invocation
msh ssh --mfa-code=123456 web-01

# Attach a justification (logged in the audit event)
msh ssh --reason="incident IR-204" web-01

# Invite extra participants into the session (for moderated roles)
msh ssh --invited=alice,bob web-01

# Cross-cluster: target a node in a trusted leaf cluster
msh ssh --cluster=production web-01

scp

Copy files between a workstation and a node through the Mezite proxy. Every transfer is authenticated with your certificate, logged in the audit trail, and — under a role with file-transfer moderation — gated by a per-file approval workflow.

File transfer bash
# Upload
msh scp ./deploy.tar.gz ubuntu@web-01:/tmp/

# Download
msh scp ubuntu@web-01:/var/log/app.log ./

# Recursive
msh scp -r ./config/ ubuntu@web-01:/etc/app/

msh scp does not support remote-to-remote copies; one side must always be local.

Transfer approval (moderated roles)

When the requester's role triggers SFTP moderation, the transfer pauses on the proxy until a designated moderator approves it. The moderator uses:

Moderator side bash
# Approve a pending transfer
msh approve-transfer --session=<session-id> --transfer=<transfer-id>

# Deny it
msh deny-transfer --session=<session-id> --transfer=<transfer-id>

ls

List nodes visible from the active profile. --filter is repeatable and AND-combines key=value matches against node labels.

Inventory bash
msh ls
msh ls --filter=env=production
msh ls --filter=env=production --filter=team=platform
msh ls --all      # include trusted leaf clusters

app

Reach internal applications published through the proxy. HTTP apps are opened in a browser at their public address; TCP apps (databases, caches, custom daemons) are reached by opening a local port that tunnels through the proxy. See the Application Access guide for the full picture.

Application access bash
# List the apps your roles let you reach
msh app ls

# HTTP app: prints the public address to open in a browser
msh app login grafana

# TCP app: open a local listener that tunnels to the app
msh app login redis-internal --port=6379
# then point a client (e.g. redis-cli) at 127.0.0.1:6379; Ctrl-C to stop

# Bind the tunnel to a different local address
msh app login redis-internal --port=6379 --listen=0.0.0.0

# Apps whose role requires per-session MFA: supply or be prompted for a code
msh app login redis-internal --port=6379 --mfa-code=123456

msh app ls shows an AUTH column flagging any app that requires extra per-session proof (mfa or a trusted device). Apps you can't reach do not appear in the list.


config

Generate ~/.ssh/config entries for every node visible from the active profile. Each entry pins the Mezite host CA via UserKnownHostsFile ~/.mezite/known_hosts and routes through msh proxy ssh, so native ssh, rsync, Ansible, and editor SSH integrations all benefit from certificate auth and audit.

SSH config generation bash
msh config              # print to stdout
msh config --append     # append to ~/.ssh/config
msh config --cluster=production  # change the Host alias suffix

proxy ssh

Use msh proxy ssh as an OpenSSH ProxyCommand to route native ssh(1) through the Mezite proxy. The argument takes a single [user@]host:port token, so OpenSSH's %r@%h:%p substitution drops in directly.

ProxyCommand usage bash
# Typical entry generated by 'msh config'
#   ProxyCommand msh proxy ssh %r@%h:%p

# Manual one-off
ssh -o 'ProxyCommand=msh proxy ssh %r@%h:%p' ubuntu@web-01.mezite

# Direct invocation
msh proxy ssh ubuntu@web-01:22

play

Replay a recorded session in the terminal. Speed is configurable.

Playback bash
msh play <session-id>
msh play --speed=2.0 <session-id>

sessions / recordings

Inspect recorded sessions. msh sessions ls and msh recordings ls are aliases; both surface the same list.

Listing bash
msh sessions ls
msh recordings ls

join

Join an active or pending session. For roles configured with require_session_join, the session is held open at start time until the required moderators have joined; this command is how a moderator answers that hold.

Session join bash
# As a moderator, attach to a session in observer mode
msh join --mode=observer <session-id>

# As a peer, attach in interactive mode (if the role allows)
msh join --mode=peer <session-id>

request

Create, list, and cancel access requests for elevated roles.

Access requests bash
msh request create --roles=admin --reason="Deploy hotfix"
msh request ls
msh request cancel <request-id>

Access requests are currently role-only — a request asks for one or more additional roles via requested_roles. Resource-mode requests are not implemented yet.


device

Manage the device-trust enrollment of the current machine. Required for any role with device_trust_mode: required.

Device trust bash
msh device serial      # print this device's hardware serial
msh device enroll      # enroll this device as a trusted device
msh device status      # report whether this device is enrolled and trusted

status / logout

Profile status bash
msh status   # show cluster, user, roles, cert expiry
msh logout   # remove local certificates and end the session

Global flags

  • --proxy <host:port> — Override the active profile's proxy address.
  • --cluster <name> — Target a specific trusted cluster.
  • --insecure — Skip server certificate verification. Dev-only.