import { exec } from "node:child_process";import util from "node:util";import { findServerById } from "@dokploy/server/services/server";import { Client } from "ssh2";export const execAsync = util.promisify(exec); export const execAsyncRemote = async ( serverId: string | null, command: string, onData?: (data: string) => void,): Promise<{ stdout: string; stderr: string }> => { if (!serverId) return { stdout: "", stderr: "" }; const server = await findServerById(serverId); if (!server.sshKeyId) throw new Error("No SSH key available for this server"); let stdout = ""; let stderr = ""; return new Promise((resolve, reject) => { const conn = new Client(); sleep(1000); conn .once("ready", () => { conn.exec(command, (err, stream) => { if (err) { onData?.(err.message); throw err; } stream .on("close", (code: number, _signal: string) => { conn.end(); if (code === 0) { resolve({ stdout, stderr }); } else { reject( new Error( `Command exited with code ${code}. Stderr: ${stderr}, command: ${command}`, ), ); } }) .on("data", (data: string) => { stdout += data.toString(); onData?.(data.toString()); }) .stderr.on("data", (data) => { stderr += data.toString(); onData?.(data.toString()); }); }); }) .on("error", (err) => { conn.end(); if (err.level === "client-authentication") { onData?.( `Authentication failed: Invalid SSH private key. ❌ Error: ${err.message} ${err.level}`, ); reject( new Error( `Authentication failed: Invalid SSH private key. ❌ Error: ${err.message} ${err.level}`, ), ); } else { onData?.(`SSH connection error: ${err.message}`); reject(new Error(`SSH connection error: ${err.message}`)); } }) .connect({ host: server.ipAddress, port: server.port, username: server.username, privateKey: server.sshKey?.privateKey, timeout: 99999, }); });}; export const sleep = (ms: number) => { return new Promise((resolve) => setTimeout(resolve, ms));};
import { exec } from "node:child_process";
import util from "node:util";
import { findServerById } from "@dokploy/server/services/server";
import { Client } from "ssh2";
export const execAsync = util.promisify(exec);
export const execAsyncRemote = async (
serverId: string | null,
command: string,
onData?: (data: string) => void,
): Promise<{ stdout: string; stderr: string }> => {
if (!serverId) return { stdout: "", stderr: "" };
const server = await findServerById(serverId);
if (!server.sshKeyId) throw new Error("No SSH key available for this server");
let stdout = "";
let stderr = "";
return new Promise((resolve, reject) => {
const conn = new Client();
sleep(1000);
conn
.once("ready", () => {
conn.exec(command, (err, stream) => {
if (err) {
onData?.(err.message);
throw err;
}
stream
.on("close", (code: number, _signal: string) => {
conn.end();
if (code === 0) {
resolve({ stdout, stderr });
} else {
reject(
new Error(
`Command exited with code ${code}. Stderr: ${stderr}, command: ${command}`,
),
);
}
})
.on("data", (data: string) => {
stdout += data.toString();
onData?.(data.toString());
})
.stderr.on("data", (data) => {
stderr += data.toString();
onData?.(data.toString());
});
});
})
.on("error", (err) => {
conn.end();
if (err.level === "client-authentication") {
onData?.(
`Authentication failed: Invalid SSH private key. ❌ Error: ${err.message} ${err.level}`,
);
reject(
new Error(
`Authentication failed: Invalid SSH private key. ❌ Error: ${err.message} ${err.level}`,
),
);
} else {
onData?.(`SSH connection error: ${err.message}`);
reject(new Error(`SSH connection error: ${err.message}`));
}
})
.connect({
host: server.ipAddress,
port: server.port,
username: server.username,
privateKey: server.sshKey?.privateKey,
timeout: 99999,
});
});
};
export const sleep = (ms: number) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};