wip: trpc
This commit is contained in:
@@ -823,3 +823,116 @@ export async function startTraefikTCPProxy(
|
||||
});
|
||||
}
|
||||
}
|
||||
export async function startTraefikProxy(id: string): Promise<void> {
|
||||
const { engine, network, remoteEngine, remoteIpAddress } =
|
||||
await prisma.destinationDocker.findUnique({ where: { id } });
|
||||
const { found } = await checkContainer({
|
||||
dockerId: id,
|
||||
container: 'coolify-proxy',
|
||||
remove: true
|
||||
});
|
||||
const { id: settingsId, ipv4, ipv6 } = await listSettings();
|
||||
|
||||
if (!found) {
|
||||
const { stdout: coolifyNetwork } = await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker network ls --filter 'name=coolify-infra' --no-trunc --format "{{json .}}"`
|
||||
});
|
||||
|
||||
if (!coolifyNetwork) {
|
||||
await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker network create --attachable coolify-infra`
|
||||
});
|
||||
}
|
||||
const { stdout: Config } = await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker network inspect ${network} --format '{{json .IPAM.Config }}'`
|
||||
});
|
||||
const ip = JSON.parse(Config)[0].Gateway;
|
||||
let traefikUrl = mainTraefikEndpoint;
|
||||
if (remoteEngine) {
|
||||
let ip = null;
|
||||
if (isDev) {
|
||||
ip = getAPIUrl();
|
||||
} else {
|
||||
ip = `http://${ipv4 || ipv6}:3000`;
|
||||
}
|
||||
traefikUrl = `${ip}/webhooks/traefik/remote/${id}`;
|
||||
}
|
||||
await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker run --restart always \
|
||||
--add-host 'host.docker.internal:host-gateway' \
|
||||
${ip ? `--add-host 'host.docker.internal:${ip}'` : ''} \
|
||||
-v coolify-traefik-letsencrypt:/etc/traefik/acme \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
--network coolify-infra \
|
||||
-p "80:80" \
|
||||
-p "443:443" \
|
||||
--name coolify-proxy \
|
||||
-d ${defaultTraefikImage} \
|
||||
--entrypoints.web.address=:80 \
|
||||
--entrypoints.web.forwardedHeaders.insecure=true \
|
||||
--entrypoints.websecure.address=:443 \
|
||||
--entrypoints.websecure.forwardedHeaders.insecure=true \
|
||||
--providers.docker=true \
|
||||
--providers.docker.exposedbydefault=false \
|
||||
--providers.http.endpoint=${traefikUrl} \
|
||||
--providers.http.pollTimeout=5s \
|
||||
--certificatesresolvers.letsencrypt.acme.httpchallenge=true \
|
||||
--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json \
|
||||
--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web \
|
||||
--log.level=error`
|
||||
});
|
||||
await prisma.destinationDocker.update({
|
||||
where: { id },
|
||||
data: { isCoolifyProxyUsed: true }
|
||||
});
|
||||
}
|
||||
// Configure networks for local docker engine
|
||||
if (engine) {
|
||||
const destinations = await prisma.destinationDocker.findMany({ where: { engine } });
|
||||
for (const destination of destinations) {
|
||||
await configureNetworkTraefikProxy(destination);
|
||||
}
|
||||
}
|
||||
// Configure networks for remote docker engine
|
||||
if (remoteEngine) {
|
||||
const destinations = await prisma.destinationDocker.findMany({ where: { remoteIpAddress } });
|
||||
for (const destination of destinations) {
|
||||
await configureNetworkTraefikProxy(destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function configureNetworkTraefikProxy(destination: any): Promise<void> {
|
||||
const { id } = destination;
|
||||
const { stdout: networks } = await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker ps -a --filter name=coolify-proxy --format '{{json .Networks}}'`
|
||||
});
|
||||
const configuredNetworks = networks.replace(/"/g, '').replace('\n', '').split(',');
|
||||
if (!configuredNetworks.includes(destination.network)) {
|
||||
await executeCommand({
|
||||
dockerId: destination.id,
|
||||
command: `docker network connect ${destination.network} coolify-proxy`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function stopTraefikProxy(id: string): Promise<{ stdout: string; stderr: string }> {
|
||||
const { found } = await checkContainer({ dockerId: id, container: 'coolify-proxy' });
|
||||
await prisma.destinationDocker.update({
|
||||
where: { id },
|
||||
data: { isCoolifyProxyUsed: false }
|
||||
});
|
||||
if (found) {
|
||||
return await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker stop -t 0 coolify-proxy && docker rm coolify-proxy`,
|
||||
shell: true
|
||||
});
|
||||
}
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
|
@@ -8,7 +8,8 @@ import {
|
||||
applicationsRouter,
|
||||
servicesRouter,
|
||||
databasesRouter,
|
||||
sourcesRouter
|
||||
sourcesRouter,
|
||||
destinationsRouter
|
||||
} from './routers';
|
||||
|
||||
export const appRouter = router({
|
||||
@@ -18,7 +19,8 @@ export const appRouter = router({
|
||||
applications: applicationsRouter,
|
||||
services: servicesRouter,
|
||||
databases: databasesRouter,
|
||||
sources: sourcesRouter
|
||||
sources: sourcesRouter,
|
||||
destinations: destinationsRouter
|
||||
});
|
||||
|
||||
export type AppRouter = typeof appRouter;
|
||||
|
218
apps/server/src/trpc/routers/destinations/index.ts
Normal file
218
apps/server/src/trpc/routers/destinations/index.ts
Normal file
@@ -0,0 +1,218 @@
|
||||
import { z } from 'zod';
|
||||
import { privateProcedure, router } from '../../trpc';
|
||||
import {
|
||||
listSettings,
|
||||
startTraefikProxy,
|
||||
startTraefikTCPProxy,
|
||||
stopTraefikProxy
|
||||
} from '../../../lib/common';
|
||||
import { prisma } from '../../../prisma';
|
||||
|
||||
import { executeCommand } from '../../../lib/executeCommand';
|
||||
import { checkContainer } from '../../../lib/docker';
|
||||
|
||||
export const destinationsRouter = router({
|
||||
restartProxy: privateProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string()
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { id } = input;
|
||||
await stopTraefikProxy(id);
|
||||
await startTraefikProxy(id);
|
||||
await prisma.destinationDocker.update({
|
||||
where: { id },
|
||||
data: { isCoolifyProxyUsed: true }
|
||||
});
|
||||
}),
|
||||
startProxy: privateProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string()
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { id } = input;
|
||||
await startTraefikProxy(id);
|
||||
}),
|
||||
stopProxy: privateProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string()
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { id } = input;
|
||||
await stopTraefikProxy(id);
|
||||
}),
|
||||
saveSettings: privateProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
engine: z.string(),
|
||||
isCoolifyProxyUsed: z.boolean()
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { id, engine, isCoolifyProxyUsed } = input;
|
||||
await prisma.destinationDocker.updateMany({
|
||||
where: { engine },
|
||||
data: { isCoolifyProxyUsed }
|
||||
});
|
||||
}),
|
||||
status: privateProcedure.input(z.object({ id: z.string() })).query(async ({ input, ctx }) => {
|
||||
const { id } = input;
|
||||
const destination = await prisma.destinationDocker.findUnique({ where: { id } });
|
||||
const { found: isRunning } = await checkContainer({
|
||||
dockerId: destination.id,
|
||||
container: 'coolify-proxy',
|
||||
remove: true
|
||||
});
|
||||
return {
|
||||
isRunning
|
||||
};
|
||||
}),
|
||||
save: privateProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
htmlUrl: z.string(),
|
||||
apiUrl: z.string(),
|
||||
customPort: z.number(),
|
||||
customUser: z.string(),
|
||||
isSystemWide: z.boolean().default(false)
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { teamId } = ctx.user;
|
||||
let {
|
||||
id,
|
||||
name,
|
||||
network,
|
||||
engine,
|
||||
isCoolifyProxyUsed,
|
||||
remoteIpAddress,
|
||||
remoteUser,
|
||||
remotePort
|
||||
} = input;
|
||||
if (id === 'new') {
|
||||
if (engine) {
|
||||
const { stdout } = await await executeCommand({
|
||||
command: `docker network ls --filter 'name=^${network}$' --format '{{json .}}'`
|
||||
});
|
||||
if (stdout === '') {
|
||||
await await executeCommand({
|
||||
command: `docker network create --attachable ${network}`
|
||||
});
|
||||
}
|
||||
await prisma.destinationDocker.create({
|
||||
data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed }
|
||||
});
|
||||
const destinations = await prisma.destinationDocker.findMany({ where: { engine } });
|
||||
const destination = destinations.find((destination) => destination.network === network);
|
||||
if (destinations.length > 0) {
|
||||
const proxyConfigured = destinations.find(
|
||||
(destination) =>
|
||||
destination.network !== network && destination.isCoolifyProxyUsed === true
|
||||
);
|
||||
if (proxyConfigured) {
|
||||
isCoolifyProxyUsed = !!proxyConfigured.isCoolifyProxyUsed;
|
||||
}
|
||||
await prisma.destinationDocker.updateMany({
|
||||
where: { engine },
|
||||
data: { isCoolifyProxyUsed }
|
||||
});
|
||||
}
|
||||
if (isCoolifyProxyUsed) {
|
||||
await startTraefikProxy(destination.id);
|
||||
}
|
||||
return { id: destination.id };
|
||||
} else {
|
||||
const destination = await prisma.destinationDocker.create({
|
||||
data: {
|
||||
name,
|
||||
teams: { connect: { id: teamId } },
|
||||
engine,
|
||||
network,
|
||||
isCoolifyProxyUsed,
|
||||
remoteEngine: true,
|
||||
remoteIpAddress,
|
||||
remoteUser,
|
||||
remotePort: Number(remotePort)
|
||||
}
|
||||
});
|
||||
return { id: destination.id };
|
||||
}
|
||||
} else {
|
||||
await prisma.destinationDocker.update({ where: { id }, data: { name, engine, network } });
|
||||
return {};
|
||||
}
|
||||
}),
|
||||
check: privateProcedure
|
||||
.input(
|
||||
z.object({
|
||||
network: z.string()
|
||||
})
|
||||
)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const { network } = input;
|
||||
const found = await prisma.destinationDocker.findFirst({ where: { network } });
|
||||
if (found) {
|
||||
throw {
|
||||
message: `Network already exists: ${network}`
|
||||
};
|
||||
}
|
||||
}),
|
||||
delete: privateProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string()
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { id } = input;
|
||||
const { network, remoteVerified, engine, isCoolifyProxyUsed } =
|
||||
await prisma.destinationDocker.findUnique({ where: { id } });
|
||||
if (isCoolifyProxyUsed) {
|
||||
if (engine || remoteVerified) {
|
||||
const { stdout: found } = await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker ps -a --filter network=${network} --filter name=coolify-proxy --format '{{.}}'`
|
||||
});
|
||||
if (found) {
|
||||
await executeCommand({
|
||||
dockerId: id,
|
||||
command: `docker network disconnect ${network} coolify-proxy`
|
||||
});
|
||||
await executeCommand({ dockerId: id, command: `docker network rm ${network}` });
|
||||
}
|
||||
}
|
||||
}
|
||||
await prisma.destinationDocker.delete({ where: { id } });
|
||||
}),
|
||||
getDestinationById: privateProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string()
|
||||
})
|
||||
)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const { id } = input;
|
||||
const { teamId } = ctx.user;
|
||||
const destination = await prisma.destinationDocker.findFirst({
|
||||
where: { id, teams: { some: { id: teamId === '0' ? undefined : teamId } } },
|
||||
include: { sshKey: true, application: true, service: true, database: true }
|
||||
});
|
||||
if (!destination && id !== 'new') {
|
||||
throw { status: 404, message: `Destination not found.` };
|
||||
}
|
||||
const settings = await listSettings();
|
||||
return {
|
||||
destination,
|
||||
settings
|
||||
};
|
||||
})
|
||||
});
|
@@ -5,3 +5,4 @@ export * from './applications';
|
||||
export * from './services';
|
||||
export * from './databases';
|
||||
export * from './sources';
|
||||
export * from './destinations';
|
||||
|
Reference in New Issue
Block a user