wip(fix): traefik

This commit is contained in:
Andras Bacsai 2022-05-18 12:32:53 +02:00
parent 59086e9eb4
commit dc3add495c
5 changed files with 64 additions and 58 deletions

View File

@ -108,6 +108,7 @@ export async function checkHAProxy(haproxy?: Got): Promise<void> {
} }
export async function stopTcpHttpProxy( export async function stopTcpHttpProxy(
id: string,
destinationDocker: DestinationDocker, destinationDocker: DestinationDocker,
publicPort: number, publicPort: number,
forceName: string = null forceName: string = null
@ -115,7 +116,7 @@ export async function stopTcpHttpProxy(
const { engine } = destinationDocker; const { engine } = destinationDocker;
const host = getEngine(engine); const host = getEngine(engine);
const settings = await db.listSettings(); const settings = await db.listSettings();
let containerName = `proxy-for-${publicPort}`; let containerName = `${id}-${publicPort}`;
if (!settings.isTraefikUsed) { if (!settings.isTraefikUsed) {
containerName = `haproxy-for-${publicPort}`; containerName = `haproxy-for-${publicPort}`;
} }
@ -141,7 +142,7 @@ export async function startTraefikTCPProxy(
const { network, engine } = destinationDocker; const { network, engine } = destinationDocker;
const host = getEngine(engine); const host = getEngine(engine);
const containerName = `proxy-for-${publicPort}`; const containerName = `${id}-${publicPort}`;
const found = await checkContainer(engine, containerName, true); const found = await checkContainer(engine, containerName, true);
const foundDependentContainer = await checkContainer(engine, id, true); const foundDependentContainer = await checkContainer(engine, id, true);
@ -154,8 +155,8 @@ export async function startTraefikTCPProxy(
const tcpProxy = { const tcpProxy = {
version: '3.5', version: '3.5',
services: { services: {
[id]: { [`${id}-${publicPort}`]: {
container_name: `proxy-for-${publicPort}`, container_name: containerName,
image: 'traefik:v2.6', image: 'traefik:v2.6',
command: [ command: [
`--entrypoints.tcp.address=:${publicPort}`, `--entrypoints.tcp.address=:${publicPort}`,
@ -241,7 +242,7 @@ export async function startTraefikHTTPProxy(
const { network, engine } = destinationDocker; const { network, engine } = destinationDocker;
const host = getEngine(engine); const host = getEngine(engine);
const containerName = `proxy-for-${publicPort}`; const containerName = `${id}-${publicPort}`;
const found = await checkContainer(engine, containerName, true); const found = await checkContainer(engine, containerName, true);
const foundDependentContainer = await checkContainer(engine, id, true); const foundDependentContainer = await checkContainer(engine, id, true);
@ -251,21 +252,21 @@ export async function startTraefikHTTPProxy(
`DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'` `DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'`
); );
const ip = JSON.parse(Config)[0].Gateway; const ip = JSON.parse(Config)[0].Gateway;
console.log({ privatePort, publicPort });
const tcpProxy = { const tcpProxy = {
version: '3.5', version: '3.5',
services: { services: {
[id]: { [`${id}-${publicPort}`]: {
container_name: `proxy-for-${publicPort}`, container_name: containerName,
image: 'traefik:v2.6', image: 'traefik:v2.6',
command: [ command: [
`--entrypoints.http.address=:${publicPort}`, `--entrypoints.http.address=:${publicPort}`,
`--providers.http.endpoint=${otherTraefikEndpoint}?id=${id}&privatePort=${privatePort}&publicPort=${publicPort}&type=http`, `--providers.http.endpoint=${otherTraefikEndpoint}?id=${id}&privatePort=${privatePort}&publicPort=${publicPort}&type=http`,
'--providers.http.pollTimeout=2s', '--providers.http.pollTimeout=2s',
'--log.level=error' '--log.level=debug'
], ],
ports: [`${publicPort}:${publicPort}`], ports: [`${publicPort}:${publicPort}`],
extra_hosts: ['host.docker.internal:host-gateway', `host.docker.internal:${ip}`], extra_hosts: ['host.docker.internal:host-gateway', `host.docker.internal:${ip}`],
volumes: ['/var/run/docker.sock:/var/run/docker.sock'],
networks: ['coolify-infra', network] networks: ['coolify-infra', network]
} }
}, },
@ -377,7 +378,7 @@ export async function startTraefikProxy(engine: string): Promise<void> {
--certificatesresolvers.letsencrypt.acme.httpchallenge=true \ --certificatesresolvers.letsencrypt.acme.httpchallenge=true \
--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json \ --certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json \
--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web \ --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web \
--log.level=error` --log.level=debug`
); );
await db.prisma.setting.update({ where: { id }, data: { proxyHash: null } }); await db.prisma.setting.update({ where: { id }, data: { proxyHash: null } });
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: true }); await db.setDestinationSettings({ engine, isCoolifyProxyUsed: true });

View File

@ -21,7 +21,7 @@ export default async function (): Promise<void | {
const engine = '/var/run/docker.sock'; const engine = '/var/run/docker.sock';
const settings = await prisma.setting.findFirst(); const settings = await prisma.setting.findFirst();
const localDocker = await prisma.destinationDocker.findFirst({ const localDocker = await prisma.destinationDocker.findFirst({
where: { engine } where: { engine, network: 'coolify' }
}); });
if (localDocker && localDocker.isCoolifyProxyUsed) { if (localDocker && localDocker.isCoolifyProxyUsed) {
if (settings.isTraefikUsed) { if (settings.isTraefikUsed) {
@ -46,10 +46,10 @@ export default async function (): Promise<void | {
if (destinationDocker.isCoolifyProxyUsed) { if (destinationDocker.isCoolifyProxyUsed) {
const { privatePort } = generateDatabaseConfiguration(database); const { privatePort } = generateDatabaseConfiguration(database);
if (settings.isTraefikUsed) { if (settings.isTraefikUsed) {
await stopTcpHttpProxy(destinationDocker, publicPort, `haproxy-for-${publicPort}`); await stopTcpHttpProxy(id, destinationDocker, publicPort, `haproxy-for-${publicPort}`);
await startTraefikTCPProxy(destinationDocker, id, publicPort, privatePort); await startTraefikTCPProxy(destinationDocker, id, publicPort, privatePort);
} else { } else {
await stopTcpHttpProxy(destinationDocker, publicPort, `proxy-for-${publicPort}`); await stopTcpHttpProxy(id, destinationDocker, publicPort, `${id}-${publicPort}`);
await startTcpProxy(destinationDocker, id, publicPort, privatePort); await startTcpProxy(destinationDocker, id, publicPort, privatePort);
} }
} }
@ -66,13 +66,14 @@ export default async function (): Promise<void | {
if (destinationDocker.isCoolifyProxyUsed) { if (destinationDocker.isCoolifyProxyUsed) {
if (settings.isTraefikUsed) { if (settings.isTraefikUsed) {
await stopTcpHttpProxy( await stopTcpHttpProxy(
id,
destinationDocker, destinationDocker,
ftpPublicPort, ftpPublicPort,
`haproxy-for-${ftpPublicPort}` `haproxy-for-${ftpPublicPort}`
); );
await startTraefikTCPProxy(destinationDocker, `${id}-ftp`, ftpPublicPort, 22); await startTraefikTCPProxy(destinationDocker, `${id}-ftp`, ftpPublicPort, 22);
} else { } else {
await stopTcpHttpProxy(destinationDocker, ftpPublicPort, `proxy-for-${ftpPublicPort}`); await stopTcpHttpProxy(id, destinationDocker, ftpPublicPort, `${id}-${ftpPublicPort}`);
await startTcpProxy(destinationDocker, `${id}-ftp`, ftpPublicPort, 22); await startTcpProxy(destinationDocker, `${id}-ftp`, ftpPublicPort, 22);
} }
} }
@ -90,10 +91,10 @@ export default async function (): Promise<void | {
if (destinationDockerId) { if (destinationDockerId) {
if (destinationDocker.isCoolifyProxyUsed) { if (destinationDocker.isCoolifyProxyUsed) {
if (settings.isTraefikUsed) { if (settings.isTraefikUsed) {
await stopTcpHttpProxy(destinationDocker, publicPort, `haproxy-for-${publicPort}`); await stopTcpHttpProxy(id, destinationDocker, publicPort, `haproxy-for-${publicPort}`);
await startTraefikHTTPProxy(destinationDocker, id, publicPort, 9000); await startTraefikHTTPProxy(destinationDocker, id, publicPort, 9000);
} else { } else {
await stopTcpHttpProxy(destinationDocker, publicPort, `proxy-for-${publicPort}`); await stopTcpHttpProxy(id, destinationDocker, publicPort, `${id}-${publicPort}`);
await startHttpProxy(destinationDocker, id, publicPort, 9000); await startHttpProxy(destinationDocker, id, publicPort, 9000);
} }
} }

View File

@ -3,7 +3,6 @@ import * as db from '$lib/database';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import yaml from 'js-yaml'; import yaml from 'js-yaml';
import type { RequestHandler } from '@sveltejs/kit'; import type { RequestHandler } from '@sveltejs/kit';
import { startHttpProxy } from '$lib/haproxy';
import { ErrorHandler, getFreePort, getServiceImage } from '$lib/database'; import { ErrorHandler, getFreePort, getServiceImage } from '$lib/database';
import { makeLabelForServices } from '$lib/buildPacks/common'; import { makeLabelForServices } from '$lib/buildPacks/common';
import type { ComposeFile } from '$lib/types/composeFile'; import type { ComposeFile } from '$lib/types/composeFile';
@ -95,7 +94,6 @@ export const post: RequestHandler = async (event) => {
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} pull`); await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} pull`);
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`); await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
await db.updateMinioService({ id, publicPort }); await db.updateMinioService({ id, publicPort });
await startHttpProxy(destinationDocker, id, publicPort, apiPort);
return { return {
status: 200 status: 200
}; };

View File

@ -6,38 +6,10 @@ import { listServicesWithIncludes } from '$lib/database';
import { checkContainer } from '$lib/haproxy'; import { checkContainer } from '$lib/haproxy';
import type { RequestHandler } from '@sveltejs/kit'; import type { RequestHandler } from '@sveltejs/kit';
const traefik = { function configureMiddleware(
http: { { id, port, domain, nakedDomain, isHttps, isWWW, isDualCerts },
routers: {}, traefik
services: {}, ) {
middlewares: {
'redirect-to-https': {
redirectscheme: {
scheme: 'https'
}
},
'redirect-to-http': {
redirectscheme: {
scheme: 'http'
}
},
'redirect-to-non-www': {
redirectregex: {
regex: '^https?://www\\.(.+)',
replacement: 'http://${1}'
}
},
'redirect-to-www': {
redirectregex: {
regex: '^https?://(?:www\\.)?(.+)',
replacement: 'http://www.${1}'
}
}
}
}
};
function configureMiddleware({ id, port, domain, nakedDomain, isHttps, isWWW, isDualCerts }) {
if (isHttps) { if (isHttps) {
traefik.http.routers[id] = { traefik.http.routers[id] = {
entrypoints: ['web'], entrypoints: ['web'],
@ -155,6 +127,36 @@ function configureMiddleware({ id, port, domain, nakedDomain, isHttps, isWWW, is
} }
} }
export const get: RequestHandler = async (event) => { export const get: RequestHandler = async (event) => {
const traefik = {
http: {
routers: {},
services: {},
middlewares: {
'redirect-to-https': {
redirectscheme: {
scheme: 'https'
}
},
'redirect-to-http': {
redirectscheme: {
scheme: 'http'
}
},
'redirect-to-non-www': {
redirectregex: {
regex: '^https?://www\\.(.+)',
replacement: 'http://${1}'
}
},
'redirect-to-www': {
redirectregex: {
regex: '^https?://(?:www\\.)?(.+)',
replacement: 'http://www.${1}'
}
}
}
}
};
const applications = await db.prisma.application.findMany({ const applications = await db.prisma.application.findMany({
include: { destinationDocker: true, settings: true } include: { destinationDocker: true, settings: true }
}); });
@ -230,7 +232,6 @@ export const get: RequestHandler = async (event) => {
type, type,
destinationDocker, destinationDocker,
destinationDockerId, destinationDockerId,
updatedAt,
dualCerts, dualCerts,
plausibleAnalytics plausibleAnalytics
} = service; } = service;
@ -288,11 +289,11 @@ export const get: RequestHandler = async (event) => {
}); });
} }
for (const application of data.applications) { for (const application of data.applications) {
configureMiddleware(application); configureMiddleware(application, traefik);
} }
for (const service of data.services) { for (const service of data.services) {
const { id, scriptName } = service; const { id, scriptName } = service;
configureMiddleware(service); configureMiddleware(service, traefik);
if (scriptName) { if (scriptName) {
traefik.http.middlewares[`${id}-redir`] = { traefik.http.middlewares[`${id}-redir`] = {
@ -309,9 +310,14 @@ export const get: RequestHandler = async (event) => {
} }
} }
for (const coolify of data.coolify) { for (const coolify of data.coolify) {
configureMiddleware(coolify); configureMiddleware(coolify, traefik);
}
if (Object.keys(traefik.http.routers).length === 0) {
traefik.http.routers = null;
}
if (Object.keys(traefik.http.services).length === 0) {
traefik.http.services = null;
} }
return { return {
status: 200, status: 200,
body: { body: {

View File

@ -40,14 +40,14 @@ export const get: RequestHandler = async (event) => {
traefik = { traefik = {
[type]: { [type]: {
routers: { routers: {
[id]: { [`${id}-${publicPort}`]: {
entrypoints: [type], entrypoints: [type],
rule: `Host(\`${domain}\`)`, rule: `Host(\`${domain}\`)`,
service: id service: `${id}-${publicPort}`
} }
}, },
services: { services: {
[id]: { [`${id}-${publicPort}`]: {
loadbalancer: { loadbalancer: {
servers: [{ url: `http://${id}:${privatePort}` }] servers: [{ url: `http://${id}:${privatePort}` }]
} }