diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 6b43db8b7..49ab78187 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -10,6 +10,7 @@ import { asyncExecShell, createRemoteEngineConfiguration, getDomain, isDev, list import { scheduler } from './lib/scheduler'; import { compareVersions } from 'compare-versions'; import Graceful from '@ladjs/graceful' +import { verifyRemoteDockerEngineFn } from './routes/api/v1/destinations/handlers'; declare module 'fastify' { interface FastifyInstance { config: { @@ -27,7 +28,8 @@ declare module 'fastify' { const port = isDev ? 3001 : 3000; const host = '0.0.0.0'; -prisma.setting.findFirst().then(async (settings) => { +(async () => { + const settings = prisma.setting.findFirst() const fastify = Fastify({ logger: settings?.isAPIDebuggingEnabled || false, trustProxy: true @@ -117,11 +119,8 @@ prisma.setting.findFirst().then(async (settings) => { // console.log('not allowed', request.headers.host) } }) - fastify.listen({ port, host }, async (err: any, address: any) => { - if (err) { - console.error(err); - process.exit(1); - } + try { + await fastify.listen({ port, host }) console.log(`Coolify's API is listening on ${host}:${port}`); await initServer(); @@ -162,19 +161,28 @@ prisma.setting.findFirst().then(async (settings) => { getIPAddress(), configureRemoteDockers(), ]) - }); -}) + } catch (error) { + console.error(error); + process.exit(1); + } + + + +})(); + async function getIPAddress() { const { publicIpv4, publicIpv6 } = await import('public-ip') try { const settings = await listSettings(); if (!settings.ipv4) { + console.log(`Getting public IPv4 address...`); const ipv4 = await publicIpv4({ timeout: 2000 }) await prisma.setting.update({ where: { id: settings.id }, data: { ipv4 } }) } if (!settings.ipv6) { + console.log(`Getting public IPv6 address...`); const ipv6 = await publicIpv6({ timeout: 2000 }) await prisma.setting.update({ where: { id: settings.id }, data: { ipv6 } }) } @@ -183,6 +191,7 @@ async function getIPAddress() { } async function initServer() { try { + console.log(`Initializing server...`); await asyncExecShell(`docker network create --attachable coolify`); } catch (error) { } try { @@ -196,6 +205,7 @@ async function getArch() { try { const settings = await prisma.setting.findFirst({}) if (settings && !settings.arch) { + console.log(`Getting architecture...`); await prisma.setting.update({ where: { id: settings.id }, data: { arch: process.arch } }) } } catch (error) { } @@ -207,9 +217,13 @@ async function configureRemoteDockers() { where: { remoteVerified: true, remoteEngine: true } }); if (remoteDocker.length > 0) { + console.log(`Verifying Remote Docker Engines...`); for (const docker of remoteDocker) { - await createRemoteEngineConfiguration(docker.id) + console.log('Verifying:', docker.remoteIpAddress) + await verifyRemoteDockerEngineFn(docker.id); } } - } catch (error) { } + } catch (error) { + console.log(error) + } } diff --git a/apps/api/src/routes/api/v1/destinations/handlers.ts b/apps/api/src/routes/api/v1/destinations/handlers.ts index e4f038881..83373edd8 100644 --- a/apps/api/src/routes/api/v1/destinations/handlers.ts +++ b/apps/api/src/routes/api/v1/destinations/handlers.ts @@ -4,7 +4,7 @@ import sshConfig from 'ssh-config' import fs from 'fs/promises' import os from 'os'; -import { asyncExecShell, createRemoteEngineConfiguration, decrypt, errorHandler, executeDockerCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; +import { asyncExecShell, createRemoteEngineConfiguration, decrypt, errorHandler, executeDockerCmd, executeSSHCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; import { checkContainer } from '../../../../lib/docker'; import type { OnlyId } from '../../../../types'; @@ -202,25 +202,44 @@ export async function assignSSHKey(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function verifyRemoteDockerEngine(request: FastifyRequest, reply: FastifyReply) { +export async function verifyRemoteDockerEngineFn(id: string) { + await createRemoteEngineConfiguration(id); + const { remoteIpAddress, remoteUser, network, isCoolifyProxyUsed } = await prisma.destinationDocker.findFirst({ where: { id } }) + const host = `ssh://${remoteUser}@${remoteIpAddress}` + const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`); + if (!stdout) { + await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`); + } + const { stdout: coolifyNetwork } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=coolify-infra' --no-trunc --format "{{json .}}"`); + if (!coolifyNetwork) { + await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable coolify-infra`); + } + if (isCoolifyProxyUsed) await startTraefikProxy(id); + const { stdout: daemonJson } = await executeSSHCmd({ dockerId: id, command: `cat /etc/docker/daemon.json` }); try { - const { id } = request.params; - await createRemoteEngineConfiguration(id); - const { remoteIpAddress, remoteUser, network, isCoolifyProxyUsed } = await prisma.destinationDocker.findFirst({ where: { id } }) - const host = `ssh://${remoteUser}@${remoteIpAddress}` - const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`); - if (!stdout) { - await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`); + let daemonJsonParsed = JSON.parse(daemonJson); + if (!daemonJsonParsed['live-restore'] || daemonJsonParsed['live-restore'] !== true) { + daemonJsonParsed['live-restore'] = true + await executeSSHCmd({ dockerId: id, command: `echo '${JSON.stringify(daemonJsonParsed)}' > /etc/docker/daemon.json` }); + await executeSSHCmd({ dockerId: id, command: `systemctl restart docker` }); } - const { stdout: coolifyNetwork } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=coolify-infra' --no-trunc --format "{{json .}}"`); - if (!coolifyNetwork) { - await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable coolify-infra`); + } catch (error) { + const daemonJsonParsed = { + "live-restore": true } - if (isCoolifyProxyUsed) await startTraefikProxy(id); - await prisma.destinationDocker.update({ where: { id }, data: { remoteVerified: true } }) + console.log(JSON.stringify(daemonJsonParsed)) + await executeSSHCmd({ dockerId: id, command: `echo '${JSON.stringify(daemonJsonParsed)}' > /etc/docker/daemon.json` }); + await executeSSHCmd({ dockerId: id, command: `systemctl restart docker` }); + } + await prisma.destinationDocker.update({ where: { id }, data: { remoteVerified: true } }) +} +export async function verifyRemoteDockerEngine(request: FastifyRequest, reply: FastifyReply) { + const { id } = request.params; + try { + await verifyRemoteDockerEngineFn(id); return reply.code(201).send() - } catch ({ status, message }) { + await prisma.destinationDocker.update({ where: { id }, data: { remoteVerified: false } }) return errorHandler({ status, message }) } } diff --git a/apps/api/src/routes/api/v1/servers/handlers.ts b/apps/api/src/routes/api/v1/servers/handlers.ts index d9705e9ef..874f5a9f7 100644 --- a/apps/api/src/routes/api/v1/servers/handlers.ts +++ b/apps/api/src/routes/api/v1/servers/handlers.ts @@ -8,7 +8,16 @@ export async function listServers(request: FastifyRequest) { try { const userId = request.user.userId; const teamId = request.user.teamId; - const servers = await prisma.destinationDocker.findMany({ where: { teams: { some: { id: teamId === '0' ? undefined : teamId } }}, distinct: ['remoteIpAddress', 'engine'] }) + let servers = await prisma.destinationDocker.findMany({ where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } }, distinct: ['remoteIpAddress', 'engine'] }) + servers = servers.filter((server) => { + if (server.remoteEngine) { + if (server.remoteVerified) { + return server + } + } else { + return server + } + }) return { servers } @@ -78,7 +87,7 @@ export async function showUsage(request: FastifyRequest) { freeMemPercentage: (parsed.totalMemoryKB - parsed.usedMemoryKB) / parsed.totalMemoryKB * 100 }, cpu: { - load: [0,0,0], + load: [0, 0, 0], usage: cpuUsage, count: cpus }, diff --git a/apps/ui/src/routes/destinations/[id]/_RemoteDocker.svelte b/apps/ui/src/routes/destinations/[id]/_RemoteDocker.svelte index e9c444e3d..4c65e7796 100644 --- a/apps/ui/src/routes/destinations/[id]/_RemoteDocker.svelte +++ b/apps/ui/src/routes/destinations/[id]/_RemoteDocker.svelte @@ -175,24 +175,23 @@ disabled={loading.save} >{$t('forms.save')} - {#if !destination.remoteVerified} - - {:else} - - {/if} + + + {/if}