SSH in your browser.
No client required.
CloudShell is a self-hosted, Docker-deployable web SSH gateway. Manage multiple SSH connections to any device right from your browser tab, with encryption at rest, audit logging, and an SFTP file manager included.
See it in action
A clean, familiar terminal experience right in your browser tab.
Everything you need
A free, self-hosted alternative to paid web SSH gateways — no subscriptions, no limits.
Full xterm.js Terminal
ANSI/VT100 support, copy & paste, and proper SIGWINCH resize propagation — just like a native client.
Multi-Tab Sessions
Open multiple concurrent SSH connections to different devices simultaneously, each in its own browser tab.
Device Manager
Add, edit, and delete SSH targets with name, host, port, and credentials — all stored encrypted at rest.
AES-256-GCM Encryption
Passwords and SSH private keys are encrypted at rest with AES-256-GCM, key derived via PBKDF2 (260k iterations).
SSH Key Auth & Generator
Paste an existing key, load from a file, or generate a fresh RSA-4096 key pair directly from the UI.
JWT Session Auth
Configurable session TTL with silent token refresh 10 minutes before expiry. Token revocation on logout.
Audit Log
Tamper-evident activity log covering logins, logouts, SSH session events, and password changes, with configurable retention.
SFTP File Manager
Browse, upload, download, rename, and delete files on any connected device directly from the browser.
Toast Notifications
Non-blocking feedback for every action, plus a graceful error boundary for unexpected frontend errors.
Session Expiry Badge
A live countdown in the header turns yellow then red as the session approaches its expiry time.
Single-Command Deploy
One docker compose up -d is all it takes to run in production with the prebuilt images from GHCR.
Change Password at Runtime
Update the admin password from the UI without restarting the backend — the change takes effect immediately.
Split View
View multiple sessions side-by-side with configurable layouts — vertical, horizontal, 2x2, or any custom grid up to 4x4.
Up and running in minutes
No complicated setup. Just Docker Compose and a single environment file.
Create your compose file
Save the following as docker-compose.yml:
services:
backend:
image: ghcr.io/iu2frl/cloudshell-backend:latest
restart: unless-stopped
expose:
- "8000"
volumes:
- cloudshell_data:/data
environment:
SECRET_KEY: "changeme-asap" # openssl rand -hex 32
ADMIN_USER: "admin"
ADMIN_PASSWORD: "changeme"
TOKEN_TTL_HOURS: "8"
networks:
- internal
frontend:
image: ghcr.io/iu2frl/cloudshell-frontend:latest
restart: unless-stopped
ports:
- "8080:80"
depends_on:
backend:
condition: service_healthy
networks:
- internal
volumes:
cloudshell_data:
networks:
internal:
driver: bridge
Generate a strong secret key
openssl rand -hex 32
Replace changeme-asap and changeme with strong values before starting.
Launch
docker compose up -d
Open http://localhost:8080 and log in. That is it.
Prefer to build from source?
git clone https://github.com/iu2frl/CloudShell
cd CloudShell
cp .env.example .env # edit .env first
docker compose up -d
Built with security in mind
Defense-in-depth from storage to network.
| Concern | Mitigation |
|---|---|
| Stored passwords | AES-256-GCM, key derived from SECRET_KEY via PBKDF2 (260k iterations) |
| SSH private keys | Encrypted .enc files, chmod 600, never stored in plaintext |
| Web session | Short-lived JWT (HS256), revocation via DB deny-list, silent refresh |
| WebSocket token | Passed as query param on WS upgrade — use HTTPS/WSS in production |
| Host key verification | known_hosts persisted in DATA_DIR; accept-new policy |
| Admin password | bcrypt-hashed in DB after first change; env-var fallback on first boot only |
It is recommended to run CloudShell behind a reverse proxy (Nginx, Caddy, Traefik) with TLS and keep it accessible only within a trusted network.
Ready to ditch the paid SSH gateways?
CloudShell is free, open source, and yours to self-host. No subscriptions, no telemetry, no limits.