diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index cb389b93a5ec4..68953eb14e434 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -66,6 +66,10 @@ Clients include the coder cli, vs code extension, and the web UI. --ssh-hostname-prefix string, $CODER_SSH_HOSTNAME_PREFIX (default: coder.) The SSH deployment prefix is used in the Host of the ssh config. + --web-terminal-renderer string, $CODER_WEB_TERMINAL_RENDERER (default: canvas) + The renderer to use when opening a web terminal. Valid values are + 'canvas', 'webgl', or 'dom'. + CONFIG OPTIONS: Use a YAML configuration file when your server launch become unwieldy. diff --git a/cli/testdata/server-config.yaml.golden b/cli/testdata/server-config.yaml.golden index 689004ba5be57..31304d68e1633 100644 --- a/cli/testdata/server-config.yaml.golden +++ b/cli/testdata/server-config.yaml.golden @@ -411,6 +411,10 @@ client: # incorrectly can break SSH to your deployment, use cautiously. # (default: , type: string-array) sshConfigOptions: [] + # The renderer to use when opening a web terminal. Valid values are 'canvas', + # 'webgl', or 'dom'. + # (default: canvas, type: string) + webTerminalRenderer: canvas # Support links to display in the top right drop down menu. # (default: , type: struct[[]codersdk.LinkConfig]) supportLinks: [] diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 0e8c9f63dd7cc..32424c5ffe1a2 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -8209,6 +8209,9 @@ const docTemplate = `{ "verbose": { "type": "boolean" }, + "web_terminal_renderer": { + "type": "string" + }, "wgtunnel_host": { "type": "string" }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index a14c65f120df4..71c7cbef07a7e 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -7347,6 +7347,9 @@ "verbose": { "type": "boolean" }, + "web_terminal_renderer": { + "type": "string" + }, "wgtunnel_host": { "type": "string" }, diff --git a/codersdk/deployment.go b/codersdk/deployment.go index bd89af4201a10..3a09c31de4b7b 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -180,6 +180,7 @@ type DeploymentValues struct { ProxyHealthStatusInterval clibase.Duration `json:"proxy_health_status_interval,omitempty" typescript:",notnull"` EnableTerraformDebugMode clibase.Bool `json:"enable_terraform_debug_mode,omitempty" typescript:",notnull"` UserQuietHoursSchedule UserQuietHoursScheduleConfig `json:"user_quiet_hours_schedule,omitempty" typescript:",notnull"` + WebTerminalRenderer clibase.String `json:"web_terminal_renderer,omitempty" typescript:",notnull"` Config clibase.YAMLConfigPath `json:"config,omitempty" typescript:",notnull"` WriteConfig clibase.Bool `json:"write_config,omitempty" typescript:",notnull"` @@ -1762,7 +1763,18 @@ Write out the current server config as YAML to stdout.`, Group: &deploymentGroupUserQuietHoursSchedule, YAML: "defaultQuietHoursSchedule", }, + { + Name: "Web Terminal Renderer", + Description: "The renderer to use when opening a web terminal. Valid values are 'canvas', 'webgl', or 'dom'.", + Flag: "web-terminal-renderer", + Env: "CODER_WEB_TERMINAL_RENDERER", + Default: "canvas", + Value: &c.WebTerminalRenderer, + Group: &deploymentGroupClient, + YAML: "webTerminalRenderer", + }, } + return opts } diff --git a/docs/api/general.md b/docs/api/general.md index bd6942fd3d271..1362b6edcd280 100644 --- a/docs/api/general.md +++ b/docs/api/general.md @@ -389,6 +389,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \ "default_schedule": "string" }, "verbose": true, + "web_terminal_renderer": "string", "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 6ca7143579930..f3bcc6cb9e43e 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -2246,6 +2246,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "default_schedule": "string" }, "verbose": true, + "web_terminal_renderer": "string", "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, @@ -2614,6 +2615,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "default_schedule": "string" }, "verbose": true, + "web_terminal_renderer": "string", "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, @@ -2687,6 +2689,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `update_check` | boolean | false | | | | `user_quiet_hours_schedule` | [codersdk.UserQuietHoursScheduleConfig](#codersdkuserquiethoursscheduleconfig) | false | | | | `verbose` | boolean | false | | | +| `web_terminal_renderer` | string | false | | | | `wgtunnel_host` | string | false | | | | `wildcard_access_url` | [clibase.URL](#clibaseurl) | false | | | | `write_config` | boolean | false | | | diff --git a/docs/cli/server.md b/docs/cli/server.md index 0db6c9e871489..9258f0f92f7e6 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -997,6 +997,17 @@ Enables trace exporting to Honeycomb.io using the provided API Key. Periodically check for new releases of Coder and inform the owner. The check is performed once per day. +### --web-terminal-renderer + +| | | +| ----------- | ----------------------------------------- | +| Type | string | +| Environment | $CODER_WEB_TERMINAL_RENDERER | +| YAML | client.webTerminalRenderer | +| Default | canvas | + +The renderer to use when opening a web terminal. Valid values are 'canvas', 'webgl', or 'dom'. + ### --wildcard-access-url | | | diff --git a/enterprise/cli/testdata/coder_server_--help.golden b/enterprise/cli/testdata/coder_server_--help.golden index f9faa4e5bf66c..f4bb522f5ec62 100644 --- a/enterprise/cli/testdata/coder_server_--help.golden +++ b/enterprise/cli/testdata/coder_server_--help.golden @@ -67,6 +67,10 @@ Clients include the coder cli, vs code extension, and the web UI. --ssh-hostname-prefix string, $CODER_SSH_HOSTNAME_PREFIX (default: coder.) The SSH deployment prefix is used in the Host of the ssh config. + --web-terminal-renderer string, $CODER_WEB_TERMINAL_RENDERER (default: canvas) + The renderer to use when opening a web terminal. Valid values are + 'canvas', 'webgl', or 'dom'. + CONFIG OPTIONS: Use a YAML configuration file when your server launch become unwieldy. diff --git a/site/e2e/playwright.config.ts b/site/e2e/playwright.config.ts index e82a4e841dac0..792944f26dde9 100644 --- a/site/e2e/playwright.config.ts +++ b/site/e2e/playwright.config.ts @@ -49,6 +49,7 @@ export default defineConfig({ `--dangerous-disable-rate-limits ` + `--provisioner-daemons 10 ` + `--provisioner-daemons-echo ` + + `--web-terminal-renderer=dom ` + `--pprof-enable`, env: { ...process.env, diff --git a/site/src/AppRouter.tsx b/site/src/AppRouter.tsx index abef366dbcbfa..3568b3230ab0a 100644 --- a/site/src/AppRouter.tsx +++ b/site/src/AppRouter.tsx @@ -339,7 +339,7 @@ export const AppRouter: FC = () => { {/* Terminal and CLI auth pages don't have the dashboard layout */} } + element={} /> } /> } /> diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 45b2676666904..a4e6a7df8c7f9 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -404,6 +404,7 @@ export interface DeploymentValues { readonly proxy_health_status_interval?: number; readonly enable_terraform_debug_mode?: boolean; readonly user_quiet_hours_schedule?: UserQuietHoursScheduleConfig; + readonly web_terminal_renderer?: string; readonly config?: string; readonly write_config?: boolean; readonly address?: string; diff --git a/site/src/pages/TerminalPage/TerminalPage.test.tsx b/site/src/pages/TerminalPage/TerminalPage.test.tsx index d8fb9d28ddd69..e922f0ff4fc74 100644 --- a/site/src/pages/TerminalPage/TerminalPage.test.tsx +++ b/site/src/pages/TerminalPage/TerminalPage.test.tsx @@ -37,7 +37,7 @@ Object.defineProperty(window, "TextEncoder", { const renderTerminal = async ( route = `/${MockUser.username}/${MockWorkspace.name}/terminal`, ) => { - const utils = renderWithAuth(, { + const utils = renderWithAuth(, { route, path: "/:username/:workspace/terminal", }); diff --git a/site/src/pages/TerminalPage/TerminalPage.tsx b/site/src/pages/TerminalPage/TerminalPage.tsx index 9292c5c657a0d..958d7ef7329e7 100644 --- a/site/src/pages/TerminalPage/TerminalPage.tsx +++ b/site/src/pages/TerminalPage/TerminalPage.tsx @@ -7,6 +7,7 @@ import { colors } from "theme/colors"; import { v4 as uuidv4 } from "uuid"; import * as XTerm from "xterm"; import { WebglAddon } from "xterm-addon-webgl"; +import { CanvasAddon } from "xterm-addon-canvas"; import { FitAddon } from "xterm-addon-fit"; import { WebLinksAddon } from "xterm-addon-web-links"; import { Unicode11Addon } from "xterm-addon-unicode11"; @@ -28,6 +29,8 @@ import { LoadedScriptsAlert, LoadingScriptsAlert, } from "./TerminalAlerts"; +import { useQuery } from "react-query"; +import { deploymentConfig } from "api/queries/deployment"; export const Language = { workspaceErrorMessagePrefix: "Unable to fetch workspace: ", @@ -35,11 +38,7 @@ export const Language = { websocketErrorMessagePrefix: "WebSocket failed: ", }; -type TerminalPageProps = React.PropsWithChildren<{ - renderer: "webgl" | "dom"; -}>; - -const TerminalPage: FC = ({ renderer }) => { +const TerminalPage: FC = () => { const navigate = useNavigate(); const styles = useStyles(); const { proxy } = useProxy(); @@ -101,6 +100,8 @@ const TerminalPage: FC = ({ renderer }) => { prevLifecycleState.current = lifecycleState; }, [lifecycleState]); + const config = useQuery(deploymentConfig()); + // handleWebLink handles opening of URLs in the terminal! const handleWebLink = useCallback( (uri: string) => { @@ -166,9 +167,10 @@ const TerminalPage: FC = ({ renderer }) => { background: colors.gray[16], }, }); - // DOM is the default renderer. - if (renderer === "webgl") { + if (config.data?.config.web_terminal_renderer === "webgl") { terminal.loadAddon(new WebglAddon()); + } else if (config.data?.config.web_terminal_renderer === "canvas") { + terminal.loadAddon(new CanvasAddon()); } const fitAddon = new FitAddon(); setFitAddon(fitAddon); @@ -208,7 +210,7 @@ const TerminalPage: FC = ({ renderer }) => { window.removeEventListener("resize", listener); terminal.dispose(); }; - }, [renderer, sendEvent, xtermRef, handleWebLink]); + }, [config.data, sendEvent, xtermRef, handleWebLink]); // Triggers the initial terminal connection using // the reconnection token and workspace name found