-
-
Notifications
You must be signed in to change notification settings - Fork 43
SSH Connections and Host Keys
WebSSH opens SSH connections from the server process to the target. The browser does not connect directly to the SSH server.
Open Quick Connect or launch a saved profile. A connection includes:
- hostname or IP address;
- SSH port, normally
22; - remote operating-system username;
- password, stored SSH key, or authorized Tailscale SSH mode;
- optional jump host;
- optional persistent tmux selection;
- optional post-connect command or command set.
Connection passwords are not stored in profiles or audit logs. Stored private keys are encrypted at rest and decrypted only when needed for authentication.
WebSSH accepts RSA, Ed25519, and ECDSA private keys supported by the installed Paramiko runtime. Each user's keys are isolated below their own data directory.
Private-key content is encrypted with Fernet. A per-user key is derived from
SECRET_KEY:user_id through PBKDF2-HMAC-SHA256 with 600,000 iterations. Key
directories use mode 0700 and files use 0600 on POSIX systems.
SECRET_KEY is the root of this protection. Anyone with both the application
secret and encrypted files can decrypt the keys. Preserve the secret during
updates and protect backups accordingly.
The key manager supports upload/import, rename, replacement, and deletion. Key paths are validated against the owning user's key directory, and writes are atomic.
WebSSH uses persistent trust on first use (TOFU):
- On the first connection to a host identity, the server key fingerprint is stored and logged.
- Later connections require the stored key to match.
- A changed key is rejected instead of being silently accepted.
Trust is scoped to the relevant user or administrator-managed global store. Users can inspect and revoke their own trust records in the Security Center; administrators can manage global trust.
Do not immediately delete the record and retry. A change may indicate:
- a legitimate server rebuild or SSH host-key rotation;
- DNS or IP reassignment;
- a load balancer reaching a different host;
- interception.
Verify the new fingerprint out of band with the system owner. Only then revoke the old record and reconnect.
BLOCK_INTERNAL_SSH=true blocks loopback, link-local, private, reserved, and
other unsafe destinations after DNS resolution. The production profile requires
this protection.
The homelab profile defaults to false because private addresses are often the intended targets. If untrusted users can access the instance, private-target access turns WebSSH into a powerful network pivot. Isolate the instance or enforce a reviewed target policy.
DNS results are validated. ProxyJump normally uses locally validated target
resolution. PROXY_JUMP_REMOTE_DNS_ALLOWLIST permits only exact hostnames that a
trusted bastion must resolve remotely; wildcards and IP literals are rejected.
Save a jump host once and reference it from profiles. A jump host can have its own hostname, port, remote username, and authentication method.
WebSSH opens the target through Paramiko's existing bounded channel helpers. The UI marks a connection as routed through the selected bastion. Deleting or changing a referenced jump host can affect saved profiles, so verify dependents before removal.
Every live SSH session is owned by one WebSSH user. Socket.IO input, resize, disconnect, SFTP, diagnostics, and transfer operations authenticate the browser session and verify resource ownership.
Terminal output is emitted to the owning user's private room. Lock, deletion, logout, and LDAP revalidation close tracked resources.
Defaults:
- 10 concurrent SSH sessions globally;
- 5 per user;
- 10 SSH or quick-connect attempts per minute per user;
- 12 temporary SSH/SFTP connections globally;
- 3 temporary connections per user.
All counters are process-local and rely on the mandatory single-worker model.
Check DNS, routing, firewall rules, target port, jump-host reachability, and the container network. Confirm the target is not blocked by network policy.
Verify the remote username and selected method. For keys, check the public key is installed for that remote user and the private-key format is supported. For a jump host, distinguish bastion authentication from target authentication.
Review the trust record and verify the new fingerprint. Do not disable host-key verification.
SESSION_TIMEOUT defaults to 1800 seconds and closes idle SSH sessions. A tmux
session may keep the remote shell alive for later reattachment even though the
WebSSH transport closed.
WebSSH documentation - Project - Issues - Discussions - Security
WebSSH Wiki
Install and operate
- Installation from Source
- Docker and Docker Compose
- Production Deployment
- Reverse Proxy and Subfolder Deployment
- Upgrading, Rollback, and FAQ
Identity and access
- Users and Account Management
- Authentication Overview
- LDAP and Active Directory
- OpenID Connect
- Passkeys and Recovery Codes
SSH and files
- SSH Connections and Host Keys
- Profiles, Jump Hosts, and Commands
- Terminal and Persistent tmux Sessions
- SFTP File Workspace and Transfers
- Tailscale SSH
Reference and administration