diff --git a/apps/dokploy/server/wss/terminal.ts b/apps/dokploy/server/wss/terminal.ts index b1ecb908..fa268124 100644 --- a/apps/dokploy/server/wss/terminal.ts +++ b/apps/dokploy/server/wss/terminal.ts @@ -1,8 +1,9 @@ import type http from "node:http"; import { findServerById, validateWebSocketRequest } from "@dokploy/server"; import { publicIpv4, publicIpv6 } from "public-ip"; -import { Client } from "ssh2"; +import { Client, type ConnectConfig } from "ssh2"; import { WebSocketServer } from "ws"; +import { getLocalServerPrivateKey } from "./utils"; export const getPublicIpWithFallback = async () => { // @ts-ignore @@ -55,21 +56,67 @@ export const setupTerminalWebSocketServer = ( return; } - const server = await findServerById(serverId); + let connectionDetails: ConnectConfig = {}; - if (!server) { - ws.close(); - return; + const isLocalServer = serverId === "local"; + + if (isLocalServer) { + const port = Number(url.searchParams.get("port")); + const username = url.searchParams.get("username"); + + if (!port || !username) { + ws.close(); + return; + } + + ws.send("Getting private SSH key...\n"); + const privateKey = await getLocalServerPrivateKey(); + + if (!privateKey) { + ws.close(); + return; + } + + connectionDetails = { + host: "localhost", + port, + username, + privateKey, + }; + } else { + ws.send("Getting server data...\n"); + const server = await findServerById(serverId); + + if (!server) { + ws.close(); + return; + } + + const { ipAddress, port, username, sshKey, sshKeyId } = server; + + if (!sshKeyId) { + throw new Error("No SSH key available for this server"); + } + + connectionDetails = { + host: ipAddress, + port: port, + username: username, + privateKey: sshKey?.privateKey, + }; } - if (!server.sshKeyId) - throw new Error("No SSH key available for this server"); - const conn = new Client(); let stdout = ""; let stderr = ""; + + ws.send("Connecting...\n"); + conn .once("ready", () => { + // Clear terminal content once connected + ws.send("\x1bc"); + conn.shell({}, (err, stream) => { if (err) throw err; @@ -112,18 +159,13 @@ export const setupTerminalWebSocketServer = ( .on("error", (err) => { if (err.level === "client-authentication") { ws.send( - `Authentication failed: Invalid SSH private key. āŒ Error: ${err.message} ${err.level}`, + `Authentication failed: Unauthorized ${isLocalServer ? "" : "private SSH key or "}username.\nāŒ Error: ${err.message} ${err.level}`, ); } else { ws.send(`SSH connection error: ${err.message}`); } conn.end(); }) - .connect({ - host: server.ipAddress, - port: server.port, - username: server.username, - privateKey: server.sshKey?.privateKey, - }); + .connect(connectionDetails); }); };