coolify/apps/api/src/index.ts

230 lines
6.5 KiB
TypeScript
Raw Normal View History

2022-07-06 11:02:36 +02:00
import Fastify from 'fastify';
import cors from '@fastify/cors';
import serve from '@fastify/static';
import env from '@fastify/env';
import cookie from '@fastify/cookie';
2022-09-21 15:48:32 +02:00
import multipart from '@fastify/multipart';
2022-07-06 11:02:36 +02:00
import path, { join } from 'path';
import autoLoad from '@fastify/autoload';
2022-09-06 10:14:39 +02:00
import { asyncExecShell, createRemoteEngineConfiguration, getDomain, isDev, listSettings, prisma, version } from './lib/common';
2022-10-02 10:38:08 +02:00
import { scheduler } from './lib/scheduler';
import { compareVersions } from 'compare-versions';
2022-08-26 08:29:06 +02:00
import Graceful from '@ladjs/graceful'
import { verifyRemoteDockerEngineFn } from './routes/api/v1/destinations/handlers';
2022-07-06 11:02:36 +02:00
declare module 'fastify' {
interface FastifyInstance {
config: {
COOLIFY_APP_ID: string,
COOLIFY_SECRET_KEY: string,
COOLIFY_DATABASE_URL: string,
COOLIFY_SENTRY_DSN: string,
COOLIFY_IS_ON: string,
2022-08-11 16:34:39 +02:00
COOLIFY_WHITE_LABELED: string,
2022-07-06 11:02:36 +02:00
COOLIFY_WHITE_LABELED_ICON: string | null,
2022-08-11 16:34:39 +02:00
COOLIFY_AUTO_UPDATE: string,
2022-07-06 11:02:36 +02:00
};
}
}
const port = isDev ? 3001 : 3000;
const host = '0.0.0.0';
(async () => {
2022-10-04 21:46:01 +02:00
// const settings = prisma.setting.findFirst()
2022-09-06 14:08:10 +02:00
const fastify = Fastify({
2022-10-04 21:46:01 +02:00
logger: false,
2022-09-06 14:08:10 +02:00
trustProxy: true
});
2022-09-21 15:48:32 +02:00
2022-09-06 14:08:10 +02:00
const schema = {
type: 'object',
required: ['COOLIFY_SECRET_KEY', 'COOLIFY_DATABASE_URL', 'COOLIFY_IS_ON'],
properties: {
COOLIFY_APP_ID: {
type: 'string',
},
COOLIFY_SECRET_KEY: {
type: 'string',
},
COOLIFY_DATABASE_URL: {
type: 'string',
default: 'file:../db/dev.db'
},
COOLIFY_SENTRY_DSN: {
type: 'string',
default: null
},
COOLIFY_IS_ON: {
type: 'string',
default: 'docker'
},
COOLIFY_WHITE_LABELED: {
type: 'string',
default: 'false'
},
COOLIFY_WHITE_LABELED_ICON: {
type: 'string',
default: null
},
COOLIFY_AUTO_UPDATE: {
type: 'string',
default: 'false'
},
2022-07-06 11:02:36 +02:00
2022-09-06 14:08:10 +02:00
}
};
2022-07-06 11:02:36 +02:00
2022-09-06 14:08:10 +02:00
const options = {
schema,
dotenv: true
};
fastify.register(env, options);
if (!isDev) {
fastify.register(serve, {
root: path.join(__dirname, './public'),
preCompressed: true
});
fastify.setNotFoundHandler(async function (request, reply) {
if (request.raw.url && request.raw.url.startsWith('/api')) {
return reply.status(404).send({
success: false
});
}
return reply.status(200).sendFile('index.html');
});
}
2022-09-21 15:48:32 +02:00
fastify.register(multipart, { limits: { fileSize: 100000 } });
2022-09-06 14:08:10 +02:00
fastify.register(autoLoad, {
dir: join(__dirname, 'plugins')
2022-07-06 11:02:36 +02:00
});
2022-09-06 14:08:10 +02:00
fastify.register(autoLoad, {
dir: join(__dirname, 'routes')
2022-07-06 11:02:36 +02:00
});
2022-09-06 14:08:10 +02:00
fastify.register(cookie)
fastify.register(cors);
2022-10-04 21:46:01 +02:00
// fastify.addHook('onRequest', async (request, reply) => {
// let allowedList = ['coolify:3000'];
// const { ipv4, ipv6, fqdn } = await prisma.setting.findFirst({})
// ipv4 && allowedList.push(`${ipv4}:3000`);
// ipv6 && allowedList.push(ipv6);
// fqdn && allowedList.push(getDomain(fqdn));
// isDev && allowedList.push('localhost:3000') && allowedList.push('localhost:3001') && allowedList.push('host.docker.internal:3001');
// const remotes = await prisma.destinationDocker.findMany({ where: { remoteEngine: true, remoteVerified: true } })
// if (remotes.length > 0) {
// remotes.forEach(remote => {
// allowedList.push(`${remote.remoteIpAddress}:3000`);
// })
// }
// if (!allowedList.includes(request.headers.host)) {
// // console.log('not allowed', request.headers.host)
// }
// })
try {
await fastify.listen({ port, host })
2022-09-06 14:08:10 +02:00
console.log(`Coolify's API is listening on ${host}:${port}`);
await initServer();
2022-09-06 10:08:31 +02:00
2022-10-04 21:46:01 +02:00
// const graceful = new Graceful({ brees: [scheduler] });
// graceful.listen();
2022-08-26 09:01:48 +02:00
2022-10-04 21:46:01 +02:00
// setInterval(async () => {
// if (!scheduler.workers.has('deployApplication')) {
// scheduler.run('deployApplication');
// }
// if (!scheduler.workers.has('infrastructure')) {
// scheduler.run('infrastructure');
// }
// }, 2000)
2022-09-06 14:08:10 +02:00
// autoUpdater
2022-10-04 21:46:01 +02:00
// setInterval(async () => {
// scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:autoUpdater")
// }, 60000 * 15)
// // cleanupStorage
// setInterval(async () => {
// scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:cleanupStorage")
// }, 60000 * 10)
// // checkProxies and checkFluentBit
// setInterval(async () => {
// scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:checkProxies")
// scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:checkFluentBit")
// }, 10000)
// setInterval(async () => {
// scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:copySSLCertificates")
// }, 2000)
// await Promise.all([
// getArch(),
// getIPAddress(),
// configureRemoteDockers(),
// ])
} catch (error) {
console.error(error);
process.exit(1);
}
})();
2022-07-06 11:02:36 +02:00
2022-07-22 22:48:04 +02:00
async function getIPAddress() {
const { publicIpv4, publicIpv6 } = await import('public-ip')
try {
const settings = await listSettings();
if (!settings.ipv4) {
console.log(`Getting public IPv4 address...`);
2022-07-22 22:48:04 +02:00
const ipv4 = await publicIpv4({ timeout: 2000 })
2022-10-04 21:46:01 +02:00
// await prisma.setting.update({ where: { id: settings.id }, data: { ipv4 } })
2022-07-22 22:48:04 +02:00
}
if (!settings.ipv6) {
console.log(`Getting public IPv6 address...`);
2022-07-22 22:48:04 +02:00
const ipv6 = await publicIpv6({ timeout: 2000 })
2022-10-04 21:46:01 +02:00
// await prisma.setting.update({ where: { id: settings.id }, data: { ipv6 } })
2022-07-22 22:48:04 +02:00
}
2022-07-06 11:02:36 +02:00
2022-07-22 22:48:04 +02:00
} catch (error) { }
}
2022-07-06 11:02:36 +02:00
async function initServer() {
try {
console.log(`Initializing server...`);
2022-07-06 11:02:36 +02:00
await asyncExecShell(`docker network create --attachable coolify`);
} catch (error) { }
2022-08-25 10:04:46 +02:00
try {
const isOlder = compareVersions('3.8.1', version);
2022-08-27 09:46:06 +02:00
if (isOlder === 1) {
2022-08-25 10:04:46 +02:00
await prisma.build.updateMany({ where: { status: { in: ['running', 'queued'] } }, data: { status: 'failed' } });
}
} catch (error) { }
2022-07-06 11:02:36 +02:00
}
2022-07-25 21:16:30 +02:00
async function getArch() {
try {
const settings = await prisma.setting.findFirst({})
if (settings && !settings.arch) {
console.log(`Getting architecture...`);
2022-07-25 21:16:30 +02:00
await prisma.setting.update({ where: { id: settings.id }, data: { arch: process.arch } })
}
} catch (error) { }
}
2022-07-06 11:02:36 +02:00
2022-09-05 12:09:13 +02:00
async function configureRemoteDockers() {
try {
const remoteDocker = await prisma.destinationDocker.findMany({
where: { remoteVerified: true, remoteEngine: true }
});
if (remoteDocker.length > 0) {
console.log(`Verifying Remote Docker Engines...`);
2022-09-05 12:09:13 +02:00
for (const docker of remoteDocker) {
console.log('Verifying:', docker.remoteIpAddress)
await verifyRemoteDockerEngineFn(docker.id);
2022-09-05 12:09:13 +02:00
}
}
} catch (error) {
console.log(error)
}
2022-09-05 12:09:13 +02:00
}