coolify/apps/api/src/lib.ts

242 lines
11 KiB
TypeScript
Raw Normal View History

2022-10-19 10:24:53 +02:00
import { decrypt, encrypt, getDomain, prisma } from "./lib/common";
2022-10-18 12:51:53 +02:00
import { includeServices } from "./lib/services/common";
2022-10-19 10:55:16 +02:00
import templates from "./lib/templates";
2022-10-18 12:51:53 +02:00
export async function migrateServicesToNewTemplate() {
// This function migrates old hardcoded services to the new template based services
try {
const services = await prisma.service.findMany({ include: includeServices })
for (const service of services) {
if (service.type === 'plausibleanalytics' && service.plausibleAnalytics) await plausibleAnalytics(service)
2022-10-18 13:52:47 +02:00
if (service.type === 'fider' && service.fider) await fider(service)
2022-10-18 14:12:33 +02:00
if (service.type === 'minio' && service.minio) await minio(service)
2022-10-18 14:45:30 +02:00
if (service.type === 'vscodeserver' && service.vscodeserver) await vscodeserver(service)
2022-10-18 15:01:18 +02:00
if (service.type === 'wordpress' && service.wordpress) await wordpress(service)
2022-10-19 10:24:53 +02:00
if (service.type === 'ghost' && service.ghost) await ghost(service)
2022-10-19 10:55:16 +02:00
if (service.type === 'meilisearch' && service.meiliSearch) await meilisearch(service)
2022-10-19 11:26:27 +02:00
if (service.type === 'umami' && service.umami) await umami(service)
2022-10-19 10:55:16 +02:00
await createVolumes(service);
2022-10-18 12:51:53 +02:00
}
} catch (error) {
console.log(error)
}
}
2022-10-19 11:26:27 +02:00
async function umami(service: any) {
const { postgresqlUser, postgresqlPassword, postgresqlDatabase, umamiAdminPassword, hashSalt } = service.ghost
2022-10-19 10:29:08 +02:00
2022-10-19 11:26:27 +02:00
const secrets = [
`HASH_SALT@@@${hashSalt}`,
`POSTGRES_PASSWORD@@@${postgresqlPassword}`,
`ADMIN_PASSWORD@@@${umamiAdminPassword}`,
]
const settings = [
`DATABASE_URL@@@${encrypt(`postgres://${postgresqlUser}:${decrypt(postgresqlPassword)}@$$generate_fqdn:5432/${postgresqlDatabase}`)}`,
`POSTGRES_USER@@@${postgresqlUser}`,
`POSTGRES_DB@@@${postgresqlDatabase}`,
]
await migrateSecrets(secrets, service);
await migrateSettings(settings, service);
// Remove old service data
// await prisma.service.update({ where: { id: service.id }, data: { wordpress: { delete: true } } })
}
2022-10-19 10:29:08 +02:00
async function meilisearch(service: any) {
2022-10-19 10:55:16 +02:00
const { masterKey } = service.meiliSearch
2022-10-19 10:29:08 +02:00
const secrets = [
`MEILI_MASTER_KEY@@@${masterKey}`,
]
await migrateSecrets(secrets, service);
// Remove old service data
// await prisma.service.update({ where: { id: service.id }, data: { wordpress: { delete: true } } })
}
2022-10-19 10:24:53 +02:00
async function ghost(service: any) {
const { defaultEmail, defaultPassword, mariadbUser, mariadbPassword, mariadbRootUser, mariadbRootUserPassword, mariadbDatabase } = service.ghost
const { fqdn } = service
const isHttps = fqdn.startsWith('https://');
const secrets = [
`GHOST_PASSWORD@@@${defaultPassword}`,
`MARIADB_PASSWORD@@@${mariadbPassword}`,
`MARIADB_ROOT_PASSWORD@@@${mariadbRootUserPassword}`,
`GHOST_DATABASE_PASSWORD@@@${mariadbPassword}`,
]
const settings = [
`GHOST_EMAIL@@@${defaultEmail}`,
`GHOST_DATABASE_HOST@@@${service.id}-mariadb`,
`GHOST_DATABASE_USER@@@${mariadbUser}`,
`GHOST_DATABASE_NAME@@@${mariadbDatabase}`,
`GHOST_DATABASE_PORT_NUMBER@@@3306`,
`MARIADB_USER@@@${mariadbUser}`,
`MARIADB_DATABASE@@@${mariadbDatabase}`,
`MARIADB_ROOT_USER@@@${mariadbRootUser}`,
`GHOST_HOST@@@${getDomain(fqdn)}`,
`url@@@${fqdn}`,
`GHOST_ENABLE_HTTPS@@@${isHttps ? 'yes' : 'no'}`
]
await migrateSecrets(secrets, service);
await migrateSettings(settings, service);
// Remove old service data
// await prisma.service.update({ where: { id: service.id }, data: { wordpress: { delete: true } } })
}
2022-10-18 15:01:18 +02:00
async function wordpress(service: any) {
const { extraConfig, tablePrefix, ownMysql, mysqlHost, mysqlPort, mysqlUser, mysqlPassword, mysqlRootUser, mysqlRootUserPassword, mysqlDatabase, ftpEnabled, ftpUser, ftpPassword, ftpPublicPort, ftpHostKey, ftpHostKeyPrivate } = service.wordpress
const secrets = [
`MYSQL_ROOT_PASSWORD@@@${mysqlRootUserPassword}`,
`MYSQL_PASSWORD@@@${mysqlPassword}`,
2022-10-18 15:17:59 +02:00
ftpPassword && `COOLIFY_FTP_PASSWORD@@@${ftpPassword}`,
ftpHostKeyPrivate && `COOLIFY_FTP_HOST_KEY_PRIVATE@@@${ftpHostKeyPrivate}`,
ftpHostKey && `COOLIFY_FTP_HOST_KEY@@@${ftpHostKey}`,
2022-10-18 15:01:18 +02:00
]
const settings = [
`MYSQL_ROOT_USER@@@${mysqlRootUser}`,
`MYSQL_USER@@@${mysqlUser}`,
`MYSQL_DATABASE@@@${mysqlDatabase}`,
2022-10-18 15:17:59 +02:00
`MYSQL_HOST@@@${ownMysql ? mysqlHost : `${service.id}-mysql`}`,
2022-10-18 15:01:18 +02:00
`MYSQL_PORT@@@${mysqlPort}`,
`WORDPRESS_CONFIG_EXTRA@@@${extraConfig}`,
`WORDPRESS_TABLE_PREFIX@@@${tablePrefix}`,
2022-10-18 15:17:59 +02:00
`WORDPRESS_DB_HOST@@@${ownMysql ? mysqlHost : `${service.id}-mysql`}`,
`COOLIFY_OWN_DB@@@${ownMysql}`,
`COOLIFY_FTP_ENABLED@@@${ftpEnabled}`,
`COOLIFY_FTP_USER@@@${ftpUser}`,
`COOLIFY_FTP_PUBLIC_PORT@@@${ftpPublicPort}`,
2022-10-18 14:34:10 +02:00
2022-10-18 15:01:18 +02:00
]
await migrateSecrets(secrets, service);
await migrateSettings(settings, service);
// Remove old service data
// await prisma.service.update({ where: { id: service.id }, data: { wordpress: { delete: true } } })
}
2022-10-18 14:34:10 +02:00
async function vscodeserver(service: any) {
2022-10-18 14:45:30 +02:00
const { password } = service.vscodeserver
2022-10-18 14:34:10 +02:00
const secrets = [
`PASSWORD@@@${password}`,
]
await migrateSecrets(secrets, service);
// Remove old service data
// await prisma.service.update({ where: { id: service.id }, data: { vscodeserver: { delete: true } } })
2022-10-18 13:52:47 +02:00
}
2022-10-18 14:12:33 +02:00
async function minio(service: any) {
2022-10-18 14:34:10 +02:00
const { rootUser, rootUserPassword, apiFqdn } = service.minio
2022-10-18 14:12:33 +02:00
const secrets = [
`MINIO_ROOT_PASSWORD@@@${rootUserPassword}`,
]
const settings = [
`MINIO_ROOT_USER@@@${rootUser}`,
`MINIO_SERVER_URL@@@${apiFqdn}`,
`MINIO_BROWSER_REDIRECT_URL@@@$$generate_fqdn`,
`MINIO_DOMAIN@@@$$generate_domain`,
]
await migrateSettings(settings, service);
await migrateSecrets(secrets, service);
// Remove old service data
// await prisma.service.update({ where: { id: service.id }, data: { minio: { delete: true } } })
}
2022-10-18 13:52:47 +02:00
async function fider(service: any) {
const { postgresqlUser, postgresqlPassword, postgresqlDatabase, jwtSecret, emailNoreply, emailMailgunApiKey, emailMailgunDomain, emailMailgunRegion, emailSmtpHost, emailSmtpPort, emailSmtpUser, emailSmtpPassword, emailSmtpEnableStartTls } = service.fider
const secrets = [
`JWT_SECRET@@@${jwtSecret}`,
emailMailgunApiKey && `EMAIL_MAILGUN_API_KEY@@@${emailMailgunApiKey}`,
emailSmtpPassword && `EMAIL_SMTP_PASSWORD@@@${emailSmtpPassword}`,
`POSTGRES_PASSWORD@@@${postgresqlPassword}`,
]
const settings = [
`BASE_URL@@@$$generate_fqdn`,
`EMAIL_NOREPLY@@@${emailNoreply || 'noreply@example.com'}`,
`EMAIL_MAILGUN_DOMAIN@@@${emailMailgunDomain || ''}`,
`EMAIL_MAILGUN_REGION@@@${emailMailgunRegion || ''}`,
`EMAIL_SMTP_HOST@@@${emailSmtpHost || ''}`,
`EMAIL_SMTP_PORT@@@${emailSmtpPort || 587}`,
`EMAIL_SMTP_USER@@@${emailSmtpUser || ''}`,
`EMAIL_SMTP_PASSWORD@@@${emailSmtpPassword || ''}`,
`EMAIL_SMTP_ENABLE_STARTTLS@@@${emailSmtpEnableStartTls || 'false'}`,
`POSTGRES_USER@@@${postgresqlUser}`,
`POSTGRES_DB@@@${postgresqlDatabase}`,
]
await migrateSettings(settings, service);
await migrateSecrets(secrets, service);
// Remove old service data
2022-10-18 14:34:10 +02:00
// await prisma.service.update({ where: { id: service.id }, data: { fider: { delete: true } } })
2022-10-18 13:52:47 +02:00
2022-10-18 12:51:53 +02:00
}
async function plausibleAnalytics(service: any) {
const { email = 'admin@example.com', username = 'admin', password, postgresqlUser, postgresqlPassword, postgresqlDatabase, secretKeyBase, scriptName } = service.plausibleAnalytics;
2022-10-18 13:52:47 +02:00
const settings = [
`BASE_URL@@@$$generate_fqdn`,
`ADMIN_USER_EMAIL@@@${email}`,
`ADMIN_USER_NAME@@@${username}`,
`DISABLE_AUTH@@@false`,
`DISABLE_REGISTRATION@@@true`,
`POSTGRESQL_USER@@@${postgresqlUser}`,
`POSTGRESQL_DATABASE@@@${postgresqlDatabase}`,
`SCRIPT_NAME@@@${scriptName}`,
]
const secrets = [
`ADMIN_USER_PWD@@@${password}`,
`SECRET_KEY_BASE@@@${secretKeyBase}`,
`POSTGRES_PASSWORD@@@${postgresqlPassword}`,
`DATABASE_URL@@@${encrypt(`postgres://${postgresqlUser}:${decrypt(postgresqlPassword)}@$$generate_fqdn:5432/${postgresqlDatabase}`)}`,
]
await migrateSettings(settings, service);
await migrateSecrets(secrets, service);
2022-10-19 10:55:16 +02:00
await createVolumes(service);
2022-10-18 12:51:53 +02:00
// Remove old service data
2022-10-18 14:34:10 +02:00
// await prisma.service.update({ where: { id: service.id }, data: { plausibleAnalytics: { delete: true } } })
}
async function migrateSettings(settings: any[], service: any) {
for (const setting of settings) {
if (!setting) continue;
const [name, value] = setting.split('@@@')
2022-10-19 10:55:16 +02:00
// console.log('Migrating setting', name, value, 'for service', service.id, ', service name:', service.name)
2022-10-18 14:34:10 +02:00
await prisma.serviceSetting.findFirst({ where: { name, serviceId: service.id } }) || await prisma.serviceSetting.create({ data: { name, value, service: { connect: { id: service.id } } } })
}
}
async function migrateSecrets(secrets: any[], service: any) {
for (const secret of secrets) {
if (!secret) continue;
const [name, value] = secret.split('@@@')
2022-10-19 10:55:16 +02:00
// console.log('Migrating secret', name, value, 'for service', service.id, ', service name:', service.name)
2022-10-18 14:34:10 +02:00
await prisma.serviceSecret.findFirst({ where: { name, serviceId: service.id } }) || await prisma.serviceSecret.create({ data: { name, value, service: { connect: { id: service.id } } } })
}
}
2022-10-19 10:55:16 +02:00
async function createVolumes(service: any) {
const volumes = [];
let template = templates.find(t => t.name === service.type)
if (template) {
template = JSON.parse(JSON.stringify(template).replaceAll('$$id', service.id))
for (const s of Object.keys(template.services)) {
if (template.services[s].volumes && template.services[s].volumes.length > 0) {
for (const volume of template.services[s].volumes) {
const volumeName = volume.split(':')[0]
const volumePath = volume.split(':')[1]
const volumeService = service.id
volumes.push(`${volumeName}@@@${volumePath}@@@${volumeService}`)
}
}
}
}
2022-10-18 14:34:10 +02:00
for (const volume of volumes) {
const [volumeName, path, containerId] = volume.split('@@@')
2022-10-19 10:55:16 +02:00
// console.log('Creating volume', volumeName, path, containerId, 'for service', service.id, ', service name:', service.name)
2022-10-18 14:34:10 +02:00
await prisma.servicePersistentStorage.findFirst({ where: { volumeName, serviceId: service.id } }) || await prisma.servicePersistentStorage.create({ data: { volumeName, path, containerId, predefined: true, service: { connect: { id: service.id } } } })
}
2022-10-18 12:51:53 +02:00
}