feat: finish the docker plugin (B15)

This commit is contained in:
LukeGus committed 2026-09-24 11:58:20 -05:00
1 parent 0a3f05d99d
commit 993a91c899
167 files changed
+26299 -5136

No files matched your search

+2 -7
View File
@@ -798,7 +798,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
tunnel_connections TEXT,
jump_hosts TEXT,
enable_file_manager INTEGER NOT NULL DEFAULT 1,
enable_docker INTEGER NOT NULL DEFAULT 0,
enable_web_ui INTEGER NOT NULL DEFAULT 0,
show_terminal_in_sidebar INTEGER NOT NULL DEFAULT 1,
show_file_manager_in_sidebar INTEGER NOT NULL DEFAULT 0,
@@ -808,7 +807,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
default_path TEXT,
status_check_enabled INTEGER NOT NULL DEFAULT 1,
status_check_interval INTEGER,
docker_config TEXT,
web_ui_config TEXT,
terminal_config TEXT,
quick_actions TEXT,
@@ -929,8 +927,8 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
const sshHosts =
await createCurrentHostRepository().listDecryptedByUserId(userId);
const insertHost = exportDb.prepare(`
INSERT INTO ssh_data (id, user_id, connection_type, name, ip, port, username, folder, tags, pin, auth_type, force_keyboard_interactive, password, key, key_password, key_type, sudo_password, autostart_password, autostart_key, autostart_key_password, credential_id, override_credential_username, enable_terminal, enable_tunnel, tunnel_connections, jump_hosts, enable_file_manager, enable_docker, enable_web_ui, show_terminal_in_sidebar, show_file_manager_in_sidebar, show_tunnel_in_sidebar, show_docker_in_sidebar, show_server_stats_in_sidebar, default_path, status_check_enabled, status_check_interval, docker_config, web_ui_config, terminal_config, quick_actions, notes, use_socks5, socks5_host, socks5_port, socks5_username, socks5_password, socks5_proxy_chain, domain, mac_address, port_knock_sequence, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
INSERT INTO ssh_data (id, user_id, connection_type, name, ip, port, username, folder, tags, pin, auth_type, force_keyboard_interactive, password, key, key_password, key_type, sudo_password, autostart_password, autostart_key, autostart_key_password, credential_id, override_credential_username, enable_terminal, enable_tunnel, tunnel_connections, jump_hosts, enable_file_manager, enable_web_ui, show_terminal_in_sidebar, show_file_manager_in_sidebar, show_tunnel_in_sidebar, show_docker_in_sidebar, show_server_stats_in_sidebar, default_path, status_check_enabled, status_check_interval, web_ui_config, terminal_config, quick_actions, notes, use_socks5, socks5_host, socks5_port, socks5_username, socks5_password, socks5_proxy_chain, domain, mac_address, port_knock_sequence, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
for (const decrypted of sshHosts) {
@@ -962,7 +960,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
decrypted.tunnelConnections || null,
decrypted.jumpHosts || null,
decrypted.enableFileManager ? 1 : 0,
decrypted.enableDocker ? 1 : 0,
decrypted.enableWebUi ? 1 : 0,
decrypted.showTerminalInSidebar ? 1 : 0,
decrypted.showFileManagerInSidebar ? 1 : 0,
@@ -972,7 +969,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
decrypted.defaultPath || null,
decrypted.statusCheckEnabled === false ? 0 : 1,
decrypted.statusCheckInterval ?? null,
decrypted.dockerConfig || null,
decrypted.webUiConfig || null,
decrypted.terminalConfig || null,
decrypted.quickActions || null,
@@ -1369,7 +1365,6 @@ app.post(
tunnelConnections: host.tunnel_connections,
jumpHosts: host.jump_hosts,
enableFileManager: Boolean(host.enable_file_manager),
enableDocker: Boolean(host.enable_docker),
showTerminalInSidebar: Boolean(host.show_terminal_in_sidebar),
showFileManagerInSidebar: Boolean(
host.show_file_manager_in_sidebar,
-8
View File
@@ -327,7 +327,6 @@ async function initializeCompleteDatabase(): Promise<void> {
enable_tunnel INTEGER NOT NULL DEFAULT 1,
tunnel_connections TEXT,
enable_file_manager INTEGER NOT NULL DEFAULT 1,
enable_docker INTEGER NOT NULL DEFAULT 0,
enable_web_ui INTEGER NOT NULL DEFAULT 0,
default_path TEXT,
autostart_password TEXT,
@@ -336,7 +335,6 @@ async function initializeCompleteDatabase(): Promise<void> {
force_keyboard_interactive TEXT,
status_check_enabled INTEGER NOT NULL DEFAULT 1,
status_check_interval INTEGER,
docker_config TEXT,
web_ui_config TEXT,
terminal_config TEXT,
notes TEXT,
@@ -1075,12 +1073,6 @@ const migrateSchema = () => {
addColumnIfNotExists("ssh_data", "status_check_interval", "INTEGER");
addColumnIfNotExists("ssh_data", "terminal_config", "TEXT");
addColumnIfNotExists("ssh_data", "quick_actions", "TEXT");
addColumnIfNotExists(
"ssh_data",
"enable_docker",
"INTEGER NOT NULL DEFAULT 0",
);
addColumnIfNotExists("ssh_data", "docker_config", "TEXT");
addColumnIfNotExists(
"ssh_data",
"enable_web_ui",
-4
View File
@@ -264,9 +264,6 @@ export const hosts = mysqlTable(
.notNull()
.default(true),
scpLegacy: boolean("scp_legacy").notNull().default(false),
enableDocker: boolean("enable_docker")
.notNull()
.default(false),
enableWebUi: boolean("enable_web_ui")
.notNull()
.default(false),
@@ -299,7 +296,6 @@ export const hosts = mysqlTable(
.notNull()
.default(true),
statusCheckInterval: int("status_check_interval"),
dockerConfig: text("docker_config"),
webUiConfig: text("web_ui_config"),
terminalConfig: text("terminal_config"),
quickActions: text("quick_actions"),
-4
View File
@@ -265,9 +265,6 @@ export const hosts = pgTable(
.notNull()
.default(true),
scpLegacy: boolean("scp_legacy").notNull().default(false),
enableDocker: boolean("enable_docker")
.notNull()
.default(false),
enableWebUi: boolean("enable_web_ui")
.notNull()
.default(false),
@@ -300,7 +297,6 @@ export const hosts = pgTable(
.notNull()
.default(true),
statusCheckInterval: integer("status_check_interval"),
dockerConfig: text("docker_config"),
webUiConfig: text("web_ui_config"),
terminalConfig: text("terminal_config"),
quickActions: text("quick_actions"),
-4
View File
@@ -257,9 +257,6 @@ export const hosts = sqliteTable(
.notNull()
.default(true),
scpLegacy: integer("scp_legacy", { mode: "boolean" }).notNull().default(false),
enableDocker: integer("enable_docker", { mode: "boolean" })
.notNull()
.default(false),
enableWebUi: integer("enable_web_ui", { mode: "boolean" })
.notNull()
.default(false),
@@ -292,7 +289,6 @@ export const hosts = sqliteTable(
.notNull()
.default(true),
statusCheckInterval: integer("status_check_interval"),
dockerConfig: text("docker_config"),
webUiConfig: text("web_ui_config"),
terminalConfig: text("terminal_config"),
quickActions: text("quick_actions"),
@@ -284,8 +284,6 @@ export function registerHostBulkRoutes(
simpleUpdates.enableTunnel = updates.enableTunnel;
if (typeof updates.enableFileManager === "boolean")
simpleUpdates.enableFileManager = updates.enableFileManager;
if (typeof updates.enableDocker === "boolean")
simpleUpdates.enableDocker = updates.enableDocker;
if (typeof updates.enableTmuxMonitor === "boolean")
simpleUpdates.enableTmuxMonitor = updates.enableTmuxMonitor;
if (typeof updates.enableTerminalToolbar === "boolean")
@@ -751,7 +749,6 @@ export function registerHostBulkRoutes(
enableTerminal: hostData.enableTerminal !== false,
enableTunnel: hostData.enableTunnel !== false,
enableFileManager: hostData.enableFileManager !== false,
enableDocker: hostData.enableDocker || false,
enableTmuxMonitor: hostData.enableTmuxMonitor || false,
enableTerminalToolbar: hostData.enableTerminalToolbar !== false,
enableAiAssistant: hostData.enableAiAssistant || false,
@@ -771,9 +768,6 @@ export function registerHostBulkRoutes(
? JSON.stringify(hostData.quickActions)
: null,
...importedStatusCheck(hostData as Record<string, unknown>),
dockerConfig: hostData.dockerConfig
? JSON.stringify(hostData.dockerConfig)
: null,
terminalConfig: hostData.terminalConfig
? JSON.stringify(hostData.terminalConfig)
: null,
@@ -1016,7 +1010,6 @@ export function registerHostBulkRoutes(
enableTerminal: true,
enableTunnel: true,
enableFileManager: true,
enableDocker: false,
enableTmuxMonitor: false,
enableTerminalToolbar: true,
enableAiAssistant: false,
@@ -1034,7 +1027,6 @@ export function registerHostBulkRoutes(
quickActions: null,
statusCheckEnabled: true,
statusCheckInterval: null,
dockerConfig: null,
terminalConfig: null,
forceKeyboardInteractive: "false",
notes: null,
@@ -174,7 +174,6 @@ export type NormalizedImportedHost = Record<string, unknown> & {
enableTerminal?: unknown;
enableTunnel?: unknown;
enableFileManager?: unknown;
enableDocker?: unknown;
enableWebUi?: unknown;
enableProxmox?: unknown;
enableTmuxMonitor?: unknown;
@@ -193,7 +192,6 @@ export type NormalizedImportedHost = Record<string, unknown> & {
quickActions?: unknown;
statusCheckEnabled?: unknown;
statusCheckInterval?: unknown;
dockerConfig?: unknown;
webUiConfig?: unknown;
proxmoxConfig?: unknown;
enableProxmoxStats?: unknown;
@@ -340,7 +338,6 @@ const CONNECT_LEVEL_FIELDS = new Set([
"enableTerminal",
"enableTunnel",
"enableFileManager",
"enableDocker",
"enableTmuxMonitor",
"enableTerminalToolbar",
"enableAiAssistant",
@@ -437,7 +434,6 @@ export function transformHostResponse(
enableTerminal: !!host.enableTerminal,
enableTunnel: !!host.enableTunnel,
enableFileManager: host.enableFileManager !== false,
enableDocker: !!host.enableDocker,
enableTmuxMonitor: !!host.enableTmuxMonitor,
enableTerminalToolbar: host.enableTerminalToolbar !== false,
enableAiAssistant: !!host.enableAiAssistant,
@@ -468,9 +464,6 @@ export function transformHostResponse(
terminalConfig: host.terminalConfig
? JSON.parse(host.terminalConfig as string)
: undefined,
dockerConfig: host.dockerConfig
? JSON.parse(host.dockerConfig as string)
: undefined,
forceKeyboardInteractive: host.forceKeyboardInteractive === "true",
useWarpgate: !!host.useWarpgate,
socks5ProxyChain: host.socks5ProxyChain
-25
View File
@@ -199,7 +199,6 @@ router.post(
enableTunnel,
enableFileManager,
scpLegacy,
enableDocker,
enableProxmox,
enableTmuxMonitor,
enableTerminalToolbar,
@@ -215,7 +214,6 @@ router.post(
quickActions,
statusCheckEnabled,
statusCheckInterval,
dockerConfig,
proxmoxConfig,
enableProxmoxStats,
proxmoxStatsConfig,
@@ -332,7 +330,6 @@ router.post(
: null,
enableFileManager: enableFileManager ? 1 : 0,
scpLegacy: scpLegacy ? 1 : 0,
enableDocker: enableDocker ? 1 : 0,
enableTmuxMonitor: enableTmuxMonitor ? 1 : 0,
enableTerminalToolbar: enableTerminalToolbar === false ? 0 : 1,
enableAiAssistant: enableAiAssistant ? 1 : 0,
@@ -344,11 +341,6 @@ router.post(
defaultPath: defaultPath || null,
statusCheckEnabled: statusCheckEnabled === false ? 0 : 1,
statusCheckInterval: normalizeStatusInterval(statusCheckInterval),
dockerConfig: dockerConfig
? typeof dockerConfig === "string"
? dockerConfig
: JSON.stringify(dockerConfig)
: null,
terminalConfig: terminalConfig
? typeof terminalConfig === "string"
? terminalConfig
@@ -764,7 +756,6 @@ router.post(
enableTerminal: true,
enableTunnel: false,
enableFileManager: true,
enableDocker: false,
enableWebUi: false,
enableTmuxMonitor: false,
enableTerminalToolbar: true,
@@ -895,7 +886,6 @@ router.put(
enableTunnel,
enableFileManager,
scpLegacy,
enableDocker,
enableProxmox,
enableTmuxMonitor,
enableTerminalToolbar,
@@ -911,7 +901,6 @@ router.put(
quickActions,
statusCheckEnabled,
statusCheckInterval,
dockerConfig,
proxmoxConfig,
enableProxmoxStats,
proxmoxStatsConfig,
@@ -1029,7 +1018,6 @@ router.put(
: null,
enableFileManager: enableFileManager ? 1 : 0,
scpLegacy: scpLegacy ? 1 : 0,
enableDocker: enableDocker ? 1 : 0,
enableTmuxMonitor: enableTmuxMonitor ? 1 : 0,
enableTerminalToolbar: enableTerminalToolbar === false ? 0 : 1,
enableAiAssistant: enableAiAssistant ? 1 : 0,
@@ -1041,11 +1029,6 @@ router.put(
defaultPath: defaultPath || null,
statusCheckEnabled: statusCheckEnabled === false ? 0 : 1,
statusCheckInterval: normalizeStatusInterval(statusCheckInterval),
dockerConfig: dockerConfig
? typeof dockerConfig === "string"
? dockerConfig
: JSON.stringify(dockerConfig)
: null,
terminalConfig: terminalConfig
? typeof terminalConfig === "string"
? terminalConfig
@@ -2099,7 +2082,6 @@ router.get(
enableTunnel: !!resolvedHost.enableTunnel,
enableFileManager: resolvedHost.enableFileManager !== false,
scpLegacy: !!resolvedHost.scpLegacy,
enableDocker: !!resolvedHost.enableDocker,
enableWebUi: !!webEndpointSettings?.enableWebUi,
enableProxmox: !!proxmoxSettings?.enableProxmox,
enableProxmoxStats: !!proxmoxSettings?.enableProxmoxStats,
@@ -2123,9 +2105,6 @@ router.get(
? JSON.parse(resolvedHost.quickActions as string)
: null,
webUiConfig: webEndpointSettings?.webUiConfig ?? { endpoints: [] },
dockerConfig: resolvedHost.dockerConfig
? JSON.parse(resolvedHost.dockerConfig as string)
: null,
proxmoxConfig: proxmoxSettings?.proxmoxConfig ?? null,
proxmoxStatsConfig: proxmoxSettings?.proxmoxStatsConfig ?? null,
terminalConfig: resolvedHost.terminalConfig
@@ -2260,7 +2239,6 @@ router.get(
enableCommandHistory: resolvedHost.enableCommandHistory !== false,
enableTunnel: !!resolvedHost.enableTunnel,
enableFileManager: resolvedHost.enableFileManager !== false,
enableDocker: !!resolvedHost.enableDocker,
enableWebUi: !!webEndpointSettings?.enableWebUi,
enableProxmox: !!proxmoxSettings?.enableProxmox,
enableTmuxMonitor: !!resolvedHost.enableTmuxMonitor,
@@ -2288,9 +2266,6 @@ router.get(
webUiConfig: webEndpointSettings?.webUiConfig ?? {
endpoints: [],
},
dockerConfig: resolvedHost.dockerConfig
? JSON.parse(resolvedHost.dockerConfig as string)
: null,
proxmoxConfig: proxmoxSettings?.proxmoxConfig ?? null,
terminalConfig: resolvedHost.terminalConfig
? JSON.parse(resolvedHost.terminalConfig as string)
-1
View File
@@ -85,7 +85,6 @@ function toRecord(host: Record<string, unknown>): PluginHostRecord {
enableTerminal: (host.enableTerminal as boolean | null) ?? null,
enableFileManager: (host.enableFileManager as boolean | null) ?? null,
enableTunnel: (host.enableTunnel as boolean | null) ?? null,
enableDocker: (host.enableDocker as boolean | null) ?? null,
createdAt: (host.createdAt as string | null) ?? null,
updatedAt: (host.updatedAt as string | null) ?? null,
...host,
+4
View File
@@ -393,6 +393,10 @@ async function provisionLocalDesktopUserIfNeeded(): Promise<void> {
const { runHostMetricsSettingsMigration } =
await import("./utils/crypto-migration/host-metrics-settings-migration.js");
await runHostMetricsSettingsMigration();
const { runDockerSettingsMigration } =
await import("./utils/crypto-migration/docker-settings-migration.js");
await runDockerSettingsMigration();
} catch (error) {
systemLogger.warn("Plugin runtime failed to initialize", {
operation: "plugin_init",
@@ -129,7 +129,6 @@ describe("HostRepository Proxmox sync inserts", () => {
enableTerminal: true,
enableFileManager: true,
enableTunnel: true,
enableDocker: false,
enableSsh: true,
enableRdp: false,
rdpUser: null,
@@ -148,7 +147,6 @@ describe("HostRepository Proxmox sync inserts", () => {
tunnelConnections: "[]",
jumpHosts: null,
quickActions: null,
dockerConfig: null,
terminalConfig: null,
forceKeyboardInteractive: "false",
useSocks5: 0,
@@ -0,0 +1,197 @@
/**
* The Docker host settings migration.
*
* An upgrade must be lossless: every host with Docker on, and every host on
* Podman, must come through into the docker plugin's host settings, whatever
* shape the engine returned the flag in. Running it twice must not duplicate
* or clobber what it moved.
*/
import { beforeEach, describe, expect, it, vi } from "vitest";
const state = vi.hoisted(() => ({
pluginRows: [] as Array<{
pluginId: string;
scope: string;
scopeId: string | null;
key: string;
value: string | null;
}>,
hostRows: [] as Array<Record<string, unknown>>,
pluginInstalled: true,
columnsGone: false,
}));
vi.mock("../../database/repositories/factory.js", () => ({
createCurrentPluginRepository: () => ({
findById: async (id: string) =>
state.pluginInstalled && id === "docker" ? { id } : null,
}),
createCurrentPluginSettingsRepository: () => ({
getAll: async (_pluginId: string, scope: string, scopeId: string | null) =>
state.pluginRows.filter(
(row) => row.scope === scope && row.scopeId === scopeId,
),
set: async (
pluginId: string,
scope: string,
scopeId: string | null,
key: string,
value: string | null,
) => {
const existing = state.pluginRows.find(
(row) =>
row.scope === scope && row.scopeId === scopeId && row.key === key,
);
if (existing) {
existing.value = value;
return;
}
state.pluginRows.push({ pluginId, scope, scopeId, key, value });
},
}),
}));
vi.mock("../../utils/crypto-migration/raw-rows.js", () => ({
selectRows: async () => {
if (state.columnsGone) throw new Error("no such column: enable_docker");
return state.hostRows;
},
}));
vi.mock("../../utils/logger.js", () => ({
databaseLogger: { info: vi.fn(), warn: vi.fn() },
}));
import {
dockerSettingsFromRow,
runDockerSettingsMigration,
} from "../../utils/crypto-migration/docker-settings-migration.js";
const hostValues = (hostId: number) =>
Object.fromEntries(
state.pluginRows
.filter((row) => row.scope === "host" && row.scopeId === String(hostId))
.map((row) => [row.key, JSON.parse(row.value ?? "null")]),
);
beforeEach(() => {
state.pluginRows = [];
state.hostRows = [];
state.pluginInstalled = true;
state.columnsGone = false;
});
describe("dockerSettingsFromRow", () => {
it("reads SQLite integers, real booleans and strings", () => {
expect(
dockerSettingsFromRow({ id: 1, enable_docker: 1, docker_config: null }),
).toEqual({ enableDocker: true });
expect(
dockerSettingsFromRow({
id: 1,
enable_docker: true,
docker_config: null,
}),
).toEqual({ enableDocker: true });
expect(
dockerSettingsFromRow({ id: 1, enable_docker: 0, docker_config: null }),
).toEqual({});
expect(
dockerSettingsFromRow({
id: 1,
enable_docker: false,
docker_config: null,
}),
).toEqual({});
});
it("keeps a Podman runtime and ignores the default or broken config", () => {
expect(
dockerSettingsFromRow({
id: 1,
enable_docker: 1,
docker_config: '{"runtime":"podman"}',
}),
).toEqual({ enableDocker: true, containerRuntime: "podman" });
expect(
dockerSettingsFromRow({
id: 1,
enable_docker: 1,
docker_config: '{"runtime":"docker"}',
}),
).toEqual({ enableDocker: true });
expect(
dockerSettingsFromRow({
id: 1,
enable_docker: 1,
docker_config: "{oops",
}),
).toEqual({ enableDocker: true });
});
});
describe("runDockerSettingsMigration", () => {
it("moves every host's docker options and skips hosts with nothing set", async () => {
state.hostRows = [
{ id: 1, enable_docker: 1, docker_config: null },
{ id: 2, enable_docker: 1, docker_config: '{"runtime":"podman"}' },
{ id: 3, enable_docker: 0, docker_config: null },
];
const result = await runDockerSettingsMigration();
expect(result).toEqual({ hostsMoved: 2, hostsSkipped: 0 });
expect(hostValues(1)).toEqual({ enableDocker: true });
expect(hostValues(2)).toEqual({
enableDocker: true,
containerRuntime: "podman",
});
expect(hostValues(3)).toEqual({});
});
it("changes nothing when run twice", async () => {
state.hostRows = [
{ id: 1, enable_docker: 1, docker_config: '{"runtime":"podman"}' },
];
await runDockerSettingsMigration();
const before = JSON.stringify(state.pluginRows);
const second = await runDockerSettingsMigration();
expect(second).toEqual({ hostsMoved: 0, hostsSkipped: 1 });
expect(JSON.stringify(state.pluginRows)).toBe(before);
});
it("keeps a value already saved in the plugin", async () => {
state.pluginRows.push({
pluginId: "docker",
scope: "host",
scopeId: "1",
key: "enableDocker",
value: "false",
});
state.hostRows = [{ id: 1, enable_docker: 1, docker_config: null }];
await runDockerSettingsMigration();
expect(hostValues(1)).toEqual({ enableDocker: false });
});
it("does nothing before the plugin row exists or once the columns are gone", async () => {
state.hostRows = [{ id: 1, enable_docker: 1, docker_config: null }];
state.pluginInstalled = false;
expect(await runDockerSettingsMigration()).toEqual({
hostsMoved: 0,
hostsSkipped: 0,
});
state.pluginInstalled = true;
state.columnsGone = true;
expect(await runDockerSettingsMigration()).toEqual({
hostsMoved: 0,
hostsSkipped: 0,
});
expect(state.pluginRows).toEqual([]);
});
});
@@ -0,0 +1,118 @@
/**
* Moves each host's Docker options out of ssh_data and into the docker
* plugin's host settings: enable_docker becomes enableDocker and the runtime
* in docker_config becomes containerRuntime.
*
* The columns stay in the database, unused: core's drizzle migrations run
* before this does, so dropping them there would lose the data first.
*
* Idempotent: a host that already has any docker row is skipped, so this is
* safe on every boot.
*/
import { sql } from "drizzle-orm";
import { databaseLogger } from "../logger.js";
import {
createCurrentPluginRepository,
createCurrentPluginSettingsRepository,
} from "../../database/repositories/factory.js";
import { selectRows } from "./raw-rows.js";
const PLUGIN_ID = "docker";
interface LegacyHostRow {
id: number;
enable_docker: number | boolean | string | null;
docker_config: string | null;
}
/** The plugin's host settings for one legacy row, defaults left out. */
export function dockerSettingsFromRow(
row: LegacyHostRow,
): Record<string, unknown> {
const values: Record<string, unknown> = {};
const flag = row.enable_docker;
if (flag === true || flag === 1 || flag === "1" || flag === "true") {
values.enableDocker = true;
}
if (row.docker_config) {
try {
const config = JSON.parse(row.docker_config) as { runtime?: unknown };
if (config?.runtime === "podman") values.containerRuntime = "podman";
} catch {
// unreadable config means the default runtime
}
}
return values;
}
export interface DockerSettingsMigrationResult {
hostsMoved: number;
hostsSkipped: number;
}
export async function runDockerSettingsMigration(): Promise<DockerSettingsMigrationResult> {
const result: DockerSettingsMigrationResult = {
hostsMoved: 0,
hostsSkipped: 0,
};
// plugin_settings has a foreign key to plugins: nothing to migrate into
// until the plugin row exists.
try {
const plugin = await createCurrentPluginRepository().findById(PLUGIN_ID);
if (!plugin) return result;
} catch {
return result;
}
const pluginSettings = createCurrentPluginSettingsRepository();
let rows: LegacyHostRow[];
try {
// Raw SQL: schema.ts no longer declares these columns.
rows = await selectRows<LegacyHostRow>(
sql`SELECT id, enable_docker, docker_config FROM ssh_data`,
);
} catch {
// A fresh install never had the columns.
return result;
}
for (const row of rows) {
const values = dockerSettingsFromRow(row);
if (Object.keys(values).length === 0) continue;
const scopeId = String(row.id);
try {
const existing = await pluginSettings.getAll(PLUGIN_ID, "host", scopeId);
if (existing.length > 0) {
result.hostsSkipped++;
continue;
}
for (const [key, value] of Object.entries(values)) {
await pluginSettings.set(
PLUGIN_ID,
"host",
scopeId,
key,
JSON.stringify(value),
);
}
result.hostsMoved++;
} catch (error) {
databaseLogger.warn("Docker host settings migration failed for a host", {
operation: "docker_settings_migration",
hostId: row.id,
error: error instanceof Error ? error.message : String(error),
});
}
}
if (result.hostsMoved > 0) {
databaseLogger.info(
`Moved Docker settings for ${result.hostsMoved} host(s) into plugin settings`,
{ operation: "docker_settings_migration" },
);
}
return result;
}
-6
View File
@@ -22,7 +22,6 @@ export type WidgetTypeId =
| "ssh_terminal"
| "quick_connect"
| "file_manager_widget"
| "docker_widget"
| "tunnel_widget"
| "calendar"
| "countdown"
@@ -35,7 +34,6 @@ export type WidgetTypeId =
| "dashboard_links"
| "search_links"
| "link_tree"
| "docker_activity"
| "ssh_quick_connect"
| (string & {});
@@ -213,10 +211,6 @@ export interface FileManagerWidgetConfig {
hostId: number;
}
export interface DockerWidgetConfig {
hostId: number;
}
export interface SshTerminalConfig {
hostId: number;
autoConnect: boolean;
-54
View File
@@ -157,7 +157,6 @@ export interface HostFeatureFlags {
enableTerminal: boolean; // SSH, Telnet only
enableTunnel: boolean; // SSH only
enableFileManager: boolean; // SSH only
enableDocker: boolean; // SSH only
enableTmuxMonitor: boolean; // SSH only
enableTerminalToolbar: boolean; // SSH, RDP, VNC, and Telnet
enableAiAssistant: boolean; // SSH only
@@ -216,7 +215,6 @@ export type Host = {
enableTunnel: boolean;
enableFileManager: boolean;
scpLegacy?: boolean;
enableDocker: boolean;
enableTmuxMonitor: boolean;
enableTerminalToolbar: boolean;
enableAiAssistant: boolean;
@@ -253,7 +251,6 @@ export type Host = {
/** "ssh", or the id of the plugin protocol a host without SSH uses. */
connectionType?: string;
domain?: string;
dockerConfig?: Record<string, unknown> | null;
enableWebUi?: boolean;
webUiConfig?: WebUiConfig | null;
@@ -368,7 +365,6 @@ export interface HostData {
enableTunnel?: boolean;
enableFileManager?: boolean;
scpLegacy?: boolean;
enableDocker?: boolean;
enableProxmox?: boolean;
enableTmuxMonitor?: boolean;
enableTerminalToolbar?: boolean;
@@ -410,7 +406,6 @@ export interface HostData {
/** "ssh", or the id of the plugin protocol a host without SSH uses. */
connectionType?: string;
domain?: string;
dockerConfig?: Record<string, unknown> | null;
enableWebUi?: boolean;
webUiConfig?: WebUiConfig | null;
@@ -1005,52 +1000,3 @@ export interface RestoreRequestBody {
// ============================================================================
// DOCKER TYPES
// ============================================================================
export interface DockerContainer {
id: string;
name: string;
image: string;
status: string;
state:
| "created"
| "running"
| "paused"
| "restarting"
| "removing"
| "exited"
| "dead";
ports: string;
created: string;
command?: string;
labels?: Record<string, string>;
networks?: string[];
mounts?: string[];
}
export interface DockerStats {
cpu: string;
memoryUsed: string;
memoryLimit: string;
memoryPercent: string;
netInput: string;
netOutput: string;
blockRead: string;
blockWrite: string;
pids?: string;
}
export interface DockerLogOptions {
tail?: number;
timestamps?: boolean;
since?: string;
until?: string;
follow?: boolean;
}
export interface DockerValidation {
available: boolean;
version?: string;
runtime?: "docker" | "podman";
error?: string;
code?: string;
}
-4
View File
@@ -100,10 +100,6 @@ export type Host = {
scpLegacy?: boolean;
defaultPath?: string;
enableDocker: boolean;
dockerConfig?: {
runtime?: "docker" | "podman";
} | null;
enableWebUi?: boolean;
enableProxmox: boolean;
enableTmuxMonitor: boolean;
-1
View File
@@ -2490,7 +2490,6 @@ export function AppShell({
enableCommandHistory: false,
enableTunnel: false,
enableFileManager: false,
enableDocker: false,
enableProxmox: false,
enableProxmoxStats: false,
enableTmuxMonitor: false,
-2
View File
@@ -26,10 +26,8 @@ export function hostToSSHHost(h: Host): SSHHost {
enableTerminal: h.enableTerminal ?? false,
enableTunnel: h.enableTunnel ?? false,
enableFileManager: h.enableFileManager ?? false,
enableDocker: h.enableDocker ?? false,
enableTerminalToolbar: h.enableTerminalToolbar ?? true,
enableAiAssistant: h.enableAiAssistant ?? false,
dockerConfig: h.dockerConfig ?? null,
enableWebUi: h.enableWebUi ?? false,
webUiConfig: (h.pluginSettings?.["web-endpoint"]?.webUiConfig as
SSHHost["webUiConfig"] | undefined) ?? { endpoints: [] },
-3
View File
@@ -1241,8 +1241,6 @@
"disableTerminalFeature": "Disable Terminal",
"enableFilesFeature": "Enable Files",
"disableFilesFeature": "Disable Files",
"enableDockerFeature": "Enable Docker",
"disableDockerFeature": "Disable Docker",
"enableProxmoxFeature": "Enable Proxmox",
"disableProxmoxFeature": "Disable Proxmox",
"addTagsPlaceholder": "Add tags...",
@@ -1364,7 +1362,6 @@
"filterFeaturesGroup": "Features",
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "File Manager",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Tags",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Deaktiveer lêers",
"enableTunnelsFeature": "Aktiveer tonnels",
"disableTunnelsFeature": "Deaktiveer tonnels",
"enableDockerFeature": "Aktiveer Docker",
"disableDockerFeature": "Deaktiveer Docker",
"enableProxmoxFeature": "Aktiveer Proxmox",
"disableProxmoxFeature": "Deaktiveer Proxmox",
"addTagsPlaceholder": "Voeg etikette by...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminaal",
"filterFeatureFileManager": "Lêerbestuurder",
"filterFeatureTunnel": "Tonnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Etikette",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "تعطيل الملفات",
"enableTunnelsFeature": "تفعيل الأنفاق",
"disableTunnelsFeature": "تعطيل الأنفاق",
"enableDockerFeature": "تفعيل Docker",
"disableDockerFeature": "تعطيل Docker",
"enableProxmoxFeature": "تفعيل Proxmox",
"disableProxmoxFeature": "تعطيل Proxmox",
"addTagsPlaceholder": "إضافة علامات...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "الطرفية",
"filterFeatureFileManager": "مدير الملفات",
"filterFeatureTunnel": "نفق",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "الوسوم",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Деактивиране на файлове",
"enableTunnelsFeature": "Активиране на тунели",
"disableTunnelsFeature": "Деактивиране на тунелите",
"enableDockerFeature": "Активиране на Докер",
"disableDockerFeature": "Деактивиране на Докер",
"enableProxmoxFeature": "Активиране на Proxmox",
"disableProxmoxFeature": "Деактивиране на Proxmox",
"addTagsPlaceholder": "Добавяне на етикети...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Терминал",
"filterFeatureFileManager": "Файлов мениджър",
"filterFeatureTunnel": "Тунел",
"filterFeatureDocker": "Докер",
"filterTagsGroup": "Етикети",
"connectRdp": "ПРСР",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "ফাইলগুলি নিষ্ক্রিয় করুন",
"enableTunnelsFeature": "টানেলগুলি সক্ষম করুন",
"disableTunnelsFeature": "টানেল নিষ্ক্রিয় করুন",
"enableDockerFeature": "ডকার সক্রিয় করুন",
"disableDockerFeature": "ডকার নিষ্ক্রিয় করুন",
"enableProxmoxFeature": "প্রক্সমক্স সক্রিয় করুন",
"disableProxmoxFeature": "প্রক্সমক্স নিষ্ক্রিয় করুন",
"addTagsPlaceholder": "ট্যাগ যোগ করুন...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "টার্মিনাল",
"filterFeatureFileManager": "ফাইল ম্যানেজার",
"filterFeatureTunnel": "টানেল",
"filterFeatureDocker": "ডকার",
"filterTagsGroup": "ট্যাগ",
"connectRdp": "আরডিপি",
"connectVnc": "ভিএনসি",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Desactiva els fitxers",
"enableTunnelsFeature": "Habilita els túnels",
"disableTunnelsFeature": "Desactiva els túnels",
"enableDockerFeature": "Activa Docker",
"disableDockerFeature": "Desactiva Docker",
"enableProxmoxFeature": "Activa Proxmox",
"disableProxmoxFeature": "Desactiva Proxmox",
"addTagsPlaceholder": "Afegeix etiquetes...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Gestor de fitxers",
"filterFeatureTunnel": "Túnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Etiquetes",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Zakázat soubory",
"enableTunnelsFeature": "Povolit tunely",
"disableTunnelsFeature": "Zakázat tunely",
"enableDockerFeature": "Povolit Docker",
"disableDockerFeature": "Zakázat Docker",
"enableProxmoxFeature": "Povolit Proxmox",
"disableProxmoxFeature": "Zakázat Proxmox",
"addTagsPlaceholder": "Přidat štítky...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminál",
"filterFeatureFileManager": "Správce souborů",
"filterFeatureTunnel": "Tunel",
"filterFeatureDocker": "Přístavní dělník",
"filterTagsGroup": "Štítky",
"connectRdp": "PRV",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Deaktiver filer",
"enableTunnelsFeature": "Aktivér tunneler",
"disableTunnelsFeature": "Deaktiver tunneler",
"enableDockerFeature": "Aktivér Docker",
"disableDockerFeature": "Deaktiver Docker",
"enableProxmoxFeature": "Aktivér Proxmox",
"disableProxmoxFeature": "Deaktiver Proxmox",
"addTagsPlaceholder": "Tilføj tags...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Filhåndtering",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Tags",
"connectRdp": "Landdistriktsudviklingsplan",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Dateien deaktivieren",
"enableTunnelsFeature": "Tunnels aktivieren",
"disableTunnelsFeature": "Tunnels deaktivieren",
"enableDockerFeature": "Docker aktivieren",
"disableDockerFeature": "Docker deaktivieren",
"enableProxmoxFeature": "Proxmox aktivieren",
"disableProxmoxFeature": "Proxmox deaktivieren",
"addTagsPlaceholder": "Tags hinzufügen...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Dateimanager",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Tags",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Απενεργοποίηση αρχείων",
"enableTunnelsFeature": "Ενεργοποίηση σηράγγων",
"disableTunnelsFeature": "Απενεργοποίηση σηράγγων",
"enableDockerFeature": "Ενεργοποίηση Docker",
"disableDockerFeature": "Απενεργοποίηση Docker",
"enableProxmoxFeature": "Ενεργοποίηση Proxmox",
"disableProxmoxFeature": "Απενεργοποίηση Proxmox",
"addTagsPlaceholder": "Προσθήκη ετικετών...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Τερματικό",
"filterFeatureFileManager": "Διαχειριστής αρχείων",
"filterFeatureTunnel": "Σήραγγα",
"filterFeatureDocker": "Λιμενεργάτης",
"filterTagsGroup": "Ετικέτες",
"connectRdp": "ΠΑΑ",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Deshabilitar archivos",
"enableTunnelsFeature": "Activar túneles",
"disableTunnelsFeature": "Desactivar túneles",
"enableDockerFeature": "Activar Docker",
"disableDockerFeature": "Desactivar Docker",
"enableProxmoxFeature": "Activar Proxmox",
"disableProxmoxFeature": "Desactivar Proxmox",
"addTagsPlaceholder": "Añadir etiquetas...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Gestor de archivos",
"filterFeatureTunnel": "Túnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Etiquetas",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Poista tiedostot käytöstä",
"enableTunnelsFeature": "Ota tunnelit käyttöön",
"disableTunnelsFeature": "Tunnelien poistaminen käytöstä",
"enableDockerFeature": "Ota Docker käyttöön",
"disableDockerFeature": "Poista Docker käytöstä",
"enableProxmoxFeature": "Ota Proxmox käyttöön",
"disableProxmoxFeature": "Poista Proxmox käytöstä",
"addTagsPlaceholder": "Lisää tunnisteita...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminaali",
"filterFeatureFileManager": "Tiedostonhallinta",
"filterFeatureTunnel": "Tunneli",
"filterFeatureDocker": "Satamatyöläinen",
"filterTagsGroup": "Tunnisteet",
"connectRdp": "Maaseudun kehittämisohjelma",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Désactiver les fichiers",
"enableTunnelsFeature": "Activer les tunnels",
"disableTunnelsFeature": "Désactiver les tunnels",
"enableDockerFeature": "Activer Docker",
"disableDockerFeature": "Désactiver Docker",
"enableProxmoxFeature": "Activer Proxmox",
"disableProxmoxFeature": "Désactiver Proxmox",
"addTagsPlaceholder": "Ajouter des étiquettes...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Gestionnaire de fichiers",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Étiquettes",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "השבת קבצים",
"enableTunnelsFeature": "הפעל מנהרות",
"disableTunnelsFeature": "השבת מנהרות",
"enableDockerFeature": "הפעל את Docker",
"disableDockerFeature": "השבת את Docker",
"enableProxmoxFeature": "הפעל את Proxmox",
"disableProxmoxFeature": "השבת את פרוקסמוקס",
"addTagsPlaceholder": "הוסף תגיות...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "מָסוֹף",
"filterFeatureFileManager": "מנהל הקבצים",
"filterFeatureTunnel": "מִנהָרָה",
"filterFeatureDocker": "דוקר",
"filterTagsGroup": "תגיות",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "फ़ाइलें अक्षम करें",
"enableTunnelsFeature": "टनल सक्षम करें",
"disableTunnelsFeature": "टनल अक्षम करें",
"enableDockerFeature": "Docker सक्षम करें",
"disableDockerFeature": "Docker अक्षम करें",
"enableProxmoxFeature": "Proxmox सक्षम करें",
"disableProxmoxFeature": "Proxmox अक्षम करें",
"addTagsPlaceholder": "टैग जोड़ें…",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "टर्मिनल",
"filterFeatureFileManager": "फ़ाइल प्रबंधक",
"filterFeatureTunnel": "टनल",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "टैग्स",
"connectRdp": "आरडीपी",
"connectVnc": "वीएनसी",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Fájlok letiltása",
"enableTunnelsFeature": "Alagutak engedélyezése",
"disableTunnelsFeature": "Alagutak letiltása",
"enableDockerFeature": "Docker engedélyezése",
"disableDockerFeature": "Docker letiltása",
"enableProxmoxFeature": "Proxmox engedélyezése",
"disableProxmoxFeature": "Proxmox letiltása",
"addTagsPlaceholder": "Címkék hozzáadása...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminál",
"filterFeatureFileManager": "Fájlkezelő",
"filterFeatureTunnel": "Alagút",
"filterFeatureDocker": "Dokkmunkás",
"filterTagsGroup": "Címkék",
"connectRdp": "Vidékfejlesztési Program",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Nonaktifkan File",
"enableTunnelsFeature": "Aktifkan Terowongan",
"disableTunnelsFeature": "Nonaktifkan Terowongan",
"enableDockerFeature": "Aktifkan Docker",
"disableDockerFeature": "Nonaktifkan Docker",
"enableProxmoxFeature": "Aktifkan Proxmox",
"disableProxmoxFeature": "Nonaktifkan Proxmox",
"addTagsPlaceholder": "Tambahkan tag...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Pengelola File",
"filterFeatureTunnel": "Terowongan",
"filterFeatureDocker": "Buruh pelabuhan",
"filterTagsGroup": "Tag",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Disabilita File",
"enableTunnelsFeature": "Abilita tunnel",
"disableTunnelsFeature": "Disabilita tunnel",
"enableDockerFeature": "Abilita Docker",
"disableDockerFeature": "Disabilita Docker",
"enableProxmoxFeature": "Abilita Proxmox",
"disableProxmoxFeature": "Disabilita Proxmox",
"addTagsPlaceholder": "Aggiungi tag...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminale",
"filterFeatureFileManager": "Gestione file",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Tag",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "ファイルを無効化",
"enableTunnelsFeature": "トンネルを有効化",
"disableTunnelsFeature": "トンネルを無効化",
"enableDockerFeature": "Dockerを有効化",
"disableDockerFeature": "Dockerを無効化",
"enableProxmoxFeature": "Proxmoxを有効化",
"disableProxmoxFeature": "Proxmoxを無効化",
"addTagsPlaceholder": "タグを追加...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "ターミナル",
"filterFeatureFileManager": "ファイルマネージャー",
"filterFeatureTunnel": "トンネル",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "タグ",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "파일 비활성화",
"enableTunnelsFeature": "터널 활성화",
"disableTunnelsFeature": "터널 비활성화",
"enableDockerFeature": "Docker 활성화",
"disableDockerFeature": "Docker 비활성화",
"enableProxmoxFeature": "Proxmox 활성화",
"disableProxmoxFeature": "Proxmox 비활성화",
"addTagsPlaceholder": "태그 추가...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "터미널",
"filterFeatureFileManager": "파일 관리자",
"filterFeatureTunnel": "터널",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "태그",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Bestanden uitschakelen",
"enableTunnelsFeature": "Tunnels inschakelen",
"disableTunnelsFeature": "Tunnels uitschakelen",
"enableDockerFeature": "Docker inschakelen",
"disableDockerFeature": "Docker uitschakelen",
"enableProxmoxFeature": "Proxmox inschakelen",
"disableProxmoxFeature": "Proxmox uitschakelen",
"addTagsPlaceholder": "Tags toevoegen...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Bestandsbeheerder",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Tags",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Deaktiver filer",
"enableTunnelsFeature": "Aktiver tunneler",
"disableTunnelsFeature": "Deaktiver tunneler",
"enableDockerFeature": "Aktiver Docker",
"disableDockerFeature": "Deaktiver Docker",
"enableProxmoxFeature": "Aktiver Proxmox",
"disableProxmoxFeature": "Deaktiver Proxmox",
"addTagsPlaceholder": "Legg til tagger...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Filbehandler",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Dokker",
"filterTagsGroup": "Tagger",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Wyłącz pliki",
"enableTunnelsFeature": "Włącz tunele",
"disableTunnelsFeature": "Wyłącz tunele",
"enableDockerFeature": "Włącz Docker",
"disableDockerFeature": "Wyłącz Docker",
"enableProxmoxFeature": "Włącz Proxmox",
"disableProxmoxFeature": "Wyłącz Proxmox",
"addTagsPlaceholder": "Dodaj tagi...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Menedżer plików",
"filterFeatureTunnel": "Tunel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Tagi",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Desativar arquivos",
"enableTunnelsFeature": "Ativar túneis",
"disableTunnelsFeature": "Desativar túneis",
"enableDockerFeature": "Habilitar Docker",
"disableDockerFeature": "Desativar o Docker",
"enableProxmoxFeature": "Ativar Proxmox",
"disableProxmoxFeature": "Desativar Proxmox",
"addTagsPlaceholder": "Adicionar etiquetas...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "terminal",
"filterFeatureFileManager": "Gerenciador de arquivos",
"filterFeatureTunnel": "Túnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Etiquetas",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Desativar Ficheiros",
"enableTunnelsFeature": "Ativar Tunnels",
"disableTunnelsFeature": "Desativar Tunnels",
"enableDockerFeature": "Ativar Docker",
"disableDockerFeature": "Desativar Docker",
"enableProxmoxFeature": "Ativar Proxmox",
"disableProxmoxFeature": "Desativar Proxmox",
"addTagsPlaceholder": "Adicionar tags...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Gestor de Ficheiros",
"filterFeatureTunnel": "Túnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Etiquetas",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Dezactivați fișierele",
"enableTunnelsFeature": "Activează tunelurile",
"disableTunnelsFeature": "Dezactivați tunelurile",
"enableDockerFeature": "Activează Docker",
"disableDockerFeature": "Dezactivați Docker",
"enableProxmoxFeature": "Activează Proxmox",
"disableProxmoxFeature": "Dezactivați Proxmox",
"addTagsPlaceholder": "Adăugați etichete...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Manager de fișiere",
"filterFeatureTunnel": "Tunel",
"filterFeatureDocker": "Docher",
"filterTagsGroup": "Etichete",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Отключить файлы",
"enableTunnelsFeature": "Включить туннели",
"disableTunnelsFeature": "Отключить туннели",
"enableDockerFeature": "Включить Docker",
"disableDockerFeature": "Отключить Docker",
"enableProxmoxFeature": "Включить Proxmox",
"disableProxmoxFeature": "Отключить Proxmox",
"addTagsPlaceholder": "Добавить теги...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Терминал",
"filterFeatureFileManager": "Файловый менеджер",
"filterFeatureTunnel": "Туннель",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Теги",
"connectRdp": "РДП",
"connectVnc": "ВНК",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Онемогући датотеке",
"enableTunnelsFeature": "Омогући тунеле",
"disableTunnelsFeature": "Онемогући тунеле",
"enableDockerFeature": "Омогући Докер",
"disableDockerFeature": "Онемогући Докер",
"enableProxmoxFeature": "Омогући Proxmox",
"disableProxmoxFeature": "Онемогући Проксмокс",
"addTagsPlaceholder": "Додај ознаке...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Терминал",
"filterFeatureFileManager": "Менаџер датотека",
"filterFeatureTunnel": "Тунел",
"filterFeatureDocker": "Докер",
"filterTagsGroup": "Ознаке",
"connectRdp": "РДП",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Inaktivera filer",
"enableTunnelsFeature": "Aktivera tunnlar",
"disableTunnelsFeature": "Inaktivera tunnlar",
"enableDockerFeature": "Aktivera Docker",
"disableDockerFeature": "Inaktivera Docker",
"enableProxmoxFeature": "Aktivera Proxmox",
"disableProxmoxFeature": "Inaktivera Proxmox",
"addTagsPlaceholder": "Lägg till taggar...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Filhanteraren",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Hamnarbetare",
"filterTagsGroup": "Taggar",
"connectRdp": "Landsbygdsutveckling",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "ปิดใช้งานไฟล์",
"enableTunnelsFeature": "เปิดใช้งานอุโมงค์",
"disableTunnelsFeature": "ปิดใช้งานอุโมงค์",
"enableDockerFeature": "เปิดใช้งาน Docker",
"disableDockerFeature": "ปิดใช้งาน Docker",
"enableProxmoxFeature": "เปิดใช้งาน Proxmox",
"disableProxmoxFeature": "ปิดใช้งาน Proxmox",
"addTagsPlaceholder": "เพิ่มแท็ก...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "เทอร์มินัล",
"filterFeatureFileManager": "ตัวจัดการไฟล์",
"filterFeatureTunnel": "อุโมงค์",
"filterFeatureDocker": "ด็อกเกอร์",
"filterTagsGroup": "แท็ก",
"connectRdp": "อาร์ดีพี",
"connectVnc": "วีเอ็นซี",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Dosyaları Devre Dışı Bırak",
"enableTunnelsFeature": "Tünelleri Etkinleştir",
"disableTunnelsFeature": "Tünelleri Devre Dışı Bırak",
"enableDockerFeature": "Docker'ı Etkinleştir",
"disableDockerFeature": "Docker'ı Devre Dışı Bırak",
"enableProxmoxFeature": "Proxmox'u Etkinleştir",
"disableProxmoxFeature": "Proxmox'u Devre Dışı Bırak",
"addTagsPlaceholder": "Etiket ekle...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Dosya Yöneticisi",
"filterFeatureTunnel": "Tünel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Etiketler",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Вимкнути файли",
"enableTunnelsFeature": "Увімкнути тунелі",
"disableTunnelsFeature": "Вимкнути тунелі",
"enableDockerFeature": "Увімкнути Докер",
"disableDockerFeature": "Вимкнути Докер",
"enableProxmoxFeature": "Увімкнути Proxmox",
"disableProxmoxFeature": "Вимкнути Proxmox",
"addTagsPlaceholder": "Додати теги...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Термінал",
"filterFeatureFileManager": "Файловий менеджер",
"filterFeatureTunnel": "Тунель",
"filterFeatureDocker": "Докер",
"filterTagsGroup": "Теги",
"connectRdp": "ПРП",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "Tắt Files",
"enableTunnelsFeature": "Bật Tunnels",
"disableTunnelsFeature": "Tắt Tunnels",
"enableDockerFeature": "Bật Docker",
"disableDockerFeature": "Tắt Docker",
"enableProxmoxFeature": "Bật Proxmox",
"disableProxmoxFeature": "Tắt Proxmox",
"addTagsPlaceholder": "Thêm thẻ...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Trình quản lý file",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Thẻ",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "禁用文件",
"enableTunnelsFeature": "启用隧道",
"disableTunnelsFeature": "禁用隧道",
"enableDockerFeature": "启用 Docker",
"disableDockerFeature": "禁用 Docker",
"enableProxmoxFeature": "启用 Proxmox",
"disableProxmoxFeature": "禁用 Proxmox",
"addTagsPlaceholder": "添加标签...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "终端",
"filterFeatureFileManager": "文件管理器",
"filterFeatureTunnel": "隧道",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "标签",
"connectRdp": "RDP",
"connectVnc": "VNC",
-3
View File
@@ -1245,8 +1245,6 @@
"disableFilesFeature": "停用檔案",
"enableTunnelsFeature": "啟用通道",
"disableTunnelsFeature": "停用通道",
"enableDockerFeature": "啟用 Docker",
"disableDockerFeature": "停用 Docker",
"enableProxmoxFeature": "啟用 Proxmox",
"disableProxmoxFeature": "停用 Proxmox",
"addTagsPlaceholder": "新增標籤...",
@@ -1369,7 +1367,6 @@
"filterFeatureTerminal": "終端機",
"filterFeatureFileManager": "檔案管理員",
"filterFeatureTunnel": "通道",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "標籤",
"connectRdp": "遠端桌面協定",
"connectVnc": "VNC",
-9
View File
@@ -770,12 +770,6 @@ function initializeApiInstances() {
// RBAC API (port 30001)
rbacApi = createApiInstance(getApiUrl("", 30001), "RBAC");
// Docker Management API - the docker plugin, mounted on the main backend.
dockerApi = createApiInstance(
getApiUrl("/plugin-api/docker/docker", 30001),
"DOCKER",
);
// Tmux Monitor API (port 30010) --- tmux-monitor ---
tmuxMonitorApi = createApiInstance(
getApiUrl("/tmux_monitor", 30010),
@@ -803,9 +797,6 @@ export let dashboardApi: AxiosInstance;
// RBAC API (port 30001)
export let rbacApi: AxiosInstance;
// Docker Management API (docker plugin)
export let dockerApi: AxiosInstance;
// Tmux Monitor API (port 30010) --- tmux-monitor ---
export let tmuxMonitorApi: AxiosInstance;
+4 -1
View File
@@ -85,7 +85,10 @@ export * from "@/components/sheet";
export { useConfirmation } from "@/hooks/use-confirmation";
export { useAdaptivePolling } from "@/hooks/use-adaptive-polling";
// Per-area display density and chart options the user picked in Appearance.
export { useAreaPreferences } from "@/contexts/UiPreferencesContext";
export {
useAreaPreferences,
useUiPreferencesContext,
} from "@/contexts/UiPreferencesContext";
// Homepage widget pieces, for plugins that register a widget.
export { WidgetTitle } from "@/features/homepage/widgets/WidgetTitle";
export { runVisibleInterval } from "@/features/homepage/use-visible-interval";
+2 -14
View File
@@ -163,23 +163,13 @@ export function createHostEditorForm(
host?.enableCommandHistory ?? d?.enableCommandHistory ?? true,
enableFileManager: host?.enableFileManager ?? false,
scpLegacy: host?.scpLegacy ?? false,
enableDocker: host?.enableDocker ?? false,
dockerConfig: host?.dockerConfig ?? { runtime: "docker" as const },
enableTmuxMonitor: host?.enableTmuxMonitor ?? false,
enableTerminalToolbar: host?.enableTerminalToolbar ?? true,
enableAiAssistant: host?.enableAiAssistant ?? false,
enableProxmox: (proxmoxSettings.enableProxmox as boolean) ?? false,
// The proxmox tab fills in its own defaults when this is unset.
proxmoxConfig:
((proxmoxSettings.proxmoxConfig as Host["proxmoxConfig"]) ?? {
defaultCredentialId: null,
defaultAuthType: "password",
windowsPatterns: "win, windows",
dockerPatterns: "docker",
preferredPrefixes: "10., 192.168.",
autoSyncEnabled: false,
syncIntervalMinutes: 15,
markMissingGuests: true,
}) as Host["proxmoxConfig"],
(proxmoxSettings.proxmoxConfig as Host["proxmoxConfig"]) ?? null,
enableProxmoxStats:
(proxmoxSettings.enableProxmoxStats as boolean) ?? false,
proxmoxStatsConfig:
@@ -436,8 +426,6 @@ export function buildHostEditorPayload(
enableCommandHistory: form.enableCommandHistory,
enableFileManager: form.enableFileManager,
scpLegacy: form.scpLegacy,
enableDocker: form.enableDocker,
dockerConfig: form.enableDocker ? form.dockerConfig : null,
enableTmuxMonitor: form.enableTmuxMonitor,
enableTerminalToolbar: form.enableTerminalToolbar,
enableAiAssistant: form.enableAiAssistant,
-2
View File
@@ -95,8 +95,6 @@ export function sshHostToHost(h: SSHHostWithStatus): Host {
enableCommandHistory: h.enableCommandHistory ?? true,
enableTunnel: h.enableTunnel ?? false,
enableFileManager: h.enableFileManager ?? true,
enableDocker: h.enableDocker ?? false,
dockerConfig: h.dockerConfig ?? null,
enableWebUi: h.enableWebUi ?? false,
enableProxmox: (proxmoxSettings.enableProxmox as boolean) ?? false,
enableProxmoxStats:
+15 -21
View File
@@ -152,8 +152,7 @@ function hostPassesFilters(host: Host, filters: FilterState): boolean {
}
if (filters.features.length > 0) {
const ok =
(filters.features.includes("fileManager") && host.enableFileManager) ||
(filters.features.includes("docker") && host.enableDocker);
filters.features.includes("fileManager") && host.enableFileManager;
if (!ok) return false;
}
if (filters.tags.length > 0) {
@@ -355,7 +354,6 @@ export function HostsPanel({
enableTerminal: true,
enableTunnel: false,
enableFileManager: true,
enableDocker: false,
defaultPath: "/var/www",
},
{
@@ -373,7 +371,6 @@ export function HostsPanel({
enableTerminal: true,
enableTunnel: true,
enableFileManager: false,
enableDocker: false,
},
],
},
@@ -780,23 +777,20 @@ export function HostsPanel({
<DropdownMenuLabel>
{t("hosts.filterFeaturesGroup")}
</DropdownMenuLabel>
{(
[
["fileManager", "FileManager"],
["docker", "Docker"],
] as const
).map(([val, key]) => (
<DropdownMenuCheckboxItem
key={val}
checked={filterState.features.includes(val)}
onCheckedChange={() =>
handleFilterToggle("features", val)
}
onSelect={(e) => e.preventDefault()}
>
{t(`hosts.filterFeature${key}`)}
</DropdownMenuCheckboxItem>
))}
{([["fileManager", "FileManager"]] as const).map(
([val, key]) => (
<DropdownMenuCheckboxItem
key={val}
checked={filterState.features.includes(val)}
onCheckedChange={() =>
handleFilterToggle("features", val)
}
onSelect={(e) => e.preventDefault()}
>
{t(`hosts.filterFeature${key}`)}
</DropdownMenuCheckboxItem>
),
)}
{allTags.length > 0 && (
<>
<DropdownMenuSeparator />
-2
View File
@@ -44,7 +44,6 @@ export const FIELD_GROUP_KEYS: Record<FieldGroup, string[]> = {
"enableTerminalToolbar",
"enableAiAssistant",
"enableFileManager",
"enableDocker",
"enableWebUi",
"enableProxmox",
"enableTmuxMonitor",
@@ -59,7 +58,6 @@ export const FIELD_GROUP_KEYS: Record<FieldGroup, string[]> = {
advanced: [
"statusCheckEnabled",
"statusCheckInterval",
"dockerConfig",
"webUiConfig",
"proxmoxConfig",
"terminalConfig",
-3
View File
@@ -34,7 +34,6 @@ export function createQuickConnectHost(input: QuickConnectInput): Host {
enableCommandHistory: false,
enableFileManager: false,
enableTunnel: false,
enableDocker: false,
enableTerminalToolbar: false,
enableAiAssistant: false,
enableSsh: false,
@@ -71,7 +70,6 @@ export function createQuickConnectHost(input: QuickConnectInput): Host {
enableCommandHistory: true,
enableFileManager: true,
enableTunnel: true,
enableDocker: true,
enableProxmox: false,
enableProxmoxStats: false,
enableTmuxMonitor: false,
@@ -102,7 +100,6 @@ export function quickConnectHostToPayload(host: Host): SSHHostData {
enableCommandHistory: host.enableCommandHistory,
enableFileManager: host.enableFileManager,
enableTunnel: host.enableTunnel,
enableDocker: host.enableDocker,
enableProxmox: host.enableProxmox,
enableTmuxMonitor: host.enableTmuxMonitor,
enableTerminalToolbar: host.enableTerminalToolbar,
-14
View File
@@ -11,7 +11,6 @@ import { useTranslation } from "react-i18next";
import { useVirtualizer } from "@tanstack/react-virtual";
import { useAreaPreferences } from "@/contexts/UiPreferencesContext";
import {
Box,
Boxes,
ChevronDown,
Download,
@@ -612,7 +611,6 @@ export function SidebarTree({
enableTerminal: host.enableTerminal,
enableTunnel: host.enableTunnel,
enableFileManager: host.enableFileManager,
enableDocker: host.enableDocker,
sshPort: host.sshPort,
rdpUser: host.rdpUser ?? null,
rdpPassword: host.rdpPassword ?? null,
@@ -1173,18 +1171,6 @@ export function SidebarTree({
value: false,
icon: FolderSearch,
},
{
labelKey: "hosts.enableDockerFeature",
field: "enableDocker",
value: true,
icon: Box,
},
{
labelKey: "hosts.disableDockerFeature",
field: "enableDocker",
value: false,
icon: Box,
},
{
labelKey: "hosts.enableProxmoxFeature",
field: "enableProxmox",
@@ -49,7 +49,6 @@ function makeHost(overrides: Partial<Host>): Host {
enableTunnel: false,
serverTunnels: [],
enableFileManager: true,
enableDocker: false,
enableProxmox: false,
enableProxmoxStats: false,
enableTmuxMonitor: false,
@@ -50,7 +50,6 @@ function sshHost(
enableCommandHistory: false,
enableTunnel: false,
enableFileManager: false,
enableDocker: false,
enableTmuxMonitor: false,
enableTerminalToolbar: true,
enableAiAssistant: false,
@@ -28,7 +28,6 @@ function host(id: string, name: string): Host {
enableTerminal: true,
enableTunnel: false,
enableFileManager: true,
enableDocker: false,
quickActions: [],
} as Host;
}
@@ -61,7 +61,6 @@ const baseHost: Host = {
enableCommandHistory: true,
enableTunnel: true,
enableFileManager: true,
enableDocker: true,
enableRdp: true,
enableVnc: true,
enableTelnet: true,