diff --git a/package.json b/package.json index 81ea664eb..dd531e946 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "coolify", "description": "An open-source & self-hostable Heroku / Netlify alternative.", - "version": "2.0.23", + "version": "2.0.24", "license": "AGPL-3.0", "scripts": { "dev": "docker-compose -f docker-compose-dev.yaml up -d && NODE_ENV=development svelte-kit dev --host 0.0.0.0", @@ -74,6 +74,7 @@ "js-cookie": "3.0.1", "js-yaml": "4.1.0", "jsonwebtoken": "8.5.1", + "mustache": "^4.2.0", "node-forge": "1.2.1", "svelte-kit-cookie-session": "2.1.2", "tailwindcss-scrollbar": "^0.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 742b45b03..a9411c6f3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,7 @@ specifiers: js-yaml: 4.1.0 jsonwebtoken: 8.5.1 lint-staged: 12.3.4 + mustache: ^4.2.0 node-forge: 1.2.1 postcss: 8.4.6 prettier: 2.5.1 @@ -70,6 +71,7 @@ dependencies: js-cookie: 3.0.1 js-yaml: 4.1.0 jsonwebtoken: 8.5.1 + mustache: 4.2.0 node-forge: 1.2.1 svelte-kit-cookie-session: 2.1.2 tailwindcss-scrollbar: 0.1.0_tailwindcss@3.0.23 @@ -4091,6 +4093,14 @@ packages: msgpackr-extract: 1.0.15 dev: false + /mustache/4.2.0: + resolution: + { + integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== + } + hasBin: true + dev: false + /nan/2.15.0: resolution: { diff --git a/prisma/migrations/20220301101928_proxyhash/migration.sql b/prisma/migrations/20220301101928_proxyhash/migration.sql new file mode 100644 index 000000000..87845b38b --- /dev/null +++ b/prisma/migrations/20220301101928_proxyhash/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Setting" ADD COLUMN "proxyHash" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9ec70de70..688e312b7 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -16,6 +16,7 @@ model Setting { maxPort Int @default(9100) proxyPassword String proxyUser String + proxyHash String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } diff --git a/prisma/seed.cjs b/prisma/seed.cjs index 2dacc9a72..61f3928f6 100644 --- a/prisma/seed.cjs +++ b/prisma/seed.cjs @@ -27,6 +27,15 @@ async function main() { proxyUser: cuid() } }); + } else { + await prisma.setting.update({ + where: { + id: settingsFound.id + }, + data: { + proxyHash: null + } + }); } const localDocker = await prisma.destinationDocker.findFirst({ where: { engine: '/var/run/docker.sock' } diff --git a/src/lib/database/applications.ts b/src/lib/database/applications.ts index b2d7ceacd..64cc1444e 100644 --- a/src/lib/database/applications.ts +++ b/src/lib/database/applications.ts @@ -1,5 +1,4 @@ import { decrypt, encrypt } from '$lib/crypto'; -import { removeProxyConfiguration } from '$lib/haproxy'; import { asyncExecShell, getEngine } from '$lib/common'; import { getDomain, removeDestinationDocker } from '$lib/common'; @@ -136,13 +135,13 @@ export async function getApplication({ id, teamId }) { } }); - if (body.gitSource?.githubApp?.clientSecret) { + if (body?.gitSource?.githubApp?.clientSecret) { body.gitSource.githubApp.clientSecret = decrypt(body.gitSource.githubApp.clientSecret); } - if (body.gitSource?.githubApp?.webhookSecret) { + if (body?.gitSource?.githubApp?.webhookSecret) { body.gitSource.githubApp.webhookSecret = decrypt(body.gitSource.githubApp.webhookSecret); } - if (body.gitSource?.githubApp?.privateKey) { + if (body?.gitSource?.githubApp?.privateKey) { body.gitSource.githubApp.privateKey = decrypt(body.gitSource.githubApp.privateKey); } if (body?.gitSource?.gitlabApp?.appSecret) { diff --git a/src/lib/haproxy/configuration.ts b/src/lib/haproxy/configuration.ts new file mode 100644 index 000000000..97cb76c97 --- /dev/null +++ b/src/lib/haproxy/configuration.ts @@ -0,0 +1,259 @@ +import { dev } from '$app/env'; +import got from 'got'; +import mustache from 'mustache'; +import crypto from 'crypto'; + +import * as db from '$lib/database'; +import { checkContainer, checkHAProxy } from '.'; +import { asyncExecShell, getDomain, getEngine } from '$lib/common'; + +const url = dev ? 'http://localhost:5555' : 'http://coolify-haproxy:5555'; + +let template = `program api + command /usr/bin/dataplaneapi -f /usr/local/etc/haproxy/dataplaneapi.hcl --userlist haproxy-dataplaneapi + no option start-on-reload + +global + stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners + log stdout format raw local0 debug + +defaults + mode http + log global + timeout http-request 60s + timeout connect 10s + timeout client 60s + timeout server 60s + +userlist haproxy-dataplaneapi + user admin insecure-password "\${HAPROXY_PASSWORD}" + +frontend http + mode http + bind :80 + bind :443 ssl crt /usr/local/etc/haproxy/ssl/ alpn h2,http/1.1 + acl is_certbot path_beg /.well-known/acme-challenge/ + {{#applications}} + {{#isHttps}} + http-request redirect scheme https code ${ + dev ? 302 : 301 + } if { hdr(host) -i {{domain}} } !{ ssl_fc } + {{/isHttps}} + http-request redirect location {{{redirectValue}}} code ${ + dev ? 302 : 301 + } if { req.hdr(host) -i {{redirectTo}} } + {{/applications}} + {{#services}} + {{#isHttps}} + http-request redirect scheme https code ${ + dev ? 302 : 301 + } if { hdr(host) -i {{domain}} } !{ ssl_fc } + {{/isHttps}} + http-request redirect location {{{redirectValue}}} code ${ + dev ? 302 : 301 + } if { req.hdr(host) -i {{redirectTo}} } + {{/services}} + {{#coolify}} + {{#isHttps}} + http-request redirect scheme https code ${ + dev ? 302 : 301 + } if { hdr(host) -i {{domain}} } !{ ssl_fc } + {{/isHttps}} + http-request redirect location {{{redirectValue}}} code ${ + dev ? 302 : 301 + } if { req.hdr(host) -i {{redirectTo}} } + {{/coolify}} + use_backend backend-certbot if is_certbot + use_backend %[req.hdr(host),lower] + +frontend stats + bind *:8404 + stats enable + stats uri / + stats admin if TRUE + stats auth "\${HAPROXY_USERNAME}:\${HAPROXY_PASSWORD}" + +backend backend-certbot + mode http + server certbot host.docker.internal:9080 + +{{#applications}} +{{#isRunning}} +# updatedAt={{updatedAt}} +backend {{domain}} + option forwardfor + server {{id}} {{id}}:{{port}} check +{{/isRunning}} +{{/applications}} + +{{#services}} +{{#isRunning}} +# updatedAt={{updatedAt}} +backend {{domain}} + option forwardfor + server {{id}} {{id}}:{{port}} check +{{/isRunning}} +{{/services}} + +{{#coolify}} +backend {{domain}} + option forwardfor + option httpchk GET /undead.json + server {{id}} {{id}}:{{port}} check fall 10 +{{/coolify}} +`; +export async function haproxyInstance() { + const { proxyPassword } = await db.listSettings(); + return got.extend({ + prefixUrl: url, + username: 'admin', + password: proxyPassword + }); +} + +export async function configureHAProxy() { + try { + const haproxy = await haproxyInstance(); + await checkHAProxy(haproxy); + const data = { + applications: [], + services: [], + coolify: [] + }; + const applications = await db.prisma.application.findMany({ + include: { destinationDocker: true, settings: true } + }); + for (const application of applications) { + const { + fqdn, + id, + port, + destinationDocker, + destinationDockerId, + settings: { previews }, + updatedAt + } = application; + if (destinationDockerId) { + const { engine, network } = destinationDocker; + const isRunning = await checkContainer(engine, id); + if (fqdn) { + const domain = getDomain(fqdn); + const isHttps = fqdn.startsWith('https://'); + const isWWW = fqdn.includes('www.'); + const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`; + if (isRunning) { + data.applications.push({ + id, + port: port || 3000, + domain, + isRunning, + isHttps, + redirectValue, + redirectTo: isWWW ? domain : 'www.' + domain, + updatedAt: updatedAt.getTime() + }); + } + if (previews) { + const host = getEngine(engine); + const { stdout } = await asyncExecShell( + `DOCKER_HOST=${host} docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"` + ); + const containers = stdout + .trim() + .split('\n') + .filter((a) => a) + .map((c) => c.replace(/"/g, '')); + if (containers.length > 0) { + for (const container of containers) { + let previewDomain = `${container.split('-')[1]}.${domain}`; + data.applications.push({ + id: container, + port: port || 3000, + domain: previewDomain, + isRunning, + isHttps, + redirectValue, + redirectTo: isWWW ? previewDomain : 'www.' + previewDomain, + updatedAt: updatedAt.getTime() + }); + } + } + } + } + } + } + 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, destinationDockerId, updatedAt } = service; + if (destinationDockerId) { + const { engine } = destinationDocker; + const found = db.supportedServiceTypesAndVersions.find((a) => a.name === type); + if (found) { + const port = found.ports.main; + const publicPort = service[type]?.publicPort; + const isRunning = await checkContainer(engine, id); + if (fqdn) { + const domain = getDomain(fqdn); + const isHttps = fqdn.startsWith('https://'); + const isWWW = fqdn.includes('www.'); + const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`; + if (isRunning) { + data.services.push({ + id, + port, + publicPort, + domain, + isRunning, + isHttps, + redirectValue, + redirectTo: isWWW ? domain : 'www.' + domain, + updatedAt: updatedAt.getTime() + }); + } + } + } + } + } + const { fqdn } = await db.prisma.setting.findFirst(); + if (fqdn) { + const domain = getDomain(fqdn); + const isHttps = fqdn.startsWith('https://'); + const isWWW = fqdn.includes('www.'); + const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`; + data.coolify.push({ + id: dev ? 'host.docker.internal' : 'coolify', + port: 3000, + domain, + isHttps, + redirectValue, + redirectTo: isWWW ? domain : 'www.' + domain + }); + } + const output = mustache.render(template, data); + const newHash = crypto.createHash('md5').update(output).digest('hex'); + const { proxyHash, id } = await db.listSettings(); + if (proxyHash !== newHash) { + await db.prisma.setting.update({ where: { id }, data: { proxyHash: newHash } }); + await haproxy.post(`v2/services/haproxy/configuration/raw`, { + searchParams: { + skip_version: true + }, + body: output, + headers: { + 'Content-Type': 'text/plain' + } + }); + } + } catch (error) { + throw error; + } +} diff --git a/src/lib/haproxy/index.ts b/src/lib/haproxy/index.ts index fffba0ba7..deedd0bf2 100644 --- a/src/lib/haproxy/index.ts +++ b/src/lib/haproxy/index.ts @@ -1,5 +1,5 @@ import { dev } from '$app/env'; -import { asyncExecShell, getDomain, getEngine } from '$lib/common'; +import { asyncExecShell, getEngine } from '$lib/common'; import got from 'got'; import * as db from '$lib/database'; @@ -47,113 +47,6 @@ export async function completeTransaction(transactionId) { const haproxy = await haproxyInstance(); return await haproxy.put(`v2/services/haproxy/transactions/${transactionId}`); } - -export async function removeProxyConfiguration(fqdn) { - const domain = getDomain(fqdn); - const haproxy = await haproxyInstance(); - const backendFound = await haproxy - .get(`v2/services/haproxy/configuration/backends/${domain}`) - .json(); - if (backendFound) { - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${domain}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - await completeTransaction(transactionId); - } - await forceSSLOffApplication(domain); - await removeWwwRedirection(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`, { - 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) { - 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(); - } - } - } catch (error) { - console.log(error); - } finally { - if (transactionId) await completeTransaction(transactionId); - } -} -export async function forceSSLOnApplication(domain) { - const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); - let transactionId; - try { - const rules: any = 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; - } - transactionId = await getNextTransactionId(); - - 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(); - } catch (error) { - console.log(error); - throw error; - } finally { - if (transactionId) await completeTransaction(transactionId); - } -} - export async function deleteProxy({ id }) { const haproxy = await haproxyInstance(); await checkHAProxy(haproxy); @@ -177,7 +70,7 @@ export async function deleteProxy({ id }) { }) .json(); } catch (error) { - console.log(error.response.body); + console.log(error.response?.body || error); } finally { if (transactionId) await completeTransaction(transactionId); } @@ -187,169 +80,6 @@ export async function reloadHaproxy(engine) { const host = getEngine(engine); return await asyncExecShell(`DOCKER_HOST=${host} docker exec coolify-haproxy kill -HUP 1`); } -export async function checkProxyConfigurations() { - const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); - try { - const stats: any = await haproxy.get(`v2/services/haproxy/stats/native`).json(); - 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.getApplicationById(name); - if (!application) { - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${backendName}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - return await completeTransaction(transactionId); - } - 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 (lastchg > 120) { - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${backendName}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - await completeTransaction(transactionId); - } - } - } - } catch (error) { - console.log(error); - } -} -export async function configureProxyForApplication({ domain, imageId, applicationId, port }) { - const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); - - 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/${imageId}`, { - 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 === 'enabled') { - if (server.data.address === imageId) { - if (server.data.port === port) { - serverConfigured = true; - } - } - } - } - } - } - } 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}`, { - searchParams: { - transaction_id: transactionId - } - }) - .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 - } - }); - } catch (error) { - throw error?.response?.body || error; - } finally { - await completeTransaction(transactionId); - } -} - -export async function configureCoolifyProxyOff(fqdn) { - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); - - try { - await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json(); - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${domain}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - await completeTransaction(transactionId); - if (isHttps) await forceSSLOffApplication(domain); - await removeWwwRedirection(fqdn); - } catch (error) { - throw error?.response?.body || error; - } -} export async function checkHAProxy(haproxy?: any) { if (!haproxy) haproxy = await haproxyInstance(); try { @@ -361,76 +91,6 @@ export async function checkHAProxy(haproxy?: any) { }; } } -export async function configureCoolifyProxyOn(fqdn) { - const domain = getDomain(fqdn); - const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); - 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/coolify`, { - 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 === 'enabled') { - if (server.data.address === dev ? 'host.docker.internal' : 'coolify') { - if (server.data.port === 3000) { - serverConfigured = true; - } - } - } - } - } - } - } catch (error) {} - if (serverConfigured) return; - const transactionId = await getNextTransactionId(); - try { - await haproxy.post('v2/services/haproxy/configuration/backends', { - searchParams: { - transaction_id: transactionId - }, - json: { - adv_check: 'httpchk', - httpchk_params: { - method: 'GET', - uri: '/undead.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: dev ? 'host.docker.internal' : 'coolify', - check: 'enabled', - fall: 10, - name: 'coolify', - port: 3000 - } - }); - } catch (error) { - console.log(error); - throw error; - } finally { - await completeTransaction(transactionId); - } -} export async function stopTcpHttpProxy(destinationDocker, publicPort) { const { engine } = destinationDocker; @@ -494,7 +154,7 @@ export async function startHttpProxy(destinationDocker, id, publicPort, privateP export async function startCoolifyProxy(engine) { const host = getEngine(engine); const found = await checkContainer(engine, 'coolify-haproxy'); - const { proxyPassword, proxyUser } = await db.listSettings(); + const { proxyPassword, proxyUser, id } = await db.listSettings(); if (!found) { const { stdout: Config } = await asyncExecShell( `DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'` @@ -503,6 +163,7 @@ export async function startCoolifyProxy(engine) { await asyncExecShell( `DOCKER_HOST="${host}" docker run -e HAPROXY_USERNAME=${proxyUser} -e HAPROXY_PASSWORD=${proxyPassword} --restart always --add-host 'host.docker.internal:host-gateway' --add-host 'host.docker.internal:${ip}' -v coolify-ssl-certs:/usr/local/etc/haproxy/ssl --network coolify-infra -p "80:80" -p "443:443" -p "8404:8404" -p "5555:5555" -p "5000:5000" --name coolify-haproxy -d coollabsio/${defaultProxyImage}` ); + await db.prisma.setting.update({ where: { id }, data: { proxyHash: null } }); } await configureNetworkCoolifyProxy(engine); } @@ -535,6 +196,8 @@ export async function stopCoolifyProxy(engine) { const host = getEngine(engine); const found = await checkContainer(engine, 'coolify-haproxy'); await db.setDestinationSettings({ engine, isCoolifyProxyUsed: false }); + const { id } = await db.prisma.setting.findFirst({}); + await db.prisma.setting.update({ where: { id }, data: { proxyHash: null } }); try { if (found) { await asyncExecShell( @@ -559,171 +222,3 @@ export async function configureNetworkCoolifyProxy(engine) { } }); } - -export async function configureSimpleServiceProxyOn({ id, domain, port }) { - const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); - 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 === 'enabled') { - if (server.data.address === id) { - if (server.data.port === port) { - serverConfigured = true; - } - } - } - } - } - } - } catch (error) {} - if (serverConfigured) return; - const transactionId = await getNextTransactionId(); - 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: id, - check: 'enabled', - name: id, - port: port - } - }); - await completeTransaction(transactionId); -} - -export async function configureSimpleServiceProxyOff(fqdn) { - if (!fqdn) { - return; - } - const domain = getDomain(fqdn); - const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); - try { - await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json(); - const transactionId = await getNextTransactionId(); - await haproxy - .delete(`v2/services/haproxy/configuration/backends/${domain}`, { - searchParams: { - transaction_id: transactionId - } - }) - .json(); - await completeTransaction(transactionId); - } catch (error) {} - await forceSSLOffApplication(domain); - await removeWwwRedirection(fqdn); - return; -} - -export async function removeWwwRedirection(fqdn) { - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`; - - 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' - } - }) - .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); - } - } -} -export async function setWwwRedirection(fqdn) { - const haproxy = await haproxyInstance(); - await checkHAProxy(haproxy); - let transactionId; - - try { - 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}`} }`; - const rules: any = 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; - } - - transactionId = await getNextTransactionId(); - 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; - } finally { - if (transactionId) await completeTransaction(transactionId); - } -} 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/index.ts similarity index 57% rename from src/lib/letsencrypt.ts rename to src/lib/letsencrypt/index.ts index d70de1812..43e5d8a63 100644 --- a/src/lib/letsencrypt.ts +++ b/src/lib/letsencrypt/index.ts @@ -1,11 +1,11 @@ -import { dev } from '$app/env'; -import { forceSSLOffApplication, forceSSLOnApplication } from '$lib/haproxy'; -import { asyncExecShell, getEngine } from './common'; +import { asyncExecShell, getDomain, getEngine } from '$lib/common'; +import { checkContainer } from '$lib/haproxy'; import * as db from '$lib/database'; +import { dev } from '$app/env'; 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,85 @@ export async function letsEncrypt({ domain, isCoolify = false, id = null }) { if (error.code !== 0) { throw error; } - } finally { - if (!isCoolify) { - await forceSSLOnApplication(domain); + } +} + +export async function generateSSLCerts() { + const ssls = []; + const applications = await db.prisma.application.findMany({ + include: { destinationDocker: true, settings: true } + }); + for (const application of applications) { + const { + fqdn, + id, + destinationDocker: { engine, network }, + settings: { previews } + } = application; + const isRunning = await checkContainer(engine, id); + const domain = getDomain(fqdn); + const isHttps = fqdn.startsWith('https://'); + if (isRunning) { + if (isHttps) ssls.push({ domain, id, isCoolify: false }); + } + if (previews) { + const host = getEngine(engine); + const { stdout } = await asyncExecShell( + `DOCKER_HOST=${host} docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"` + ); + const containers = stdout + .trim() + .split('\n') + .filter((a) => a) + .map((c) => c.replace(/"/g, '')); + if (containers.length > 0) { + for (const container of containers) { + let previewDomain = `${container.split('-')[1]}.${domain}`; + if (isHttps) ssls.push({ domain: previewDomain, id, isCoolify: false }); + } + } + } + } + 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 domain = getDomain(fqdn); + const isHttps = fqdn.startsWith('https://'); + const isRunning = await checkContainer(engine, id); + if (isRunning) { + if (isHttps) ssls.push({ domain, id, isCoolify: false }); + } + } + } + const { fqdn } = await db.prisma.setting.findFirst(); + if (fqdn) { + const domain = getDomain(fqdn); + const isHttps = fqdn.startsWith('https://'); + if (isHttps) ssls.push({ domain, id: 'coolify', isCoolify: true }); + } + if (ssls.length > 0) { + for (const ssl of ssls) { + if (!dev) { + await letsEncrypt(ssl.domain, ssl.id, ssl.isCoolify); + } else { + console.log('Generate ssl for', ssl.domain); + } } } } diff --git a/src/lib/queues/builder.ts b/src/lib/queues/builder.ts index 4c1ad631e..cefcfc6ed 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,6 @@ 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 updated shortly.', buildId, applicationId }); } } diff --git a/src/lib/queues/cleanup.ts b/src/lib/queues/cleanup.ts index 981173a31..53c1896a7 100644 --- a/src/lib/queues/cleanup.ts +++ b/src/lib/queues/cleanup.ts @@ -8,48 +8,53 @@ export default async function () { for (const destinationDocker of destinationDockers) { const host = getEngine(destinationDocker.engine); // Tagging images with labels - try { - const images = [ - `coollabsio/${defaultProxyImageTcp}`, - `coollabsio/${defaultProxyImageHttp}`, - 'certbot/certbot:latest', - 'node:16.14.0-alpine', - 'alpine:latest', - 'nginx:stable-alpine', - 'node:lts', - 'php:apache', - 'rust:latest' - ]; - for (const image of images) { - try { - await asyncExecShell(`DOCKER_HOST=${host} docker image inspect ${image}`); - } catch (error) { - await asyncExecShell( - `DOCKER_HOST=${host} docker pull ${image} && echo "FROM ${image}" | docker build --label coolify.image="true" -t "${image}" -` - ); - } - } - } catch (error) {} + // try { + // const images = [ + // `coollabsio/${defaultProxyImageTcp}`, + // `coollabsio/${defaultProxyImageHttp}`, + // 'certbot/certbot:latest', + // 'node:16.14.0-alpine', + // 'alpine:latest', + // 'nginx:stable-alpine', + // 'node:lts', + // 'php:apache', + // 'rust:latest' + // ]; + // for (const image of images) { + // try { + // await asyncExecShell(`DOCKER_HOST=${host} docker image inspect ${image}`); + // } catch (error) { + // await asyncExecShell( + // `DOCKER_HOST=${host} docker pull ${image} && echo "FROM ${image}" | docker build --label coolify.image="true" -t "${image}" -` + // ); + // } + // } + // } catch (error) {} try { await asyncExecShell(`DOCKER_HOST=${host} docker container prune -f`); } catch (error) { console.log(error); } - if (!dev) { - // Cleanup images that are not managed by coolify - try { - await asyncExecShell( - `DOCKER_HOST=${host} docker image prune --filter 'label!=coolify.image=true' -a -f` - ); - } catch (error) { - console.log(error); - } - // Cleanup old images >3 days - try { - await asyncExecShell(`DOCKER_HOST=${host} docker image prune --filter "until=72h" -a -f`); - } catch (error) { - console.log(error); - } + try { + await asyncExecShell(`DOCKER_HOST=${host} docker image prune -f`); + } catch (error) { + console.log(error); } + // if (!dev) { + // // Cleanup images that are not managed by coolify + // try { + // await asyncExecShell( + // `DOCKER_HOST=${host} docker image prune --filter 'label!=coolify.image=true' -a -f` + // ); + // } catch (error) { + // console.log(error); + // } + // // Cleanup old images >3 days + // try { + // await asyncExecShell(`DOCKER_HOST=${host} docker image prune --filter "until=72h" -a -f`); + // } catch (error) { + // console.log(error); + // } + // } } } diff --git a/src/lib/queues/index.ts b/src/lib/queues/index.ts index 45c9c8a52..1ce9411c4 100644 --- a/src/lib/queues/index.ts +++ b/src/lib/queues/index.ts @@ -86,7 +86,7 @@ const cron = async () => { ); await queue.proxy.add('proxy', {}, { repeat: { every: 10000 } }); - // await queue.ssl.add('ssl', {}, { repeat: { every: 10000 } }); + await queue.ssl.add('ssl', {}, { repeat: { every: 60000 } }); await queue.cleanup.add('cleanup', {}, { repeat: { every: 600000 } }); await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } }); diff --git a/src/lib/queues/proxy.ts b/src/lib/queues/proxy.ts index 074ac55ab..3705139ce 100644 --- a/src/lib/queues/proxy.ts +++ b/src/lib/queues/proxy.ts @@ -1,116 +1,12 @@ -import { getDomain } from '$lib/common'; -import { getApplicationById, prisma, supportedServiceTypesAndVersions } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { - checkContainer, - checkProxyConfigurations, - configureCoolifyProxyOn, - configureProxyForApplication, - configureSimpleServiceProxyOn, - forceSSLOnApplication, - reloadHaproxy, - setWwwRedirection, - startCoolifyProxy, - startHttpProxy -} from '$lib/haproxy'; -import * as db from '$lib/database'; -// import { generateRemoteEngine } from '$lib/components/common'; +import { dev } from '$app/env'; +import { ErrorHandler } from '$lib/database'; +import { configureHAProxy } from '$lib/haproxy/configuration'; export default async function () { try { - await checkProxyConfigurations(); + return await configureHAProxy(); } catch (error) { - 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 services = await prisma.service.findMany({}); - // Check Coolify FQDN and configure proxy if needed - const { fqdn } = await db.listSettings(); - if (fqdn) { - const domain = getDomain(fqdn); - await startCoolifyProxy('/var/run/docker.sock'); - await configureCoolifyProxyOn(fqdn); - await setWwwRedirection(fqdn); - const isHttps = fqdn.startsWith('https://'); - if (isHttps) await forceSSLOnApplication(domain); - } - } catch (error) { - throw error; + console.log(error.response?.body || error); + return ErrorHandler(error.response?.body || error); } } diff --git a/src/lib/queues/ssl.ts b/src/lib/queues/ssl.ts index cbc7964c0..d14fc0822 100644 --- a/src/lib/queues/ssl.ts +++ b/src/lib/queues/ssl.ts @@ -1,76 +1,9 @@ -import { asyncExecShell, getDomain, getEngine } from '$lib/common'; -import { prisma } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { forceSSLOnApplication } from '$lib/haproxy'; -import * as db from '$lib/database'; -import { dev } from '$app/env'; -import getPort, { portNumbers } from 'get-port'; -import cuid from 'cuid'; +import { generateSSLCerts } from '$lib/letsencrypt'; export default async function () { try { - const data = await db.prisma.setting.findFirst(); - const { minPort, maxPort } = data; - - const publicPort = await getPort({ port: portNumbers(minPort, maxPort) }); - const randomCuid = cuid(); - const destinationDockers = await prisma.destinationDocker.findMany({}); - for (const destination of destinationDockers) { - if (destination.isCoolifyProxyUsed) { - 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) { - const parsedConfiguration = JSON.parse( - Buffer.from(configuration.Labels['coolify.configuration'], 'base64').toString() - ); - if (configuration.Labels['coolify.type'] === 'standalone-application') { - const { fqdn } = parsedConfiguration; - if (fqdn) { - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - if (isHttps) { - if (dev) { - console.log('DEV MODE: SSL is enabled'); - } else { - const host = getEngine(destination.engine); - await asyncExecShell( - `DOCKER_HOST=${host} docker run --rm --name certbot-${randomCuid} -p 9080:${publicPort} -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 ${publicPort} -d ${domain} --agree-tos --non-interactive --register-unsafely-without-email` - ); - const { stderr } = await asyncExecShell( - `DOCKER_HOST=${host} docker run --rm -v "coolify-letsencrypt:/etc/letsencrypt" -v "coolify-ssl-certs:/app/ssl" alpine:latest cat /etc/letsencrypt/live/${domain}/fullchain.pem /etc/letsencrypt/live/${domain}/privkey.pem > /app/ssl/${domain}.pem` - ); - if (stderr) throw new Error(stderr); - } - } - } - } - } - } - } - const { fqdn } = await db.listSettings(); - if (fqdn) { - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - if (isHttps) { - if (dev) { - console.log('DEV MODE: SSL is enabled'); - } else { - await asyncExecShell( - `docker run --rm --name certbot-${randomCuid} -p 9080:${publicPort} -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 ${publicPort} -d ${domain} --agree-tos --non-interactive --register-unsafely-without-email` - ); - - const { stderr } = await asyncExecShell( - `docker run --rm -v "coolify-letsencrypt:/etc/letsencrypt" -v "coolify-ssl-certs:/app/ssl" alpine:latest cat /etc/letsencrypt/live/${domain}/fullchain.pem /etc/letsencrypt/live/${domain}/privkey.pem > /app/ssl/${domain}.pem` - ); - if (stderr) throw new Error(stderr); - } - } - } + return await generateSSLCerts(); } catch (error) { - console.log(error); throw error; } } diff --git a/src/routes/__layout.svelte b/src/routes/__layout.svelte index fc85ac8f5..ec314efb0 100644 --- a/src/routes/__layout.svelte +++ b/src/routes/__layout.svelte @@ -38,13 +38,13 @@ import { errorNotification } from '$lib/form'; import { asyncSleep } from '$lib/components/common'; import { del, get, post } from '$lib/api'; - import { browser } from '$app/env'; - import { fade } from 'svelte/transition'; + import { browser, dev } from '$app/env'; let isUpdateAvailable = false; + let updateStatus = { + found: false, loading: false, - checking: false, success: null }; let latestVersion = 'latest'; @@ -60,16 +60,19 @@ } if ($session.teamId === '0') { try { - updateStatus.checking = true; const data = await get(`/update.json`); if (overrideVersion || data?.isUpdateAvailable) { latestVersion = overrideVersion || data.latestVersion; - isUpdateAvailable = overrideVersion ? true : data?.isUpdateAvailable; - await post(`/update.json`, { type: 'pull', latestVersion }); + console.log('checking update'); + const { exists } = await post(`/update.json`, { + type: 'check', + latestVersion, + overrideVersion + }); + isUpdateAvailable = exists; } } catch (error) { } finally { - updateStatus.checking = false; } } } @@ -97,26 +100,32 @@ async function update() { updateStatus.loading = true; try { - await post(`/update.json`, { type: 'update', latestVersion }); - toast.push('Update completed.

Waiting for the new version to start...'); - let reachable = false; - let tries = 0; - do { + if (dev) { + console.log(`updating to ${latestVersion}`); await asyncSleep(4000); - try { - await get(`/undead.json`); - reachable = true; - } catch (error) { - reachable = false; - } - if (reachable) break; - tries++; - } while (!reachable || tries < 120); - toast.push('New version reachable. Reloading...'); - updateStatus.loading = false; - updateStatus.success = true; - await asyncSleep(3000); - return window.location.reload(); + return window.location.reload(); + } else { + await post(`/update.json`, { type: 'update', latestVersion }); + toast.push('Update completed.

Waiting for the new version to start...'); + let reachable = false; + let tries = 0; + do { + await asyncSleep(4000); + try { + await get(`/undead.json`); + reachable = true; + } catch (error) { + reachable = false; + } + if (reachable) break; + tries++; + } while (!reachable || tries < 120); + toast.push('New version reachable. Reloading...'); + updateStatus.loading = false; + updateStatus.success = true; + await asyncSleep(3000); + return window.location.reload(); + } } catch ({ error }) { updateStatus.success = false; updateStatus.loading = false; @@ -311,35 +320,10 @@
{#if $session.teamId === '0'} - {#if updateStatus.checking} - - {:else if isUpdateAvailable} + {#if isUpdateAvailable}
-
- - - - - - - - - - {#each applicationSecrets as secret} - {#key secret.id} - - s.name === secret.name)} - isPRMRSecret - name={secret.name} - value={secret.value} - isBuildSecret={secret.isBuildSecret} - on:refresh={refreshSecrets} - /> - - {/key} - {/each} - -
NameValueNeed during buildtime? -
-
+{#if applicationSecrets.length !== 0} +
+ + + + + + + + + + + {#each applicationSecrets as secret} + {#key secret.id} + + s.name === secret.name)} + isPRMRSecret + name={secret.name} + value={secret.value} + isBuildSecret={secret.isBuildSecret} + on:refresh={refreshSecrets} + /> + + {/key} + {/each} + +
NameValueNeed during buildtime?Action
+
+{/if}
Please add secrets to the application first.

These values overwrite application secrets in PR/MR deployments. Useful for creating staging environments." + ? "You can add secrets to PR/MR deployments. Please add secrets to the application first.
Useful for creating staging environments." : "These values overwrite application secrets in PR/MR deployments. Useful for creating staging environments."} />
diff --git a/src/routes/applications/[id]/stop.json.ts b/src/routes/applications/[id]/stop.json.ts index c9d5b9364..999d8c106 100644 --- a/src/routes/applications/[id]/stop.json.ts +++ b/src/routes/applications/[id]/stop.json.ts @@ -1,8 +1,7 @@ -import { getDomain, getUserDetails } from '$lib/common'; +import { asyncExecShell, getEngine, getUserDetails, removeDestinationDocker } from '$lib/common'; import * as db from '$lib/database'; import { ErrorHandler } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { removeProxyConfiguration } from '$lib/haproxy'; +import { checkContainer } from '$lib/haproxy'; import type { RequestHandler } from '@sveltejs/kit'; export const post: RequestHandler = async (event) => { @@ -17,10 +16,12 @@ export const post: RequestHandler = async (event) => { teamId }); if (destinationDockerId) { - const docker = dockerInstance({ destinationDocker }); - await docker.engine.getContainer(id).stop(); + const { engine } = destinationDocker; + const found = await checkContainer(engine, id); + if (found) { + await removeDestinationDocker({ id, engine }); + } } - await removeProxyConfiguration(fqdn); return { status: 200 }; diff --git a/src/routes/destinations/[id]/_LocalDocker.svelte b/src/routes/destinations/[id]/_LocalDocker.svelte index 287f544ef..bf4d8447a 100644 --- a/src/routes/destinations/[id]/_LocalDocker.svelte +++ b/src/routes/destinations/[id]/_LocalDocker.svelte @@ -117,6 +117,8 @@ setTimeout(() => { window.location.reload(); }, 5000); + } finally { + restarting = false; } } } diff --git a/src/routes/destinations/[id]/restart.json.ts b/src/routes/destinations/[id]/restart.json.ts index 65a3e0cd4..9d2da459a 100644 --- a/src/routes/destinations/[id]/restart.json.ts +++ b/src/routes/destinations/[id]/restart.json.ts @@ -1,30 +1,19 @@ -import { getDomain, getUserDetails } from '$lib/common'; +import { getUserDetails } from '$lib/common'; import { ErrorHandler } from '$lib/database'; import * as db from '$lib/database'; -import { - configureCoolifyProxyOn, - forceSSLOnApplication, - setWwwRedirection, - startCoolifyProxy, - stopCoolifyProxy -} from '$lib/haproxy'; +import { startCoolifyProxy, stopCoolifyProxy } from '$lib/haproxy'; import type { RequestHandler } from '@sveltejs/kit'; export const post: RequestHandler = async (event) => { const { teamId, status, body } = await getUserDetails(event); if (status === 401) return { status, body }; - const { engine, fqdn } = await event.request.json(); + const { engine } = await event.request.json(); try { - const domain = getDomain(fqdn); await stopCoolifyProxy(engine); await startCoolifyProxy(engine); await db.setDestinationSettings({ engine, isCoolifyProxyUsed: true }); - await configureCoolifyProxyOn(fqdn); - await setWwwRedirection(fqdn); - const isHttps = fqdn.startsWith('https://'); - if (isHttps) await forceSSLOnApplication(domain); 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..5512bded8 100644 --- a/src/routes/services/[id]/minio/start.json.ts +++ b/src/routes/services/[id]/minio/start.json.ts @@ -3,15 +3,7 @@ import * as db from '$lib/database'; import { promises as fs } from 'fs'; import yaml from 'js-yaml'; import type { RequestHandler } from '@sveltejs/kit'; -import { letsEncrypt } from '$lib/letsencrypt'; -import { - checkHAProxy, - checkProxyConfigurations, - configureSimpleServiceProxyOn, - reloadHaproxy, - setWwwRedirection, - startHttpProxy -} from '$lib/haproxy'; +import { startHttpProxy } from '$lib/haproxy'; import getPort, { portNumbers } from 'get-port'; import { getDomain } from '$lib/components/common'; import { ErrorHandler } from '$lib/database'; @@ -24,7 +16,6 @@ export const post: RequestHandler = async (event) => { const { id } = event.params; try { - await checkHAProxy(); const service = await db.getService({ id, teamId }); const { type, @@ -38,9 +29,6 @@ export const post: RequestHandler = async (event) => { const data = await db.prisma.setting.findFirst(); const { minPort, maxPort } = data; - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - const network = destinationDockerId && destinationDocker.network; const host = getEngine(destinationDocker.engine); @@ -96,16 +84,8 @@ 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 db.updateMinioService({ id, publicPort }); await startHttpProxy(destinationDocker, id, publicPort, apiPort); - - 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..3e2340237 100644 --- a/src/routes/services/[id]/minio/stop.json.ts +++ b/src/routes/services/[id]/minio/stop.json.ts @@ -1,9 +1,7 @@ -import { getEngine, getUserDetails, removeDestinationDocker } from '$lib/common'; -import { getDomain } from '$lib/components/common'; +import { getUserDetails, removeDestinationDocker } from '$lib/common'; import * as db from '$lib/database'; import { ErrorHandler } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { checkContainer, configureSimpleServiceProxyOff, stopTcpHttpProxy } from '$lib/haproxy'; +import { checkContainer, stopTcpHttpProxy } from '$lib/haproxy'; import type { RequestHandler } from '@sveltejs/kit'; export const post: RequestHandler = async (event) => { @@ -21,7 +19,6 @@ export const post: RequestHandler = async (event) => { minio: { publicPort } } = service; await db.updateMinioService({ id, publicPort: null }); - const domain = getDomain(fqdn); if (destinationDockerId) { const engine = destinationDocker.engine; @@ -35,7 +32,6 @@ export const post: RequestHandler = async (event) => { } try { await stopTcpHttpProxy(destinationDocker, publicPort); - 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..ef9ac485c 100644 --- a/src/routes/services/[id]/nocodb/start.json.ts +++ b/src/routes/services/[id]/nocodb/start.json.ts @@ -3,15 +3,6 @@ import * as db from '$lib/database'; import { promises as fs } from 'fs'; import yaml from 'js-yaml'; import type { RequestHandler } from '@sveltejs/kit'; -import { letsEncrypt } from '$lib/letsencrypt'; -import { - checkHAProxy, - checkProxyConfigurations, - configureSimpleServiceProxyOn, - reloadHaproxy, - setWwwRedirection -} from '$lib/haproxy'; -import { getDomain } from '$lib/components/common'; import { ErrorHandler } from '$lib/database'; import { makeLabelForServices } from '$lib/buildPacks/common'; @@ -22,13 +13,8 @@ export const post: RequestHandler = async (event) => { const { id } = event.params; try { - await checkHAProxy(); const service = await db.getService({ id, teamId }); - const { type, version, fqdn, destinationDockerId, destinationDocker } = service; - - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - + const { type, version, destinationDockerId, destinationDocker } = service; const network = destinationDockerId && destinationDocker.network; const host = getEngine(destinationDocker.engine); @@ -56,14 +42,6 @@ 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 }); - - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/nocodb/stop.json.ts b/src/routes/services/[id]/nocodb/stop.json.ts index f15ba1012..c604e1cc3 100644 --- a/src/routes/services/[id]/nocodb/stop.json.ts +++ b/src/routes/services/[id]/nocodb/stop.json.ts @@ -1,9 +1,7 @@ import { getUserDetails, removeDestinationDocker } from '$lib/common'; -import { getDomain } from '$lib/components/common'; import * as db from '$lib/database'; import { ErrorHandler } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy'; +import { checkContainer } from '$lib/haproxy'; import type { RequestHandler } from '@sveltejs/kit'; export const post: RequestHandler = async (event) => { @@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => { try { const service = await db.getService({ id, teamId }); const { destinationDockerId, destinationDocker, fqdn } = service; - const domain = getDomain(fqdn); if (destinationDockerId) { const engine = destinationDocker.engine; @@ -27,11 +24,6 @@ export const post: RequestHandler = async (event) => { } catch (error) { console.error(error); } - try { - await configureSimpleServiceProxyOff(fqdn); - } catch (error) { - console.log(error); - } } return { diff --git a/src/routes/services/[id]/plausibleanalytics/start.json.ts b/src/routes/services/[id]/plausibleanalytics/start.json.ts index 14c4bf934..70de54499 100644 --- a/src/routes/services/[id]/plausibleanalytics/start.json.ts +++ b/src/routes/services/[id]/plausibleanalytics/start.json.ts @@ -3,15 +3,6 @@ import * as db from '$lib/database'; import { promises as fs } from 'fs'; import yaml from 'js-yaml'; import type { RequestHandler } from '@sveltejs/kit'; -import { letsEncrypt } from '$lib/letsencrypt'; -import { - checkHAProxy, - checkProxyConfigurations, - configureSimpleServiceProxyOn, - reloadHaproxy, - setWwwRedirection -} from '$lib/haproxy'; -import { getDomain } from '$lib/components/common'; import { ErrorHandler } from '$lib/database'; import { makeLabelForServices } from '$lib/buildPacks/common'; @@ -22,7 +13,6 @@ export const post: RequestHandler = async (event) => { const { id } = event.params; try { - await checkHAProxy(); const service = await db.getService({ id, teamId }); const { type, @@ -42,9 +32,6 @@ export const post: RequestHandler = async (event) => { } } = service; - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - const config = { plausibleAnalytics: { image: `plausible/analytics:${version}`, @@ -83,7 +70,6 @@ export const post: RequestHandler = async (event) => { }; const network = destinationDockerId && destinationDocker.network; const host = getEngine(destinationDocker.engine); - const engine = destinationDocker.engine; const { workdir } = await createDirectories({ repository: type, buildId: id }); @@ -187,14 +173,7 @@ 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 }); - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/plausibleanalytics/stop.json.ts b/src/routes/services/[id]/plausibleanalytics/stop.json.ts index d9b42d7b3..6ff3cac3b 100644 --- a/src/routes/services/[id]/plausibleanalytics/stop.json.ts +++ b/src/routes/services/[id]/plausibleanalytics/stop.json.ts @@ -1,9 +1,7 @@ import { getUserDetails, removeDestinationDocker } from '$lib/common'; -import { getDomain } from '$lib/components/common'; import * as db from '$lib/database'; import { ErrorHandler } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy'; +import { checkContainer } from '$lib/haproxy'; import type { RequestHandler } from '@sveltejs/kit'; export const post: RequestHandler = async (event) => { @@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => { try { const service = await db.getService({ id, teamId }); const { destinationDockerId, destinationDocker, fqdn } = service; - const domain = getDomain(fqdn); if (destinationDockerId) { const engine = destinationDocker.engine; @@ -36,12 +33,6 @@ export const post: RequestHandler = async (event) => { } catch (error) { console.error(error); } - - try { - await configureSimpleServiceProxyOff(fqdn); - } catch (error) { - console.log(error); - } } return { diff --git a/src/routes/services/[id]/vaultwarden/start.json.ts b/src/routes/services/[id]/vaultwarden/start.json.ts index 37482faef..f42481200 100644 --- a/src/routes/services/[id]/vaultwarden/start.json.ts +++ b/src/routes/services/[id]/vaultwarden/start.json.ts @@ -3,15 +3,6 @@ import * as db from '$lib/database'; import { promises as fs } from 'fs'; import yaml from 'js-yaml'; import type { RequestHandler } from '@sveltejs/kit'; -import { letsEncrypt } from '$lib/letsencrypt'; -import { - checkHAProxy, - checkProxyConfigurations, - configureSimpleServiceProxyOn, - reloadHaproxy, - setWwwRedirection -} from '$lib/haproxy'; -import { getDomain } from '$lib/components/common'; import { getServiceImage, ErrorHandler } from '$lib/database'; import { makeLabelForServices } from '$lib/buildPacks/common'; @@ -22,12 +13,8 @@ export const post: RequestHandler = async (event) => { const { id } = event.params; try { - await checkHAProxy(); const service = await db.getService({ id, teamId }); - const { type, version, fqdn, destinationDockerId, destinationDocker } = service; - - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); + const { type, version, destinationDockerId, destinationDocker } = service; const network = destinationDockerId && destinationDocker.network; const host = getEngine(destinationDocker.engine); @@ -74,14 +61,6 @@ 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 }); - - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/vaultwarden/stop.json.ts b/src/routes/services/[id]/vaultwarden/stop.json.ts index f15ba1012..3c3bfbc62 100644 --- a/src/routes/services/[id]/vaultwarden/stop.json.ts +++ b/src/routes/services/[id]/vaultwarden/stop.json.ts @@ -1,9 +1,7 @@ import { getUserDetails, removeDestinationDocker } from '$lib/common'; -import { getDomain } from '$lib/components/common'; import * as db from '$lib/database'; import { ErrorHandler } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy'; +import { checkContainer } from '$lib/haproxy'; import type { RequestHandler } from '@sveltejs/kit'; export const post: RequestHandler = async (event) => { @@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => { try { const service = await db.getService({ id, teamId }); const { destinationDockerId, destinationDocker, fqdn } = service; - const domain = getDomain(fqdn); if (destinationDockerId) { const engine = destinationDocker.engine; @@ -27,13 +24,7 @@ export const post: RequestHandler = async (event) => { } catch (error) { console.error(error); } - try { - await configureSimpleServiceProxyOff(fqdn); - } catch (error) { - console.log(error); - } } - 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..29bf3326a 100644 --- a/src/routes/services/[id]/vscodeserver/start.json.ts +++ b/src/routes/services/[id]/vscodeserver/start.json.ts @@ -3,15 +3,6 @@ import * as db from '$lib/database'; import { promises as fs } from 'fs'; import yaml from 'js-yaml'; import type { RequestHandler } from '@sveltejs/kit'; -import { letsEncrypt } from '$lib/letsencrypt'; -import { - checkHAProxy, - checkProxyConfigurations, - configureSimpleServiceProxyOn, - reloadHaproxy, - setWwwRedirection -} from '$lib/haproxy'; -import { getDomain } from '$lib/components/common'; import { ErrorHandler } from '$lib/database'; import { makeLabelForServices } from '$lib/buildPacks/common'; @@ -22,20 +13,15 @@ export const post: RequestHandler = async (event) => { const { id } = event.params; try { - await checkHAProxy(); const service = await db.getService({ id, teamId }); const { type, version, - fqdn, destinationDockerId, destinationDocker, vscodeserver: { password } } = service; - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - const network = destinationDockerId && destinationDocker.network; const host = getEngine(destinationDocker.engine); @@ -84,14 +70,6 @@ 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 }); - - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/vscodeserver/stop.json.ts b/src/routes/services/[id]/vscodeserver/stop.json.ts index cf748b709..3c3bfbc62 100644 --- a/src/routes/services/[id]/vscodeserver/stop.json.ts +++ b/src/routes/services/[id]/vscodeserver/stop.json.ts @@ -1,9 +1,7 @@ import { getUserDetails, removeDestinationDocker } from '$lib/common'; -import { getDomain } from '$lib/components/common'; import * as db from '$lib/database'; import { ErrorHandler } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy'; +import { checkContainer } from '$lib/haproxy'; import type { RequestHandler } from '@sveltejs/kit'; export const post: RequestHandler = async (event) => { @@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => { try { const service = await db.getService({ id, teamId }); const { destinationDockerId, destinationDocker, fqdn } = service; - const domain = getDomain(fqdn); if (destinationDockerId) { const engine = destinationDocker.engine; @@ -27,11 +24,6 @@ export const post: RequestHandler = async (event) => { } catch (error) { console.error(error); } - try { - await configureSimpleServiceProxyOff(fqdn); - } catch (error) { - console.log(error); - } } 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..54080478e 100644 --- a/src/routes/services/[id]/wordpress/start.json.ts +++ b/src/routes/services/[id]/wordpress/start.json.ts @@ -3,15 +3,6 @@ import * as db from '$lib/database'; import { promises as fs } from 'fs'; import yaml from 'js-yaml'; import type { RequestHandler } from '@sveltejs/kit'; -import { letsEncrypt } from '$lib/letsencrypt'; -import { - checkHAProxy, - checkProxyConfigurations, - configureSimpleServiceProxyOn, - reloadHaproxy, - setWwwRedirection -} from '$lib/haproxy'; -import { getDomain } from '$lib/components/common'; import { ErrorHandler } from '$lib/database'; import { makeLabelForServices } from '$lib/buildPacks/common'; @@ -22,7 +13,6 @@ export const post: RequestHandler = async (event) => { const { id } = event.params; try { - await checkHAProxy(); const service = await db.getService({ id, teamId }); const { type, @@ -40,9 +30,6 @@ export const post: RequestHandler = async (event) => { } } = service; - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - const network = destinationDockerId && destinationDocker.network; const host = getEngine(destinationDocker.engine); @@ -121,14 +108,6 @@ 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 }); - - if (isHttps) { - await letsEncrypt({ domain, id }); - } - await setWwwRedirection(fqdn); - await reloadHaproxy(destinationDocker.engine); return { status: 200 }; diff --git a/src/routes/services/[id]/wordpress/stop.json.ts b/src/routes/services/[id]/wordpress/stop.json.ts index 800a62de3..2fc32b5a1 100644 --- a/src/routes/services/[id]/wordpress/stop.json.ts +++ b/src/routes/services/[id]/wordpress/stop.json.ts @@ -1,9 +1,7 @@ import { getUserDetails, removeDestinationDocker } from '$lib/common'; -import { getDomain } from '$lib/components/common'; import * as db from '$lib/database'; import { ErrorHandler } from '$lib/database'; -import { dockerInstance } from '$lib/docker'; -import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy'; +import { checkContainer } from '$lib/haproxy'; import type { RequestHandler } from '@sveltejs/kit'; export const post: RequestHandler = async (event) => { @@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => { try { const service = await db.getService({ id, teamId }); const { destinationDockerId, destinationDocker, fqdn } = service; - const domain = getDomain(fqdn); if (destinationDockerId) { const engine = destinationDocker.engine; try { @@ -30,11 +27,6 @@ export const post: RequestHandler = async (event) => { } catch (error) { console.error(error); } - try { - await configureSimpleServiceProxyOff(fqdn); - } catch (error) { - console.log(error); - } } return { diff --git a/src/routes/settings/index.json.ts b/src/routes/settings/index.json.ts index bb823ed58..163877fb0 100644 --- a/src/routes/settings/index.json.ts +++ b/src/routes/settings/index.json.ts @@ -1,18 +1,6 @@ -import { dev } from '$app/env'; -import { getDomain, getUserDetails } from '$lib/common'; +import { getUserDetails } from '$lib/common'; import * as db from '$lib/database'; import { listSettings, ErrorHandler } from '$lib/database'; -import { - checkProxyConfigurations, - configureCoolifyProxyOff, - configureCoolifyProxyOn, - forceSSLOnApplication, - reloadHaproxy, - removeWwwRedirection, - setWwwRedirection, - startCoolifyProxy -} from '$lib/haproxy'; -import { letsEncrypt } from '$lib/letsencrypt'; import type { RequestHandler } from '@sveltejs/kit'; import { promises as dns } from 'dns'; @@ -52,10 +40,7 @@ export const del: RequestHandler = async (event) => { // Do not care. } try { - const domain = getDomain(fqdn); await db.prisma.setting.update({ where: { fqdn }, data: { fqdn: null } }); - await configureCoolifyProxyOff(fqdn); - await removeWwwRedirection(domain); return { status: 200, body: { @@ -80,50 +65,19 @@ export const post: RequestHandler = async (event) => { const { fqdn, isRegistrationEnabled, dualCerts, minPort, maxPort } = await event.request.json(); try { - await checkProxyConfigurations(); - const { - id, - fqdn: oldFqdn, - isRegistrationEnabled: oldIsRegistrationEnabled, - dualCerts: oldDualCerts - } = await db.listSettings(); - if (oldIsRegistrationEnabled !== isRegistrationEnabled) { + const { id } = await db.listSettings(); + if (isRegistrationEnabled) { await db.prisma.setting.update({ where: { id }, data: { isRegistrationEnabled } }); } - if (oldDualCerts !== dualCerts) { - await db.prisma.setting.update({ where: { id }, data: { dualCerts } }); - } - if (oldFqdn && oldFqdn !== fqdn) { - if (oldFqdn) { - const oldDomain = getDomain(oldFqdn); - await configureCoolifyProxyOff(oldFqdn); - await removeWwwRedirection(oldDomain); - } - } if (fqdn) { - await startCoolifyProxy('/var/run/docker.sock'); - const domain = getDomain(fqdn); - const isHttps = fqdn.startsWith('https://'); - if (domain) { - await configureCoolifyProxyOn(fqdn); - await setWwwRedirection(fqdn); - if (isHttps) { - await letsEncrypt({ domain, isCoolify: true }); - await forceSSLOnApplication(domain); - await reloadHaproxy('/var/run/docker.sock'); - } - } - await db.prisma.setting.update({ where: { id }, data: { fqdn } }); - await db.prisma.destinationDocker.updateMany({ - where: { engine: '/var/run/docker.sock' }, - data: { isCoolifyProxyUsed: true } - }); + } + if (dualCerts) { + await db.prisma.setting.update({ where: { id }, data: { dualCerts } }); } if (minPort && maxPort) { await db.prisma.setting.update({ where: { id }, data: { minPort, maxPort } }); } - return { status: 201 }; diff --git a/src/routes/settings/index.svelte b/src/routes/settings/index.svelte index 0db5122aa..bf6ee64c3 100644 --- a/src/routes/settings/index.svelte +++ b/src/routes/settings/index.svelte @@ -78,6 +78,7 @@ if (fqdn !== settings.fqdn) { await post(`/settings/check.json`, { fqdn }); await post(`/settings.json`, { fqdn }); + return window.location.reload(); } if (minPort !== settings.minPort || maxPort !== settings.maxPort) { await post(`/settings.json`, { minPort, maxPort }); @@ -98,7 +99,7 @@ {#if $session.teamId === '0'}
-
+
Global Settings