WIP: Traefik
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
</script>
|
||||
|
||||
<script>
|
||||
export let settings;
|
||||
import '../tailwind.css';
|
||||
import { SvelteToast, toast } from '@zerodevx/svelte-toast';
|
||||
import { page, session } from '$app/stores';
|
||||
@@ -42,9 +43,11 @@
|
||||
import { asyncSleep } from '$lib/components/common';
|
||||
import { del, get, post } from '$lib/api';
|
||||
import { dev } from '$app/env';
|
||||
import { features } from '$lib/store';
|
||||
let isUpdateAvailable = false;
|
||||
import { features, isTraefikUsed } from '$lib/store';
|
||||
|
||||
$isTraefikUsed = settings?.isTraefikUsed || false;
|
||||
|
||||
let isUpdateAvailable = false;
|
||||
let updateStatus = {
|
||||
found: false,
|
||||
loading: false,
|
||||
@@ -124,13 +127,6 @@
|
||||
return errorNotification(error);
|
||||
}
|
||||
}
|
||||
async function migrateToTraefik() {
|
||||
try {
|
||||
await post(`/update.json`, { type: 'migrateToTraefik' });
|
||||
} catch ({ error }) {
|
||||
return errorNotification(error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -522,13 +518,15 @@
|
||||
>Powered by <a href="https://coolify.io" target="_blank">Coolify</a></span
|
||||
>
|
||||
{/if}
|
||||
<span class="fixed bottom-[20px] right-[10px] z-50 m-2 px-4 text-xs ">
|
||||
<button on:click={migrateToTraefik}
|
||||
>New proxy is available! <br />It is based on Traefik! Why?<br /><br />Haproxy uses a lots of
|
||||
unnecessary memory. The update will cause a small interruption, but everything should go back
|
||||
to normal in a few seconds!</button
|
||||
>
|
||||
</span>
|
||||
{#if !$isTraefikUsed}
|
||||
<span class="fixed bottom-[20px] right-[10px] z-50 m-2 px-4 text-xs ">
|
||||
<a href="/settings"
|
||||
><button class="bg-coollabs hover:bg-coollabs-100"
|
||||
>New proxy is available! <br />Click here to get more details</button
|
||||
></a
|
||||
>
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
<main>
|
||||
<slot />
|
||||
|
||||
@@ -49,6 +49,7 @@ export const get: RequestHandler = async (event) => {
|
||||
where: { userId },
|
||||
include: { team: { include: { _count: { select: { users: true } } } } }
|
||||
});
|
||||
const settings = await db.prisma.setting.findFirst();
|
||||
return {
|
||||
body: {
|
||||
teams,
|
||||
@@ -57,7 +58,8 @@ export const get: RequestHandler = async (event) => {
|
||||
destinationsCount,
|
||||
teamsCount,
|
||||
databasesCount,
|
||||
servicesCount
|
||||
servicesCount,
|
||||
settings
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getUserDetails } from '$lib/common';
|
||||
import * as db from '$lib/database';
|
||||
import { generateDatabaseConfiguration, ErrorHandler, getFreePort } from '$lib/database';
|
||||
import { startTcpProxy, stopTcpHttpProxy } from '$lib/haproxy';
|
||||
import { startTcpProxy, startTraefikTCPProxy, stopTcpHttpProxy } from '$lib/haproxy';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
export const post: RequestHandler = async (event) => {
|
||||
@@ -13,6 +13,7 @@ export const post: RequestHandler = async (event) => {
|
||||
const publicPort = await getFreePort();
|
||||
|
||||
try {
|
||||
const settings = await db.listSettings();
|
||||
await db.setDatabase({ id, isPublic, appendOnly });
|
||||
const database = await db.getDatabase({ id, teamId });
|
||||
const { destinationDockerId, destinationDocker, publicPort: oldPublicPort } = database;
|
||||
@@ -21,7 +22,11 @@ export const post: RequestHandler = async (event) => {
|
||||
if (destinationDockerId) {
|
||||
if (isPublic) {
|
||||
await db.prisma.database.update({ where: { id }, data: { publicPort } });
|
||||
await startTcpProxy(destinationDocker, id, publicPort, privatePort);
|
||||
if (settings.isTraefikUsed) {
|
||||
await startTraefikTCPProxy(destinationDocker, id, publicPort, privatePort);
|
||||
} else {
|
||||
await startTcpProxy(destinationDocker, id, publicPort, privatePort);
|
||||
}
|
||||
} else {
|
||||
await db.prisma.database.update({ where: { id }, data: { publicPort: null } });
|
||||
await stopTcpHttpProxy(destinationDocker, oldPublicPort);
|
||||
|
||||
@@ -26,8 +26,12 @@ export const get: RequestHandler = async (event) => {
|
||||
// // await saveSshKey(destination);
|
||||
// payload.state = await checkContainer(engine, 'coolify-haproxy');
|
||||
} else {
|
||||
let containerName = 'coolify-proxy';
|
||||
if (!settings.isTraefikUsed) {
|
||||
containerName = 'coolify-haproxy';
|
||||
}
|
||||
payload.state =
|
||||
destination?.engine && (await checkContainer(destination.engine, 'coolify-haproxy'));
|
||||
destination?.engine && (await checkContainer(destination.engine, containerName));
|
||||
}
|
||||
return {
|
||||
status: 200,
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { getUserDetails } from '$lib/common';
|
||||
import { ErrorHandler } from '$lib/database';
|
||||
import * as db from '$lib/database';
|
||||
import { startCoolifyProxy, stopCoolifyProxy } from '$lib/haproxy';
|
||||
import {
|
||||
startCoolifyProxy,
|
||||
startTraefikProxy,
|
||||
stopCoolifyProxy,
|
||||
stopTraefikProxy
|
||||
} from '$lib/haproxy';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
export const post: RequestHandler = async (event) => {
|
||||
@@ -11,9 +16,16 @@ export const post: RequestHandler = async (event) => {
|
||||
const { engine } = await event.request.json();
|
||||
|
||||
try {
|
||||
await stopCoolifyProxy(engine);
|
||||
await startCoolifyProxy(engine);
|
||||
const settings = await db.prisma.setting.findFirst({});
|
||||
if (settings?.isTraefikUsed) {
|
||||
await stopTraefikProxy(engine);
|
||||
await startTraefikProxy(engine);
|
||||
} else {
|
||||
await stopCoolifyProxy(engine);
|
||||
await startCoolifyProxy(engine);
|
||||
}
|
||||
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: true });
|
||||
|
||||
return {
|
||||
status: 200
|
||||
};
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { getUserDetails } from '$lib/common';
|
||||
import { ErrorHandler } from '$lib/database';
|
||||
import { startCoolifyProxy, stopCoolifyProxy } from '$lib/haproxy';
|
||||
import * as db from '$lib/database';
|
||||
import {
|
||||
startCoolifyProxy,
|
||||
startTraefikProxy,
|
||||
stopCoolifyProxy,
|
||||
stopTraefikProxy
|
||||
} from '$lib/haproxy';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
export const post: RequestHandler = async (event) => {
|
||||
@@ -8,14 +14,24 @@ export const post: RequestHandler = async (event) => {
|
||||
if (status === 401) return { status, body };
|
||||
|
||||
const { engine } = await event.request.json();
|
||||
const settings = await db.prisma.setting.findFirst({});
|
||||
|
||||
try {
|
||||
await startCoolifyProxy(engine);
|
||||
if (settings?.isTraefikUsed) {
|
||||
await startTraefikProxy(engine);
|
||||
} else {
|
||||
await startCoolifyProxy(engine);
|
||||
}
|
||||
|
||||
return {
|
||||
status: 200
|
||||
};
|
||||
} catch (error) {
|
||||
await stopCoolifyProxy(engine);
|
||||
if (settings?.isTraefikUsed) {
|
||||
await stopTraefikProxy(engine);
|
||||
} else {
|
||||
await stopCoolifyProxy(engine);
|
||||
}
|
||||
return ErrorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getUserDetails } from '$lib/common';
|
||||
import { ErrorHandler } from '$lib/database';
|
||||
import { stopCoolifyProxy } from '$lib/haproxy';
|
||||
import * as db from '$lib/database';
|
||||
import { stopCoolifyProxy, stopTraefikProxy } from '$lib/haproxy';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
export const post: RequestHandler = async (event) => {
|
||||
@@ -9,7 +10,13 @@ export const post: RequestHandler = async (event) => {
|
||||
|
||||
const { engine } = await event.request.json();
|
||||
try {
|
||||
await stopCoolifyProxy(engine);
|
||||
const settings = await db.prisma.setting.findFirst({});
|
||||
if (settings?.isTraefikUsed) {
|
||||
await stopTraefikProxy(engine);
|
||||
} else {
|
||||
await stopCoolifyProxy(engine);
|
||||
}
|
||||
|
||||
return {
|
||||
status: 200
|
||||
};
|
||||
|
||||
@@ -195,7 +195,6 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`;
|
||||
}
|
||||
};
|
||||
const composeFileDestination = `${workdir}/docker-compose.yaml`;
|
||||
console.log(JSON.stringify(composeFile, null, 2));
|
||||
await fs.writeFile(composeFileDestination, yaml.dump(composeFile));
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} pull`);
|
||||
await asyncExecShell(
|
||||
|
||||
@@ -3,7 +3,12 @@ import { asyncExecShell, getEngine, getUserDetails } from '$lib/common';
|
||||
import { decrypt, encrypt } from '$lib/crypto';
|
||||
import * as db from '$lib/database';
|
||||
import { ErrorHandler, generatePassword, getFreePort } from '$lib/database';
|
||||
import { checkContainer, startTcpProxy, stopTcpHttpProxy } from '$lib/haproxy';
|
||||
import {
|
||||
checkContainer,
|
||||
startTcpProxy,
|
||||
startTraefikTCPProxy,
|
||||
stopTcpHttpProxy
|
||||
} from '$lib/haproxy';
|
||||
import type { ComposeFile } from '$lib/types/composeFile';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import cuid from 'cuid';
|
||||
@@ -142,8 +147,12 @@ export const post: RequestHandler = async (event) => {
|
||||
await asyncExecShell(
|
||||
`DOCKER_HOST=${host} docker compose -f ${hostkeyDir}/${id}-docker-compose.yml up -d`
|
||||
);
|
||||
|
||||
await startTcpProxy(destinationDocker, `${id}-ftp`, publicPort, 22);
|
||||
const settings = await db.prisma.setting.findFirst();
|
||||
if (settings.isTraefikUsed) {
|
||||
await startTraefikTCPProxy(destinationDocker, `${id}-ftp`, publicPort, 22);
|
||||
} else {
|
||||
await startTcpProxy(destinationDocker, `${id}-ftp`, publicPort, 22);
|
||||
}
|
||||
} else {
|
||||
await db.prisma.wordpress.update({
|
||||
where: { serviceId: id },
|
||||
|
||||
@@ -72,8 +72,7 @@ export const post: RequestHandler = async (event) => {
|
||||
minPort,
|
||||
maxPort,
|
||||
isAutoUpdateEnabled,
|
||||
isDNSCheckEnabled,
|
||||
forceSave
|
||||
isDNSCheckEnabled
|
||||
} = await event.request.json();
|
||||
try {
|
||||
const { id } = await db.listSettings();
|
||||
|
||||
@@ -37,12 +37,13 @@
|
||||
import { getDomain } from '$lib/components/common';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import { t } from '$lib/translations';
|
||||
import { features } from '$lib/store';
|
||||
import { features, isTraefikUsed } from '$lib/store';
|
||||
|
||||
let isRegistrationEnabled = settings.isRegistrationEnabled;
|
||||
let dualCerts = settings.dualCerts;
|
||||
let isAutoUpdateEnabled = settings.isAutoUpdateEnabled;
|
||||
let isDNSCheckEnabled = settings.isDNSCheckEnabled;
|
||||
$isTraefikUsed = settings.isTraefikUsed;
|
||||
|
||||
let minPort = settings.minPort;
|
||||
let maxPort = settings.maxPort;
|
||||
@@ -55,7 +56,8 @@
|
||||
let isFqdnSet = !!settings.fqdn;
|
||||
let loading = {
|
||||
save: false,
|
||||
remove: false
|
||||
remove: false,
|
||||
proxyMigration: false
|
||||
};
|
||||
|
||||
async function removeFqdn() {
|
||||
@@ -86,6 +88,7 @@
|
||||
if (name === 'isDNSCheckEnabled') {
|
||||
isDNSCheckEnabled = !isDNSCheckEnabled;
|
||||
}
|
||||
|
||||
await post(`/settings.json`, {
|
||||
isRegistrationEnabled,
|
||||
dualCerts,
|
||||
@@ -156,6 +159,20 @@
|
||||
function resetView() {
|
||||
forceSave = false;
|
||||
}
|
||||
async function migrateProxy(to) {
|
||||
if (loading.proxyMigration) return;
|
||||
try {
|
||||
loading.proxyMigration = true;
|
||||
await post(`/update.json`, { type: to });
|
||||
const data = await get(`/settings.json`);
|
||||
$isTraefikUsed = data.settings.isTraefikUsed;
|
||||
return toast.push('Proxy migration completed.');
|
||||
} catch ({ error }) {
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
loading.proxyMigration = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex space-x-1 p-6 font-bold">
|
||||
@@ -192,6 +209,26 @@
|
||||
</div>
|
||||
<div class="grid grid-flow-row gap-2 px-10">
|
||||
<!-- <Language /> -->
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<div class="flex items-center py-4 pr-8">
|
||||
<div class="flex w-96 flex-col">
|
||||
<div class="text-xs font-bold text-stone-100 md:text-base">New Proxy Available!</div>
|
||||
<Explainer
|
||||
text="We are changing to <span class='text-sky-500 font-bold'>Traefik</span> as <span class='text-red-500 font-bold'>HAProxy</span> had several problems and uses a LOT of unnecessary memory (<span class='text-sky-500 font-bold'>~20MB</span> vs <span class='text-red-500 font-bold'>~200MB</span>).<br><br>You can switch back to HAProxy if something is not working and <span class='text-yellow-500 font-bold'>please let us know</span>!"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
disabled={loading.proxyMigration}
|
||||
class="bg-green-600 text-white hover:bg-green-500"
|
||||
on:click={() => migrateProxy($isTraefikUsed ? 'haproxy' : 'traefik')}
|
||||
>{loading.proxyMigration
|
||||
? 'Migrating...'
|
||||
: $isTraefikUsed
|
||||
? 'Switch back to HAProxy'
|
||||
: 'Migrate to Traefik'}</button
|
||||
>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-start">
|
||||
<div class="flex-col">
|
||||
<div class="pt-2 text-base font-bold text-stone-100">
|
||||
|
||||
@@ -1,152 +1,308 @@
|
||||
import { dev } from '$app/env';
|
||||
import { asyncExecShell, getDomain, getEngine } from '$lib/common';
|
||||
import { supportedServiceTypesAndVersions } from '$lib/components/common';
|
||||
import * as db from '$lib/database';
|
||||
import { listServicesWithIncludes } from '$lib/database';
|
||||
import { checkContainer } from '$lib/haproxy';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
export const get = async () => {
|
||||
const applications = await db.prisma.application.findMany({
|
||||
include: { destinationDocker: true, settings: true }
|
||||
});
|
||||
const data = {
|
||||
applications: [],
|
||||
services: [],
|
||||
coolify: []
|
||||
};
|
||||
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.replace('www.', '') : 'www.' + domain,
|
||||
updatedAt: updatedAt.getTime()
|
||||
});
|
||||
export const get: RequestHandler = async (event) => {
|
||||
const id = event.url.searchParams.get('id');
|
||||
if (id) {
|
||||
const privatePort = event.url.searchParams.get('privatePort');
|
||||
const publicPort = event.url.searchParams.get('publicPort');
|
||||
const type = event.url.searchParams.get('type');
|
||||
let traefik = {};
|
||||
if (publicPort) {
|
||||
traefik = {
|
||||
[type]: {
|
||||
routers: {
|
||||
[id]: {
|
||||
entrypoints: [type],
|
||||
rule: `HostSNI(\`*\`)`,
|
||||
service: id
|
||||
}
|
||||
},
|
||||
services: {
|
||||
[id]: {
|
||||
loadbalancer: {
|
||||
servers: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
const previewDomain = `${container.split('-')[1]}.${domain}`;
|
||||
data.applications.push({
|
||||
id: container,
|
||||
port: port || 3000,
|
||||
domain: previewDomain,
|
||||
};
|
||||
}
|
||||
if (type === 'tcp') {
|
||||
traefik[type].services[id].loadbalancer.servers.push({ address: `${id}:${privatePort}` });
|
||||
} else {
|
||||
traefik[type].services[id].loadbalancer.servers.push({ url: `http://${id}:${privatePort}` });
|
||||
}
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
...traefik
|
||||
}
|
||||
};
|
||||
} else {
|
||||
const applications = await db.prisma.application.findMany({
|
||||
include: { destinationDocker: true, settings: true }
|
||||
});
|
||||
const data = {
|
||||
applications: [],
|
||||
services: [],
|
||||
coolify: []
|
||||
};
|
||||
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.replace('www.', '') : '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) {
|
||||
const previewDomain = `${container.split('-')[1]}.${domain}`;
|
||||
data.applications.push({
|
||||
id: container,
|
||||
port: port || 3000,
|
||||
domain: previewDomain,
|
||||
isRunning,
|
||||
isHttps,
|
||||
redirectValue,
|
||||
redirectTo: isWWW ? previewDomain.replace('www.', '') : 'www.' + previewDomain,
|
||||
updatedAt: updatedAt.getTime()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const services = await listServicesWithIncludes();
|
||||
|
||||
for (const service of services) {
|
||||
const {
|
||||
fqdn,
|
||||
id,
|
||||
type,
|
||||
destinationDocker,
|
||||
destinationDockerId,
|
||||
updatedAt,
|
||||
plausibleAnalytics
|
||||
} = service;
|
||||
if (destinationDockerId) {
|
||||
const { engine } = destinationDocker;
|
||||
const found = 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) {
|
||||
// Plausible Analytics custom script
|
||||
let scriptName = false;
|
||||
if (
|
||||
type === 'plausibleanalytics' &&
|
||||
plausibleAnalytics.scriptName !== 'plausible.js'
|
||||
) {
|
||||
scriptName = plausibleAnalytics.scriptName;
|
||||
}
|
||||
|
||||
data.services.push({
|
||||
id,
|
||||
port,
|
||||
publicPort,
|
||||
domain,
|
||||
isRunning,
|
||||
isHttps,
|
||||
redirectValue,
|
||||
redirectTo: isWWW ? previewDomain.replace('www.', '') : 'www.' + previewDomain,
|
||||
updatedAt: updatedAt.getTime()
|
||||
redirectTo: isWWW ? domain.replace('www.', '') : 'www.' + domain,
|
||||
updatedAt: updatedAt.getTime(),
|
||||
scriptName
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const traefik = {
|
||||
http: {
|
||||
routers: {},
|
||||
services: {}
|
||||
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.replace('www.', '') : 'www.' + domain
|
||||
});
|
||||
}
|
||||
};
|
||||
for (const application of data.applications) {
|
||||
const { id, port, domain, isHttps, redirectValue, redirectTo, updatedAt } = application;
|
||||
traefik.http.routers[id] = {
|
||||
entrypoints: ['web'],
|
||||
rule: `Host(\`${domain}\`)`,
|
||||
service: id
|
||||
const traefik = {
|
||||
http: {
|
||||
routers: {},
|
||||
services: {}
|
||||
}
|
||||
};
|
||||
traefik.http.services[id] = {
|
||||
loadbalancer: {
|
||||
servers: [
|
||||
{
|
||||
url: `http://${id}:${port}`
|
||||
for (const application of data.applications) {
|
||||
const { id, port, domain, isHttps, redirectValue, redirectTo, updatedAt } = application;
|
||||
traefik.http.routers[id] = {
|
||||
entrypoints: ['web'],
|
||||
rule: `Host(\`${domain}\`)`,
|
||||
service: id
|
||||
};
|
||||
traefik.http.services[id] = {
|
||||
loadbalancer: {
|
||||
servers: [
|
||||
{
|
||||
url: `http://${id}:${port}`
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
for (const application of data.services) {
|
||||
const { id, port, domain, isHttps, redirectValue, redirectTo, updatedAt, scriptName } =
|
||||
application;
|
||||
|
||||
traefik.http.routers[id] = {
|
||||
entrypoints: ['web'],
|
||||
rule: `Host(\`${domain}\`)`,
|
||||
service: id
|
||||
};
|
||||
traefik.http.services[id] = {
|
||||
loadbalancer: {
|
||||
servers: [
|
||||
{
|
||||
url: `http://${id}:${port}`
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
if (scriptName) {
|
||||
if (!traefik.http.middlewares) traefik.http.middlewares = {};
|
||||
traefik.http.middlewares[`${id}-redir`] = {
|
||||
replacepathregex: {
|
||||
regex: `/js/${scriptName}`,
|
||||
replacement: '/js/plausible.js'
|
||||
}
|
||||
]
|
||||
};
|
||||
traefik.http.routers[id].middlewares = [`${id}-redir`];
|
||||
}
|
||||
}
|
||||
for (const application of data.coolify) {
|
||||
const { domain, id, port } = application;
|
||||
traefik.http.routers['coolify'] = {
|
||||
entrypoints: ['web'],
|
||||
rule: `Host(\`${domain}\`)`,
|
||||
service: id
|
||||
};
|
||||
traefik.http.services[id] = {
|
||||
loadbalancer: {
|
||||
servers: [
|
||||
{
|
||||
url: `http://${id}:${port}`
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
...traefik
|
||||
// "http": {
|
||||
// "routers": {
|
||||
// "coolify": {
|
||||
// "entrypoints": [
|
||||
// "web"
|
||||
// ],
|
||||
// "middlewares": [
|
||||
// "coolify-hc"
|
||||
// ],
|
||||
// "rule": "Host(`staging.coolify.io`)",
|
||||
// "service": "coolify"
|
||||
// },
|
||||
// "static.example.coolify.io": {
|
||||
// "entrypoints": [
|
||||
// "web"
|
||||
// ],
|
||||
// "rule": "Host(`static.example.coolify.io`)",
|
||||
// "service": "static.example.coolify.io"
|
||||
// }
|
||||
// },
|
||||
// "services": {
|
||||
// "coolify": {
|
||||
// "loadbalancer": {
|
||||
// "servers": [
|
||||
// {
|
||||
// "url": "http://coolify:3000"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
// "static.example.coolify.io": {
|
||||
// "loadbalancer": {
|
||||
// "servers": [
|
||||
// {
|
||||
// "url": "http://cl32p06f58068518cs3thg6vbc7:80"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "middlewares": {
|
||||
// "coolify-hc": {
|
||||
// "replacepathregex": {
|
||||
// "regex": "/dead.json",
|
||||
// "replacement": "/undead.json"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
...traefik
|
||||
// "http": {
|
||||
// "routers": {
|
||||
// "coolify": {
|
||||
// "entrypoints": [
|
||||
// "web"
|
||||
// ],
|
||||
// "middlewares": [
|
||||
// "coolify-hc"
|
||||
// ],
|
||||
// "rule": "Host(`staging.coolify.io`)",
|
||||
// "service": "coolify"
|
||||
// },
|
||||
// "static.example.coolify.io": {
|
||||
// "entrypoints": [
|
||||
// "web"
|
||||
// ],
|
||||
// "rule": "Host(`static.example.coolify.io`)",
|
||||
// "service": "static.example.coolify.io"
|
||||
// }
|
||||
// },
|
||||
// "services": {
|
||||
// "coolify": {
|
||||
// "loadbalancer": {
|
||||
// "servers": [
|
||||
// {
|
||||
// "url": "http://coolify:3000"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
// "static.example.coolify.io": {
|
||||
// "loadbalancer": {
|
||||
// "servers": [
|
||||
// {
|
||||
// "url": "http://cl32p06f58068518cs3thg6vbc7:80"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// "middlewares": {
|
||||
// "coolify-hc": {
|
||||
// "replacepathregex": {
|
||||
// "regex": "/dead.json",
|
||||
// "replacement": "/undead.json"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,6 +6,12 @@ import * as db from '$lib/database';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import compare from 'compare-versions';
|
||||
import got from 'got';
|
||||
import {
|
||||
checkContainer,
|
||||
configureNetworkTraefikProxy,
|
||||
startCoolifyProxy,
|
||||
startTraefikProxy
|
||||
} from '$lib/haproxy';
|
||||
|
||||
export const get: RequestHandler = async (request) => {
|
||||
try {
|
||||
@@ -34,14 +40,14 @@ export const get: RequestHandler = async (request) => {
|
||||
|
||||
export const post: RequestHandler = async (event) => {
|
||||
const { type, latestVersion } = await event.request.json();
|
||||
const settings = await db.prisma.setting.findFirst();
|
||||
if (type === 'update') {
|
||||
try {
|
||||
if (!dev) {
|
||||
const { isAutoUpdateEnabled } = await db.prisma.setting.findFirst();
|
||||
await asyncExecShell(`docker pull coollabsio/coolify:${latestVersion}`);
|
||||
await asyncExecShell(`env | grep COOLIFY > .env`);
|
||||
await asyncExecShell(
|
||||
`sed -i '/COOLIFY_AUTO_UPDATE=/c\COOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env`
|
||||
`sed -i '/COOLIFY_AUTO_UPDATE=/c\COOLIFY_AUTO_UPDATE=${settings.isAutoUpdateEnabled}' .env`
|
||||
);
|
||||
await asyncExecShell(
|
||||
`docker run --rm -tid --env-file .env -v /var/run/docker.sock:/var/run/docker.sock -v coolify-db coollabsio/coolify:${latestVersion} /bin/sh -c "env | grep COOLIFY > .env && echo 'TAG=${latestVersion}' >> .env && docker stop -t 0 coolify coolify-redis && docker rm coolify coolify-redis && docker compose up -d --force-recreate"`
|
||||
@@ -61,15 +67,37 @@ export const post: RequestHandler = async (event) => {
|
||||
} catch (error) {
|
||||
return ErrorHandler(error);
|
||||
}
|
||||
} else if (type === 'migrateToTraefik') {
|
||||
} else if (type === 'traefik') {
|
||||
try {
|
||||
const settings = await db.prisma.setting.findFirst({});
|
||||
const found = await checkContainer('/var/run/docker.sock', 'coolify-haproxy');
|
||||
if (found) {
|
||||
await asyncExecShell(`docker stop -t 0 coolify-haproxy`);
|
||||
await asyncExecShell(`docker rm coolify-haproxy`);
|
||||
}
|
||||
await startTraefikProxy('/var/run/docker.sock');
|
||||
await db.prisma.setting.update({
|
||||
where: { id: settings.id },
|
||||
data: { disableHaproxy: true }
|
||||
data: { isTraefikUsed: true }
|
||||
});
|
||||
return {
|
||||
status: 200,
|
||||
body: {}
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorHandler(error);
|
||||
}
|
||||
} else if (type === 'haproxy') {
|
||||
try {
|
||||
const found = await checkContainer('/var/run/docker.sock', 'coolify-proxy');
|
||||
if (found) {
|
||||
await asyncExecShell(`docker stop -t 0 coolify-proxy`);
|
||||
await asyncExecShell(`docker rm coolify-proxy`);
|
||||
}
|
||||
await startCoolifyProxy('/var/run/docker.sock');
|
||||
await db.prisma.setting.update({
|
||||
where: { id: settings.id },
|
||||
data: { isTraefikUsed: false }
|
||||
});
|
||||
await asyncExecShell(`docker stop -t 0 coolify-haproxy`);
|
||||
await asyncExecShell(`docker rm coolify-haproxy`);
|
||||
return {
|
||||
status: 200,
|
||||
body: {}
|
||||
|
||||
Reference in New Issue
Block a user