diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9ec70de70..34d8de6b1 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -147,8 +147,12 @@ model DestinationDocker { id String @id @default(cuid()) network String @unique name String - engine String + engine String? remoteEngine Boolean @default(false) + ipAddress String? + sshPrivateKey String? + user String? @default("root") + port Int? @default(22) isCoolifyProxyUsed Boolean? @default(false) teams Team[] application Application[] diff --git a/src/lib/common.ts b/src/lib/common.ts index 3ec0c923c..de33fb267 100644 --- a/src/lib/common.ts +++ b/src/lib/common.ts @@ -103,7 +103,7 @@ export const getUserDetails = async (event, isAdminRequired = true) => { }; export function getEngine(engine) { - return engine === '/var/run/docker.sock' ? 'unix:///var/run/docker.sock' : `tcp://${engine}:2375`; + return engine === '/var/run/docker.sock' ? 'unix:///var/run/docker.sock' : engine; } export async function removeContainer(id, engine) { diff --git a/src/lib/components/common.ts b/src/lib/components/common.ts index fd887526a..687819c6d 100644 --- a/src/lib/components/common.ts +++ b/src/lib/components/common.ts @@ -15,3 +15,6 @@ export const notNodeDeployments = ['php', 'docker', 'rust']; export function getDomain(domain) { return domain?.replace('https://', '').replace('http://', ''); } +export function generateRemoteEngine(destination) { + return `ssh://${destination.user}@${destination.ipAddress}:${destination.port}`; +} diff --git a/src/lib/database/destinations.ts b/src/lib/database/destinations.ts index b566becb4..3f3aadec5 100644 --- a/src/lib/database/destinations.ts +++ b/src/lib/database/destinations.ts @@ -1,4 +1,5 @@ import { asyncExecShell, getEngine } from '$lib/common'; +import { decrypt, encrypt } from '$lib/crypto'; import { dockerInstance } from '$lib/docker'; import { startCoolifyProxy } from '$lib/haproxy'; import { getDatabaseImage } from '.'; @@ -47,7 +48,36 @@ export async function updateDestination({ id, name, engine, network }) { return await prisma.destinationDocker.update({ where: { id }, data: { name, engine, network } }); } -export async function newDestination({ name, teamId, engine, network, isCoolifyProxyUsed }) { +export async function newRemoteDestination({ + name, + teamId, + engine, + network, + isCoolifyProxyUsed, + remoteEngine, + ipAddress, + user, + port, + sshPrivateKey +}) { + const encryptedPrivateKey = encrypt(sshPrivateKey); + const destination = await prisma.destinationDocker.create({ + data: { + name, + teams: { connect: { id: teamId } }, + engine, + network, + isCoolifyProxyUsed, + remoteEngine, + ipAddress, + user, + port, + sshPrivateKey: encryptedPrivateKey + } + }); + return destination.id; +} +export async function newLocalDestination({ name, teamId, engine, network, isCoolifyProxyUsed }) { const host = getEngine(engine); const docker = dockerInstance({ destinationDocker: { engine, network } }); const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } }); @@ -94,9 +124,13 @@ export async function removeDestination({ id }) { } export async function getDestination({ id, teamId }) { - return await prisma.destinationDocker.findFirst({ + let destination = await prisma.destinationDocker.findFirst({ where: { id, teams: { some: { id: teamId } } } }); + if (destination.remoteEngine) { + destination.sshPrivateKey = decrypt(destination.sshPrivateKey); + } + return destination; } export async function getDestinationByApplicationId({ id, teamId }) { return await prisma.destinationDocker.findFirst({ diff --git a/src/routes/destinations/[id]/_LocalDocker.svelte b/src/routes/destinations/[id]/_LocalDocker.svelte index 76a36787a..287f544ef 100644 --- a/src/routes/destinations/[id]/_LocalDocker.svelte +++ b/src/routes/destinations/[id]/_LocalDocker.svelte @@ -4,7 +4,7 @@ export let state; import { toast } from '@zerodevx/svelte-toast'; - import { page } from '$app/stores'; + import { page, session } from '$app/stores'; import Setting from '$lib/components/Setting.svelte'; import { errorNotification } from '$lib/form'; import { post } from '$lib/api'; @@ -125,27 +125,35 @@
Configuration
- - + {#if $session.isAdmin} + + + {/if}
- +
diff --git a/src/routes/destinations/[id]/_RemoteDocker.svelte b/src/routes/destinations/[id]/_RemoteDocker.svelte new file mode 100644 index 000000000..9c13cf465 --- /dev/null +++ b/src/routes/destinations/[id]/_RemoteDocker.svelte @@ -0,0 +1,225 @@ + + + +
+
Configuration
+ {#if $session.isAdmin} + + + {/if} + +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
${ + cannotDisable + ? 'You cannot disable this proxy as FQDN is configured for Coolify.' + : '' + }`} + /> +
+ + + + diff --git a/src/routes/destinations/[id]/index.json.ts b/src/routes/destinations/[id]/index.json.ts index 9d8804a67..7d83d9da3 100644 --- a/src/routes/destinations/[id]/index.json.ts +++ b/src/routes/destinations/[id]/index.json.ts @@ -1,4 +1,5 @@ -import { asyncExecShell, getEngine, getTeam, getUserDetails } from '$lib/common'; +import { getUserDetails } from '$lib/common'; +import { generateRemoteEngine } from '$lib/components/common'; import * as db from '$lib/database'; import { ErrorHandler } from '$lib/database'; import { checkContainer } from '$lib/haproxy'; @@ -12,15 +13,21 @@ export const get: RequestHandler = async (event) => { try { const destination = await db.getDestination({ id, teamId }); const settings = await db.listSettings(); - const state = - destination?.engine && (await checkContainer(destination.engine, 'coolify-haproxy')); + let payload = { + destination, + settings, + state: false + }; + if (destination.remoteEngine) { + const engine = await generateRemoteEngine(destination); + payload.state = await checkContainer(engine, 'coolify-haproxy'); + } else { + payload.state = + destination?.engine && (await checkContainer(destination.engine, 'coolify-haproxy')); + } return { status: 200, - body: { - destination, - settings, - state - } + body: { ...payload } }; } catch (error) { return ErrorHandler(error); diff --git a/src/routes/destinations/[id]/index.svelte b/src/routes/destinations/[id]/index.svelte index a5b2996c8..68f529b54 100644 --- a/src/routes/destinations/[id]/index.svelte +++ b/src/routes/destinations/[id]/index.svelte @@ -35,6 +35,7 @@ import type Prisma from '@prisma/client'; import LocalDocker from './_LocalDocker.svelte'; + import RemoteDocker from './_RemoteDocker.svelte';
@@ -42,6 +43,11 @@ > {destination.name}
+
- + {#if destination.remoteEngine} + + {:else} + + {/if}
diff --git a/src/routes/new/destination/_Docker.svelte b/src/routes/new/destination/_LocalDocker.svelte similarity index 75% rename from src/routes/new/destination/_Docker.svelte rename to src/routes/new/destination/_LocalDocker.svelte index 47a070049..79a2c81b0 100644 --- a/src/routes/new/destination/_Docker.svelte +++ b/src/routes/new/destination/_LocalDocker.svelte @@ -51,26 +51,7 @@ placeholder="eg: /var/run/docker.sock" bind:value={payload.engine} /> -
-
diff --git a/src/routes/new/destination/_RemoteDocker.svelte b/src/routes/new/destination/_RemoteDocker.svelte new file mode 100644 index 000000000..780c66019 --- /dev/null +++ b/src/routes/new/destination/_RemoteDocker.svelte @@ -0,0 +1,90 @@ + + +
+
+
+
Configuration
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +