fix: Improved tcp proxy monitoring for databases/ftp
This commit is contained in:
parent
ce2757f514
commit
2bd3802a6f
@ -9,6 +9,7 @@ import { default as ProdPrisma } from '@prisma/client';
|
||||
import type { Database, DatabaseSettings } from '@prisma/client';
|
||||
import generator from 'generate-password';
|
||||
import forge from 'node-forge';
|
||||
import getPort, { portNumbers } from 'get-port';
|
||||
|
||||
export function generatePassword(length = 24): string {
|
||||
return generator.generate({
|
||||
@ -251,3 +252,29 @@ export function generateDatabaseConfiguration(database: Database & { settings: D
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFreePort() {
|
||||
const data = await prisma.setting.findFirst();
|
||||
const { minPort, maxPort } = data;
|
||||
|
||||
const dbUsed = await (
|
||||
await prisma.database.findMany({
|
||||
where: { publicPort: { not: null } },
|
||||
select: { publicPort: true }
|
||||
})
|
||||
).map((a) => a.publicPort);
|
||||
const wpFtpUsed = await (
|
||||
await prisma.wordpress.findMany({
|
||||
where: { ftpPublicPort: { not: null } },
|
||||
select: { ftpPublicPort: true }
|
||||
})
|
||||
).map((a) => a.ftpPublicPort);
|
||||
const wpUsed = await (
|
||||
await prisma.wordpress.findMany({
|
||||
where: { mysqlPublicPort: { not: null } },
|
||||
select: { mysqlPublicPort: true }
|
||||
})
|
||||
).map((a) => a.mysqlPublicPort);
|
||||
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed];
|
||||
return await getPort({ port: portNumbers(minPort, maxPort), exclude: usedPorts });
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import builder from './builder';
|
||||
import logger from './logger';
|
||||
import cleanup from './cleanup';
|
||||
import proxy from './proxy';
|
||||
import proxyTcpHttp from './proxyTcpHttp';
|
||||
import ssl from './ssl';
|
||||
import sslrenewal from './sslrenewal';
|
||||
|
||||
@ -29,17 +30,20 @@ const connectionOptions = {
|
||||
|
||||
const cron = async (): Promise<void> => {
|
||||
new QueueScheduler('proxy', connectionOptions);
|
||||
new QueueScheduler('proxyTcpHttp', connectionOptions);
|
||||
new QueueScheduler('cleanup', connectionOptions);
|
||||
new QueueScheduler('ssl', connectionOptions);
|
||||
new QueueScheduler('sslRenew', connectionOptions);
|
||||
|
||||
const queue = {
|
||||
proxy: new Queue('proxy', { ...connectionOptions }),
|
||||
proxyTcpHttp: new Queue('proxyTcpHttp', { ...connectionOptions }),
|
||||
cleanup: new Queue('cleanup', { ...connectionOptions }),
|
||||
ssl: new Queue('ssl', { ...connectionOptions }),
|
||||
sslRenew: new Queue('sslRenew', { ...connectionOptions })
|
||||
};
|
||||
await queue.proxy.drain();
|
||||
await queue.proxyTcpHttp.drain();
|
||||
await queue.cleanup.drain();
|
||||
await queue.ssl.drain();
|
||||
await queue.sslRenew.drain();
|
||||
@ -54,6 +58,16 @@ const cron = async (): Promise<void> => {
|
||||
}
|
||||
);
|
||||
|
||||
new Worker(
|
||||
'proxyTcpHttp',
|
||||
async () => {
|
||||
await proxyTcpHttp();
|
||||
},
|
||||
{
|
||||
...connectionOptions
|
||||
}
|
||||
);
|
||||
|
||||
new Worker(
|
||||
'ssl',
|
||||
async () => {
|
||||
@ -85,6 +99,7 @@ const cron = async (): Promise<void> => {
|
||||
);
|
||||
|
||||
await queue.proxy.add('proxy', {}, { repeat: { every: 10000 } });
|
||||
await queue.proxyTcpHttp.add('proxyTcpHttp', {}, { repeat: { every: 10000 } });
|
||||
await queue.ssl.add('ssl', {}, { repeat: { every: dev ? 10000 : 60000 } });
|
||||
if (!dev) await queue.cleanup.add('cleanup', {}, { repeat: { every: 300000 } });
|
||||
await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } });
|
||||
|
34
src/lib/queues/proxyTcpHttp.ts
Normal file
34
src/lib/queues/proxyTcpHttp.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { ErrorHandler, generateDatabaseConfiguration, prisma } from '$lib/database';
|
||||
import { checkContainer, startTcpProxy } from '$lib/haproxy';
|
||||
|
||||
export default async function (): Promise<void | {
|
||||
status: number;
|
||||
body: { message: string; error: string };
|
||||
}> {
|
||||
try {
|
||||
const databasesWithPublicPort = await prisma.database.findMany({
|
||||
where: { publicPort: { not: null } },
|
||||
include: { settings: true, destinationDocker: true }
|
||||
});
|
||||
for (const database of databasesWithPublicPort) {
|
||||
const { destinationDockerId, destinationDocker, publicPort, id } = database;
|
||||
if (destinationDockerId) {
|
||||
const { privatePort } = generateDatabaseConfiguration(database);
|
||||
await startTcpProxy(destinationDocker, id, publicPort, privatePort);
|
||||
}
|
||||
}
|
||||
const wordpressWithFtp = await prisma.wordpress.findMany({
|
||||
where: { ftpPublicPort: { not: null } },
|
||||
include: { service: { include: { destinationDocker: true } } }
|
||||
});
|
||||
for (const ftp of wordpressWithFtp) {
|
||||
const { service, ftpPublicPort, id } = ftp;
|
||||
const { destinationDockerId, destinationDocker } = service;
|
||||
if (destinationDockerId) {
|
||||
await startTcpProxy(destinationDocker, `${id}-ftp`, ftpPublicPort, 22);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return ErrorHandler(error.response?.body || error);
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@
|
||||
name="rootUserPassword"
|
||||
bind:value={database.rootUserPassword}
|
||||
/>
|
||||
<Explainer text="Could be changed while the database is running." />
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="dbUser" class="text-base font-bold text-stone-100">User</label>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { getUserDetails } from '$lib/common';
|
||||
import * as db from '$lib/database';
|
||||
import { ErrorHandler, stopDatabase } from '$lib/database';
|
||||
import { deleteProxy } from '$lib/haproxy';
|
||||
import { stopTcpHttpProxy } from '$lib/haproxy';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
export const del: RequestHandler = async (event) => {
|
||||
@ -12,7 +12,7 @@ export const del: RequestHandler = async (event) => {
|
||||
const database = await db.getDatabase({ id, teamId });
|
||||
if (database.destinationDockerId) {
|
||||
const everStarted = await stopDatabase(database);
|
||||
if (everStarted) await deleteProxy({ id });
|
||||
if (everStarted) await stopTcpHttpProxy(database.destinationDocker, database.publicPort);
|
||||
}
|
||||
await db.removeDatabase({ id });
|
||||
return { status: 200 };
|
||||
|
@ -1,20 +1,16 @@
|
||||
import { getUserDetails } from '$lib/common';
|
||||
import * as db from '$lib/database';
|
||||
import { generateDatabaseConfiguration, ErrorHandler } from '$lib/database';
|
||||
import { generateDatabaseConfiguration, ErrorHandler, getFreePort } from '$lib/database';
|
||||
import { startTcpProxy, stopTcpHttpProxy } from '$lib/haproxy';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import getPort, { portNumbers } from 'get-port';
|
||||
|
||||
export const post: RequestHandler = async (event) => {
|
||||
const { status, body, teamId } = await getUserDetails(event);
|
||||
if (status === 401) return { status, body };
|
||||
|
||||
const { id } = event.params;
|
||||
const data = await db.prisma.setting.findFirst();
|
||||
const { minPort, maxPort } = data;
|
||||
|
||||
const { isPublic, appendOnly = true } = await event.request.json();
|
||||
const publicPort = await getPort({ port: portNumbers(minPort, maxPort) });
|
||||
const publicPort = await getFreePort();
|
||||
|
||||
try {
|
||||
await db.setDatabase({ id, isPublic, appendOnly });
|
||||
|
@ -4,9 +4,7 @@ import { promises as fs } from 'fs';
|
||||
import yaml from 'js-yaml';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import { startHttpProxy } from '$lib/haproxy';
|
||||
import getPort, { portNumbers } from 'get-port';
|
||||
import { getDomain } from '$lib/components/common';
|
||||
import { ErrorHandler, getServiceImage } from '$lib/database';
|
||||
import { ErrorHandler, getFreePort, getServiceImage } from '$lib/database';
|
||||
import { makeLabelForServices } from '$lib/buildPacks/common';
|
||||
import type { ComposeFile } from '$lib/types/composeFile';
|
||||
|
||||
@ -28,13 +26,10 @@ export const post: RequestHandler = async (event) => {
|
||||
serviceSecret
|
||||
} = service;
|
||||
|
||||
const data = await db.prisma.setting.findFirst();
|
||||
const { minPort, maxPort } = data;
|
||||
|
||||
const network = destinationDockerId && destinationDocker.network;
|
||||
const host = getEngine(destinationDocker.engine);
|
||||
|
||||
const publicPort = await getPort({ port: portNumbers(minPort, maxPort) });
|
||||
const publicPort = await getFreePort();
|
||||
|
||||
const consolePort = 9001;
|
||||
const apiPort = 9000;
|
||||
|
@ -2,7 +2,7 @@ import { dev } from '$app/env';
|
||||
import { asyncExecShell, getEngine, getUserDetails } from '$lib/common';
|
||||
import { decrypt, encrypt } from '$lib/crypto';
|
||||
import * as db from '$lib/database';
|
||||
import { generateDatabaseConfiguration, ErrorHandler, generatePassword } from '$lib/database';
|
||||
import { ErrorHandler, generatePassword, getFreePort } from '$lib/database';
|
||||
import { checkContainer, startTcpProxy, stopTcpHttpProxy } from '$lib/haproxy';
|
||||
import type { ComposeFile } from '$lib/types/composeFile';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
@ -16,11 +16,10 @@ export const post: RequestHandler = async (event) => {
|
||||
if (status === 401) return { status, body };
|
||||
|
||||
const { id } = event.params;
|
||||
const data = await db.prisma.setting.findFirst();
|
||||
const { minPort, maxPort } = data;
|
||||
|
||||
const { ftpEnabled } = await event.request.json();
|
||||
const publicPort = await getPort({ port: portNumbers(minPort, maxPort) });
|
||||
const publicPort = await getFreePort();
|
||||
|
||||
let ftpUser = cuid();
|
||||
let ftpPassword = generatePassword();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user