From f340ca9d0587b0921983f3d2b6d9f14dc8c8b751 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Feb 2022 16:06:44 +0100 Subject: [PATCH] WIP --- src/lib/haproxy/index.ts | 486 ++++++++++++------ src/lib/importers/github.ts | 2 +- src/lib/letsencrypt.ts | 7 +- src/lib/queues/builder.ts | 49 +- src/lib/queues/index.ts | 4 +- src/lib/queues/proxy.ts | 127 ++--- src/routes/applications/[id]/stop.json.ts | 2 +- src/routes/services/[id]/minio/start.json.ts | 16 +- src/routes/services/[id]/minio/stop.json.ts | 2 +- src/routes/services/[id]/nocodb/start.json.ts | 14 +- .../[id]/plausibleanalytics/start.json.ts | 14 +- .../services/[id]/vaultwarden/start.json.ts | 14 +- .../services/[id]/vscodeserver/start.json.ts | 14 +- .../services/[id]/wordpress/start.json.ts | 14 +- 14 files changed, 445 insertions(+), 320 deletions(-) diff --git a/src/lib/haproxy/index.ts b/src/lib/haproxy/index.ts index 47c9c85e1..90f81e34d 100644 --- a/src/lib/haproxy/index.ts +++ b/src/lib/haproxy/index.ts @@ -2,6 +2,7 @@ import { dev } from '$app/env'; import { asyncExecShell, getDomain, getEngine } from '$lib/common'; import got from 'got'; import * as db from '$lib/database'; +import { letsEncrypt } from '$lib/letsencrypt'; const url = dev ? 'http://localhost:5555' : 'http://coolify-haproxy:5555'; @@ -71,7 +72,9 @@ export async function removeProxyConfiguration(fqdn) { export async function forceSSLOffApplication(domain) { const haproxy = await haproxyInstance(); await checkHAProxy(haproxy); + let transactionId; + try { const rules: any = await haproxy .get(`v2/services/haproxy/configuration/http_request_rules`, { @@ -87,7 +90,6 @@ export async function forceSSLOffApplication(domain) { ); if (rule) { transactionId = await getNextTransactionId(); - await haproxy .delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, { searchParams: { @@ -188,168 +190,325 @@ export async function reloadHaproxy(engine) { return await asyncExecShell(`DOCKER_HOST=${host} docker exec coolify-haproxy kill -HUP 1`); } export async function checkProxyConfigurations() { + const timeout = 10; const haproxy = await haproxyInstance(); await checkHAProxy(haproxy); try { const stats: any = await haproxy.get(`v2/services/haproxy/stats/native`).json(); + let transactionId = null; for (const stat of stats[0].stats) { - if (stat.stats.status === 'DOWN' && stat.type === 'server') { - const { - name, - backend_name: backendName, - stats: { lastchg } - } = stat; - - const { fqdn } = await db.listSettings(); - if (fqdn) { - const domain = getDomain(fqdn); - if (backendName === domain) { - return; - } - } - const application = await db.prisma.application.findUnique({ - where: { id: name }, - include: { destinationDocker: true } - }); - const service = await db.prisma.service.findUnique({ - where: { id: name }, - include: { destinationDocker: true } - }); - if (!application && !service) { - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${backendName}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - return await completeTransaction(transactionId); - } - if (application?.destinationDocker?.engine && lastchg > 120) { - const found = await checkContainer(application.destinationDocker.engine, name); - if (!found) { - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${backendName}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - return await completeTransaction(transactionId); - } - } - - if (service?.destinationDocker?.engine && lastchg > 120) { - const found = await checkContainer(service.destinationDocker.engine, name); - if (!found) { - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${backendName}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - return await completeTransaction(transactionId); - } - } - - if (lastchg > 120) { - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${backendName}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - await completeTransaction(transactionId); - } + if (stat.stats.status !== 'no check' && stat.type === 'server') { + if (!transactionId) await getNextTransactionId(); + const { backend_name: backendName } = stat; + await haproxy + .delete(`v2/services/haproxy/configuration/backends/${backendName}`, { + searchParams: { + transaction_id: transactionId + } + }) + .json(); } } + if (transactionId) await completeTransaction(transactionId); } catch (error) { - console.log(error); + console.log(error.response.body); } } -export async function configureProxyForApplication({ domain, imageId, applicationId, port }) { +export async function configureHAProxy(fqdn, id, port, containerRunning, engine) { + const domain = getDomain(fqdn); + const isHttps = fqdn.startsWith('https://'); + const isWWW = fqdn.includes('www.'); + const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`; + const contTest = `{ req.hdr(host) -i ${isWWW ? domain.replace('www.', '') : `www.${domain}`} }`; + + console.log({ application: true, fqdn, domain, id, port, containerRunning, isHttps, isWWW }); + const haproxy = await haproxyInstance(); await checkHAProxy(haproxy); - let serverConfigured = false; - let backendAvailable: any = null; + let transactionId; - try { - backendAvailable = await haproxy - .get(`v2/services/haproxy/configuration/backends/${domain}`) - .json(); - const server: any = await haproxy - .get(`v2/services/haproxy/configuration/servers/${imageId}`, { - searchParams: { - backend: domain + if (!containerRunning) { + try { + await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json(); + transactionId = await getNextTransactionId(); + await haproxy + .delete(`v2/services/haproxy/configuration/backends/${domain}`, { + searchParams: { + transaction_id: transactionId + } + }) + .json(); + } catch (error) { + // + } + try { + if (!transactionId) await getNextTransactionId(); + let rules: any; + // Force SSL off + rules = await haproxy + .get(`v2/services/haproxy/configuration/http_request_rules`, { + searchParams: { + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); + if (rules.data.length > 0) { + const rule = rules.data.find((rule) => + rule.cond_test.includes(`{ hdr(host) -i ${domain} } !{ ssl_fc }`) + ); + if (rule) { + await haproxy + .delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, { + searchParams: { + transaction_id: transactionId, + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); } - }) - .json(); + } - if (backendAvailable && server) { - // Very sophisticated way to check if the server is already configured in proxy - if (backendAvailable.data.forwardfor.enabled === 'enabled') { - if (backendAvailable.data.name === domain) { - if (server.data.check === 'enabled') { - if (server.data.address === imageId) { - if (server.data.port === port) { - serverConfigured = true; + // Force WWW off + rules = await haproxy + .get(`v2/services/haproxy/configuration/http_request_rules`, { + searchParams: { + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); + if (rules.data.length > 0) { + const rule = rules.data.find((rule) => rule.redir_value.includes(redirectValue)); + if (rule) { + await haproxy + .delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, { + searchParams: { + transaction_id: transactionId, + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); + } + } + } catch (error) { + console.log(error); + // + } finally { + try { + if (transactionId) { + console.log(transactionId); + await haproxy.put(`v2/services/haproxy/transactions/${transactionId}`); + } + } catch (error) { + if (error?.response?.body) { + const json = JSON.parse(error.response.body); + if (json.code === 400 && json.message.includes('could not resolve address')) { + await stopCoolifyProxy(engine); + await startCoolifyProxy(engine); + } + } + } + } + return; + } else { + console.log('adding ', domain); + let serverConfigured = false; + let backendAvailable: any = null; + try { + backendAvailable = await haproxy + .get(`v2/services/haproxy/configuration/backends/${domain}`) + .json(); + const server: any = await haproxy + .get(`v2/services/haproxy/configuration/servers/${id}`, { + searchParams: { + backend: domain + } + }) + .json(); + + if (backendAvailable && server) { + // Very sophisticated way to check if the server is already configured in proxy + if (backendAvailable.data.forwardfor.enabled === 'enabled') { + if (backendAvailable.data.name === domain) { + if (server.data.check === 'disabled') { + if (server.data.address === id) { + if (server.data.port === port) { + serverConfigured = true; + } } } } } } + } catch (error) { + // } - } catch (error) { - //console.log('error getting backend or server', error?.response?.body); - // - } - - if (serverConfigured) return; - const transactionId = await getNextTransactionId(); - if (backendAvailable) { - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${domain}`, { + if (serverConfigured) { + console.log('server configured'); + return; + } + if (!transactionId) transactionId = await getNextTransactionId(); + if (backendAvailable) { + await haproxy + .delete(`v2/services/haproxy/configuration/backends/${domain}`, { + searchParams: { + transaction_id: transactionId + } + }) + .json(); + } + try { + console.log('adding ', domain); + await haproxy.post('v2/services/haproxy/configuration/backends', { searchParams: { transaction_id: transactionId + }, + json: { + 'init-addr': 'last,libc,none', + forwardfor: { enabled: 'enabled' }, + name: domain } - }) - .json(); - } - try { - await haproxy.post('v2/services/haproxy/configuration/backends', { - searchParams: { - transaction_id: transactionId - }, - json: { - 'init-addr': 'last,libc,none', - forwardfor: { enabled: 'enabled' }, - name: domain - } - }); + }); - await haproxy.post('v2/services/haproxy/configuration/servers', { - searchParams: { - transaction_id: transactionId, - backend: domain - }, - json: { - address: imageId, - check: 'enabled', - name: imageId, - port: port + await haproxy.post('v2/services/haproxy/configuration/servers', { + searchParams: { + transaction_id: transactionId, + backend: domain + }, + json: { + address: id, + check: 'disabled', + name: id, + port: port + } + }); + + let rules: any; + + // Force SSL off + rules = await haproxy + .get(`v2/services/haproxy/configuration/http_request_rules`, { + searchParams: { + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); + if (rules.data.length > 0) { + const rule = rules.data.find((rule) => + rule.cond_test.includes(`{ hdr(host) -i ${domain} } !{ ssl_fc }`) + ); + if (rule) { + await haproxy + .delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, { + searchParams: { + transaction_id: transactionId, + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); + } } - }); - } catch (error) { - throw error?.response?.body || error; - } finally { - await completeTransaction(transactionId); + + // Generate SSL && force SSL on + + if (isHttps) { + await letsEncrypt(domain, id, false); + rules = await haproxy + .get(`v2/services/haproxy/configuration/http_request_rules`, { + searchParams: { + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); + let nextRule = 0; + if (rules.data.length > 0) { + const rule = rules.data.find((rule) => + rule.cond_test.includes(`{ hdr(host) -i ${domain} } !{ ssl_fc }`) + ); + if (rule) return; + nextRule = rules.data[rules.data.length - 1].index + 1; + } + + await haproxy + .post(`v2/services/haproxy/configuration/http_request_rules`, { + searchParams: { + transaction_id: transactionId, + parent_name: 'http', + parent_type: 'frontend' + }, + json: { + index: nextRule, + cond: 'if', + cond_test: `{ hdr(host) -i ${domain} } !{ ssl_fc }`, + type: 'redirect', + redir_type: 'scheme', + redir_value: 'https', + redir_code: dev ? 302 : 301 + } + }) + .json(); + } + + // WWW redirect on + rules = await haproxy + .get(`v2/services/haproxy/configuration/http_request_rules`, { + searchParams: { + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); + let nextRule = 0; + if (rules.data.length > 0) { + const rule = rules.data.find((rule) => rule.redir_value.includes(redirectValue)); + if (rule) return; + nextRule = rules.data[rules.data.length - 1].index + 1; + } + + await haproxy + .post(`v2/services/haproxy/configuration/http_request_rules`, { + searchParams: { + transaction_id: transactionId, + parent_name: 'http', + parent_type: 'frontend' + }, + json: { + index: nextRule, + cond: 'if', + cond_test: contTest, + type: 'redirect', + redir_type: 'location', + redir_value: redirectValue, + redir_code: dev ? 302 : 301 + } + }) + .json(); + } catch (error) { + console.log(error); + throw error?.response?.body || error; + } finally { + try { + if (transactionId) { + console.log('Committing transaction'); + await haproxy.put(`v2/services/haproxy/transactions/${transactionId}`); + } + } catch (error) { + if (error?.response?.body) { + const json = JSON.parse(error.response.body); + if (json.code === 400 && json.message.includes('could not resolve address')) { + await stopCoolifyProxy(engine); + await startCoolifyProxy(engine); + } + } + } + } } } @@ -444,7 +603,7 @@ export async function configureCoolifyProxyOn(fqdn) { }, json: { address: dev ? 'host.docker.internal' : 'coolify', - check: 'enabled', + check: 'enable', fall: 10, name: 'coolify', port: 3000 @@ -587,6 +746,7 @@ export async function configureNetworkCoolifyProxy(engine) { } export async function configureSimpleServiceProxyOn({ id, domain, port }) { + console.log({ service: true, id, domain, port }); const haproxy = await haproxyInstance(); await checkHAProxy(haproxy); let serverConfigured = false; @@ -637,7 +797,7 @@ export async function configureSimpleServiceProxyOn({ id, domain, port }) { }, json: { address: id, - check: 'enabled', + check: 'enable', name: id, port: port } @@ -676,29 +836,37 @@ export async function removeWwwRedirection(fqdn) { const haproxy = await haproxyInstance(); await checkHAProxy(); - const rules: any = await haproxy - .get(`v2/services/haproxy/configuration/http_request_rules`, { - searchParams: { - parent_name: 'http', - parent_type: 'frontend' + + let transactionId; + + try { + const rules: any = await haproxy + .get(`v2/services/haproxy/configuration/http_request_rules`, { + searchParams: { + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); + if (rules.data.length > 0) { + const rule = rules.data.find((rule) => rule.redir_value.includes(redirectValue)); + if (rule) { + transactionId = await getNextTransactionId(); + await haproxy + .delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, { + searchParams: { + transaction_id: transactionId, + parent_name: 'http', + parent_type: 'frontend' + } + }) + .json(); } - }) - .json(); - if (rules.data.length > 0) { - const rule = rules.data.find((rule) => rule.redir_value.includes(redirectValue)); - if (rule) { - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, { - searchParams: { - transaction_id: transactionId, - parent_name: 'http', - parent_type: 'frontend' - } - }) - .json(); - await completeTransaction(transactionId); } + } catch (error) { + console.log(error); + } finally { + if (transactionId) await completeTransaction(transactionId); } } export async function setWwwRedirection(fqdn) { diff --git a/src/lib/importers/github.ts b/src/lib/importers/github.ts index 418fe596a..608b6bd36 100644 --- a/src/lib/importers/github.ts +++ b/src/lib/importers/github.ts @@ -14,7 +14,7 @@ export default async function ({ buildId }): Promise { try { - saveBuildLog({ line: 'GitHub importer started', buildId, applicationId }); + saveBuildLog({ line: 'GitHub importer started.', buildId, applicationId }); const { privateKey, appId, installationId } = await db.getUniqueGithubApp({ githubAppId }); const githubPrivateKey = privateKey.replace(/\\n/g, '\n').replace(/"/g, ''); diff --git a/src/lib/letsencrypt.ts b/src/lib/letsencrypt.ts index d70de1812..c062287ea 100644 --- a/src/lib/letsencrypt.ts +++ b/src/lib/letsencrypt.ts @@ -5,7 +5,7 @@ import * as db from '$lib/database'; import cuid from 'cuid'; import getPort, { portNumbers } from 'get-port'; -export async function letsEncrypt({ domain, isCoolify = false, id = null }) { +export async function letsEncrypt(domain, id = null, isCoolify = false) { try { const data = await db.prisma.setting.findFirst(); const { minPort, maxPort } = data; @@ -47,7 +47,6 @@ export async function letsEncrypt({ domain, isCoolify = false, id = null }) { } } } - await forceSSLOffApplication(domain); if (dualCerts) { await asyncExecShell( `DOCKER_HOST=${host} docker run --rm --name certbot-${randomCuid} -p 9080:${randomPort} -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs certonly --standalone --preferred-challenges http --http-01-address 0.0.0.0 --http-01-port ${randomPort} -d ${nakedDomain} -d ${wwwDomain} --expand --agree-tos --non-interactive --register-unsafely-without-email ${ @@ -71,9 +70,5 @@ export async function letsEncrypt({ domain, isCoolify = false, id = null }) { if (error.code !== 0) { throw error; } - } finally { - if (!isCoolify) { - await forceSSLOnApplication(domain); - } } } diff --git a/src/lib/queues/builder.ts b/src/lib/queues/builder.ts index 4c1ad631e..0de934bef 100644 --- a/src/lib/queues/builder.ts +++ b/src/lib/queues/builder.ts @@ -4,12 +4,6 @@ import * as buildpacks from '../buildPacks'; import * as importers from '../importers'; import { dockerInstance } from '../docker'; import { asyncExecShell, createDirectories, getDomain, getEngine, saveBuildLog } from '../common'; -import { - checkProxyConfigurations, - configureProxyForApplication, - reloadHaproxy, - setWwwRedirection -} from '../haproxy'; import * as db from '$lib/database'; import { decrypt } from '$lib/crypto'; import { sentry } from '$lib/common'; @@ -261,26 +255,27 @@ export default async function (job) { sentry.captureException(error); throw new Error(error); } - try { - if (destinationDockerId && destinationDocker.isCoolifyProxyUsed) { - saveBuildLog({ line: 'Proxy configuration started!', buildId, applicationId }); - await checkProxyConfigurations(); - await configureProxyForApplication({ domain, imageId, applicationId, port }); - if (isHttps) await letsEncrypt({ domain, id: applicationId }); - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); - saveBuildLog({ line: 'Proxy configuration successful!', buildId, applicationId }); - } else { - saveBuildLog({ - line: 'Coolify Proxy is not configured for this destination. Nothing else to do.', - buildId, - applicationId - }); - } - } catch (error) { - saveBuildLog({ line: error.stdout || error, buildId, applicationId }); - sentry.captureException(error); - throw new Error(error); - } + saveBuildLog({ line: 'Proxy will be configured shortly.', buildId, applicationId }); + // try { + // if (destinationDockerId && destinationDocker.isCoolifyProxyUsed) { + // saveBuildLog({ line: 'Proxy configuration started!', buildId, applicationId }); + // await checkProxyConfigurations(); + // await configureProxyForApplication(domain, imageId, port); + // if (isHttps) await letsEncrypt({ domain, id: applicationId }); + // await setWwwRedirection(fqdn); + // await reloadHaproxy(destinationDocker.engine); + // saveBuildLog({ line: 'Proxy configuration successful!', buildId, applicationId }); + // } else { + // saveBuildLog({ + // line: 'Coolify Proxy is not configured for this destination. Nothing else to do.', + // buildId, + // applicationId + // }); + // } + // } catch (error) { + // saveBuildLog({ line: error.stdout || error, buildId, applicationId }); + // sentry.captureException(error); + // throw new Error(error); + // } } } diff --git a/src/lib/queues/index.ts b/src/lib/queues/index.ts index 45c9c8a52..28a080ed3 100644 --- a/src/lib/queues/index.ts +++ b/src/lib/queues/index.ts @@ -87,8 +87,8 @@ const cron = async () => { await queue.proxy.add('proxy', {}, { repeat: { every: 10000 } }); // await queue.ssl.add('ssl', {}, { repeat: { every: 10000 } }); - await queue.cleanup.add('cleanup', {}, { repeat: { every: 600000 } }); - await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } }); + // await queue.cleanup.add('cleanup', {}, { repeat: { every: 600000 } }); + // await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } }); const events = { proxy: new QueueEvents('proxy', { ...connectionOptions }), diff --git a/src/lib/queues/proxy.ts b/src/lib/queues/proxy.ts index 074ac55ab..cb6aaf2cc 100644 --- a/src/lib/queues/proxy.ts +++ b/src/lib/queues/proxy.ts @@ -1,20 +1,15 @@ +import * as db from '$lib/database'; import { getDomain } from '$lib/common'; -import { getApplicationById, prisma, supportedServiceTypesAndVersions } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; import { checkContainer, checkProxyConfigurations, configureCoolifyProxyOn, - configureProxyForApplication, - configureSimpleServiceProxyOn, + configureHAProxy, forceSSLOnApplication, - reloadHaproxy, setWwwRedirection, startCoolifyProxy, startHttpProxy } from '$lib/haproxy'; -import * as db from '$lib/database'; -// import { generateRemoteEngine } from '$lib/components/common'; export default async function () { try { @@ -23,83 +18,55 @@ export default async function () { console.log(error); } try { - // Check destination containers and configure proxy if needed - const destinationDockers = await prisma.destinationDocker.findMany({}); - for (const destination of destinationDockers) { - if (destination.isCoolifyProxyUsed) { - // if (destination.remoteEngine) { - // const engine = generateRemoteEngine(destination); - // } - const docker = dockerInstance({ destinationDocker: destination }); - const containers = await docker.engine.listContainers(); - const configurations = containers.filter( - (container) => container.Labels['coolify.managed'] - ); - for (const configuration of configurations) { - if (configuration.Labels['coolify.configuration']) { - const parsedConfiguration = JSON.parse( - Buffer.from(configuration.Labels['coolify.configuration'], 'base64').toString() - ); - if ( - parsedConfiguration && - configuration.Labels['coolify.type'] === 'standalone-application' - ) { - const { fqdn, applicationId, port, pullmergeRequestId } = parsedConfiguration; - if (fqdn) { - const found = await getApplicationById({ id: applicationId }); - if (found) { - const domain = getDomain(fqdn); - await configureProxyForApplication({ - domain, - imageId: pullmergeRequestId - ? `${applicationId}-${pullmergeRequestId}` - : applicationId, - applicationId, - port - }); - const isHttps = fqdn.startsWith('https://'); - if (isHttps) await forceSSLOnApplication(domain); - await setWwwRedirection(fqdn); - } - } - } - } - } - for (const container of containers) { - const image = container.Image.split(':')[0]; - const found = supportedServiceTypesAndVersions.find((a) => a.baseImage === image); - if (found) { - const type = found.name; - const mainPort = found.ports.main; - const id = container.Names[0].replace('/', ''); - const service = await db.prisma.service.findUnique({ - where: { id }, - include: { - destinationDocker: true, - minio: true, - plausibleAnalytics: true, - vscodeserver: true, - wordpress: true - } - }); - const { fqdn } = service; - const domain = getDomain(fqdn); - await configureSimpleServiceProxyOn({ id, domain, port: mainPort }); - const publicPort = service[type]?.publicPort; - if (publicPort) { - const containerFound = await checkContainer( - destination.engine, - `haproxy-for-${publicPort}` - ); - if (!containerFound) { - await startHttpProxy(destination, id, publicPort, 9000); - } - } + const applications = await db.prisma.application.findMany({ + include: { destinationDocker: true } + }); + + for (const application of applications) { + const { + fqdn, + id, + port, + destinationDocker: { engine } + } = application; + const containerRunning = await checkContainer(engine, id); + await configureHAProxy(fqdn, id, port, containerRunning, engine); + } + + const services = await db.prisma.service.findMany({ + include: { + destinationDocker: true, + minio: true, + plausibleAnalytics: true, + vscodeserver: true, + wordpress: true + } + }); + + for (const service of services) { + const { + fqdn, + id, + type, + destinationDocker: { engine } + } = service; + const found = db.supportedServiceTypesAndVersions.find((a) => a.name === type); + if (found) { + const port = found.ports.main; + const publicPort = service[type]?.publicPort; + const containerRunning = await checkContainer(engine, id); + await configureHAProxy(fqdn, id, port, containerRunning, engine); + if (publicPort) { + const containerFound = await checkContainer( + service.destinationDocker.engine, + `haproxy-for-${publicPort}` + ); + if (!containerFound) { + await startHttpProxy(service.destinationDocker, id, publicPort, 9000); } } } } - const services = await prisma.service.findMany({}); // Check Coolify FQDN and configure proxy if needed const { fqdn } = await db.listSettings(); if (fqdn) { diff --git a/src/routes/applications/[id]/stop.json.ts b/src/routes/applications/[id]/stop.json.ts index c9d5b9364..58064c07a 100644 --- a/src/routes/applications/[id]/stop.json.ts +++ b/src/routes/applications/[id]/stop.json.ts @@ -20,7 +20,7 @@ export const post: RequestHandler = async (event) => { const docker = dockerInstance({ destinationDocker }); await docker.engine.getContainer(id).stop(); } - await removeProxyConfiguration(fqdn); + // await removeProxyConfiguration(fqdn); return { status: 200 }; diff --git a/src/routes/services/[id]/minio/start.json.ts b/src/routes/services/[id]/minio/start.json.ts index 78372470a..1d1a0655e 100644 --- a/src/routes/services/[id]/minio/start.json.ts +++ b/src/routes/services/[id]/minio/start.json.ts @@ -24,7 +24,7 @@ export const post: RequestHandler = async (event) => { const { id } = event.params; try { - await checkHAProxy(); + // await checkHAProxy(); const service = await db.getService({ id, teamId }); const { type, @@ -96,16 +96,16 @@ export const post: RequestHandler = async (event) => { } try { await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`); - await checkProxyConfigurations(); - await configureSimpleServiceProxyOn({ id, domain, port: consolePort }); + // await checkProxyConfigurations(); + // await configureSimpleServiceProxyOn({ id, domain, port: consolePort }); await db.updateMinioService({ id, publicPort }); await startHttpProxy(destinationDocker, id, publicPort, apiPort); - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); + // if (isHttps) { + // await letsEncrypt({ domain, id }); + // } + // await setWwwRedirection(fqdn); + // await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/minio/stop.json.ts b/src/routes/services/[id]/minio/stop.json.ts index aed702b1b..0285e776c 100644 --- a/src/routes/services/[id]/minio/stop.json.ts +++ b/src/routes/services/[id]/minio/stop.json.ts @@ -35,7 +35,7 @@ export const post: RequestHandler = async (event) => { } try { await stopTcpHttpProxy(destinationDocker, publicPort); - await configureSimpleServiceProxyOff(fqdn); + // await configureSimpleServiceProxyOff(fqdn); } catch (error) { console.log(error); } diff --git a/src/routes/services/[id]/nocodb/start.json.ts b/src/routes/services/[id]/nocodb/start.json.ts index b6606be7b..82ccd2a1c 100644 --- a/src/routes/services/[id]/nocodb/start.json.ts +++ b/src/routes/services/[id]/nocodb/start.json.ts @@ -56,14 +56,14 @@ export const post: RequestHandler = async (event) => { try { await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`); - await checkProxyConfigurations(); - await configureSimpleServiceProxyOn({ id, domain, port: 8080 }); + // await checkProxyConfigurations(); + // await configureSimpleServiceProxyOn({ id, domain, port: 8080 }); - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); + // if (isHttps) { + // await letsEncrypt({ domain, id }); + // } + // await setWwwRedirection(fqdn); + // await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/plausibleanalytics/start.json.ts b/src/routes/services/[id]/plausibleanalytics/start.json.ts index 14c4bf934..fe0171267 100644 --- a/src/routes/services/[id]/plausibleanalytics/start.json.ts +++ b/src/routes/services/[id]/plausibleanalytics/start.json.ts @@ -187,14 +187,14 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`; await asyncExecShell( `DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up --build -d` ); - await checkProxyConfigurations(); - await configureSimpleServiceProxyOn({ id, domain, port: 8000 }); + // await checkProxyConfigurations(); + // await configureSimpleServiceProxyOn({ id, domain, port: 8000 }); - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); + // if (isHttps) { + // await letsEncrypt({ domain, id }); + // } + // await setWwwRedirection(fqdn); + // await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/vaultwarden/start.json.ts b/src/routes/services/[id]/vaultwarden/start.json.ts index 37482faef..5dcacbea3 100644 --- a/src/routes/services/[id]/vaultwarden/start.json.ts +++ b/src/routes/services/[id]/vaultwarden/start.json.ts @@ -74,14 +74,14 @@ export const post: RequestHandler = async (event) => { } try { await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`); - await checkProxyConfigurations(); - await configureSimpleServiceProxyOn({ id, domain, port: 80 }); + // await checkProxyConfigurations(); + // await configureSimpleServiceProxyOn({ id, domain, port: 80 }); - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); + // if (isHttps) { + // await letsEncrypt({ domain, id }); + // } + // await setWwwRedirection(fqdn); + // await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/vscodeserver/start.json.ts b/src/routes/services/[id]/vscodeserver/start.json.ts index 8bd06b17c..ee5f2670b 100644 --- a/src/routes/services/[id]/vscodeserver/start.json.ts +++ b/src/routes/services/[id]/vscodeserver/start.json.ts @@ -84,14 +84,14 @@ export const post: RequestHandler = async (event) => { try { await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`); - await checkProxyConfigurations(); - await configureSimpleServiceProxyOn({ id, domain, port: 8080 }); + // await checkProxyConfigurations(); + // await configureSimpleServiceProxyOn({ id, domain, port: 8080 }); - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); + // if (isHttps) { + // await letsEncrypt({ domain, id }); + // } + // await setWwwRedirection(fqdn); + // await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/wordpress/start.json.ts b/src/routes/services/[id]/wordpress/start.json.ts index fde5cfe66..76e113bce 100644 --- a/src/routes/services/[id]/wordpress/start.json.ts +++ b/src/routes/services/[id]/wordpress/start.json.ts @@ -121,14 +121,14 @@ export const post: RequestHandler = async (event) => { try { await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`); - await checkProxyConfigurations(); - await configureSimpleServiceProxyOn({ id, domain, port: 80 }); + // await checkProxyConfigurations(); + // await configureSimpleServiceProxyOn({ id, domain, port: 80 }); - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); + // if (isHttps) { + // await letsEncrypt({ domain, id }); + // } + // await setWwwRedirection(fqdn); + // await reloadHaproxy(destinationDocker.engine); return { status: 200 };