The Problem

ssheasy delivers a fully functional SSH and SFTP client that runs inside a browser, compiled from Go to WebAssembly. It eliminates the need for a local terminal or native SSH binary while still offering tunneling, file‑manager UI and monitoring integrations. The pain point it solves is enabling remote command‑line and file‑transfer access from any device with a browser, without installing platform‑specific clients.

What This Does

The repository is split into three logical layers:

  • proxy/ – a Go service (proxy/main.go) that receives WebSocket messages from the browser and forwards TCP traffic to an upstream SSH daemon. proxy/fileserver.go (615 LOC) implements the file‑transfer logic and a simple HTTP file‑server used by the WebSocket handler.
  • web/ – contains the frontend build (web/main.go, web/proxy.go, web/webauth.go) that compiles the Go‑based WASM SSH/SFTP binary and serves the HTML UI (web/html/index.html). The UI relies on the xterm.js terminal emulator and several add‑ons (@xterm/addon-fit, @xterm/addon-search, @xterm/addon-serialize) stored in web/html/node_modules.
  • nginx/ – a reverse‑proxy Dockerfile and config that serves the static web content and terminates TLS, exposing the application on port 8080.

The three projects inside the repo interact as follows: docker-compose up builds the WASM binary, starts the Go proxy, launches nginx, and spawns a test SSHD container. The browser contacts /connect?host=… which auto‑populates the connection form and opens a WebSocket to the proxy, which then proxies the SSH session to the container‑running sshd.

How It Is Wired

  • Entry points – proxy/main.go starts an HTTP server + WebSocket endpoint (/ws). web/main.go is the build script that produces the WASM file; web/html/index.html loads the WASM and instantiates the terminal.
  • Call graph – The import graph contains a single internal module with zero import edges and no circular dependencies (10 of 10 Go/Shell/JavaScript files analysed). The most connected module is web/html/sw (Ca = 0, Ce = 0, instability = 0).
  • Out‑of‑process effects – The proxy forwards raw TCP over WebSocket to the SSH daemon; nginx only serves static assets. No database or external storage is used.
  • File‑by‑file responsibility –
  • proxy/main.go – websocket accept, connection‑initiation (/connect query parsing).
  • proxy/fileserver.go – file‑transfer handling, HTTP file‑server (oversized, high cognitive‑load).
  • web/main.go – WASM build orchestration, early‑return guard needed (deep nesting).
  • nginx/Dockerfile – base image nginx:1.23.3 (mutable, needs digest pinning).
  • web/html/index.html – loads xterm.js and connect URL parameters.

How To Use It

Setup

# Clone the repo (verbatum URL)
git clone https://github.com/moses-y/ssheasy.git

# From the repo root
docker-compose up --build

This command compiles the Go→WASM client, starts the proxy, nginx, and a test SSHD container.

Configuration

  • Connect via URL query, e.g.

http://localhost:8080/connect?host=testssh&port=22&user=root&password=root

  • Environment variables or secrets are not required for the basic demo; the docker-compose.yaml defines the test SSHD credentials (root/root).
  • For WebAuthn support, copy the displayed public key into ssh_conf/.ssh/authorized_keys and restart the testopenssh service (see README).

Running it After docker-compose up open http://localhost:8080 in a browser. The connection form is pre‑filled with the query parameters; press Connect to start the SSH session.

Real‑World Use

A distributed team needs to give developers quick SSH access to a bastion host from corporate laptops that cannot install native clients. By pointing a browser at the ssheasy URL, each user gets a terminal and SFTP pane without touching the OS package manager. The proxy can be placed behind an internal load balancer, and the nginx container can terminate TLS, making the service reachable over the public internet while keeping the SSH daemon internal.

Code Health & Issues

  • MEDISE cognitive‑load findings (static analysis):
  • Deep nesting x2 – proxy/fileserver.go, web/main.go (max indentation depth 6). Fix: flatten with guard clauses / extract inner blocks.
  • Oversized file – proxy/fileserver.go (615 LOC). Fix: split into cohesive units by responsibility.
  • CODE HEALTH AUDIT (5 findings, 0 critical, 3 high, 2 medium, 0 low):
  • [HIGH] Remove the committed node_modules directory (149 files committed). Gitignore it, git rm -r --cached the tree, then reinstall from web/go.sum/package-lock.json.
  • [HIGH] Add a CI workflow that builds and tests the repository (9 source files, no CI config).
  • [HIGH] Add a build gate for deployable artifacts – validate docker-compose.yaml images on every push.
  • [MEDIUM] Enable Dependabot/Renovate (2 manifests, no update bot).
  • [MEDIUM] Pin container base images by digest in nginx/Dockerfile (golang:1.23.3-alpine, nginx:1.23.3).
  • SDLC observations – No .github/ CI config, no licence file detected in the root (LICENSE present), no committed secrets, but node_modules is checked in, which breaks automated dependency scanning.

The Bottom Line

ssheasy is a pragmatic proof‑of‑concept for a browser‑based SSH/SFTP experience built on Go + WASM. The architecture is clean (proxy ↔ WebSocket ↔ xterm.js) and the docker-compose setup gets a functional demo running in minutes. However, the code base shows signs of rushed development: an oversized proxy file, deep nesting, and a committed node_modules that blocks proper dependency management. Adding CI, a Dependabot pipeline, and digest‑pinned base images would bring the project to production‑ready quality with modest effort. It is well‑suited for internal tools, demos, or teams that need zero‑client remote access without installing SSH binaries.