Breaking Changes in Configuration Format
June 17, 2026 · View on GitHub
This document outlines the breaking changes and updates to the configuration format between versions. These changes require manual updates to your existing config.json files.
Major Structure Changes
Removed Sections
The following sections have been completely removed:
socketio- Socket.IO configuration is now handled internallyterminal- Terminal configuration moved to client-sideserverlog- Logging configuration simplifiedalgorithms- Moved under thesshsectionaccesslog- Removedverify- RemovedsafeShutdownDuration- Removed
Renamed and Restructured Sections
HTTP Configuration
- Old:
socketio.origins - New:
http.origins
- "socketio": {
- "serveClient": false,
- "path": "/ssh/socket.io",
- "origins": ["localhost:2222"]
- }
+ "http": {
+ "origins": ["*.*"]
+ }
SSH Algorithms
- Old: Root-level
algorithmsobject - New: Moved to
ssh.algorithms
- "algorithms": {
+ "ssh": {
+ "algorithms": {
"kex": [...],
"cipher": [...],
"hmac": [...],
"compress": [...]
+ "serverHostKey": [...]
}
+ }
Session Configuration
"session": {
- "name": "WebSSH2",
+ "name": "webssh2",
"secret": "secret"
}
New Options
SSH Configuration
Added under the ssh section:
{
"ssh": {
"alwaysSendKeyboardInteractivePrompts": false,
"disableInteractiveAuth": false
}
}
Feature Options
Renamed and expanded options:
"options": {
"challengeButton": true,
- "allowreauth": false
+ "autoLog": false,
+ "allowReauth": true,
+ "allowReconnect": true,
+ "allowReplay": true
}
Detailed Changes
1. Authentication Options
- Added support for SSH private key authentication via
user.privateKeyand passphrase encrypted private keys viauser.passphrase - Removed
user.overridebasicoption - Added keyboard-interactive authentication controls
2. Server Settings
- Default port changed from 2224 to 2222
- Socket.IO path is now fixed at "/ssh/socket.io"
- Added server host key algorithm configurations
2a. Security Headers (New Default)
- The server now applies a secure set of HTTP response headers by default via
app/security-headers.ts. - A Content Security Policy (CSP) is included and tightened for xterm.js.
script-srcno longer allows'unsafe-inline'(removed in Phase 2 via JSON config-block injection);style-srcretains'unsafe-inline'for xterm.js inline styles. - These headers are applied before session middleware in
app/middleware.ts.
Notes:
- The CSP mode and key directives are controlled via the
cspconfig block andWEBSSH2_CSP_*environment variables — see Security Headers & CSP. - HSTS (
Strict-Transport-Security) is set only when the request is HTTPS (req.secure).
3. Terminal Configuration
All terminal-specific configurations have been removed from server config:
- "terminal": {
- "cursorBlink": true,
- "scrollback": 10000,
- "tabStopWidth": 8,
- "bellStyle": "sound",
- "fontSize": 14
- }
These settings are now managed client-side.
Migration Guide
- Create a new
config.jsonfile based on the new format - Move your existing settings to their new locations
- Remove any deprecated options
- Add new required options
- Test your configuration before deploying to production
Default Configuration Example
{
"listen": {
"ip": "0.0.0.0",
"port": 2222
},
"http": {
"origins": ["*.*"]
},
"user": {
"name": null,
"password": null,
"privateKey": null,
"passphrase": null
},
"ssh": {
"host": null,
"port": 22,
"term": "xterm-color",
"readyTimeout": 20000,
"keepaliveInterval": 120000,
"keepaliveCountMax": 10,
"algorithms": {
"cipher": [
"aes128-ctr",
"aes192-ctr",
"aes256-ctr",
"aes128-gcm",
"aes128-gcm@openssh.com",
"aes256-gcm",
"aes256-gcm@openssh.com",
"aes256-cbc"
],
"compress": [
"none",
"zlib@openssh.com",
"zlib"
],
"hmac": [
"hmac-sha2-256",
"hmac-sha2-512",
"hmac-sha1"
],
"kex": [
"ecdh-sha2-nistp256",
"ecdh-sha2-nistp384",
"ecdh-sha2-nistp521",
"diffie-hellman-group-exchange-sha256",
"diffie-hellman-group14-sha1"
],
"serverHostKey": [
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"ssh-rsa"
]
},
"envAllowlist": ["ONLY_THIS", "AND_THAT"],
"maxExecOutputBytes": 10485760,
"outputRateLimitBytesPerSec": 0,
"socketHighWaterMark": 16384,
"hostKeyVerification": {
"enabled": false,
"mode": "hybrid",
"unknownKeyAction": "prompt",
"serverStore": {
"enabled": true,
"dbPath": "/data/hostkeys.db"
},
"clientStore": {
"enabled": true
}
}
},
"options": {
"challengeButton": true,
"autoLog": false,
"allowReauth": true,
"allowReconnect": true,
"allowReplay": true
}
}
Security Headers & CSP (Reference)
The security-headers middleware applies a set of standard headers on every response. Header names and common defaults are centralized in app/constants.ts (HEADERS, DEFAULTS).
X-Content-Type-Options:nosniffX-XSS-Protection:1; mode=blockReferrer-Policy:strict-origin-when-cross-originPermissions-Policy: disables geolocation, microphone, cameraStrict-Transport-Security: 1 year (HTTPS requests only); max-age isDEFAULTS.HSTS_MAX_AGE_SECONDS.X-Frame-Options: derived fromcsp.frameAncestors— see below.Content-Security-Policy/Content-Security-Policy-Report-Only: controlled by thecspconfig block — see below.
Content Security Policy (CSP)
The CSP is config-toggled and tightened. The csp block in config.json controls the mode, reporting endpoint, and the two operator-adjustable directive values:
"csp": {
"mode": "report-only",
"reportUri": "/ssh/csp-report",
"connectSrc": [],
"frameAncestors": ["none"]
}
csp.mode
| Value | Behaviour |
|---|---|
off | No CSP header is sent |
report-only | Content-Security-Policy-Report-Only header — browsers report violations but are not blocked. A security_posture warn is logged at startup |
enforce | Content-Security-Policy header — browsers block policy violations. A security_posture warn is logged when combined with wildcard http.origins |
report-only is the default. It is the recommended starting posture: deploy, collect csp_violation events, verify the policy is clean, then switch to enforce.
Tightened directive set
The policy shipped in Phase 2 removes 'unsafe-inline' from script-src (made possible by the JSON config-block injection, which eliminated the legacy inline script):
script-src 'self'— no inline scripts permittedstyle-src 'self' 'unsafe-inline'— inline styles required by xterm.jsobject-src 'none'base-uri 'none'connect-src— derived (see below)frame-ancestors— derived fromcsp.frameAncestors(see below)report-uri+Reporting-Endpoints/report-to— the value ofcsp.reportUri
csp.connectSrc and connect-src derivation
connect-src is built from three sources, merged at startup:
'self'(always included)- Entries from
http.originsthat are not wildcards — concrete origins such ashttps://gw.example:8443are safe CSP sources and are added automatically - Entries from
csp.connectSrc— the operator allowlist
Wildcard caveat: The default http.origins value is ["*:*"]. Wildcard patterns are not valid CSP source expressions and are silently dropped. With the default wildcard CORS setting, connect-src is therefore just 'self'. For split client/gateway deployments where the browser connects to a different origin than the page origin, either add explicit socket gateway URLs to csp.connectSrc or replace http.origins with a concrete allowlist.
{
"http": { "origins": ["https://gw.example:8443"] },
"csp": {
"mode": "enforce",
"connectSrc": ["wss://gw.example:8443"]
}
}
csp.frameAncestors and X-Frame-Options
csp.frameAncestors is an array of origins that may embed WebSSH2 in an <iframe>. It drives both the CSP frame-ancestors directive and the legacy X-Frame-Options header:
frameAncestors value | frame-ancestors directive | X-Frame-Options |
|---|---|---|
["none"] (default) | frame-ancestors 'none' | DENY |
["self"] | frame-ancestors 'self' | SAMEORIGIN |
| explicit origin list | frame-ancestors <origins> | omitted (CSP alone) |
CSP violation reporting
POST /ssh/csp-report is an unauthenticated endpoint that receives browser violation reports. Key properties:
- Per-IP rate-limited (default 60 reports/min) and body-capped at 8 KB
- Logs a structured
csp_violationevent (see logging.md) - Always returns
204 No Content - The CSP header advertises the endpoint via
report-uriandreport-to/Reporting-Endpoints - Operators should also apply an upstream/reverse-proxy rate limit on
POST /ssh/csp-report
Legacy inline-script transition note
During the deprecation window, the client HTML still contains a legacy window.webssh2Config = null; inline script. Under enforce mode this script is blocked harmlessly (the JSON config block supplies configuration instead), but it produces one expected csp_violation report per page load. This report is demoted to debug log level so operators do not mistake it for a regression. It will be removed in a future major release.
Centralized Constants
Common defaults live in app/constants.ts:
DEFAULTS: server defaults (e.g.,SSH_READY_TIMEOUT_MS,IO_PING_INTERVAL_MS,SESSION_COOKIE_NAME,HSTS_MAX_AGE_SECONDS).ENV_LIMITS: caps for environment variables forwarded to SSH.HEADERS: canonical HTTP header names used by the server.
Credential Replay Line Ending
You can choose whether credential replay sends a carriage return (CR) or carriage return + line feed (CRLF).
options.replayCRLF(boolean, defaultfalse): Whentrue, the server will send CRLF when replaying credentials (useful for some sudo/tty configurations). Whenfalse(default), it sends CR only.
This option can also be controlled via the environment variable WEBSSH2_OPTIONS_REPLAY_CRLF.
SSH Environment Variable Allowlist
Control which environment variable names are forwarded to the SSH session. If unset or empty, WebSSH2 applies format/value filtering but does not restrict by name beyond that.
ssh.envAllowlist(array of strings): Only names in this list are forwarded, e.g.['VIM_FILE','CUSTOM_ENV'].- Env var:
WEBSSH2_SSH_ENV_ALLOWLISTcan be provided as comma-separated or JSON array.
Notes:
- Keys must still match
^[A-Z][A-Z0-9_]*$and values must not contain; & | \$` characters. - A safety cap limits forwarding to the first 50 pairs.
SSH Stream Backpressure and Output Limits
New in v2.4.0 - Prevent OOM crashes from high-volume SSH output streams.
Control resource usage when SSH commands or shell sessions generate large amounts of data (e.g., cat large_file.txt or cat /dev/urandom | base64).
Configuration Options
-
ssh.maxExecOutputBytes(number, default:10485760= 10MB): Maximum bytes buffered for exec command output. When exceeded, output is truncated with a[OUTPUT TRUNCATED]message. -
ssh.outputRateLimitBytesPerSec(number, default:0= unlimited): Rate limit for shell stream output in bytes per second. When non-zero, SSH streams are throttled to prevent overwhelming the WebSocket connection and browser. Set to0to disable rate limiting. -
ssh.socketHighWaterMark(number, default:16384= 16KB): Socket.IO buffer high-water mark for backpressure control. SSH streams pause when Socket.IO send buffer exceeds this threshold.
Use Cases
Prevent OOM from infinite streams:
{
"ssh": {
"outputRateLimitBytesPerSec": 1048576
}
}
This limits shell output to 1MB/s, preventing Node.js heap exhaustion from commands like cat /dev/urandom | base64.
Limit exec command output:
{
"ssh": {
"maxExecOutputBytes": 5242880
}
}
Exec commands (via Socket.IO exec event) will truncate at 5MB instead of the default 10MB.
High-throughput environments:
{
"ssh": {
"maxExecOutputBytes": 52428800,
"outputRateLimitBytesPerSec": 5242880,
"socketHighWaterMark": 65536
}
}
Allows 50MB exec output, 5MB/s rate limit, and 64KB socket buffer for trusted users with high-volume workflows.
Restricted environments:
{
"ssh": {
"maxExecOutputBytes": 1048576,
"outputRateLimitBytesPerSec": 262144,
"socketHighWaterMark": 8192
}
}
Strict limits (1MB exec, 256KB/s rate, 8KB buffer) for untrusted users or resource-constrained deployments.
Environment Variables
These options can also be configured via environment variables:
WEBSSH2_SSH_MAX_EXEC_OUTPUT_BYTESWEBSSH2_SSH_OUTPUT_RATE_LIMIT_BYTES_PER_SECWEBSSH2_SSH_SOCKET_HIGH_WATER_MARK
See ENVIRONMENT-VARIABLES.md for details.
SFTP Configuration
The SFTP feature provides a web-based file browser for uploading and downloading files through the SSH connection.
Configuration Options
-
ssh.sftp.enabled(boolean, default:false): Enable or disable SFTP functionality. When disabled (the default), the file browser UI is hidden. -
ssh.sftp.maxFileSize(number, default:104857600= 100MB): Maximum file size for uploads and downloads in bytes. -
ssh.sftp.transferRateLimitBytesPerSec(number, default:0= unlimited): Rate limit for file transfers in bytes per second. Set to0to disable rate limiting. -
ssh.sftp.chunkSize(number, default:32768= 32KB): Chunk size for file transfers. Larger chunks may improve throughput but use more memory. Valid range: 1KB - 1MB. -
ssh.sftp.maxConcurrentTransfers(number, default:2): Maximum number of simultaneous file transfers per session. -
ssh.sftp.allowedPaths(array of strings | null, default:null): Restrict SFTP access to specific directories. Whennull, all paths accessible by the SSH user are allowed. The tilde (~) is expanded to the user's home directory. -
ssh.sftp.blockedExtensions(array of strings, default:[]): File extensions to block from uploads and downloads (e.g.,[".exe", ".sh"]). -
ssh.sftp.timeout(number, default:30000= 30s): Operation timeout in milliseconds for SFTP commands.
Default SFTP Configuration
{
"ssh": {
"sftp": {
"enabled": false,
"maxFileSize": 104857600,
"transferRateLimitBytesPerSec": 0,
"chunkSize": 32768,
"maxConcurrentTransfers": 2,
"allowedPaths": null,
"blockedExtensions": [],
"timeout": 30000
}
}
}
Note: SFTP is disabled by default. Set
enabledtotrueto enable the file browser functionality.
Use Cases
Enable SFTP with basic settings:
{
"ssh": {
"sftp": {
"enabled": true
}
}
}
This enables SFTP with all default settings (100MB file limit, no rate limiting).
Restricted file access for shared hosting:
{
"ssh": {
"sftp": {
"enabled": true,
"maxFileSize": 52428800,
"allowedPaths": ["~", "/var/www"],
"blockedExtensions": [".exe", ".sh", ".bash", ".py", ".php", ".pl"],
"transferRateLimitBytesPerSec": 1048576
}
}
}
This configuration enables SFTP, limits uploads to 50MB, restricts browsing to home and /var/www directories, blocks executable files, and limits transfer speed to 1MB/s.
High-performance for trusted environments:
{
"ssh": {
"sftp": {
"enabled": true,
"maxFileSize": 524288000,
"chunkSize": 65536,
"maxConcurrentTransfers": 5,
"transferRateLimitBytesPerSec": 0
}
}
}
This enables SFTP and allows 500MB files, uses 64KB chunks for better throughput, allows 5 concurrent transfers, and has no rate limiting.
Disable SFTP (default):
{
"ssh": {
"sftp": {
"enabled": false
}
}
}
SFTP is disabled by default. This configuration is only needed if you want to explicitly disable it after previously enabling it.
Environment Variables
These options can also be configured via environment variables:
WEBSSH2_SSH_SFTP_ENABLEDWEBSSH2_SSH_SFTP_MAX_FILE_SIZEWEBSSH2_SSH_SFTP_TRANSFER_RATE_LIMIT_BYTES_PER_SECWEBSSH2_SSH_SFTP_CHUNK_SIZEWEBSSH2_SSH_SFTP_MAX_CONCURRENT_TRANSFERSWEBSSH2_SSH_SFTP_ALLOWED_PATHSWEBSSH2_SSH_SFTP_BLOCKED_EXTENSIONSWEBSSH2_SSH_SFTP_TIMEOUT
See ENVIRONMENT-VARIABLES.md for details on environment variable format and examples.
Host Key Verification
SSH host key verification provides TOFU (Trust On First Use) protection against man-in-the-middle attacks. It supports three modes of operation: server-only (SQLite store), client-only (browser localStorage), and hybrid (server-first with client fallback).
Security: Host key verification is disabled by default and the server logs a startup warning until it is enabled. See Default security posture.
Configuration Options
-
ssh.hostKeyVerification.enabled(boolean, default:false): Enable or disable host key verification. When disabled (the default), all host keys are accepted without verification. -
ssh.hostKeyVerification.mode('server'|'client'|'hybrid', default:'hybrid'): Operational mode.serveruses only the SQLite store,clientuses only the browser localStorage store,hybridchecks the server store first and falls back to the client store for unknown keys. The mode sets sensible defaults for which stores are enabled, but explicit store flags override mode defaults. -
ssh.hostKeyVerification.unknownKeyAction('prompt'|'alert'|'reject', default:'prompt'): Action when an unknown key is encountered (no match in any enabled store).promptasks the user to accept or reject,alertallows the connection with a warning,rejectblocks the connection. -
ssh.hostKeyVerification.serverStore.enabled(boolean): Whether the server-side SQLite store is active. Defaults are derived frommodebut can be overridden explicitly. -
ssh.hostKeyVerification.serverStore.dbPath(string, default:'/data/hostkeys.db'): Path to the SQLite database file. The application opens it read-only. Usenpm run hostkeysto manage keys. -
ssh.hostKeyVerification.clientStore.enabled(boolean): Whether the client-side browser localStorage store is active. Defaults are derived frommodebut can be overridden explicitly.
Default Host Key Verification Configuration
{
"ssh": {
"hostKeyVerification": {
"enabled": false,
"mode": "hybrid",
"unknownKeyAction": "prompt",
"serverStore": {
"enabled": true,
"dbPath": "/data/hostkeys.db"
},
"clientStore": {
"enabled": true
}
}
}
}
Note: Host key verification is disabled by default. Set
enabledtotrueto activate it.
Use Cases
Enable with hybrid mode (recommended):
{
"ssh": {
"hostKeyVerification": {
"enabled": true,
"mode": "hybrid"
}
}
}
Server store is checked first. If the key is unknown on the server, the client's browser store is consulted. Unknown keys prompt the user.
Server-only mode (centrally managed keys):
{
"ssh": {
"hostKeyVerification": {
"enabled": true,
"mode": "server",
"unknownKeyAction": "reject"
}
}
}
Only the server SQLite store is used. Unknown keys are rejected — administrators must pre-seed keys via npm run hostkeys.
Client-only mode (no server database):
{
"ssh": {
"hostKeyVerification": {
"enabled": true,
"mode": "client"
}
}
}
Only the client browser store is used. Users manage their own trusted keys via the settings UI.
Alert-only (log but don't block):
{
"ssh": {
"hostKeyVerification": {
"enabled": true,
"mode": "server",
"unknownKeyAction": "alert"
}
}
}
Unknown keys show a warning indicator but connections proceed. Useful for monitoring before enforcing.
Override mode defaults with explicit flags:
{
"ssh": {
"hostKeyVerification": {
"enabled": true,
"mode": "server",
"serverStore": { "enabled": true, "dbPath": "/data/hostkeys.db" },
"clientStore": { "enabled": true }
}
}
}
Mode is server but clientStore.enabled is explicitly set to true, making it behave like hybrid. Explicit flags always take precedence over mode defaults.
Seeding the Server Store
Use the built-in CLI tool to manage the SQLite database:
# Probe a host and add its key
npm run hostkeys -- --host server1.example.com
# Probe a host on a non-standard port
npm run hostkeys -- --host server1.example.com:2222
# Import from OpenSSH known_hosts file
npm run hostkeys -- --known-hosts ~/.ssh/known_hosts
# List all stored keys
npm run hostkeys -- --list
# Remove keys for a host
npm run hostkeys -- --remove server1.example.com
# Use a custom database path
npm run hostkeys -- --db /custom/path/hostkeys.db --host server1.example.com
Environment Variables
These options can also be configured via environment variables:
WEBSSH2_SSH_HOSTKEY_ENABLEDWEBSSH2_SSH_HOSTKEY_MODEWEBSSH2_SSH_HOSTKEY_UNKNOWN_ACTIONWEBSSH2_SSH_HOSTKEY_DB_PATHWEBSSH2_SSH_HOSTKEY_SERVER_ENABLEDWEBSSH2_SSH_HOSTKEY_CLIENT_ENABLED
See ENVIRONMENT-VARIABLES.md for details.
WEBSSH2_SSH_SFTP_MAX_FILE_SIZEWEBSSH2_SSH_SFTP_TRANSFER_RATE_LIMIT_BYTES_PER_SECWEBSSH2_SSH_SFTP_CHUNK_SIZEWEBSSH2_SSH_SFTP_MAX_CONCURRENT_TRANSFERSWEBSSH2_SSH_SFTP_ALLOWED_PATHSWEBSSH2_SSH_SFTP_BLOCKED_EXTENSIONSWEBSSH2_SSH_SFTP_TIMEOUT
See ENVIRONMENT-VARIABLES.md for details on environment variable format and examples.
Telnet Configuration
Security Warning: Telnet transmits all data, including credentials, in plain text. It should only be used on trusted networks or for connecting to legacy devices that do not support SSH. Never expose telnet endpoints to the public internet without additional network-level protections (e.g., VPN, firewall rules).
WebSSH2 includes optional telnet support for connecting to legacy devices and systems that do not support SSH. Telnet is disabled by default and must be explicitly enabled.
Configuration Options
-
telnet.enabled(boolean, default:false): Enable telnet support. Whenfalse, all/telnetroutes return 404. -
telnet.defaultPort(number, default:23): Default telnet port used when no port is specified in the connection request. -
telnet.timeout(number, default:30000): Connection timeout in milliseconds. If the connection cannot be established within this time, it is aborted. -
telnet.term(string, default:"vt100"): Terminal type sent during TERMINAL-TYPE negotiation. Common values includevt100,vt220,xterm, andansi. -
telnet.auth.loginPrompt(string, regex, default:"login:\\s*$"): Regular expression pattern used to detect the login prompt. The authenticator watches incoming data for this pattern to know when to send the username. -
telnet.auth.passwordPrompt(string, regex, default:"[Pp]assword:\\s*$"): Regular expression pattern used to detect the password prompt. The authenticator watches incoming data for this pattern to know when to send the password. -
telnet.auth.failurePattern(string, regex, default:"Login incorrect|Access denied|Login failed"): Regular expression pattern used to detect authentication failure. When matched, the connection reports an authentication error. -
telnet.auth.expectTimeout(number, default:10000): Maximum time in milliseconds to wait for prompt pattern matches during authentication. If no prompt is detected within this time, the authenticator falls back to pass-through mode, forwarding raw data to the terminal. -
telnet.allowedSubnets(string[], default:[]): Restrict which hosts can be connected to via telnet. Uses the same CIDR notation format asssh.allowedSubnets. When empty, all hosts are allowed.
Security: Empty
ssh.allowedSubnets/telnet.allowedSubnetslists allow connections to ANY host (open proxy / SSRF exposure) and the server logs a startup warning until they are restricted. See Default security posture.
Default Telnet Configuration
{
"telnet": {
"enabled": false,
"defaultPort": 23,
"timeout": 30000,
"term": "vt100",
"auth": {
"loginPrompt": "login:\\s*$",
"passwordPrompt": "[Pp]assword:\\s*$",
"failurePattern": "Login incorrect|Access denied|Login failed",
"expectTimeout": 10000
},
"allowedSubnets": []
}
}
Note: Telnet is disabled by default. Set
enabledtotrueto activate telnet support.
Use Cases
Enable telnet for legacy network devices:
{
"telnet": {
"enabled": true,
"defaultPort": 23,
"term": "vt100"
}
}
This enables telnet with default authentication patterns, suitable for most Linux/Unix systems and network equipment.
Custom prompts for non-standard devices:
{
"telnet": {
"enabled": true,
"auth": {
"loginPrompt": "Username:\\s*$",
"passwordPrompt": "Password:\\s*$",
"failurePattern": "Authentication failed|Bad password|Access denied",
"expectTimeout": 15000
}
}
}
Some devices use non-standard prompt text. Adjust the regex patterns to match your equipment.
Restrict telnet to specific subnets:
{
"telnet": {
"enabled": true,
"allowedSubnets": ["10.0.0.0/8", "192.168.1.0/24"],
"timeout": 15000
}
}
Only allow telnet connections to hosts within the specified private network ranges.
Disable telnet (default):
{
"telnet": {
"enabled": false
}
}
Telnet is disabled by default. This configuration is only needed if you want to explicitly disable it after previously enabling it.
Environment Variables
These options can also be configured via environment variables:
WEBSSH2_TELNET_ENABLEDWEBSSH2_TELNET_DEFAULT_PORTWEBSSH2_TELNET_TIMEOUTWEBSSH2_TELNET_TERMWEBSSH2_TELNET_AUTH_LOGIN_PROMPTWEBSSH2_TELNET_AUTH_PASSWORD_PROMPTWEBSSH2_TELNET_AUTH_FAILURE_PATTERNWEBSSH2_TELNET_AUTH_EXPECT_TIMEOUT
See ENVIRONMENT-VARIABLES.md for details.
Terminal Theming (options.theming)
WebSSH2 includes an opt-in terminal theming system. Theming is disabled by default so upgrades do not change the rendered terminal appearance. See features/THEMING.md for the operator guide.
Configuration Options
-
options.theming.enabled(boolean, default:false): Master switch for the theming system. Whenfalse, the settings modal hides theming controls and the terminal renders with the previous (non-themed) defaults. -
options.theming.allowCustom(boolean, default:true): Whentrue, the settings modal exposes a JSON paste textarea that lets users define their own theme. User-pasted themes are stored in browserlocalStorageonly and are never sent to the server. Whenfalse, users can only choose from the operator-supplied list. -
options.theming.themes(array of strings ornull, default:null): Allowlist of built-in theme names.nullexposes all built-ins. An explicit array (even empty) restricts the picker to those names only. Built-in names:Default,Dracula,Nord,Solarized Dark,One Dark,Monokai,Gruvbox Dark,Tokyo Night,Catppuccin Mocha. (Solarized Light is not shipped because it fails WCAG AA contrast at 4.13:1.) -
options.theming.additionalThemes(array ofAdditionalTheme, default:[]): Operator-defined themes injected at startup. Each entry has the shape:
{
name: string (must match /^[\w .\-()]{1,64}$/u),
colors: object of hex strings keyed by allowed color names,
license: optional attribution string (max 256 chars),
source: optional https:// URL (max 256 chars)
}
Names that collide with a built-in (case-insensitive) are rejected. The reserved names default and custom are rejected. Each theme's serialized JSON must be ≤ 4 KiB. Color values must be hex (#rgb, #rrggbb, or #rrggbbaa). Allowed color keys are: background, foreground, cursor, cursorAccent, selectionBackground, selectionForeground, selectionInactiveBackground, black, red, green, yellow, blue, magenta, cyan, white, brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite. Entries that fail validation are dropped at startup; the rest of the array is preserved.
-
options.theming.defaultTheme(string, default:"Default"): The picker's initial value. Must resolve to either a built-in (subject tothemesfiltering) or an entry inadditionalThemes. Falls back to"Default"if the configured value fails the name regex. -
options.theming.headerBackground("independent"|"followTerminal"|"locked", default:"independent"): Header bar coupling.independentkeeps the header at the configuredheader.backgroundcolor (current behavior).followTerminalmakes the header track the active terminal theme's background color.lockedis reserved for a future "always honor configured value, even when followTerminal would otherwise apply" mode and currently behaves identically toindependent.
Default Theming Configuration
{
"options": {
"theming": {
"enabled": false,
"allowCustom": true,
"themes": null,
"additionalThemes": [],
"defaultTheme": "Default",
"headerBackground": "independent"
}
}
}
Note: Theming is disabled by default. Set
enabledtotrueto activate it.
Use Cases
Enable theming with all built-ins:
{
"options": {
"theming": {
"enabled": true
}
}
}
This enables theming with all nine built-in themes available in the picker, the JSON paste textarea visible, and the header bar in independent mode.
Restrict the picker to a curated subset:
{
"options": {
"theming": {
"enabled": true,
"themes": ["Default", "Dracula", "Tokyo Night"],
"defaultTheme": "Tokyo Night",
"allowCustom": false
}
}
}
Only three built-ins are exposed, the user cannot paste custom themes, and the picker starts on Tokyo Night.
Ship a branded theme and follow the terminal background:
{
"options": {
"theming": {
"enabled": true,
"allowCustom": false,
"headerBackground": "followTerminal",
"defaultTheme": "Acme Corp",
"additionalThemes": [
{
"name": "Acme Corp",
"license": "Proprietary - Acme Corp",
"source": "https://internal.acme.example/themes/acme-corp",
"colors": {
"background": "#0b1220",
"foreground": "#e6edf3",
"cursor": "#58a6ff",
"selectionBackground": "#1f6feb",
"black": "#1f2937",
"red": "#f87171",
"green": "#4ade80",
"yellow": "#fde047",
"blue": "#60a5fa",
"magenta": "#c084fc",
"cyan": "#67e8f9",
"white": "#e6edf3"
}
}
]
}
}
}
The branded Acme Corp theme is the default, the user cannot paste custom themes, and the header bar background tracks the terminal background color.
Environment Variables
These options can also be configured via environment variables:
WEBSSH2_THEMING_ENABLEDWEBSSH2_THEMING_ALLOW_CUSTOMWEBSSH2_THEMING_THEMESWEBSSH2_THEMING_ADDITIONAL_THEMES(base64-encoded JSON array)WEBSSH2_THEMING_DEFAULT_THEMEWEBSSH2_THEMING_HEADER_BACKGROUND
See ENVIRONMENT-VARIABLES.md for details and the base64 encoding example, and features/THEMING.md for the full operator guide.