fix: cleanupstorage
This commit is contained in:
@@ -6,14 +6,27 @@ import cookie from '@fastify/cookie';
|
|||||||
import multipart from '@fastify/multipart';
|
import multipart from '@fastify/multipart';
|
||||||
import path, { join } from 'path';
|
import path, { join } from 'path';
|
||||||
import autoLoad from '@fastify/autoload';
|
import autoLoad from '@fastify/autoload';
|
||||||
import socketIO from 'fastify-socket.io'
|
import socketIO from 'fastify-socket.io';
|
||||||
import socketIOServer from './realtime'
|
import socketIOServer from './realtime';
|
||||||
|
|
||||||
import { cleanupDockerStorage, createRemoteEngineConfiguration, decrypt, executeCommand, generateDatabaseConfiguration, isDev, listSettings, prisma, sentryDSN, startTraefikProxy, startTraefikTCPProxy, version } from './lib/common';
|
import {
|
||||||
|
cleanupDockerStorage,
|
||||||
|
createRemoteEngineConfiguration,
|
||||||
|
decrypt,
|
||||||
|
executeCommand,
|
||||||
|
generateDatabaseConfiguration,
|
||||||
|
isDev,
|
||||||
|
listSettings,
|
||||||
|
prisma,
|
||||||
|
sentryDSN,
|
||||||
|
startTraefikProxy,
|
||||||
|
startTraefikTCPProxy,
|
||||||
|
version
|
||||||
|
} from './lib/common';
|
||||||
import { scheduler } from './lib/scheduler';
|
import { scheduler } from './lib/scheduler';
|
||||||
import { compareVersions } from 'compare-versions';
|
import { compareVersions } from 'compare-versions';
|
||||||
import Graceful from '@ladjs/graceful'
|
import Graceful from '@ladjs/graceful';
|
||||||
import yaml from 'js-yaml'
|
import yaml from 'js-yaml';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import { verifyRemoteDockerEngineFn } from './routes/api/v1/destinations/handlers';
|
import { verifyRemoteDockerEngineFn } from './routes/api/v1/destinations/handlers';
|
||||||
import { checkContainer } from './lib/docker';
|
import { checkContainer } from './lib/docker';
|
||||||
@@ -23,13 +36,13 @@ import * as Sentry from '@sentry/node';
|
|||||||
declare module 'fastify' {
|
declare module 'fastify' {
|
||||||
interface FastifyInstance {
|
interface FastifyInstance {
|
||||||
config: {
|
config: {
|
||||||
COOLIFY_APP_ID: string,
|
COOLIFY_APP_ID: string;
|
||||||
COOLIFY_SECRET_KEY: string,
|
COOLIFY_SECRET_KEY: string;
|
||||||
COOLIFY_DATABASE_URL: string,
|
COOLIFY_DATABASE_URL: string;
|
||||||
COOLIFY_IS_ON: string,
|
COOLIFY_IS_ON: string;
|
||||||
COOLIFY_WHITE_LABELED: string,
|
COOLIFY_WHITE_LABELED: string;
|
||||||
COOLIFY_WHITE_LABELED_ICON: string | null,
|
COOLIFY_WHITE_LABELED_ICON: string | null;
|
||||||
COOLIFY_AUTO_UPDATE: string,
|
COOLIFY_AUTO_UPDATE: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,7 +51,7 @@ const port = isDev ? 3001 : 3000;
|
|||||||
const host = '0.0.0.0';
|
const host = '0.0.0.0';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const settings = await prisma.setting.findFirst()
|
const settings = await prisma.setting.findFirst();
|
||||||
const fastify = Fastify({
|
const fastify = Fastify({
|
||||||
logger: settings?.isAPIDebuggingEnabled || false,
|
logger: settings?.isAPIDebuggingEnabled || false,
|
||||||
trustProxy: true
|
trustProxy: true
|
||||||
@@ -49,10 +62,10 @@ const host = '0.0.0.0';
|
|||||||
required: ['COOLIFY_SECRET_KEY', 'COOLIFY_DATABASE_URL', 'COOLIFY_IS_ON'],
|
required: ['COOLIFY_SECRET_KEY', 'COOLIFY_DATABASE_URL', 'COOLIFY_IS_ON'],
|
||||||
properties: {
|
properties: {
|
||||||
COOLIFY_APP_ID: {
|
COOLIFY_APP_ID: {
|
||||||
type: 'string',
|
type: 'string'
|
||||||
},
|
},
|
||||||
COOLIFY_SECRET_KEY: {
|
COOLIFY_SECRET_KEY: {
|
||||||
type: 'string',
|
type: 'string'
|
||||||
},
|
},
|
||||||
COOLIFY_DATABASE_URL: {
|
COOLIFY_DATABASE_URL: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
@@ -73,8 +86,7 @@ const host = '0.0.0.0';
|
|||||||
COOLIFY_AUTO_UPDATE: {
|
COOLIFY_AUTO_UPDATE: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: 'false'
|
default: 'false'
|
||||||
},
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const options = {
|
const options = {
|
||||||
@@ -103,13 +115,13 @@ const host = '0.0.0.0';
|
|||||||
fastify.register(autoLoad, {
|
fastify.register(autoLoad, {
|
||||||
dir: join(__dirname, 'routes')
|
dir: join(__dirname, 'routes')
|
||||||
});
|
});
|
||||||
fastify.register(cookie)
|
fastify.register(cookie);
|
||||||
fastify.register(cors);
|
fastify.register(cors);
|
||||||
fastify.register(socketIO, {
|
fastify.register(socketIO, {
|
||||||
cors: {
|
cors: {
|
||||||
origin: isDev ? "*" : ''
|
origin: isDev ? '*' : ''
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
// To detect allowed origins
|
// To detect allowed origins
|
||||||
// fastify.addHook('onRequest', async (request, reply) => {
|
// fastify.addHook('onRequest', async (request, reply) => {
|
||||||
// console.log(request.headers.host)
|
// console.log(request.headers.host)
|
||||||
@@ -131,10 +143,9 @@ const host = '0.0.0.0';
|
|||||||
// }
|
// }
|
||||||
// })
|
// })
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fastify.listen({ port, host })
|
await fastify.listen({ port, host });
|
||||||
await socketIOServer(fastify)
|
await socketIOServer(fastify);
|
||||||
console.log(`Coolify's API is listening on ${host}:${port}`);
|
console.log(`Coolify's API is listening on ${host}:${port}`);
|
||||||
|
|
||||||
migrateServicesToNewTemplate();
|
migrateServicesToNewTemplate();
|
||||||
@@ -148,105 +159,100 @@ const host = '0.0.0.0';
|
|||||||
if (!scheduler.workers.has('deployApplication')) {
|
if (!scheduler.workers.has('deployApplication')) {
|
||||||
scheduler.run('deployApplication');
|
scheduler.run('deployApplication');
|
||||||
}
|
}
|
||||||
}, 2000)
|
}, 2000);
|
||||||
|
|
||||||
// autoUpdater
|
// autoUpdater
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
await autoUpdater()
|
await autoUpdater();
|
||||||
}, 60000 * 15)
|
}, 60000 * 15);
|
||||||
|
|
||||||
// cleanupStorage
|
// cleanupStorage
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
await cleanupStorage()
|
await cleanupStorage();
|
||||||
}, 60000 * 10)
|
}, 2000);
|
||||||
|
|
||||||
// checkProxies, checkFluentBit & refresh templates
|
// checkProxies, checkFluentBit & refresh templates
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
await checkProxies();
|
await checkProxies();
|
||||||
await checkFluentBit();
|
await checkFluentBit();
|
||||||
}, 60000)
|
}, 60000);
|
||||||
|
|
||||||
// Refresh and check templates
|
// Refresh and check templates
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
await refreshTemplates()
|
await refreshTemplates();
|
||||||
}, 60000)
|
}, 60000);
|
||||||
|
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
await refreshTags()
|
await refreshTags();
|
||||||
}, 60000)
|
}, 60000);
|
||||||
|
|
||||||
setInterval(async () => {
|
setInterval(
|
||||||
await migrateServicesToNewTemplate()
|
async () => {
|
||||||
}, isDev ? 10000 : 60000)
|
await migrateServicesToNewTemplate();
|
||||||
|
},
|
||||||
|
isDev ? 10000 : 60000
|
||||||
|
);
|
||||||
|
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
await copySSLCertificates();
|
await copySSLCertificates();
|
||||||
}, 10000)
|
}, 10000);
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
getTagsTemplates(),
|
|
||||||
getArch(),
|
|
||||||
getIPAddress(),
|
|
||||||
configureRemoteDockers(),
|
|
||||||
])
|
|
||||||
|
|
||||||
|
await Promise.all([getTagsTemplates(), getArch(), getIPAddress(), configureRemoteDockers()]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
async function getIPAddress() {
|
async function getIPAddress() {
|
||||||
const { publicIpv4, publicIpv6 } = await import('public-ip')
|
const { publicIpv4, publicIpv6 } = await import('public-ip');
|
||||||
try {
|
try {
|
||||||
const settings = await listSettings();
|
const settings = await listSettings();
|
||||||
if (!settings.ipv4) {
|
if (!settings.ipv4) {
|
||||||
const ipv4 = await publicIpv4({ timeout: 2000 })
|
const ipv4 = await publicIpv4({ timeout: 2000 });
|
||||||
console.log(`Getting public IPv4 address...`);
|
console.log(`Getting public IPv4 address...`);
|
||||||
await prisma.setting.update({ where: { id: settings.id }, data: { ipv4 } })
|
await prisma.setting.update({ where: { id: settings.id }, data: { ipv4 } });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!settings.ipv6) {
|
if (!settings.ipv6) {
|
||||||
const ipv6 = await publicIpv6({ timeout: 2000 })
|
const ipv6 = await publicIpv6({ timeout: 2000 });
|
||||||
console.log(`Getting public IPv6 address...`);
|
console.log(`Getting public IPv6 address...`);
|
||||||
await prisma.setting.update({ where: { id: settings.id }, data: { ipv6 } })
|
await prisma.setting.update({ where: { id: settings.id }, data: { ipv6 } });
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
async function getTagsTemplates() {
|
async function getTagsTemplates() {
|
||||||
const { default: got } = await import('got')
|
const { default: got } = await import('got');
|
||||||
try {
|
try {
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
const templates = await fs.readFile('./devTemplates.yaml', 'utf8')
|
const templates = await fs.readFile('./devTemplates.yaml', 'utf8');
|
||||||
const tags = await fs.readFile('./devTags.json', 'utf8')
|
const tags = await fs.readFile('./devTags.json', 'utf8');
|
||||||
await fs.writeFile('./templates.json', JSON.stringify(yaml.load(templates)))
|
await fs.writeFile('./templates.json', JSON.stringify(yaml.load(templates)));
|
||||||
await fs.writeFile('./tags.json', tags)
|
await fs.writeFile('./tags.json', tags);
|
||||||
console.log('[004] Tags and templates loaded in dev mode...')
|
console.log('[004] Tags and templates loaded in dev mode...');
|
||||||
} else {
|
} else {
|
||||||
const tags = await got.get('https://get.coollabs.io/coolify/service-tags.json').text()
|
const tags = await got.get('https://get.coollabs.io/coolify/service-tags.json').text();
|
||||||
const response = await got.get('https://get.coollabs.io/coolify/service-templates.yaml').text()
|
const response = await got
|
||||||
await fs.writeFile('/app/templates.json', JSON.stringify(yaml.load(response)))
|
.get('https://get.coollabs.io/coolify/service-templates.yaml')
|
||||||
await fs.writeFile('/app/tags.json', tags)
|
.text();
|
||||||
console.log('[004] Tags and templates loaded...')
|
await fs.writeFile('/app/templates.json', JSON.stringify(yaml.load(response)));
|
||||||
|
await fs.writeFile('/app/tags.json', tags);
|
||||||
|
console.log('[004] Tags and templates loaded...');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Couldn't get latest templates.")
|
console.log("Couldn't get latest templates.");
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function initServer() {
|
async function initServer() {
|
||||||
const appId = process.env['COOLIFY_APP_ID'];
|
const appId = process.env['COOLIFY_APP_ID'];
|
||||||
const settings = await prisma.setting.findUnique({ where: { id: '0' } })
|
const settings = await prisma.setting.findUnique({ where: { id: '0' } });
|
||||||
try {
|
try {
|
||||||
if (settings.doNotTrack === true) {
|
if (settings.doNotTrack === true) {
|
||||||
console.log('[000] Telemetry disabled...')
|
console.log('[000] Telemetry disabled...');
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (settings.sentryDSN !== sentryDSN) {
|
if (settings.sentryDSN !== sentryDSN) {
|
||||||
await prisma.setting.update({ where: { id: '0' }, data: { sentryDSN } })
|
await prisma.setting.update({ where: { id: '0' }, data: { sentryDSN } });
|
||||||
}
|
}
|
||||||
// Initialize Sentry
|
// Initialize Sentry
|
||||||
// Sentry.init({
|
// Sentry.init({
|
||||||
@@ -257,7 +263,7 @@ async function initServer() {
|
|||||||
// console.log('[000] Sentry initialized...')
|
// console.log('[000] Sentry initialized...')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
console.log(`[001] Initializing server...`);
|
console.log(`[001] Initializing server...`);
|
||||||
@@ -267,23 +273,26 @@ async function initServer() {
|
|||||||
console.log(`[002] Cleanup stucked builds...`);
|
console.log(`[002] Cleanup stucked builds...`);
|
||||||
const isOlder = compareVersions('3.8.1', version);
|
const isOlder = compareVersions('3.8.1', version);
|
||||||
if (isOlder === 1) {
|
if (isOlder === 1) {
|
||||||
await prisma.build.updateMany({ where: { status: { in: ['running', 'queued'] } }, data: { status: 'failed' } });
|
await prisma.build.updateMany({
|
||||||
|
where: { status: { in: ['running', 'queued'] } },
|
||||||
|
data: { status: 'failed' }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
try {
|
try {
|
||||||
console.log('[003] Cleaning up old build sources under /tmp/build-sources/...');
|
console.log('[003] Cleaning up old build sources under /tmp/build-sources/...');
|
||||||
await fs.rm('/tmp/build-sources', { recursive: true, force: true })
|
await fs.rm('/tmp/build-sources', { recursive: true, force: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getArch() {
|
async function getArch() {
|
||||||
try {
|
try {
|
||||||
const settings = await prisma.setting.findFirst({})
|
const settings = await prisma.setting.findFirst({});
|
||||||
if (settings && !settings.arch) {
|
if (settings && !settings.arch) {
|
||||||
console.log(`Getting architecture...`);
|
console.log(`Getting architecture...`);
|
||||||
await prisma.setting.update({ where: { id: settings.id }, data: { arch: process.arch } })
|
await prisma.setting.update({ where: { id: settings.id }, data: { arch: process.arch } });
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
@@ -296,37 +305,44 @@ async function configureRemoteDockers() {
|
|||||||
if (remoteDocker.length > 0) {
|
if (remoteDocker.length > 0) {
|
||||||
console.log(`Verifying Remote Docker Engines...`);
|
console.log(`Verifying Remote Docker Engines...`);
|
||||||
for (const docker of remoteDocker) {
|
for (const docker of remoteDocker) {
|
||||||
console.log('Verifying:', docker.remoteIpAddress)
|
console.log('Verifying:', docker.remoteIpAddress);
|
||||||
await verifyRemoteDockerEngineFn(docker.id);
|
await verifyRemoteDockerEngineFn(docker.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function autoUpdater() {
|
async function autoUpdater() {
|
||||||
try {
|
try {
|
||||||
const { default: got } = await import('got')
|
const { default: got } = await import('got');
|
||||||
const currentVersion = version;
|
const currentVersion = version;
|
||||||
const { coolify } = await got.get('https://get.coollabs.io/versions.json', {
|
const { coolify } = await got
|
||||||
|
.get('https://get.coollabs.io/versions.json', {
|
||||||
searchParams: {
|
searchParams: {
|
||||||
appId: process.env['COOLIFY_APP_ID'] || undefined,
|
appId: process.env['COOLIFY_APP_ID'] || undefined,
|
||||||
version: currentVersion
|
version: currentVersion
|
||||||
}
|
}
|
||||||
}).json()
|
})
|
||||||
|
.json();
|
||||||
const latestVersion = coolify.main.version;
|
const latestVersion = coolify.main.version;
|
||||||
const isUpdateAvailable = compareVersions(latestVersion, currentVersion);
|
const isUpdateAvailable = compareVersions(latestVersion, currentVersion);
|
||||||
if (isUpdateAvailable === 1) {
|
if (isUpdateAvailable === 1) {
|
||||||
const activeCount = 0
|
const activeCount = 0;
|
||||||
if (activeCount === 0) {
|
if (activeCount === 0) {
|
||||||
if (!isDev) {
|
if (!isDev) {
|
||||||
const { isAutoUpdateEnabled } = await prisma.setting.findFirst();
|
const { isAutoUpdateEnabled } = await prisma.setting.findFirst();
|
||||||
if (isAutoUpdateEnabled) {
|
if (isAutoUpdateEnabled) {
|
||||||
await executeCommand({ command: `docker pull coollabsio/coolify:${latestVersion}` })
|
await executeCommand({ command: `docker pull coollabsio/coolify:${latestVersion}` });
|
||||||
await executeCommand({ shell: true, command: `env | grep '^COOLIFY' > .env` })
|
await executeCommand({ shell: true, command: `env | grep '^COOLIFY' > .env` });
|
||||||
await executeCommand({ command: `sed -i '/COOLIFY_AUTO_UPDATE=/cCOOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env` })
|
await executeCommand({
|
||||||
await executeCommand({ shell: true, command: `docker run --rm -tid --env-file .env -v /var/run/docker.sock:/var/run/docker.sock -v coolify-db coollabsio/coolify:${latestVersion} /bin/sh -c "env | grep COOLIFY > .env && echo 'TAG=${latestVersion}' >> .env && docker stop -t 0 coolify coolify-fluentbit && docker rm coolify coolify-fluentbit && docker compose pull && docker compose up -d --force-recreate"` })
|
command: `sed -i '/COOLIFY_AUTO_UPDATE=/cCOOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env`
|
||||||
|
});
|
||||||
|
await executeCommand({
|
||||||
|
shell: true,
|
||||||
|
command: `docker run --rm -tid --env-file .env -v /var/run/docker.sock:/var/run/docker.sock -v coolify-db coollabsio/coolify:${latestVersion} /bin/sh -c "env | grep COOLIFY > .env && echo 'TAG=${latestVersion}' >> .env && docker stop -t 0 coolify coolify-fluentbit && docker rm coolify coolify-fluentbit && docker compose pull && docker compose up -d --force-recreate"`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('Updating (not really in dev mode).');
|
console.log('Updating (not really in dev mode).');
|
||||||
@@ -334,7 +350,7 @@ async function autoUpdater() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,14 +361,18 @@ async function checkFluentBit() {
|
|||||||
const { id } = await prisma.destinationDocker.findFirst({
|
const { id } = await prisma.destinationDocker.findFirst({
|
||||||
where: { engine, network: 'coolify' }
|
where: { engine, network: 'coolify' }
|
||||||
});
|
});
|
||||||
const { found } = await checkContainer({ dockerId: id, container: 'coolify-fluentbit', remove: true });
|
const { found } = await checkContainer({
|
||||||
|
dockerId: id,
|
||||||
|
container: 'coolify-fluentbit',
|
||||||
|
remove: true
|
||||||
|
});
|
||||||
if (!found) {
|
if (!found) {
|
||||||
await executeCommand({ shell: true, command: `env | grep '^COOLIFY' > .env` });
|
await executeCommand({ shell: true, command: `env | grep '^COOLIFY' > .env` });
|
||||||
await executeCommand({ command: `docker compose up -d fluent-bit` });
|
await executeCommand({ command: `docker compose up -d fluent-bit` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function checkProxies() {
|
async function checkProxies() {
|
||||||
@@ -368,7 +388,7 @@ async function checkProxies() {
|
|||||||
where: { engine, network: 'coolify', isCoolifyProxyUsed: true }
|
where: { engine, network: 'coolify', isCoolifyProxyUsed: true }
|
||||||
});
|
});
|
||||||
if (localDocker) {
|
if (localDocker) {
|
||||||
portReachable = await isReachable(80, { host: ipv4 || ipv6 })
|
portReachable = await isReachable(80, { host: ipv4 || ipv6 });
|
||||||
if (!portReachable) {
|
if (!portReachable) {
|
||||||
await startTraefikProxy(localDocker.id);
|
await startTraefikProxy(localDocker.id);
|
||||||
}
|
}
|
||||||
@@ -380,13 +400,13 @@ async function checkProxies() {
|
|||||||
if (remoteDocker.length > 0) {
|
if (remoteDocker.length > 0) {
|
||||||
for (const docker of remoteDocker) {
|
for (const docker of remoteDocker) {
|
||||||
if (docker.isCoolifyProxyUsed) {
|
if (docker.isCoolifyProxyUsed) {
|
||||||
portReachable = await isReachable(80, { host: docker.remoteIpAddress })
|
portReachable = await isReachable(80, { host: docker.remoteIpAddress });
|
||||||
if (!portReachable) {
|
if (!portReachable) {
|
||||||
await startTraefikProxy(docker.id);
|
await startTraefikProxy(docker.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await createRemoteEngineConfiguration(docker.id)
|
await createRemoteEngineConfiguration(docker.id);
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,80 +446,105 @@ async function checkProxies() {
|
|||||||
// await startTraefikTCPProxy(destinationDocker, id, publicPort, 9000);
|
// await startTraefikTCPProxy(destinationDocker, id, publicPort, 9000);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
} catch (error) {
|
} catch (error) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copySSLCertificates() {
|
async function copySSLCertificates() {
|
||||||
try {
|
try {
|
||||||
const pAll = await import('p-all');
|
const pAll = await import('p-all');
|
||||||
const actions = []
|
const actions = [];
|
||||||
const certificates = await prisma.certificate.findMany({ include: { team: true } })
|
const certificates = await prisma.certificate.findMany({ include: { team: true } });
|
||||||
const teamIds = certificates.map(c => c.teamId)
|
const teamIds = certificates.map((c) => c.teamId);
|
||||||
const destinations = await prisma.destinationDocker.findMany({ where: { isCoolifyProxyUsed: true, teams: { some: { id: { in: [...teamIds] } } } } })
|
const destinations = await prisma.destinationDocker.findMany({
|
||||||
|
where: { isCoolifyProxyUsed: true, teams: { some: { id: { in: [...teamIds] } } } }
|
||||||
|
});
|
||||||
for (const certificate of certificates) {
|
for (const certificate of certificates) {
|
||||||
const { id, key, cert } = certificate
|
const { id, key, cert } = certificate;
|
||||||
const decryptedKey = decrypt(key)
|
const decryptedKey = decrypt(key);
|
||||||
await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey)
|
await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey);
|
||||||
await fs.writeFile(`/tmp/${id}-cert.pem`, cert)
|
await fs.writeFile(`/tmp/${id}-cert.pem`, cert);
|
||||||
for (const destination of destinations) {
|
for (const destination of destinations) {
|
||||||
if (destination.remoteEngine) {
|
if (destination.remoteEngine) {
|
||||||
if (destination.remoteVerified) {
|
if (destination.remoteVerified) {
|
||||||
const { id: dockerId, remoteIpAddress } = destination
|
const { id: dockerId, remoteIpAddress } = destination;
|
||||||
actions.push(async () => copyRemoteCertificates(id, dockerId, remoteIpAddress))
|
actions.push(async () => copyRemoteCertificates(id, dockerId, remoteIpAddress));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
actions.push(async () => copyLocalCertificates(id))
|
actions.push(async () => copyLocalCertificates(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await pAll.default(actions, { concurrency: 1 })
|
await pAll.default(actions, { concurrency: 1 });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
await executeCommand({ command: `find /tmp/ -maxdepth 1 -type f -name '*-*.pem' -delete` })
|
await executeCommand({ command: `find /tmp/ -maxdepth 1 -type f -name '*-*.pem' -delete` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyRemoteCertificates(id: string, dockerId: string, remoteIpAddress: string) {
|
async function copyRemoteCertificates(id: string, dockerId: string, remoteIpAddress: string) {
|
||||||
try {
|
try {
|
||||||
await executeCommand({ command: `scp /tmp/${id}-cert.pem /tmp/${id}-key.pem ${remoteIpAddress}:/tmp/` })
|
await executeCommand({
|
||||||
await executeCommand({ sshCommand: true, shell: true, dockerId, command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'` })
|
command: `scp /tmp/${id}-cert.pem /tmp/${id}-key.pem ${remoteIpAddress}:/tmp/`
|
||||||
await executeCommand({ sshCommand: true, dockerId, command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/` })
|
});
|
||||||
await executeCommand({ sshCommand: true, dockerId, command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/` })
|
await executeCommand({
|
||||||
|
sshCommand: true,
|
||||||
|
shell: true,
|
||||||
|
dockerId,
|
||||||
|
command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'`
|
||||||
|
});
|
||||||
|
await executeCommand({
|
||||||
|
sshCommand: true,
|
||||||
|
dockerId,
|
||||||
|
command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/`
|
||||||
|
});
|
||||||
|
await executeCommand({
|
||||||
|
sshCommand: true,
|
||||||
|
dockerId,
|
||||||
|
command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/`
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log({ error })
|
console.log({ error });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function copyLocalCertificates(id: string) {
|
async function copyLocalCertificates(id: string) {
|
||||||
try {
|
try {
|
||||||
await executeCommand({ command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'`, shell: true })
|
await executeCommand({
|
||||||
await executeCommand({ command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/` })
|
command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'`,
|
||||||
await executeCommand({ command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/` })
|
shell: true
|
||||||
|
});
|
||||||
|
await executeCommand({
|
||||||
|
command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/`
|
||||||
|
});
|
||||||
|
await executeCommand({
|
||||||
|
command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/`
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log({ error })
|
console.log({ error });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function cleanupStorage() {
|
async function cleanupStorage() {
|
||||||
const destinationDockers = await prisma.destinationDocker.findMany();
|
const destinationDockers = await prisma.destinationDocker.findMany();
|
||||||
let enginesDone = new Set()
|
let enginesDone = new Set();
|
||||||
for (const destination of destinationDockers) {
|
for (const destination of destinationDockers) {
|
||||||
if (enginesDone.has(destination.engine) || enginesDone.has(destination.remoteIpAddress)) return
|
if (enginesDone.has(destination.engine) || enginesDone.has(destination.remoteIpAddress)) return;
|
||||||
if (destination.engine) enginesDone.add(destination.engine)
|
if (destination.engine) enginesDone.add(destination.engine);
|
||||||
if (destination.remoteIpAddress) enginesDone.add(destination.remoteIpAddress)
|
if (destination.remoteIpAddress) enginesDone.add(destination.remoteIpAddress);
|
||||||
|
let force = false;
|
||||||
let lowDiskSpace = false;
|
let lowDiskSpace = false;
|
||||||
try {
|
try {
|
||||||
let stdout = null
|
let stdout = null;
|
||||||
if (!isDev) {
|
if (!isDev) {
|
||||||
const output = await executeCommand({ dockerId: destination.id, command: `CONTAINER=$(docker ps -lq | head -1) && docker exec $CONTAINER sh -c 'df -kPT /'`, shell: true })
|
const output = await executeCommand({
|
||||||
|
dockerId: destination.id,
|
||||||
|
command: `CONTAINER=$(docker ps -lq | head -1) && docker exec $CONTAINER sh -c 'df -kPT /'`,
|
||||||
|
shell: true
|
||||||
|
});
|
||||||
stdout = output.stdout;
|
stdout = output.stdout;
|
||||||
} else {
|
} else {
|
||||||
const output = await executeCommand({
|
const output = await executeCommand({
|
||||||
command:
|
command: `df -kPT /`
|
||||||
`df -kPT /`
|
|
||||||
});
|
});
|
||||||
stdout = output.stdout;
|
stdout = output.stdout;
|
||||||
}
|
}
|
||||||
@@ -529,9 +574,10 @@ async function cleanupStorage() {
|
|||||||
const { capacity } = data[0];
|
const { capacity } = data[0];
|
||||||
if (capacity > 0.8) {
|
if (capacity > 0.8) {
|
||||||
lowDiskSpace = true;
|
lowDiskSpace = true;
|
||||||
|
force = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
await cleanupDockerStorage(destination.id, lowDiskSpace, false)
|
await cleanupDockerStorage(destination.id, lowDiskSpace, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -19,7 +19,7 @@ import { saveBuildLog, saveDockerRegistryCredentials } from './buildPacks/common
|
|||||||
import { scheduler } from './scheduler';
|
import { scheduler } from './scheduler';
|
||||||
import type { ExecaChildProcess } from 'execa';
|
import type { ExecaChildProcess } from 'execa';
|
||||||
|
|
||||||
export const version = '3.12.4';
|
export const version = '3.12.5';
|
||||||
export const isDev = process.env.NODE_ENV === 'development';
|
export const isDev = process.env.NODE_ENV === 'development';
|
||||||
export const sentryDSN =
|
export const sentryDSN =
|
||||||
'https://409f09bcb7af47928d3e0f46b78987f3@o1082494.ingest.sentry.io/4504236622217216';
|
'https://409f09bcb7af47928d3e0f46b78987f3@o1082494.ingest.sentry.io/4504236622217216';
|
||||||
@@ -584,7 +584,7 @@ export async function executeCommand({
|
|||||||
}
|
}
|
||||||
if (sshCommand) {
|
if (sshCommand) {
|
||||||
if (shell) {
|
if (shell) {
|
||||||
return execaCommand(`ssh ${remoteIpAddress}-remote ${command}`);
|
return execaCommand(`ssh ${remoteIpAddress}-remote ${command}`, { shell: true });
|
||||||
}
|
}
|
||||||
return await execa('ssh', [`${remoteIpAddress}-remote`, dockerCommand, ...dockerArgs]);
|
return await execa('ssh', [`${remoteIpAddress}-remote`, dockerCommand, ...dockerArgs]);
|
||||||
}
|
}
|
||||||
@@ -651,11 +651,13 @@ export async function executeCommand({
|
|||||||
} else {
|
} else {
|
||||||
if (shell) {
|
if (shell) {
|
||||||
return await execaCommand(command, {
|
return await execaCommand(command, {
|
||||||
env: { DOCKER_BUILDKIT: '1', DOCKER_HOST: engine }
|
env: { DOCKER_BUILDKIT: '1', DOCKER_HOST: engine },
|
||||||
|
shell: true
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return await execa(dockerCommand, dockerArgs, {
|
return await execa(dockerCommand, dockerArgs, {
|
||||||
env: { DOCKER_BUILDKIT: '1', DOCKER_HOST: engine }
|
env: { DOCKER_BUILDKIT: '1', DOCKER_HOST: engine },
|
||||||
|
shell: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1751,6 +1753,10 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
|
|||||||
let keepImage = [];
|
let keepImage = [];
|
||||||
for (const image2 of imagesArray) {
|
for (const image2 of imagesArray) {
|
||||||
if (image2.startsWith(image)) {
|
if (image2.startsWith(image)) {
|
||||||
|
if (force) {
|
||||||
|
deleteImage.push(image2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (keepImage.length >= numberOfDockerImagesKeptLocally) {
|
if (keepImage.length >= numberOfDockerImagesKeptLocally) {
|
||||||
deleteImage.push(image2);
|
deleteImage.push(image2);
|
||||||
} else {
|
} else {
|
||||||
@@ -1760,7 +1766,11 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const image of deleteImage) {
|
for (const image of deleteImage) {
|
||||||
|
try {
|
||||||
await executeCommand({ dockerId, command: `docker image rm -f ${image}` });
|
await executeCommand({ dockerId, command: `docker image rm -f ${image}` });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune coolify managed containers
|
// Prune coolify managed containers
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "coolify",
|
"name": "coolify",
|
||||||
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
||||||
"version": "3.12.4",
|
"version": "3.12.5",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": "github:coollabsio/coolify",
|
"repository": "github:coollabsio/coolify",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
Reference in New Issue
Block a user