diff --git a/apps/api/package.json b/apps/api/package.json index 0f8c8842a..8955c00f8 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -20,8 +20,8 @@ "@fastify/cors": "8.1.0", "@fastify/env": "4.1.0", "@fastify/jwt": "6.3.2", - "@fastify/static": "6.5.0", "@fastify/multipart": "7.2.0", + "@fastify/static": "6.5.0", "@iarna/toml": "2.2.5", "@ladjs/graceful": "3.0.2", "@prisma/client": "4.3.1", diff --git a/apps/api/src/jobs/infrastructure.ts b/apps/api/src/jobs/infrastructure.ts index 289dcc2d0..e0b2d3a61 100644 --- a/apps/api/src/jobs/infrastructure.ts +++ b/apps/api/src/jobs/infrastructure.ts @@ -53,59 +53,51 @@ async function checkFluentBit() { } } } -async function copyRemoteCertificates(certificate: any, dockerId: string, remoteIpAddress: string) { +async function copyRemoteCertificates(id: string, dockerId: string, remoteIpAddress: string) { try { - const { id, key, cert } = certificate - const decryptedKey = decrypt(key) - await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey) - await fs.writeFile(`/tmp/${id}-cert.pem`, cert) await asyncExecShell(`scp /tmp/${id}-cert.pem /tmp/${id}-key.pem ${remoteIpAddress}:/tmp/`) await executeSSHCmd({ dockerId, command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'` }) await executeSSHCmd({ dockerId, command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/` }) await executeSSHCmd({ dockerId, command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/` }) - } catch (error) { - console.log('Error copying SSL certificates to remote engine', error) + console.log({ error }) } } -async function copyLocalCertificates(certificate: any) { +async function copyLocalCertificates(id: string) { try { - const { id, key, cert } = certificate - const decryptedKey = decrypt(key) await asyncExecShell(`docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'`) - await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey) - await fs.writeFile(`/tmp/${id}-cert.pem`, cert) await asyncExecShell(`docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/`) await asyncExecShell(`docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/`) } catch (error) { - console.log('Error copying SSL certificates to remote engine', error) + console.log({ error }) } } async function copySSLCertificates() { try { + const pAll = await import('p-all'); + const actions = [] const certificates = await prisma.certificate.findMany({ include: { team: true } }) const teamIds = certificates.map(c => c.teamId) const destinations = await prisma.destinationDocker.findMany({ where: { isCoolifyProxyUsed: true, teams: { some: { id: { in: [...teamIds] } } } } }) - let promises = [] - for (const destination of destinations) { - if (destination.remoteEngine) { - const { id: dockerId, remoteIpAddress, remoteVerified } = destination - if (!remoteVerified) { - continue; - } - for (const certificate of certificates) { - promises.push(copyRemoteCertificates(certificate, dockerId, remoteIpAddress)) - } - } else { - for (const certificate of certificates) { - promises.push(copyLocalCertificates(certificate)) + for (const certificate of certificates) { + const { id, key, cert } = certificate + const decryptedKey = decrypt(key) + await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey) + await fs.writeFile(`/tmp/${id}-cert.pem`, cert) + for (const destination of destinations) { + if (destination.remoteEngine) { + if (destination.remoteVerified) { + const { id: dockerId, remoteIpAddress } = destination + actions.push(async () => copyRemoteCertificates(id, dockerId, remoteIpAddress)) + } + } else { + actions.push(async () => copyLocalCertificates(id)) } } } - await Promise.all(promises) - + await pAll.default(actions, { concurrency: 1 }) } catch (error) { - console.log('Error copying SSL certificates', error) + console.log(error) } finally { await asyncExecShell(`find /tmp/ -maxdepth 1 -type f -name '*-*.pem' -delete`) } @@ -260,7 +252,8 @@ async function cleanupStorage() { (async () => { let status = { cleanupStorage: false, - autoUpdater: false + autoUpdater: false, + copySSLCertificates: false, } if (parentPort) { parentPort.on('message', async (message) => { @@ -291,7 +284,11 @@ async function cleanupStorage() { return; } if (message === 'action:copySSLCertificates') { - await copySSLCertificates(); + if (!status.copySSLCertificates) { + status.copySSLCertificates = true + await copySSLCertificates(); + status.copySSLCertificates = false + } return; } if (message === 'action:autoUpdater') { diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index 1b11cd5ac..db283d5a7 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -546,6 +546,7 @@ export async function createRemoteEngineConfiguration(id: string) { StrictHostKeyChecking: 'no', ControlMaster: 'auto', ControlPath: `${homedir}/.ssh/coolify-%r@%h:%p`, + ControlPersist: '10m' }) } const found = config.find({ Host: remoteIpAddress });