Enrolling machines

Self-service enrollment lets any host join difflab with plain curl — no agent software to install, no manual config file edits. The enrollment endpoint discovers git repositories on the target host automatically.

How it works

  1. The container generates an SSH keypair on first start (stored in $DIFFLAB_DATA).

  2. Step 1 adds the container’s public key to the target host’s authorized_keys with a restrictive prefix that limits what the key can do.

  3. Step 2 sends a registration request to difflab; difflab SSH-es into the target, scans the specified roots for git repositories, and stores the results in registry.yaml.

Enrolled targets survive restarts — difflab reloads registry.yaml at startup.

Step 1 — install the gate and authorize the key

The container key is gated by a forced-command script (gate/git-gate.sh on Linux, gate/git-gate.ps1 on Windows). The gate must be installed before the key is authorized so that the command= path in the authorized_keys line is valid when difflab first connects.

Linux / macOS:

sudo mkdir -p /usr/local/lib/difflab
sudo cp gate/git-gate.sh /usr/local/lib/difflab/git-gate.sh
sudo chmod 755 /usr/local/lib/difflab/git-gate.sh

# Authorize the gated key (fetch from the running difflab instance)
curl -s http://difflab.example.com:8747/pubkey >> ~/.ssh/authorized_keys

Windows (elevated PowerShell — administrators_authorized_keys):

New-Item -ItemType Directory -Force "C:\ProgramData\difflab"
Copy-Item gate\git-gate.ps1 "C:\ProgramData\difflab\git-gate.ps1"

# Authorize the gated key (Windows form uses powershell invocation in command=)
(Invoke-WebRequest "http://difflab.example.com:8747/pubkey?os=windows").Content |
    Add-Content "$env:ProgramData\ssh\administrators_authorized_keys"

GET /pubkey returns the POSIX gate line (default) and GET /pubkey?os=windows returns the Windows gate line. Both include the command= forced-command prefix that limits what the key can do:

command="/usr/local/lib/difflab/git-gate.sh",no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAA... difflab

The gate allows only git diff and git status --short commands. Any other command is rejected with difflab: command not permitted.

The gate blocks the auto-discovery scan (find, Get-ChildItem) that POST /register uses when roots are provided. For gated hosts, supply an explicit repos list in the registration body to bypass scanning.

Step 2 — register the machine

Send a registration request to difflab from any machine (including the target itself).

Linux / macOS:

curl -s -X POST http://difflab.example.com:8747/register \
  -H 'Content-Type: application/json' \
  -d '{
    "token": "YOUR_ENROLL_TOKEN",
    "name":  "devbox",
    "host":  "192.0.2.10",
    "user":  "alice",
    "port":  22,
    "roots": ["/home/alice/projects"]
  }'

Windows (PowerShell):

Invoke-RestMethod http://difflab.example.com:8747/register -Method POST `
  -ContentType 'application/json' `
  -Body '{
    "token": "YOUR_ENROLL_TOKEN",
    "name":  "winbox",
    "host":  "192.0.2.20",
    "user":  "alice",
    "port":  22,
    "roots": ["C:/Users/alice/projects"]
  }'

Request fields

Field Required Description

token

yes

Must match DIFFLAB_ENROLL_TOKEN.

name

yes

Short identifier for this machine (^[A-Za-z0-9][A-Za-z0-9._-]*$). Used as a prefix for discovered target names.

host

yes

SSH hostname or IP address of the target machine.

user

yes

SSH username.

port

no (default 22)

SSH port.

roots

one of roots/repos

List of directory paths to scan for git repos (up to 3 levels deep). Directories whose path contains a component starting with . are skipped.

repos

one of roots/repos

Explicit list of repo paths. Bypasses the automatic scan and the hidden-path filter.

Response

{"machine": "devbox", "targets": ["devbox-myproject", "devbox-other"], "errors": []}

targets lists the names of the discovered repos now tracked by difflab. errors lists any paths that could not be verified as git repositories.

Enabling OpenSSH Server on Windows

If the target is a Windows machine without SSH enabled:

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Set-Service sshd -StartupType Automatic
Start-Service sshd
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server' `
  -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

On Windows, OpenSSH uses %ProgramData%\ssh\administrators_authorized_keys for accounts in the Administrators group — not %USERPROFILE%\.ssh\authorized_keys. If the target user is an administrator, pipe GET /pubkey into the administrators_authorized_keys file instead.

Name conflicts

If a discovered repo’s auto-generated name conflicts with an existing target (from config.yaml or a previous enrollment), a numeric suffix is appended automatically: devbox-myrepo-2, etc.

Config-file targets always take priority — enrollment will never overwrite them.