Files
webssh/README.md
T

5.7 KiB

WebSSH - Browser-based SSH Client

Multi-connection SSH client that runs in your browser with JWT authentication.

Features

  • Multi-connection support: Manage multiple SSH connections simultaneously
  • JWT Authentication: Secure login system with token-based authentication
  • Password & SSH Key auth: Support for both password and SSH key authentication
  • SFTP File Manager: Built-in file manager with upload/download capabilities
  • Terminal emulator: Uses xterm.js for a full terminal experience
  • Connection management: Sidebar with connection list, status indicators, and quick actions
  • Remote load monitoring: Active SSH connections display the remote Linux 1/5/15-minute load average
  • Session Recording: Automatic recording of SSH sessions in asciinema format with playback and configurable retention
  • Dark theme: Modern dark UI design
  • Single port: All services run through port 8080 (HTTP API + WebSocket)

Quick Start

1. Start the Backend

docker-compose -f deployment/docker-compose.yml up -d --build

2. Open the Client

Open http://localhost:8080 in your browser. The application is served via a Caddy reverse proxy.

3. Login

Default credentials:

  • Username: admin
  • Password: admin

Configuration

Users

Set users via environment variable in deployment/docker-compose.yml:

environment:
  - WEBSSH_USERS=user1:pass1,user2:pass2

JWT Secret

Set custom JWT secret:

environment:
  - JWT_SECRET=your-secret-key-here

If not set, a random secret is generated on startup.

Max Upload Size

Set maximum file upload size (default: 100MB):

environment:
  - MAX_UPLOAD_SIZE=50M

Supported formats: 10M, 100MB, 1G, 1GB, or bytes as integer.

Session Recording

Configure automatic session recording (default: enabled, 30 days retention):

environment:
  - RECORDING_ENABLED=true
  - RECORDING_RETENTION_DAYS=30
  • RECORDING_ENABLED: Enable/disable session recording (true or false)
  • RECORDING_RETENTION_DAYS: Number of days to keep recordings before automatic deletion

Recordings are stored in /data/recordings/ in asciinema v2 format (gzip compressed).

Ports

  • 8080 - HTTP API and WebSocket (Caddy reverse proxy)

All traffic goes through port 8080. Caddy routes:

  • /ws → WebSocket SSH server (internal port 8081)
  • /api/ → HTTP API endpoints (internal port 8082)
  • Everything else → Static files (served from the repository index.html + static/)

File Structure

web-ssh/
├── src/                    # Application source code
│   ├── run.py              # Backend entry point
│   ├── serve_static.py    # Static file server
│   ├── index.html          # Main client interface
│   ├── help.html           # Help documentation
│   ├── static/             # Frontend assets
│   └── webssh_backend/     # Backend package
├── deployment/             # Docker and deployment files
│   ├── docker-compose.yml
│   ├── Dockerfile
│   ├── Caddyfile
│   ├── docker-entrypoint.sh
│   └── scripts/
├── requirements.txt        # Python dependencies
├── run.py                  # Compatibility wrapper from repo root
├── serve_static.py         # Compatibility wrapper from repo root
├── README.md               # This file
└── .github/workflows/      # CI/CD

API Endpoints

POST /api/login

Login and get JWT token.

Request:

{
  "username": "admin",
  "password": "admin"
}

Response:

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
  "username": "admin",
  "expires": "2024-01-20T12:00:00+00:00"
}

POST /api/verify

Verify JWT token validity.

Request:

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}

Response:

{
  "valid": true,
  "username": "admin"
}

WebSocket Protocol

Connect to ws://localhost:8080/ws?token=<JWT_TOKEN>

After connection, send SSH credentials:

{
  "host": "192.168.1.100",
  "port": 22,
  "username": "root",
  "password": "secret",
  "key": "-----BEGIN OPENSSH PRIVATE KEY-----..."
}

Reverse Proxy Configuration

Caddy

your-domain.com {
    reverse_proxy localhost:8080
}

Caddy

{
  auto_https off
}

:8080 {
  handle_path /ws* {
    reverse_proxy webssh:8081
  }
  handle_path /api/* {
    reverse_proxy webssh:8082
  }
  route {
    root * /srv
    try_files {path} /index.html
    file_server
  }
}

Docker Hub

Pre-built multi-arch images available:

docker pull danaildr/webssh:latest
docker pull danaildr/webssh:0.4.0

Supported architectures: linux/amd64, linux/arm64

Security Notes

  • Always use HTTPS in production (configure reverse proxy with SSL)
  • Change default credentials
  • Set a strong JWT_SECRET
  • The backend uses AutoAddPolicy() for SSH host keys (testing only - change for production)
  • Token expiry: 8 hours
  • File upload limit: configurable via MAX_UPLOAD_SIZE (default 100MB)

Building and Publishing

Local Build

docker-compose up -d --build

Build for Docker Hub (Multi-arch)

./docker-build-and-push.sh --build

This builds and pushes both linux/amd64 and linux/arm64 images with tags latest and version tag.

Version Management

./version-manager.sh

Interactive script to update version numbers across all files.

Development

# Install dependencies
pip install -r requirements.txt

# Run backend directly (for development)
python start_backend.py

# Note: When running directly, services use internal ports:
# - WebSocket SSH: port 8081
# - HTTP API: port 8082
# - WebSocket SFTP: port 8083
#
# Use docker-compose for production deployment with Caddy on port 8080