$ cd ../
$ cd ~/projects/webssh

WebSSH

~/projects/webssh $ cat README.md

A multi-connection SSH client that runs entirely in your browser. Organize hosts into groups, log in with JWT authentication, open several SSH sessions side by side, move files over SFTP and have every session recorded automatically. Built with Python, Paramiko, WebSockets and xterm.js.

~/projects/webssh $ git clone https://git.danaildr.eu/dido/webssh

# get the source and build it locally
git clone https://git.danaildr.eu/dido/webssh
cd webssh
docker-compose -f deployment/docker-compose.yml up -d --build

→ open http://localhost:8080
repo layout: src/ (app + backend) · deployment/ (Docker, Caddy) · requirements.txt

Source code: https://git.danaildr.eu/dido/webssh

~/projects/webssh $ docker pull danaildr/webssh:latest

# quick start
docker run -d \
  -p 8080:8080 \
  -e MAX_UPLOAD_SIZE=100M \
  --name webssh \
  --restart unless-stopped \
  danaildr/webssh:latest

→ open http://localhost:8080
first run: create the administrator account in the browser

features

with persistent data & auto-lock

docker run

docker run -d \
  -p 8080:8080 \
  -v webssh_data:/data \
  -e JWT_SECRET=your-256-bit-secret-here \
  -e MAX_UPLOAD_SIZE=500M \
  -e RECORDING_ENABLED=true \
  -e RECORDING_RETENTION_DAYS=30 \
  --name webssh \
  --restart unless-stopped \
  danaildr/webssh:latest

docker-compose.yml

services:
  webssh:
    image: danaildr/webssh:latest
    container_name: webssh
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - JWT_SECRET=your-secret-key-here
      - MAX_UPLOAD_SIZE=100M
    volumes:
      - webssh_data:/data
volumes:
  webssh_data:

Auto-lock and auto-disconnect are set per connection, in the connection settings modal.

user accounts & password reset

Since 0.6.0, user accounts are stored in the database, not in an environment variable. On a fresh installation, open WebSSH and create the administrator account in the browser; use a password with at least 12 characters. Administrators can manage accounts from Manage Users.

To reset a user's password in a running container, run the interactive command for your installation. It prompts for the username and new password without displaying the password, invalidates that user's active sessions and requires a password change at next login.

# quick-start docker run
docker exec -it webssh password-reset

# repository Compose setup
docker exec -it webssh-backend password-reset

For existing installations, legacy WEBSSH_USERS entries are imported into the database once at startup. The first imported user becomes an administrator; imported users must change their password at next login. Remove WEBSSH_USERS from the environment after migration. Version 0.5.1 is the last release that stores users through this environment variable.

environment variables

VariableDescriptionDefaultRequired
WEBSSH_USERSLegacy user:password pairs, imported into the database once during migrationNot setNo
JWT_SECRETSecret for token signingAuto-generatedRecommended
MAX_UPLOAD_SIZEMax file upload, e.g. 10M, 1G100MNo
RECORDING_ENABLEDEnable session recordingtrueNo
RECORDING_RETENTION_DAYSDays to keep recordings30No
TZTimezoneUTCNo
STRIX_TELEMETRY_ENABLEDEnable anonymous usage telemetry (set to false to disable)trueNo

architecture

nginx sits in front and routes everything through a single port:

:8080 — main entry point
/ws → WebSocket SSH server
/api/* → HTTP API (login, verify, SFTP ops)
/* → static UI files

Internal, not exposed: WebSocket SSH on 8081, HTTP API on 8082, WebSocket SFTP on 8083.

reverse proxy setup

Caddy

your-domain.com {
    reverse_proxy localhost:8080
}

nginx

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

security notes

  • Create a strong administrator password during first-run setup; manage user accounts in the database.
  • Set a strong JWT_SECRET — at least 32 random characters.
  • Use HTTPS — terminate TLS at the reverse proxy; the container itself serves plain HTTP.
  • SSH host keys use AutoAddPolicy() by default — configure strict host key checking for production.
  • Session recordings live in /data/recordings/, with metadata in a SQLite database.
  • File uploads are capped by MAX_UPLOAD_SIZE (default 100MB).
  • Mount /data as a volume to persist the user database and recordings.

telemetry

Starting with 0.5.0, WebSSH collects anonymous usage telemetry to help understand how many installations are active and which versions are in use.

Collected:

  • Randomly generated installation identifier (installation_uuid)
  • WebSSH version
  • Operating system
  • Operating system version
  • CPU architecture, e.g. x86_64, aarch64, armv7
  • Python runtime, e.g. CPython or CPython (Docker)
  • Python version

Not collected:

  • IP address
  • Hostname

To disable telemetry, set the environment variable STRIX_TELEMETRY_ENABLED=false.

api

tags

latest

0.7.0host groups for organizing connections

old

0.6.0database-backed user accounts and password reset command
0.5.1redesigned connection cards interface; last release with WEBSSH_USERS-based accounts
0.4.0grouped recordings, bulk operations, multi-arch support

All tags: linux/amd64, linux/arm/v7, linux/arm64