StrixWebSSH - 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:
- STRIXWEBSSH_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 (trueorfalse)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 strixwebssh:8081
}
handle_path /api/* {
reverse_proxy strixwebssh:8082
}
route {
root * /srv
try_files {path} /index.html
file_server
}
}
Docker Hub
Pre-built multi-arch images available:
docker pull danaildr/strixwebssh:latest
docker pull danaildr/strixwebssh:0.3.1
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