Skip to content

04 Joining Servers

This chapter explains how to register Linux, macOS, and Windows servers with SSH Teams using the built-in join scripts.

4.1 Prerequisites

Requirement Lab Staging Production
Server can reach SSH Teams over HTTPS Required Required Required
Operator can approve device flow in browser Required Required Required
Elevated privileges for sshd config update Recommended Required Required
Stable tagging plan (prod, db, bastion) Optional Recommended Required
Trusted TLS certificate on SSH Teams host Optional Recommended Required

Important gotcha:

  • If your SSH Teams endpoint uses a self-signed certificate, use the dashboard-provided join command variant with TLS bypass flags for bootstrap only, then move to trusted certificates.

4.2 Join Script Endpoints and When to Use Them

SSH Teams exposes two script endpoints:

graph TD
    A[Run join script on target host] --> B[Request device code scope=join]
    B --> C[Operator approves in browser]
    C --> D[Script exchanges code for access token]
    D --> E[Script calls /api/v1/ssh/join]
    E --> F[Write TrustedUserCAKeys and server-id]
    F --> G[Update sshd config and restart service]
  • https://<hostname>/join.sh for Linux and macOS hosts.
  • https://<hostname>/join.ps1 for Windows hosts.

Both scripts execute an OAuth device authorization flow with scope=join, then call:

  • POST /oauth2/device_authorization
  • POST /oauth2/token
  • POST /api/v1/ssh/join

Use the join commands shown in the dashboard so the right TLS flags are included for your certificate type.

From the dashboard:

  1. Open https://<hostname>/dashboard.
  2. Locate the Join Script panel.
  3. Click the copy icon next to Linux/macOS or Windows command.

The copied command is generated by the server and includes the correct SSH Teams hostname (and HTTPS port when non-default), so operators do not need to hand-edit the base URL. On Windows, you still need to supply the required target host argument when executing the script.

Dashboard join command panel:

SSH Teams dashboard join script panel

Typical command patterns:

curl -fsSL https://<hostname>/join.sh | bash -s -- <host>:22 [tags]
irm https://<hostname>/join.ps1 -OutFile .\join.ps1
.\join.ps1 "<host>:22" "prod,windows"

4.3 Linux and macOS Join Flow

Run the join script on the target server:

curl -fsSL https://<hostname>/join.sh | bash -s -- server-a.example.internal:22 prod,db --name "server-a"

Parameters:

  • Positional target: <hostname[:port]>.
  • Optional tags: comma-separated tags such as prod,db.
  • Optional --name <name>: friendly display name in SSH Teams.
  • Optional --config <path>: sshd config path (default /etc/ssh/sshd_config).
  • Optional --bypass-install: complete join and CA key retrieval without modifying local sshd config.

What the script does:

  1. Collects SSH host-key fingerprints from the target host.
  2. Prints a device verification URL with user_code.
  3. Waits for operator approval in browser.
  4. Registers or updates server via /api/v1/ssh/join.
  5. Writes trusted user CA keys to ~/.ssh/sshteam_trusted_user_ca_keys.
  6. Adds or updates TrustedUserCAKeys in sshd config unless --bypass-install is used.
  7. Restarts sshd (launchctl on macOS, systemctl on Linux when available).

Re-join behavior:

  • If an existing server ID is found (/etc/sshteam/server-id or ~/.ssh/sshteam_server_id), the script updates that server registration instead of creating a duplicate.

4.4 Windows Join Flow

Run from an elevated PowerShell session on the target host with explicit arguments:

irm https://<hostname>/join.ps1 -OutFile .\join.ps1
.\join.ps1 "server-win.example.internal:22" "prod,windows" -Name "server-win"

Windows script behavior mirrors Linux/macOS flow:

  • Performs OAuth device authorization (scope=join).
  • Submits join payload to /api/v1/ssh/join.
  • Saves trusted user CA keys at ~/.ssh/sshteam_trusted_user_ca_keys.
  • Updates sshd config (default C:\ProgramData\ssh\sshd_config) unless -BypassInstall is set.
  • Restarts sshd service when present.

Note:

  • Current Windows script uses a placeholder fingerprint value. Validate resulting registration details and policy matching after join.

4.5 Self-Signed Certificate Handling

If SSH Teams uses a self-signed certificate, use the dashboard-provided command variants:

  • Linux/macOS: curl -kfsSL .../join.sh | bash ...
  • Windows:
irm -SkipCertificateCheck https://<hostname>:9443/join.ps1 -OutFile .\join.ps1
.\join.ps1 "<host>:22" "prod,windows"

Guidance:

  • Use bypass flags only for initial bootstrap when needed.
  • Move to a trusted certificate as soon as practical.
  • Re-run join commands after certificate changes if operators are still using stale command snippets.

4.6 Verifying Joined Server Inventory

After join completes:

  1. Open https://<hostname>/dashboard.
  2. Confirm server count increased.
  3. Open server inventory page and validate host fields:
    • hostname
    • port
    • OS family/version
    • tags
  4. Confirm expected policy targeting (server IDs or tags) can match this server.

CLI-level verification on the target host:

  • Confirm CA keys file exists and is populated: ~/.ssh/sshteam_trusted_user_ca_keys.
  • Confirm sshd config contains TrustedUserCAKeys directive.
  • Confirm sshd restarted cleanly.

4.7 Join Troubleshooting

Common issues and fixes:

  • Script download fails:

    • Verify HTTPS reachability to https://<hostname>/join.sh or /join.ps1.
    • Check reverse proxy/TLS configuration.
  • Device authorization does not complete:

    • Ensure browser verification URL is reachable and approved by an authenticated user in the same team.
    • Retry if token polling returned authorization_pending for too long.
  • Join API returns non-2xx:

    • Capture response body from script output.
    • Validate join payload inputs (hostname, port, tags, server ID reuse).
  • Permission errors updating sshd config:

    • Use elevated privileges (sudo -v on Linux/macOS, admin PowerShell on Windows).
    • Use --bypass-install / -BypassInstall to complete registration first, then update sshd config manually.
  • Duplicate server records:

    • Preserve /etc/sshteam/server-id (or user-profile fallback file) during rebuilds so re-joins update existing registration.
  • Certificates still denied after successful join:

    • Check policy matching (tags/server selectors, user constraints, time windows).
    • Validate server appears in the correct team inventory.