mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-27 20:49:32 +00:00
fix: security hole
This commit is contained in:
@@ -8,7 +8,7 @@ import csv from 'csvtojson';
|
||||
|
||||
import { day } from '../../../../lib/dayjs';
|
||||
import { saveDockerRegistryCredentials, setDefaultBaseImage, setDefaultConfiguration } from '../../../../lib/buildPacks/common';
|
||||
import { checkDomainsIsValidInDNS, checkExposedPort, createDirectories, decrypt, defaultComposeConfiguration, encrypt, errorHandler, executeDockerCmd, generateSshKeyPair, getContainerUsage, getDomain, isDev, isDomainConfigured, listSettings, prisma, stopBuild, uniqueName } from '../../../../lib/common';
|
||||
import { checkDomainsIsValidInDNS, checkExposedPort, createDirectories, decrypt, defaultComposeConfiguration, encrypt, errorHandler, executeCommand, generateSshKeyPair, getContainerUsage, getDomain, isDev, isDomainConfigured, listSettings, prisma, stopBuild, uniqueName } from '../../../../lib/common';
|
||||
import { checkContainer, formatLabelsOnDocker, removeContainer } from '../../../../lib/docker';
|
||||
|
||||
import type { FastifyRequest } from 'fastify';
|
||||
@@ -78,7 +78,7 @@ export async function cleanupUnconfiguredApplications(request: FastifyRequest<an
|
||||
for (const application of applications) {
|
||||
if (!application.buildPack || !application.destinationDockerId || !application.branch || (!application.settings?.isBot && !application?.fqdn)) {
|
||||
if (application?.destinationDockerId && application.destinationDocker?.network) {
|
||||
const { stdout: containers } = await executeDockerCmd({
|
||||
const { stdout: containers } = await executeCommand({
|
||||
dockerId: application.destinationDocker.id,
|
||||
command: `docker ps -a --filter network=${application.destinationDocker.network} --filter name=${application.id} --format '{{json .}}'`
|
||||
})
|
||||
@@ -113,7 +113,7 @@ export async function getApplicationStatus(request: FastifyRequest<OnlyId>) {
|
||||
const application: any = await getApplicationFromDB(id, teamId);
|
||||
if (application?.destinationDockerId) {
|
||||
if (application.buildPack === 'compose') {
|
||||
const { stdout: containers } = await executeDockerCmd({
|
||||
const { stdout: containers } = await executeCommand({
|
||||
dockerId: application.destinationDocker.id,
|
||||
command:
|
||||
`docker ps -a --filter "label=coolify.applicationId=${id}" --format '{{json .}}'`
|
||||
@@ -485,7 +485,7 @@ export async function restartApplication(request: FastifyRequest<RestartApplicat
|
||||
if (imageId) {
|
||||
image = imageId
|
||||
} else {
|
||||
const { stdout: container } = await executeDockerCmd({ dockerId, command: `docker container ls --filter 'label=com.docker.compose.service=${id}' --format '{{json .}}'` })
|
||||
const { stdout: container } = await executeCommand({ dockerId, command: `docker container ls --filter 'label=com.docker.compose.service=${id}' --format '{{json .}}'` })
|
||||
const containersArray = container.trim().split('\n');
|
||||
for (const container of containersArray) {
|
||||
const containerObj = formatLabelsOnDocker(container);
|
||||
@@ -504,7 +504,7 @@ export async function restartApplication(request: FastifyRequest<RestartApplicat
|
||||
|
||||
let imageFoundLocally = false;
|
||||
try {
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId,
|
||||
command: `docker image inspect ${image}`
|
||||
})
|
||||
@@ -514,7 +514,7 @@ export async function restartApplication(request: FastifyRequest<RestartApplicat
|
||||
}
|
||||
let imageFoundRemotely = false;
|
||||
try {
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId,
|
||||
command: `docker ${location ? `--config ${location}` : ''} pull ${image}`
|
||||
})
|
||||
@@ -570,13 +570,13 @@ export async function restartApplication(request: FastifyRequest<RestartApplicat
|
||||
};
|
||||
await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile));
|
||||
try {
|
||||
await executeDockerCmd({ dockerId, command: `docker stop -t 0 ${id}` })
|
||||
await executeDockerCmd({ dockerId, command: `docker rm ${id}` })
|
||||
await executeCommand({ dockerId, command: `docker stop -t 0 ${id}` })
|
||||
await executeCommand({ dockerId, command: `docker rm ${id}` })
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
|
||||
await executeDockerCmd({ dockerId, command: `docker compose --project-directory ${workdir} up -d` })
|
||||
await executeCommand({ dockerId, command: `docker compose --project-directory ${workdir} up -d` })
|
||||
return reply.code(201).send();
|
||||
}
|
||||
throw { status: 500, message: 'Application cannot be restarted.' }
|
||||
@@ -592,7 +592,7 @@ export async function stopApplication(request: FastifyRequest<OnlyId>, reply: Fa
|
||||
if (application?.destinationDockerId) {
|
||||
const { id: dockerId } = application.destinationDocker;
|
||||
if (application.buildPack === 'compose') {
|
||||
const { stdout: containers } = await executeDockerCmd({
|
||||
const { stdout: containers } = await executeCommand({
|
||||
dockerId: application.destinationDocker.id,
|
||||
command:
|
||||
`docker ps -a --filter "label=coolify.applicationId=${id}" --format '{{json .}}'`
|
||||
@@ -627,7 +627,7 @@ export async function deleteApplication(request: FastifyRequest<DeleteApplicatio
|
||||
include: { destinationDocker: true }
|
||||
});
|
||||
if (!force && application?.destinationDockerId && application.destinationDocker?.network) {
|
||||
const { stdout: containers } = await executeDockerCmd({
|
||||
const { stdout: containers } = await executeCommand({
|
||||
dockerId: application.destinationDocker.id,
|
||||
command: `docker ps -a --filter network=${application.destinationDocker.network} --filter name=${id} --format '{{json .}}'`
|
||||
})
|
||||
@@ -720,8 +720,8 @@ export async function getDockerImages(request) {
|
||||
const application: any = await getApplicationFromDB(id, teamId);
|
||||
let imagesAvailables = [];
|
||||
try {
|
||||
const { stdout } = await executeDockerCmd({ dockerId: application.destinationDocker.id, command: `docker images --format '{{.Repository}}#{{.Tag}}#{{.CreatedAt}}' | grep -i ${id} | grep -v cache` });
|
||||
const { stdout: runningImage } = await executeDockerCmd({ dockerId: application.destinationDocker.id, command: `docker ps -a --filter 'label=com.docker.compose.service=${id}' --format {{.Image}}` });
|
||||
const { stdout } = await executeCommand({ dockerId: application.destinationDocker.id, command: `docker images --format '{{.Repository}}#{{.Tag}}#{{.CreatedAt}}' | grep -i ${id} | grep -v cache`, shell: true });
|
||||
const { stdout: runningImage } = await executeCommand({ dockerId: application.destinationDocker.id, command: `docker ps -a --filter 'label=com.docker.compose.service=${id}' --format {{.Image}}` });
|
||||
const images = stdout.trim().split('\n');
|
||||
|
||||
for (const image of images) {
|
||||
@@ -1184,7 +1184,7 @@ export async function restartPreview(request: FastifyRequest<RestartPreviewAppli
|
||||
const { workdir } = await createDirectories({ repository, buildId });
|
||||
const labels = []
|
||||
let image = null
|
||||
const { stdout: container } = await executeDockerCmd({ dockerId, command: `docker container ls --filter 'label=com.docker.compose.service=${id}-${pullmergeRequestId}' --format '{{json .}}'` })
|
||||
const { stdout: container } = await executeCommand({ dockerId, command: `docker container ls --filter 'label=com.docker.compose.service=${id}-${pullmergeRequestId}' --format '{{json .}}'` })
|
||||
const containersArray = container.trim().split('\n');
|
||||
for (const container of containersArray) {
|
||||
const containerObj = formatLabelsOnDocker(container);
|
||||
@@ -1197,7 +1197,7 @@ export async function restartPreview(request: FastifyRequest<RestartPreviewAppli
|
||||
}
|
||||
let imageFound = false;
|
||||
try {
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId,
|
||||
command: `docker image inspect ${image}`
|
||||
})
|
||||
@@ -1251,9 +1251,9 @@ export async function restartPreview(request: FastifyRequest<RestartPreviewAppli
|
||||
volumes: Object.assign({}, ...composeVolumes)
|
||||
};
|
||||
await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile));
|
||||
await executeDockerCmd({ dockerId, command: `docker stop -t 0 ${id}-${pullmergeRequestId}` })
|
||||
await executeDockerCmd({ dockerId, command: `docker rm ${id}-${pullmergeRequestId}` })
|
||||
await executeDockerCmd({ dockerId, command: `docker compose --project-directory ${workdir} up -d` })
|
||||
await executeCommand({ dockerId, command: `docker stop -t 0 ${id}-${pullmergeRequestId}` })
|
||||
await executeCommand({ dockerId, command: `docker rm ${id}-${pullmergeRequestId}` })
|
||||
await executeCommand({ dockerId, command: `docker compose --project-directory ${workdir} up -d` })
|
||||
return reply.code(201).send();
|
||||
}
|
||||
throw { status: 500, message: 'Application cannot be restarted.' }
|
||||
@@ -1294,7 +1294,7 @@ export async function loadPreviews(request: FastifyRequest<OnlyId>) {
|
||||
try {
|
||||
const { id } = request.params
|
||||
const application = await prisma.application.findUnique({ where: { id }, include: { destinationDocker: true } });
|
||||
const { stdout } = await executeDockerCmd({ dockerId: application.destinationDocker.id, command: `docker container ls --filter 'name=${id}-' --format "{{json .}}"` })
|
||||
const { stdout } = await executeCommand({ dockerId: application.destinationDocker.id, command: `docker container ls --filter 'name=${id}-' --format "{{json .}}"` })
|
||||
if (stdout === '') {
|
||||
throw { status: 500, message: 'No previews found.' }
|
||||
}
|
||||
@@ -1369,7 +1369,7 @@ export async function getApplicationLogs(request: FastifyRequest<GetApplicationL
|
||||
if (destinationDockerId) {
|
||||
try {
|
||||
const { default: ansi } = await import('strip-ansi')
|
||||
const { stdout, stderr } = await executeDockerCmd({ dockerId, command: `docker logs --since ${since} --tail 5000 --timestamps ${containerId}` })
|
||||
const { stdout, stderr } = await executeCommand({ dockerId, command: `docker logs --since ${since} --tail 5000 --timestamps ${containerId}` })
|
||||
const stripLogsStdout = stdout.toString().split('\n').map((l) => ansi(l)).filter((a) => a);
|
||||
const stripLogsStderr = stderr.toString().split('\n').map((l) => ansi(l)).filter((a) => a);
|
||||
const logs = stripLogsStderr.concat(stripLogsStdout)
|
||||
@@ -1560,19 +1560,19 @@ export async function createdBranchDatabase(database: any, baseDatabaseBranch: s
|
||||
if (destinationDockerId) {
|
||||
if (type === 'postgresql') {
|
||||
const decryptedRootUserPassword = decrypt(rootUserPassword);
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDockerId,
|
||||
command: `docker exec ${id} pg_dump -d "postgresql://postgres:${decryptedRootUserPassword}@${id}:5432/${baseDatabaseBranch}" --encoding=UTF8 --schema-only -f /tmp/${baseDatabaseBranch}.dump`
|
||||
})
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDockerId,
|
||||
command: `docker exec ${id} psql postgresql://postgres:${decryptedRootUserPassword}@${id}:5432 -c "CREATE DATABASE branch_${pullmergeRequestId}"`
|
||||
})
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDockerId,
|
||||
command: `docker exec ${id} psql -d "postgresql://postgres:${decryptedRootUserPassword}@${id}:5432/branch_${pullmergeRequestId}" -f /tmp/${baseDatabaseBranch}.dump`
|
||||
})
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDockerId,
|
||||
command: `docker exec ${id} psql postgresql://postgres:${decryptedRootUserPassword}@${id}:5432 -c "ALTER DATABASE branch_${pullmergeRequestId} OWNER TO ${dbUser}"`
|
||||
})
|
||||
@@ -1591,12 +1591,12 @@ export async function removeBranchDatabase(database: any, pullmergeRequestId: st
|
||||
if (type === 'postgresql') {
|
||||
const decryptedRootUserPassword = decrypt(rootUserPassword);
|
||||
// Terminate all connections to the database
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDockerId,
|
||||
command: `docker exec ${id} psql postgresql://postgres:${decryptedRootUserPassword}@${id}:5432 -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'branch_${pullmergeRequestId}' AND pid <> pg_backend_pid();"`
|
||||
})
|
||||
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDockerId,
|
||||
command: `docker exec ${id} psql postgresql://postgres:${decryptedRootUserPassword}@${id}:5432 -c "DROP DATABASE branch_${pullmergeRequestId}"`
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FastifyRequest } from 'fastify';
|
||||
import { FastifyReply } from 'fastify';
|
||||
import yaml from 'js-yaml';
|
||||
import fs from 'fs/promises';
|
||||
import { ComposeFile, createDirectories, decrypt, defaultComposeConfiguration, encrypt, errorHandler, executeDockerCmd, generateDatabaseConfiguration, generatePassword, getContainerUsage, getDatabaseImage, getDatabaseVersions, getFreePublicPort, listSettings, makeLabelForStandaloneDatabase, prisma, startTraefikTCPProxy, stopDatabaseContainer, stopTcpHttpProxy, supportedDatabaseTypesAndVersions, uniqueName, updatePasswordInDb } from '../../../../lib/common';
|
||||
import { ComposeFile, createDirectories, decrypt, defaultComposeConfiguration, encrypt, errorHandler, executeCommand, generateDatabaseConfiguration, generatePassword, getContainerUsage, getDatabaseImage, getDatabaseVersions, getFreePublicPort, listSettings, makeLabelForStandaloneDatabase, prisma, startTraefikTCPProxy, stopDatabaseContainer, stopTcpHttpProxy, supportedDatabaseTypesAndVersions, uniqueName, updatePasswordInDb } from '../../../../lib/common';
|
||||
import { day } from '../../../../lib/dayjs';
|
||||
|
||||
import type { OnlyId } from '../../../../types';
|
||||
@@ -89,7 +89,7 @@ export async function getDatabaseStatus(request: FastifyRequest<OnlyId>) {
|
||||
const { destinationDockerId, destinationDocker } = database;
|
||||
if (destinationDockerId) {
|
||||
try {
|
||||
const { stdout } = await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker inspect --format '{{json .State}}' ${id}` })
|
||||
const { stdout } = await executeCommand({ dockerId: destinationDocker.id, command: `docker inspect --format '{{json .State}}' ${id}` })
|
||||
|
||||
if (JSON.parse(stdout).Running) {
|
||||
isRunning = true;
|
||||
@@ -208,7 +208,7 @@ export async function saveDatabaseDestination(request: FastifyRequest<SaveDataba
|
||||
if (destinationDockerId) {
|
||||
if (type && version) {
|
||||
const baseImage = getDatabaseImage(type, arch);
|
||||
executeDockerCmd({ dockerId, command: `docker pull ${baseImage}:${version}` })
|
||||
executeCommand({ dockerId, command: `docker pull ${baseImage}:${version}` })
|
||||
}
|
||||
}
|
||||
return reply.code(201).send({})
|
||||
@@ -298,7 +298,7 @@ export async function startDatabase(request: FastifyRequest<OnlyId>) {
|
||||
};
|
||||
const composeFileDestination = `${workdir}/docker-compose.yaml`;
|
||||
await fs.writeFile(composeFileDestination, yaml.dump(composeFile));
|
||||
await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up -d` })
|
||||
await executeCommand({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up -d` })
|
||||
if (isPublic) await startTraefikTCPProxy(destinationDocker, id, publicPort, privatePort);
|
||||
return {};
|
||||
|
||||
@@ -347,7 +347,7 @@ export async function getDatabaseLogs(request: FastifyRequest<GetDatabaseLogs>)
|
||||
// const found = await checkContainer({ dockerId, container: id })
|
||||
// if (found) {
|
||||
const { default: ansi } = await import('strip-ansi')
|
||||
const { stdout, stderr } = await executeDockerCmd({ dockerId, command: `docker logs --since ${since} --tail 5000 --timestamps ${id}` })
|
||||
const { stdout, stderr } = await executeCommand({ dockerId, command: `docker logs --since ${since} --tail 5000 --timestamps ${id}` })
|
||||
const stripLogsStdout = stdout.toString().split('\n').map((l) => ansi(l)).filter((a) => a);
|
||||
const stripLogsStderr = stderr.toString().split('\n').map((l) => ansi(l)).filter((a) => a);
|
||||
const logs = stripLogsStderr.concat(stripLogsStdout)
|
||||
|
||||
@@ -4,7 +4,7 @@ import sshConfig from 'ssh-config'
|
||||
import fs from 'fs/promises'
|
||||
import os from 'os';
|
||||
|
||||
import { asyncExecShell, createRemoteEngineConfiguration, decrypt, errorHandler, executeDockerCmd, executeSSHCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common';
|
||||
import { createRemoteEngineConfiguration, decrypt, errorHandler, executeCommand, executeSSHCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common';
|
||||
import { checkContainer } from '../../../../lib/docker';
|
||||
|
||||
import type { OnlyId } from '../../../../types';
|
||||
@@ -79,9 +79,9 @@ export async function newDestination(request: FastifyRequest<NewDestination>, re
|
||||
let { name, network, engine, isCoolifyProxyUsed, remoteIpAddress, remoteUser, remotePort } = request.body
|
||||
if (id === 'new') {
|
||||
if (engine) {
|
||||
const { stdout } = await asyncExecShell(`DOCKER_HOST=unix:///var/run/docker.sock docker network ls --filter 'name=^${network}$' --format '{{json .}}'`);
|
||||
const { stdout } = await await executeCommand({ command: `docker network ls --filter 'name=^${network}$' --format '{{json .}}'` });
|
||||
if (stdout === '') {
|
||||
await asyncExecShell(`DOCKER_HOST=unix:///var/run/docker.sock docker network create --attachable ${network}`);
|
||||
await await executeCommand({ command: `docker network create --attachable ${network}` });
|
||||
}
|
||||
await prisma.destinationDocker.create({
|
||||
data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed }
|
||||
@@ -122,13 +122,13 @@ export async function deleteDestination(request: FastifyRequest<OnlyId>) {
|
||||
const { network, remoteVerified, engine, isCoolifyProxyUsed } = await prisma.destinationDocker.findUnique({ where: { id } });
|
||||
if (isCoolifyProxyUsed) {
|
||||
if (engine || remoteVerified) {
|
||||
const { stdout: found } = await executeDockerCmd({
|
||||
const { stdout: found } = await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker ps -a --filter network=${network} --filter name=coolify-proxy --format '{{.}}'`
|
||||
})
|
||||
if (found) {
|
||||
await executeDockerCmd({ dockerId: id, command: `docker network disconnect ${network} coolify-proxy` })
|
||||
await executeDockerCmd({ dockerId: id, command: `docker network rm ${network}` })
|
||||
await executeCommand({ dockerId: id, command: `docker network disconnect ${network} coolify-proxy` })
|
||||
await executeCommand({ dockerId: id, command: `docker network rm ${network}` })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,13 +206,13 @@ export async function verifyRemoteDockerEngineFn(id: string) {
|
||||
await createRemoteEngineConfiguration(id);
|
||||
const { remoteIpAddress, network, isCoolifyProxyUsed } = await prisma.destinationDocker.findFirst({ where: { id } })
|
||||
const host = `ssh://${remoteIpAddress}-remote`
|
||||
const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`);
|
||||
const { stdout } = await executeCommand({ command: `docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`, dockerId: id });
|
||||
if (!stdout) {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`);
|
||||
await executeCommand({ command: `docker network create --attachable ${network}`, dockerId: id });
|
||||
}
|
||||
const { stdout: coolifyNetwork } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=coolify-infra' --no-trunc --format "{{json .}}"`);
|
||||
const { stdout: coolifyNetwork } = await executeCommand({ command: `docker network ls --filter 'name=coolify-infra' --no-trunc --format "{{json .}}"`, dockerId: id });
|
||||
if (!coolifyNetwork) {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable coolify-infra`);
|
||||
await executeCommand({ command: `docker network create --attachable coolify-infra`, dockerId: id });
|
||||
}
|
||||
if (isCoolifyProxyUsed) await startTraefikProxy(id);
|
||||
try {
|
||||
|
||||
@@ -4,7 +4,6 @@ import bcrypt from "bcryptjs";
|
||||
import fs from 'fs/promises';
|
||||
import yaml from 'js-yaml';
|
||||
import {
|
||||
asyncExecShell,
|
||||
asyncSleep,
|
||||
cleanupDockerStorage,
|
||||
errorHandler,
|
||||
@@ -15,6 +14,7 @@ import {
|
||||
version,
|
||||
sentryDSN,
|
||||
executeDockerCmd,
|
||||
executeCommand,
|
||||
} from "../../../lib/common";
|
||||
import { scheduler } from "../../../lib/scheduler";
|
||||
import type { FastifyReply, FastifyRequest } from "fastify";
|
||||
@@ -38,7 +38,7 @@ export async function backup(request: FastifyRequest) {
|
||||
// dockerId: database.destinationDockerId,
|
||||
// command: `docker pull coollabsio/backup:latest`,
|
||||
// })
|
||||
std = await executeDockerCmd({
|
||||
std = await executeCommand({
|
||||
dockerId: database.destinationDockerId,
|
||||
command: `docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v coolify-local-backup:/app/backups -e CONTAINERS_TO_BACKUP="${backupData}" coollabsio/backup`
|
||||
})
|
||||
@@ -141,14 +141,10 @@ export async function update(request: FastifyRequest<Update>) {
|
||||
try {
|
||||
if (!isDev) {
|
||||
const { isAutoUpdateEnabled } = await prisma.setting.findFirst();
|
||||
await asyncExecShell(`docker pull coollabsio/coolify:${latestVersion}`);
|
||||
await asyncExecShell(`env | grep COOLIFY > .env`);
|
||||
await asyncExecShell(
|
||||
`sed -i '/COOLIFY_AUTO_UPDATE=/cCOOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env`
|
||||
);
|
||||
await asyncExecShell(
|
||||
`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"`
|
||||
);
|
||||
await executeCommand({ command: `docker pull coollabsio/coolify:${latestVersion}` });
|
||||
await executeCommand({ command: `env | grep COOLIFY > .env` });
|
||||
await executeCommand({ command: `sed -i '/COOLIFY_AUTO_UPDATE=/cCOOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env` });
|
||||
await executeCommand({ 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"` });
|
||||
return {};
|
||||
} else {
|
||||
await asyncSleep(2000);
|
||||
@@ -177,7 +173,7 @@ export async function restartCoolify(request: FastifyRequest<any>) {
|
||||
const teamId = request.user.teamId;
|
||||
if (teamId === "0") {
|
||||
if (!isDev) {
|
||||
asyncExecShell(`docker restart coolify`);
|
||||
await executeCommand({ command: `docker restart coolify` });
|
||||
return {};
|
||||
} else {
|
||||
return {};
|
||||
|
||||
@@ -53,9 +53,9 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
|
||||
onRequest: [fastify.authenticate]
|
||||
}, async (request) => await cleanupManually(request));
|
||||
|
||||
fastify.get('/internal/backup/:backupData', {
|
||||
onRequest: [fastify.authenticate]
|
||||
}, async (request) => await backup(request));
|
||||
// fastify.get('/internal/backup/:backupData', {
|
||||
// onRequest: [fastify.authenticate]
|
||||
// }, async (request) => await backup(request));
|
||||
};
|
||||
|
||||
export default root;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { FastifyRequest } from 'fastify';
|
||||
import { errorHandler, executeDockerCmd, prisma, createRemoteEngineConfiguration, executeSSHCmd } from '../../../../lib/common';
|
||||
import { errorHandler, prisma, executeSSHCmd } from '../../../../lib/common';
|
||||
import os from 'node:os';
|
||||
import osu from 'node-os-utils';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import yaml from 'js-yaml';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import cuid from 'cuid';
|
||||
|
||||
import { prisma, uniqueName, asyncExecShell, getServiceFromDB, getContainerUsage, isDomainConfigured, fixType, decrypt, encrypt, ComposeFile, getFreePublicPort, getDomain, errorHandler, generatePassword, isDev, stopTcpHttpProxy, executeDockerCmd, checkDomainsIsValidInDNS, checkExposedPort, listSettings, generateToken } from '../../../../lib/common';
|
||||
import { prisma, uniqueName, getServiceFromDB, getContainerUsage, isDomainConfigured, fixType, decrypt, encrypt, ComposeFile, getFreePublicPort, getDomain, errorHandler, generatePassword, isDev, stopTcpHttpProxy, checkDomainsIsValidInDNS, checkExposedPort, listSettings, generateToken, executeCommand } from '../../../../lib/common';
|
||||
import { day } from '../../../../lib/dayjs';
|
||||
import { checkContainer, } from '../../../../lib/docker';
|
||||
import { removeService } from '../../../../lib/services/common';
|
||||
@@ -48,14 +48,19 @@ export async function cleanupUnconfiguredServices(request: FastifyRequest) {
|
||||
for (const service of services) {
|
||||
if (!service.fqdn) {
|
||||
if (service.destinationDockerId) {
|
||||
await executeDockerCmd({
|
||||
const { stdout: containers } = await executeCommand({
|
||||
dockerId: service.destinationDockerId,
|
||||
command: `docker ps -a --filter 'label=com.docker.compose.project=${service.id}' --format {{.ID}}|xargs -r -n 1 docker stop -t 0`
|
||||
})
|
||||
await executeDockerCmd({
|
||||
dockerId: service.destinationDockerId,
|
||||
command: `docker ps -a --filter 'label=com.docker.compose.project=${service.id}' --format {{.ID}}|xargs -r -n 1 docker rm --force`
|
||||
command: `docker ps -a --filter 'label=com.docker.compose.project=${service.id}' --format {{.ID}}`
|
||||
})
|
||||
if (containers) {
|
||||
const containerArray = containers.split('\n');
|
||||
if (containerArray.length > 0) {
|
||||
for (const container of containerArray) {
|
||||
await executeCommand({ dockerId: service.destinationDockerId, command: `docker stop -t 0 ${container}` })
|
||||
await executeCommand({ dockerId: service.destinationDockerId, command: `docker rm --force ${container}` })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
await removeService({ id: service.id });
|
||||
}
|
||||
@@ -73,7 +78,7 @@ export async function getServiceStatus(request: FastifyRequest<OnlyId>) {
|
||||
const { destinationDockerId, settings } = service;
|
||||
let payload = {}
|
||||
if (destinationDockerId) {
|
||||
const { stdout: containers } = await executeDockerCmd({
|
||||
const { stdout: containers } = await executeCommand({
|
||||
dockerId: service.destinationDocker.id,
|
||||
command:
|
||||
`docker ps -a --filter "label=com.docker.compose.project=${id}" --format '{{json .}}'`
|
||||
@@ -443,7 +448,7 @@ export async function getServiceLogs(request: FastifyRequest<GetServiceLogs>) {
|
||||
if (destinationDockerId) {
|
||||
try {
|
||||
const { default: ansi } = await import('strip-ansi')
|
||||
const { stdout, stderr } = await executeDockerCmd({ dockerId, command: `docker logs --since ${since} --tail 5000 --timestamps ${containerId}` })
|
||||
const { stdout, stderr } = await executeCommand({ dockerId, command: `docker logs --since ${since} --tail 5000 --timestamps ${containerId}` })
|
||||
const stripLogsStdout = stdout.toString().split('\n').map((l) => ansi(l)).filter((a) => a);
|
||||
const stripLogsStderr = stderr.toString().split('\n').map((l) => ansi(l)).filter((a) => a);
|
||||
const logs = stripLogsStderr.concat(stripLogsStdout)
|
||||
@@ -749,7 +754,7 @@ export async function activatePlausibleUsers(request: FastifyRequest<OnlyId>, re
|
||||
if (destinationDockerId) {
|
||||
const databaseUrl = serviceSecret.find((secret) => secret.name === 'DATABASE_URL');
|
||||
if (databaseUrl) {
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDocker.id,
|
||||
command: `docker exec ${id}-postgresql psql -H ${databaseUrl.value} -c "UPDATE users SET email_verified = true;"`
|
||||
})
|
||||
@@ -770,9 +775,10 @@ export async function cleanupPlausibleLogs(request: FastifyRequest<OnlyId>, repl
|
||||
destinationDocker,
|
||||
} = await getServiceFromDB({ id, teamId });
|
||||
if (destinationDockerId) {
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDocker.id,
|
||||
command: `docker exec ${id}-clickhouse /usr/bin/clickhouse-client -q \\"SELECT name FROM system.tables WHERE name LIKE '%log%';\\"| xargs -I{} /usr/bin/clickhouse-client -q \"TRUNCATE TABLE system.{};\"`
|
||||
command: `docker exec ${id}-clickhouse /usr/bin/clickhouse-client -q \\"SELECT name FROM system.tables WHERE name LIKE '%log%';\\"| xargs -I{} /usr/bin/clickhouse-client -q \"TRUNCATE TABLE system.{};\"`,
|
||||
shell: true
|
||||
})
|
||||
return await reply.code(201).send()
|
||||
}
|
||||
@@ -812,36 +818,42 @@ export async function activateWordpressFtp(request: FastifyRequest<ActivateWordp
|
||||
if (user) ftpUser = user;
|
||||
if (savedPassword) ftpPassword = decrypt(savedPassword);
|
||||
|
||||
const { stdout: password } = await asyncExecShell(
|
||||
`echo ${ftpPassword} | openssl passwd -1 -stdin`
|
||||
// TODO: rewrite these to usable without shell
|
||||
const { stdout: password } = await executeCommand({
|
||||
command:
|
||||
`echo ${ftpPassword} | openssl passwd -1 -stdin`,
|
||||
shell: true
|
||||
}
|
||||
);
|
||||
if (destinationDockerId) {
|
||||
try {
|
||||
await fs.stat(hostkeyDir);
|
||||
} catch (error) {
|
||||
await asyncExecShell(`mkdir -p ${hostkeyDir}`);
|
||||
await executeCommand({ command: `mkdir -p ${hostkeyDir}` });
|
||||
}
|
||||
if (!ftpHostKey) {
|
||||
await asyncExecShell(
|
||||
`ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" -q -f ${hostkeyDir}/${id}.ed25519`
|
||||
await executeCommand({
|
||||
command:
|
||||
`ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" -q -f ${hostkeyDir}/${id}.ed25519`
|
||||
}
|
||||
);
|
||||
const { stdout: ftpHostKey } = await asyncExecShell(`cat ${hostkeyDir}/${id}.ed25519`);
|
||||
const { stdout: ftpHostKey } = await executeCommand({ command: `cat ${hostkeyDir}/${id}.ed25519` });
|
||||
await prisma.wordpress.update({
|
||||
where: { serviceId: id },
|
||||
data: { ftpHostKey: encrypt(ftpHostKey) }
|
||||
});
|
||||
} else {
|
||||
await asyncExecShell(`echo "${decrypt(ftpHostKey)}" > ${hostkeyDir}/${id}.ed25519`);
|
||||
await executeCommand({ command: `echo "${decrypt(ftpHostKey)}" > ${hostkeyDir}/${id}.ed25519`, shell: true });
|
||||
}
|
||||
if (!ftpHostKeyPrivate) {
|
||||
await asyncExecShell(`ssh-keygen -t rsa -b 4096 -N "" -f ${hostkeyDir}/${id}.rsa`);
|
||||
const { stdout: ftpHostKeyPrivate } = await asyncExecShell(`cat ${hostkeyDir}/${id}.rsa`);
|
||||
await executeCommand({ command: `ssh-keygen -t rsa -b 4096 -N "" -f ${hostkeyDir}/${id}.rsa` });
|
||||
const { stdout: ftpHostKeyPrivate } = await executeCommand({ command: `cat ${hostkeyDir}/${id}.rsa` });
|
||||
await prisma.wordpress.update({
|
||||
where: { serviceId: id },
|
||||
data: { ftpHostKeyPrivate: encrypt(ftpHostKeyPrivate) }
|
||||
});
|
||||
} else {
|
||||
await asyncExecShell(`echo "${decrypt(ftpHostKeyPrivate)}" > ${hostkeyDir}/${id}.rsa`);
|
||||
await executeCommand({ command: `echo "${decrypt(ftpHostKeyPrivate)}" > ${hostkeyDir}/${id}.rsa`, shell: true });
|
||||
}
|
||||
|
||||
await prisma.wordpress.update({
|
||||
@@ -856,9 +868,10 @@ export async function activateWordpressFtp(request: FastifyRequest<ActivateWordp
|
||||
try {
|
||||
const { found: isRunning } = await checkContainer({ dockerId: destinationDocker.id, container: `${id}-ftp` });
|
||||
if (isRunning) {
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDocker.id,
|
||||
command: `docker stop -t 0 ${id}-ftp && docker rm ${id}-ftp`
|
||||
command: `docker stop -t 0 ${id}-ftp && docker rm ${id}-ftp`,
|
||||
shell: true
|
||||
})
|
||||
}
|
||||
} catch (error) { }
|
||||
@@ -902,9 +915,9 @@ export async function activateWordpressFtp(request: FastifyRequest<ActivateWordp
|
||||
`${hostkeyDir}/${id}.sh`,
|
||||
`#!/bin/bash\nchmod 600 /etc/ssh/ssh_host_ed25519_key /etc/ssh/ssh_host_rsa_key\nuserdel -f xfs\nchown -R 33:33 /home/${ftpUser}/wordpress/`
|
||||
);
|
||||
await asyncExecShell(`chmod +x ${hostkeyDir}/${id}.sh`);
|
||||
await executeCommand({ command: `chmod +x ${hostkeyDir}/${id}.sh` });
|
||||
await fs.writeFile(`${hostkeyDir}/${id}-docker-compose.yml`, yaml.dump(compose));
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDocker.id,
|
||||
command: `docker compose -f ${hostkeyDir}/${id}-docker-compose.yml up -d`
|
||||
})
|
||||
@@ -921,9 +934,10 @@ export async function activateWordpressFtp(request: FastifyRequest<ActivateWordp
|
||||
data: { ftpPublicPort: null }
|
||||
});
|
||||
try {
|
||||
await executeDockerCmd({
|
||||
await executeCommand({
|
||||
dockerId: destinationDocker.id,
|
||||
command: `docker stop -t 0 ${id}-ftp && docker rm ${id}-ftp`
|
||||
command: `docker stop -t 0 ${id}-ftp && docker rm ${id}-ftp`,
|
||||
shell: true
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
@@ -937,8 +951,10 @@ export async function activateWordpressFtp(request: FastifyRequest<ActivateWordp
|
||||
return errorHandler({ status, message })
|
||||
} finally {
|
||||
try {
|
||||
await asyncExecShell(
|
||||
`rm -fr ${hostkeyDir}/${id}-docker-compose.yml ${hostkeyDir}/${id}.ed25519 ${hostkeyDir}/${id}.ed25519.pub ${hostkeyDir}/${id}.rsa ${hostkeyDir}/${id}.rsa.pub ${hostkeyDir}/${id}.sh`
|
||||
await executeCommand({
|
||||
command:
|
||||
`rm -fr ${hostkeyDir}/${id}-docker-compose.yml ${hostkeyDir}/${id}.ed25519 ${hostkeyDir}/${id}.ed25519.pub ${hostkeyDir}/${id}.rsa ${hostkeyDir}/${id}.rsa.pub ${hostkeyDir}/${id}.sh`
|
||||
}
|
||||
);
|
||||
} catch (error) { }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { promises as dns } from 'dns';
|
||||
import { X509Certificate } from 'node:crypto';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import type { FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { asyncExecShell, checkDomainsIsValidInDNS, decrypt, encrypt, errorHandler, getDomain, isDev, isDNSValid, isDomainConfigured, listSettings, prisma, sentryDSN, version } from '../../../../lib/common';
|
||||
import { checkDomainsIsValidInDNS, decrypt, encrypt, errorHandler, executeCommand, getDomain, isDev, isDNSValid, isDomainConfigured, listSettings, prisma, sentryDSN, version } from '../../../../lib/common';
|
||||
import { AddDefaultRegistry, CheckDNS, CheckDomain, DeleteDomain, OnlyIdInBody, SaveSettings, SaveSSHKey, SetDefaultRegistry } from './types';
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ export async function deleteCertificates(request: FastifyRequest<OnlyIdInBody>,
|
||||
try {
|
||||
const teamId = request.user.teamId;
|
||||
const { id } = request.body;
|
||||
await asyncExecShell(`docker exec coolify-proxy sh -c 'rm -f /etc/traefik/acme/custom/${id}-key.pem /etc/traefik/acme/custom/${id}-cert.pem'`)
|
||||
await executeCommand({ command: `docker exec coolify-proxy sh -c 'rm -f /etc/traefik/acme/custom/${id}-key.pem /etc/traefik/acme/custom/${id}-cert.pem'`, shell: true })
|
||||
await prisma.certificate.deleteMany({ where: { id, teamId } })
|
||||
return reply.code(201).send()
|
||||
} catch ({ status, message }) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FastifyRequest } from "fastify";
|
||||
import { errorHandler, getDomain, isDev, prisma, executeDockerCmd, fixType } from "../../../lib/common";
|
||||
import { errorHandler, getDomain, isDev, prisma, executeCommand } from "../../../lib/common";
|
||||
import { getTemplates } from "../../../lib/services";
|
||||
import { OnlyId } from "../../../types";
|
||||
|
||||
@@ -263,10 +263,12 @@ export async function proxyConfiguration(request: FastifyRequest<OnlyId>, remote
|
||||
const runningContainers = {}
|
||||
applications.forEach((app) => dockerIds.add(app.destinationDocker.id));
|
||||
for (const dockerId of dockerIds) {
|
||||
const { stdout: container } = await executeDockerCmd({ dockerId, command: `docker container ls --filter 'label=coolify.managed=true' --format '{{ .Names}}'` })
|
||||
const containersArray = container.trim().split('\n');
|
||||
if (containersArray.length > 0) {
|
||||
runningContainers[dockerId] = containersArray
|
||||
const { stdout: container } = await executeCommand({ dockerId, command: `docker container ls --filter 'label=coolify.managed=true' --format '{{ .Names}}'` })
|
||||
if (container) {
|
||||
const containersArray = container.trim().split('\n');
|
||||
if (containersArray.length > 0) {
|
||||
runningContainers[dockerId] = containersArray
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const application of applications) {
|
||||
@@ -332,7 +334,7 @@ export async function proxyConfiguration(request: FastifyRequest<OnlyId>, remote
|
||||
traefik.http.routers = { ...traefik.http.routers, ...generateRouters(serviceId, domain, nakedDomain, pathPrefix, isHttps, isWWW, dualCerts, isCustomSSL) }
|
||||
traefik.http.services = { ...traefik.http.services, ...generateServices(serviceId, id, port) }
|
||||
if (previews) {
|
||||
const { stdout } = await executeDockerCmd({ dockerId, command: `docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"` })
|
||||
const { stdout } = await executeCommand({ dockerId, command: `docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"` })
|
||||
const containers = stdout
|
||||
.trim()
|
||||
.split('\n')
|
||||
@@ -359,7 +361,7 @@ export async function proxyConfiguration(request: FastifyRequest<OnlyId>, remote
|
||||
const runningContainers = {}
|
||||
services.forEach((app) => dockerIds.add(app.destinationDocker.id));
|
||||
for (const dockerId of dockerIds) {
|
||||
const { stdout: container } = await executeDockerCmd({ dockerId, command: `docker container ls --filter 'label=coolify.managed=true' --format '{{ .Names}}'` })
|
||||
const { stdout: container } = await executeCommand({ dockerId, command: `docker container ls --filter 'label=coolify.managed=true' --format '{{ .Names}}'` })
|
||||
const containersArray = container.trim().split('\n');
|
||||
if (containersArray.length > 0) {
|
||||
runningContainers[dockerId] = containersArray
|
||||
|
||||
Reference in New Issue
Block a user