Merge branch 'main' into next
This commit is contained in:
commit
1639d1725a
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
|||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: '0.8.0'
|
defaultVersion: "0.8.0"
|
||||||
documentation: https://pocketbase.io/docs/
|
documentation: https://pocketbase.io/docs/
|
||||||
type: pocketbase
|
type: pocketbase
|
||||||
name: Pocketbase
|
name: Pocketbase
|
||||||
@ -12,7 +12,7 @@
|
|||||||
ports:
|
ports:
|
||||||
- "8080"
|
- "8080"
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 1.5.0-rc.0
|
defaultVersion: v1.5.1
|
||||||
documentation: https://plausible.io/doc/
|
documentation: https://plausible.io/doc/
|
||||||
type: plausibleanalytics-arm
|
type: plausibleanalytics-arm
|
||||||
name: Plausible Analytics (ARM)
|
name: Plausible Analytics (ARM)
|
||||||
@ -313,7 +313,7 @@
|
|||||||
defaultValue: keycloak
|
defaultValue: keycloak
|
||||||
description: ""
|
description: ""
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: v3.6
|
defaultVersion: v3.7
|
||||||
documentation: https://github.com/freyacodes/Lavalink
|
documentation: https://github.com/freyacodes/Lavalink
|
||||||
description: Standalone audio sending node based on Lavaplayer.
|
description: Standalone audio sending node based on Lavaplayer.
|
||||||
type: lavalink
|
type: lavalink
|
||||||
@ -375,7 +375,7 @@
|
|||||||
defaultValue: $$generate_password
|
defaultValue: $$generate_password
|
||||||
required: true
|
required: true
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: v1.8.6
|
defaultVersion: v1.8.9
|
||||||
documentation: https://docs.appsmith.com/getting-started/setup/instance-configuration/
|
documentation: https://docs.appsmith.com/getting-started/setup/instance-configuration/
|
||||||
type: appsmith
|
type: appsmith
|
||||||
name: Appsmith
|
name: Appsmith
|
||||||
@ -408,7 +408,7 @@
|
|||||||
defaultValue: "true"
|
defaultValue: "true"
|
||||||
description: ""
|
description: ""
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 0.56.2
|
defaultVersion: 0.57.4
|
||||||
documentation: https://hub.docker.com/r/zadam/trilium
|
documentation: https://hub.docker.com/r/zadam/trilium
|
||||||
description: "A hierarchical note taking application with focus on building large personal knowledge bases."
|
description: "A hierarchical note taking application with focus on building large personal knowledge bases."
|
||||||
labels:
|
labels:
|
||||||
@ -428,7 +428,7 @@
|
|||||||
- "8080"
|
- "8080"
|
||||||
variables: []
|
variables: []
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 1.9.2
|
defaultVersion: 1.18.5
|
||||||
documentation: https://hub.docker.com/r/louislam/uptime-kuma
|
documentation: https://hub.docker.com/r/louislam/uptime-kuma
|
||||||
description: A free & fancy self-hosted monitoring tool.
|
description: A free & fancy self-hosted monitoring tool.
|
||||||
labels:
|
labels:
|
||||||
@ -478,7 +478,7 @@
|
|||||||
- "80"
|
- "80"
|
||||||
variables: []
|
variables: []
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 9.2.3
|
defaultVersion: 9.3.1
|
||||||
documentation: https://hub.docker.com/r/grafana/grafana
|
documentation: https://hub.docker.com/r/grafana/grafana
|
||||||
type: grafana
|
type: grafana
|
||||||
name: Grafana
|
name: Grafana
|
||||||
@ -499,7 +499,7 @@
|
|||||||
- "3000"
|
- "3000"
|
||||||
variables: []
|
variables: []
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 1.0.3
|
defaultVersion: 1.1.2
|
||||||
documentation: https://appwrite.io/docs
|
documentation: https://appwrite.io/docs
|
||||||
type: appwrite
|
type: appwrite
|
||||||
name: Appwrite
|
name: Appwrite
|
||||||
@ -1669,7 +1669,7 @@
|
|||||||
defaultValue: weblate
|
defaultValue: weblate
|
||||||
description: ""
|
description: ""
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 2022.10.14-1a5b0965
|
defaultVersion: 2022.12.12-966e9c3c
|
||||||
documentation: https://docs.searxng.org/
|
documentation: https://docs.searxng.org/
|
||||||
type: searxng
|
type: searxng
|
||||||
name: SearXNG
|
name: SearXNG
|
||||||
@ -1742,7 +1742,7 @@
|
|||||||
defaultValue: $$generate_password
|
defaultValue: $$generate_password
|
||||||
description: ""
|
description: ""
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: v2.0.6
|
defaultVersion: v3.0.0
|
||||||
documentation: https://glitchtip.com/documentation
|
documentation: https://glitchtip.com/documentation
|
||||||
type: glitchtip
|
type: glitchtip
|
||||||
name: GlitchTip
|
name: GlitchTip
|
||||||
@ -1964,7 +1964,7 @@
|
|||||||
defaultValue: glitchtip
|
defaultValue: glitchtip
|
||||||
description: ""
|
description: ""
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: v2.13.0
|
defaultVersion: v2.16.0
|
||||||
documentation: https://hasura.io/docs/latest/index/
|
documentation: https://hasura.io/docs/latest/index/
|
||||||
type: hasura
|
type: hasura
|
||||||
name: Hasura
|
name: Hasura
|
||||||
@ -2031,7 +2031,7 @@
|
|||||||
defaultValue: hasura
|
defaultValue: hasura
|
||||||
description: ""
|
description: ""
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: postgresql-v1.38.0
|
defaultVersion: postgresql-v1.39.5
|
||||||
documentation: https://umami.is/docs/getting-started
|
documentation: https://umami.is/docs/getting-started
|
||||||
type: umami-postgresql
|
type: umami-postgresql
|
||||||
name: Umami
|
name: Umami
|
||||||
@ -2238,7 +2238,7 @@
|
|||||||
showOnConfiguration: true
|
showOnConfiguration: true
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
ignore: true
|
ignore: true
|
||||||
defaultVersion: postgresql-v1.38.0
|
defaultVersion: postgresql-v1.39.5
|
||||||
documentation: https://umami.is/docs/getting-started
|
documentation: https://umami.is/docs/getting-started
|
||||||
type: umami
|
type: umami
|
||||||
name: Umami
|
name: Umami
|
||||||
@ -2444,7 +2444,7 @@
|
|||||||
description: ""
|
description: ""
|
||||||
showOnConfiguration: true
|
showOnConfiguration: true
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: v0.29.1
|
defaultVersion: v0.30.1
|
||||||
documentation: https://docs.meilisearch.com/learn/getting_started/quick_start.html
|
documentation: https://docs.meilisearch.com/learn/getting_started/quick_start.html
|
||||||
type: meilisearch
|
type: meilisearch
|
||||||
name: MeiliSearch
|
name: MeiliSearch
|
||||||
@ -2592,7 +2592,7 @@
|
|||||||
defaultValue: $$generate_password
|
defaultValue: $$generate_password
|
||||||
description: ""
|
description: ""
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: "5.22"
|
defaultVersion: "5.25.3"
|
||||||
documentation: https://docs.ghost.org
|
documentation: https://docs.ghost.org
|
||||||
type: ghost-only
|
type: ghost-only
|
||||||
name: Ghost
|
name: Ghost
|
||||||
@ -2656,7 +2656,7 @@
|
|||||||
placeholder: "ghost_db"
|
placeholder: "ghost_db"
|
||||||
required: true
|
required: true
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: "5.22"
|
defaultVersion: "5.25.3"
|
||||||
documentation: https://docs.ghost.org
|
documentation: https://docs.ghost.org
|
||||||
type: ghost-mysql
|
type: ghost-mysql
|
||||||
name: Ghost
|
name: Ghost
|
||||||
@ -2897,7 +2897,7 @@
|
|||||||
define('WP_DEBUG_DISPLAY', false);
|
define('WP_DEBUG_DISPLAY', false);
|
||||||
@ini_set('display_errors', 0);
|
@ini_set('display_errors', 0);
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 4.7.1
|
defaultVersion: 4.9.0
|
||||||
documentation: https://coder.com/docs/coder-oss/latest
|
documentation: https://coder.com/docs/coder-oss/latest
|
||||||
type: vscodeserver
|
type: vscodeserver
|
||||||
name: VSCode Server
|
name: VSCode Server
|
||||||
@ -2928,7 +2928,7 @@
|
|||||||
description: ""
|
description: ""
|
||||||
showOnConfiguration: true
|
showOnConfiguration: true
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: RELEASE.2022-10-15T19-57-03Z
|
defaultVersion: RELEASE.2022-12-12T19-27-27Z
|
||||||
documentation: https://min.io/docs/minio
|
documentation: https://min.io/docs/minio
|
||||||
type: minio
|
type: minio
|
||||||
name: MinIO
|
name: MinIO
|
||||||
@ -3106,7 +3106,7 @@
|
|||||||
defaultValue: $$generate_username
|
defaultValue: $$generate_username
|
||||||
description: ""
|
description: ""
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 0.198.1
|
defaultVersion: 0.207.0
|
||||||
documentation: https://docs.n8n.io
|
documentation: https://docs.n8n.io
|
||||||
type: n8n
|
type: n8n
|
||||||
name: n8n.io
|
name: n8n.io
|
||||||
@ -3283,7 +3283,7 @@
|
|||||||
defaultValue: plausible.js
|
defaultValue: plausible.js
|
||||||
description: This is the default script name.
|
description: This is the default script name.
|
||||||
- templateVersion: 1.0.0
|
- templateVersion: 1.0.0
|
||||||
defaultVersion: 0.98.1
|
defaultVersion: 0.99.1
|
||||||
documentation: https://docs.nocodb.com
|
documentation: https://docs.nocodb.com
|
||||||
type: nocodb
|
type: nocodb
|
||||||
name: NocoDB
|
name: NocoDB
|
||||||
|
@ -19,9 +19,10 @@ import { saveBuildLog, saveDockerRegistryCredentials } from './buildPacks/common
|
|||||||
import { scheduler } from './scheduler';
|
import { scheduler } from './scheduler';
|
||||||
import type { ExecaChildProcess } from 'execa';
|
import type { ExecaChildProcess } from 'execa';
|
||||||
|
|
||||||
export const version = '3.12.0';
|
export const version = '3.12.1';
|
||||||
export const isDev = process.env.NODE_ENV === 'development';
|
export const isDev = process.env.NODE_ENV === 'development';
|
||||||
export const sentryDSN = 'https://409f09bcb7af47928d3e0f46b78987f3@o1082494.ingest.sentry.io/4504236622217216';
|
export const sentryDSN =
|
||||||
|
'https://409f09bcb7af47928d3e0f46b78987f3@o1082494.ingest.sentry.io/4504236622217216';
|
||||||
const algorithm = 'aes-256-ctr';
|
const algorithm = 'aes-256-ctr';
|
||||||
const customConfig: Config = {
|
const customConfig: Config = {
|
||||||
dictionaries: [adjectives, colors, animals],
|
dictionaries: [adjectives, colors, animals],
|
||||||
@ -92,7 +93,7 @@ export const asyncExecShellStream = async ({
|
|||||||
line: `${line.replace('\n', '')}`,
|
line: `${line.replace('\n', '')}`,
|
||||||
buildId,
|
buildId,
|
||||||
applicationId
|
applicationId
|
||||||
}
|
};
|
||||||
logs.push(log);
|
logs.push(log);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
await saveBuildLog(log);
|
await saveBuildLog(log);
|
||||||
@ -109,7 +110,7 @@ export const asyncExecShellStream = async ({
|
|||||||
line: `${line.replace('\n', '')}`,
|
line: `${line.replace('\n', '')}`,
|
||||||
buildId,
|
buildId,
|
||||||
applicationId
|
applicationId
|
||||||
}
|
};
|
||||||
logs.push(log);
|
logs.push(log);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
await saveBuildLog(log);
|
await saveBuildLog(log);
|
||||||
@ -393,7 +394,6 @@ export function generateTimestamp(): string {
|
|||||||
return `${day().format('HH:mm:ss.SSS')}`;
|
return `${day().format('HH:mm:ss.SSS')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const supportedDatabaseTypesAndVersions = [
|
export const supportedDatabaseTypesAndVersions = [
|
||||||
{
|
{
|
||||||
name: 'mongodb',
|
name: 'mongodb',
|
||||||
@ -509,7 +509,7 @@ export async function createRemoteEngineConfiguration(id: string) {
|
|||||||
} = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } });
|
} = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } });
|
||||||
await fs.writeFile(sshKeyFile, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 });
|
await fs.writeFile(sshKeyFile, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 });
|
||||||
const config = sshConfig.parse('');
|
const config = sshConfig.parse('');
|
||||||
const Host = `${remoteIpAddress}-remote`
|
const Host = `${remoteIpAddress}-remote`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await executeCommand({ command: `ssh-keygen -R ${Host}` });
|
await executeCommand({ command: `ssh-keygen -R ${Host}` });
|
||||||
@ -517,12 +517,11 @@ export async function createRemoteEngineConfiguration(id: string) {
|
|||||||
await executeCommand({ command: `ssh-keygen -R localhost:${localPort}` });
|
await executeCommand({ command: `ssh-keygen -R localhost:${localPort}` });
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
|
|
||||||
|
|
||||||
const found = config.find({ Host });
|
const found = config.find({ Host });
|
||||||
const foundIp = config.find({ Host: remoteIpAddress });
|
const foundIp = config.find({ Host: remoteIpAddress });
|
||||||
|
|
||||||
if (found) config.remove({ Host })
|
if (found) config.remove({ Host });
|
||||||
if (foundIp) config.remove({ Host: remoteIpAddress })
|
if (foundIp) config.remove({ Host: remoteIpAddress });
|
||||||
|
|
||||||
config.append({
|
config.append({
|
||||||
Host,
|
Host,
|
||||||
@ -543,15 +542,35 @@ export async function createRemoteEngineConfiguration(id: string) {
|
|||||||
}
|
}
|
||||||
return await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config));
|
return await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config));
|
||||||
}
|
}
|
||||||
export async function executeCommand({ command, dockerId = null, sshCommand = false, shell = false, stream = false, buildId, applicationId, debug }: { command: string, sshCommand?: boolean, shell?: boolean, stream?: boolean, dockerId?: string, buildId?: string, applicationId?: string, debug?: boolean }): Promise<ExecaChildProcess<string>> {
|
export async function executeCommand({
|
||||||
const { execa, execaCommand } = await import('execa')
|
command,
|
||||||
const { parse } = await import('shell-quote')
|
dockerId = null,
|
||||||
|
sshCommand = false,
|
||||||
|
shell = false,
|
||||||
|
stream = false,
|
||||||
|
buildId,
|
||||||
|
applicationId,
|
||||||
|
debug
|
||||||
|
}: {
|
||||||
|
command: string;
|
||||||
|
sshCommand?: boolean;
|
||||||
|
shell?: boolean;
|
||||||
|
stream?: boolean;
|
||||||
|
dockerId?: string;
|
||||||
|
buildId?: string;
|
||||||
|
applicationId?: string;
|
||||||
|
debug?: boolean;
|
||||||
|
}): Promise<ExecaChildProcess<string>> {
|
||||||
|
const { execa, execaCommand } = await import('execa');
|
||||||
|
const { parse } = await import('shell-quote');
|
||||||
const parsedCommand = parse(command);
|
const parsedCommand = parse(command);
|
||||||
const dockerCommand = parsedCommand[0];
|
const dockerCommand = parsedCommand[0];
|
||||||
const dockerArgs = parsedCommand.slice(1);
|
const dockerArgs = parsedCommand.slice(1);
|
||||||
|
|
||||||
if (dockerId) {
|
if (dockerId) {
|
||||||
let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
|
let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({
|
||||||
|
where: { id: dockerId }
|
||||||
|
});
|
||||||
if (remoteEngine) {
|
if (remoteEngine) {
|
||||||
await createRemoteEngineConfiguration(dockerId);
|
await createRemoteEngineConfiguration(dockerId);
|
||||||
engine = `ssh://${remoteIpAddress}-remote`;
|
engine = `ssh://${remoteIpAddress}-remote`;
|
||||||
@ -591,7 +610,7 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
|
|||||||
line: `${line.replace('\n', '')}`,
|
line: `${line.replace('\n', '')}`,
|
||||||
buildId,
|
buildId,
|
||||||
applicationId
|
applicationId
|
||||||
}
|
};
|
||||||
logs.push(log);
|
logs.push(log);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
await saveBuildLog(log);
|
await saveBuildLog(log);
|
||||||
@ -608,7 +627,7 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
|
|||||||
line: `${line.replace('\n', '')}`,
|
line: `${line.replace('\n', '')}`,
|
||||||
buildId,
|
buildId,
|
||||||
applicationId
|
applicationId
|
||||||
}
|
};
|
||||||
logs.push(log);
|
logs.push(log);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
await saveBuildLog(log);
|
await saveBuildLog(log);
|
||||||
@ -628,7 +647,7 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
|
|||||||
reject(code);
|
reject(code);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
if (shell) {
|
if (shell) {
|
||||||
return await execaCommand(command, {
|
return await execaCommand(command, {
|
||||||
@ -640,7 +659,6 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (shell) {
|
if (shell) {
|
||||||
return execaCommand(command, { shell: true });
|
return execaCommand(command, { shell: true });
|
||||||
@ -650,8 +668,13 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function startTraefikProxy(id: string): Promise<void> {
|
export async function startTraefikProxy(id: string): Promise<void> {
|
||||||
const { engine, network, remoteEngine, remoteIpAddress } = await prisma.destinationDocker.findUnique({ where: { id } })
|
const { engine, network, remoteEngine, remoteIpAddress } =
|
||||||
const { found } = await checkContainer({ dockerId: id, container: 'coolify-proxy', remove: true });
|
await prisma.destinationDocker.findUnique({ where: { id } });
|
||||||
|
const { found } = await checkContainer({
|
||||||
|
dockerId: id,
|
||||||
|
container: 'coolify-proxy',
|
||||||
|
remove: true
|
||||||
|
});
|
||||||
const { id: settingsId, ipv4, ipv6 } = await listSettings();
|
const { id: settingsId, ipv4, ipv6 } = await listSettings();
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
@ -768,9 +791,12 @@ export async function listSettings(): Promise<any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function generateToken() {
|
export function generateToken() {
|
||||||
return jsonwebtoken.sign({
|
return jsonwebtoken.sign(
|
||||||
nbf: Math.floor(Date.now() / 1000) - 30,
|
{
|
||||||
}, process.env['COOLIFY_SECRET_KEY'])
|
nbf: Math.floor(Date.now() / 1000) - 30
|
||||||
|
},
|
||||||
|
process.env['COOLIFY_SECRET_KEY']
|
||||||
|
);
|
||||||
}
|
}
|
||||||
export function generatePassword({
|
export function generatePassword({
|
||||||
length = 24,
|
length = 24,
|
||||||
@ -790,7 +816,8 @@ export function generatePassword({
|
|||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DatabaseConfiguration = {
|
type DatabaseConfiguration =
|
||||||
|
| {
|
||||||
volume: string;
|
volume: string;
|
||||||
image: string;
|
image: string;
|
||||||
command?: string;
|
command?: string;
|
||||||
@ -881,18 +908,10 @@ type DatabaseConfiguration = {
|
|||||||
EDGEDB_SERVER_DATABASE: string;
|
EDGEDB_SERVER_DATABASE: string;
|
||||||
EDGEDB_SERVER_TLS_CERT_MODE: string;
|
EDGEDB_SERVER_TLS_CERT_MODE: string;
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
export function generateDatabaseConfiguration(database: any, arch: string): DatabaseConfiguration {
|
export function generateDatabaseConfiguration(database: any, arch: string): DatabaseConfiguration {
|
||||||
const {
|
const { id, dbUser, dbUserPassword, rootUser, rootUserPassword, defaultDatabase, version, type } =
|
||||||
id,
|
database;
|
||||||
dbUser,
|
|
||||||
dbUserPassword,
|
|
||||||
rootUser,
|
|
||||||
rootUserPassword,
|
|
||||||
defaultDatabase,
|
|
||||||
version,
|
|
||||||
type,
|
|
||||||
} = database;
|
|
||||||
const baseImage = getDatabaseImage(type, arch);
|
const baseImage = getDatabaseImage(type, arch);
|
||||||
if (type === 'mysql') {
|
if (type === 'mysql') {
|
||||||
const configuration = {
|
const configuration = {
|
||||||
@ -972,7 +991,9 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
|
|||||||
}
|
}
|
||||||
return configuration;
|
return configuration;
|
||||||
} else if (type === 'redis') {
|
} else if (type === 'redis') {
|
||||||
const { settings: { appendOnly } } = database;
|
const {
|
||||||
|
settings: { appendOnly }
|
||||||
|
} = database;
|
||||||
const configuration: DatabaseConfiguration = {
|
const configuration: DatabaseConfiguration = {
|
||||||
privatePort: 6379,
|
privatePort: 6379,
|
||||||
command: undefined,
|
command: undefined,
|
||||||
@ -986,7 +1007,8 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
|
|||||||
};
|
};
|
||||||
if (isARM(arch)) {
|
if (isARM(arch)) {
|
||||||
configuration.volume = `${id}-${type}-data:/data`;
|
configuration.volume = `${id}-${type}-data:/data`;
|
||||||
configuration.command = `/usr/local/bin/redis-server --appendonly ${appendOnly ? 'yes' : 'no'
|
configuration.command = `/usr/local/bin/redis-server --appendonly ${
|
||||||
|
appendOnly ? 'yes' : 'no'
|
||||||
} --requirepass ${dbUserPassword}`;
|
} --requirepass ${dbUserPassword}`;
|
||||||
}
|
}
|
||||||
return configuration;
|
return configuration;
|
||||||
@ -1004,7 +1026,7 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
|
|||||||
if (isARM(arch)) {
|
if (isARM(arch)) {
|
||||||
configuration.volume = `${id}-${type}-data:/opt/couchdb/data`;
|
configuration.volume = `${id}-${type}-data:/opt/couchdb/data`;
|
||||||
}
|
}
|
||||||
return configuration
|
return configuration;
|
||||||
} else if (type === 'edgedb') {
|
} else if (type === 'edgedb') {
|
||||||
const configuration: DatabaseConfiguration = {
|
const configuration: DatabaseConfiguration = {
|
||||||
privatePort: 5656,
|
privatePort: 5656,
|
||||||
@ -1018,7 +1040,7 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
|
|||||||
volume: `${id}-${type}-data:/var/lib/edgedb/data`,
|
volume: `${id}-${type}-data:/var/lib/edgedb/data`,
|
||||||
ulimits: {}
|
ulimits: {}
|
||||||
};
|
};
|
||||||
return configuration
|
return configuration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function isARM(arch: string) {
|
export function isARM(arch: string) {
|
||||||
@ -1141,7 +1163,7 @@ export const createDirectories = async ({
|
|||||||
repository: string;
|
repository: string;
|
||||||
buildId: string;
|
buildId: string;
|
||||||
}): Promise<{ workdir: string; repodir: string }> => {
|
}): Promise<{ workdir: string; repodir: string }> => {
|
||||||
if (repository) repository = repository.replaceAll(' ', '')
|
if (repository) repository = repository.replaceAll(' ', '');
|
||||||
const repodir = `/tmp/build-sources/${repository}/`;
|
const repodir = `/tmp/build-sources/${repository}/`;
|
||||||
const workdir = `/tmp/build-sources/${repository}/${buildId}`;
|
const workdir = `/tmp/build-sources/${repository}/${buildId}`;
|
||||||
let workdirFound = false;
|
let workdirFound = false;
|
||||||
@ -1254,19 +1276,45 @@ export async function updatePasswordInDb(database, user, newPassword, isRoot) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function checkExposedPort({ id, configuredPort, exposePort, engine, remoteEngine, remoteIpAddress }: { id: string, configuredPort?: number, exposePort: number, engine: string, remoteEngine: boolean, remoteIpAddress?: string }) {
|
export async function checkExposedPort({
|
||||||
|
id,
|
||||||
|
configuredPort,
|
||||||
|
exposePort,
|
||||||
|
engine,
|
||||||
|
remoteEngine,
|
||||||
|
remoteIpAddress
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
configuredPort?: number;
|
||||||
|
exposePort: number;
|
||||||
|
engine: string;
|
||||||
|
remoteEngine: boolean;
|
||||||
|
remoteIpAddress?: string;
|
||||||
|
}) {
|
||||||
if (exposePort < 1024 || exposePort > 65535) {
|
if (exposePort < 1024 || exposePort > 65535) {
|
||||||
throw { status: 500, message: `Exposed Port needs to be between 1024 and 65535.` };
|
throw { status: 500, message: `Exposed Port needs to be between 1024 and 65535.` };
|
||||||
}
|
}
|
||||||
if (configuredPort) {
|
if (configuredPort) {
|
||||||
if (configuredPort !== exposePort) {
|
if (configuredPort !== exposePort) {
|
||||||
const availablePort = await getFreeExposedPort(id, exposePort, engine, remoteEngine, remoteIpAddress);
|
const availablePort = await getFreeExposedPort(
|
||||||
|
id,
|
||||||
|
exposePort,
|
||||||
|
engine,
|
||||||
|
remoteEngine,
|
||||||
|
remoteIpAddress
|
||||||
|
);
|
||||||
if (availablePort.toString() !== exposePort.toString()) {
|
if (availablePort.toString() !== exposePort.toString()) {
|
||||||
throw { status: 500, message: `Port ${exposePort} is already in use.` };
|
throw { status: 500, message: `Port ${exposePort} is already in use.` };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const availablePort = await getFreeExposedPort(id, exposePort, engine, remoteEngine, remoteIpAddress);
|
const availablePort = await getFreeExposedPort(
|
||||||
|
id,
|
||||||
|
exposePort,
|
||||||
|
engine,
|
||||||
|
remoteEngine,
|
||||||
|
remoteIpAddress
|
||||||
|
);
|
||||||
if (availablePort.toString() !== exposePort.toString()) {
|
if (availablePort.toString() !== exposePort.toString()) {
|
||||||
throw { status: 500, message: `Port ${exposePort} is already in use.` };
|
throw { status: 500, message: `Port ${exposePort} is already in use.` };
|
||||||
}
|
}
|
||||||
@ -1277,25 +1325,33 @@ export async function getFreeExposedPort(id, exposePort, engine, remoteEngine, r
|
|||||||
if (remoteEngine) {
|
if (remoteEngine) {
|
||||||
const applicationUsed = await (
|
const applicationUsed = await (
|
||||||
await prisma.application.findMany({
|
await prisma.application.findMany({
|
||||||
where: { exposePort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
|
where: {
|
||||||
|
exposePort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
destinationDocker: { remoteIpAddress }
|
||||||
|
},
|
||||||
select: { exposePort: true }
|
select: { exposePort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.exposePort);
|
).map((a) => a.exposePort);
|
||||||
const serviceUsed = await (
|
const serviceUsed = await (
|
||||||
await prisma.service.findMany({
|
await prisma.service.findMany({
|
||||||
where: { exposePort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
|
where: {
|
||||||
|
exposePort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
destinationDocker: { remoteIpAddress }
|
||||||
|
},
|
||||||
select: { exposePort: true }
|
select: { exposePort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.exposePort);
|
).map((a) => a.exposePort);
|
||||||
const usedPorts = [...applicationUsed, ...serviceUsed];
|
const usedPorts = [...applicationUsed, ...serviceUsed];
|
||||||
if (usedPorts.includes(exposePort)) {
|
if (usedPorts.includes(exposePort)) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
const found = await checkPort(exposePort, { host: remoteIpAddress });
|
const found = await checkPort(exposePort, { host: remoteIpAddress });
|
||||||
if (!found) {
|
if (!found) {
|
||||||
return exposePort
|
return exposePort;
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
const applicationUsed = await (
|
const applicationUsed = await (
|
||||||
await prisma.application.findMany({
|
await prisma.application.findMany({
|
||||||
@ -1311,13 +1367,13 @@ export async function getFreeExposedPort(id, exposePort, engine, remoteEngine, r
|
|||||||
).map((a) => a.exposePort);
|
).map((a) => a.exposePort);
|
||||||
const usedPorts = [...applicationUsed, ...serviceUsed];
|
const usedPorts = [...applicationUsed, ...serviceUsed];
|
||||||
if (usedPorts.includes(exposePort)) {
|
if (usedPorts.includes(exposePort)) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
const found = await checkPort(exposePort, { host: 'localhost' });
|
const found = await checkPort(exposePort, { host: 'localhost' });
|
||||||
if (!found) {
|
if (!found) {
|
||||||
return exposePort
|
return exposePort;
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function generateRangeArray(start, end) {
|
export function generateRangeArray(start, end) {
|
||||||
@ -1330,38 +1386,54 @@ export async function getFreePublicPort({ id, remoteEngine, engine, remoteIpAddr
|
|||||||
if (remoteEngine) {
|
if (remoteEngine) {
|
||||||
const dbUsed = await (
|
const dbUsed = await (
|
||||||
await prisma.database.findMany({
|
await prisma.database.findMany({
|
||||||
where: { publicPort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
|
where: {
|
||||||
|
publicPort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
destinationDocker: { remoteIpAddress }
|
||||||
|
},
|
||||||
select: { publicPort: true }
|
select: { publicPort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.publicPort);
|
).map((a) => a.publicPort);
|
||||||
const wpFtpUsed = await (
|
const wpFtpUsed = await (
|
||||||
await prisma.wordpress.findMany({
|
await prisma.wordpress.findMany({
|
||||||
where: { ftpPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { remoteIpAddress } } },
|
where: {
|
||||||
|
ftpPublicPort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
service: { destinationDocker: { remoteIpAddress } }
|
||||||
|
},
|
||||||
select: { ftpPublicPort: true }
|
select: { ftpPublicPort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.ftpPublicPort);
|
).map((a) => a.ftpPublicPort);
|
||||||
const wpUsed = await (
|
const wpUsed = await (
|
||||||
await prisma.wordpress.findMany({
|
await prisma.wordpress.findMany({
|
||||||
where: { mysqlPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { remoteIpAddress } } },
|
where: {
|
||||||
|
mysqlPublicPort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
service: { destinationDocker: { remoteIpAddress } }
|
||||||
|
},
|
||||||
select: { mysqlPublicPort: true }
|
select: { mysqlPublicPort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.mysqlPublicPort);
|
).map((a) => a.mysqlPublicPort);
|
||||||
const minioUsed = await (
|
const minioUsed = await (
|
||||||
await prisma.minio.findMany({
|
await prisma.minio.findMany({
|
||||||
where: { publicPort: { not: null }, id: { not: id }, service: { destinationDocker: { remoteIpAddress } } },
|
where: {
|
||||||
|
publicPort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
service: { destinationDocker: { remoteIpAddress } }
|
||||||
|
},
|
||||||
select: { publicPort: true }
|
select: { publicPort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.publicPort);
|
).map((a) => a.publicPort);
|
||||||
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
|
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
|
||||||
const range = generateRangeArray(minPort, maxPort)
|
const range = generateRangeArray(minPort, maxPort);
|
||||||
const availablePorts = range.filter(port => !usedPorts.includes(port))
|
const availablePorts = range.filter((port) => !usedPorts.includes(port));
|
||||||
for (const port of availablePorts) {
|
for (const port of availablePorts) {
|
||||||
const found = await isReachable(port, { host: remoteIpAddress })
|
const found = await isReachable(port, { host: remoteIpAddress });
|
||||||
if (!found) {
|
if (!found) {
|
||||||
return port
|
return port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
const dbUsed = await (
|
const dbUsed = await (
|
||||||
await prisma.database.findMany({
|
await prisma.database.findMany({
|
||||||
@ -1371,32 +1443,44 @@ export async function getFreePublicPort({ id, remoteEngine, engine, remoteIpAddr
|
|||||||
).map((a) => a.publicPort);
|
).map((a) => a.publicPort);
|
||||||
const wpFtpUsed = await (
|
const wpFtpUsed = await (
|
||||||
await prisma.wordpress.findMany({
|
await prisma.wordpress.findMany({
|
||||||
where: { ftpPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { engine } } },
|
where: {
|
||||||
|
ftpPublicPort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
service: { destinationDocker: { engine } }
|
||||||
|
},
|
||||||
select: { ftpPublicPort: true }
|
select: { ftpPublicPort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.ftpPublicPort);
|
).map((a) => a.ftpPublicPort);
|
||||||
const wpUsed = await (
|
const wpUsed = await (
|
||||||
await prisma.wordpress.findMany({
|
await prisma.wordpress.findMany({
|
||||||
where: { mysqlPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { engine } } },
|
where: {
|
||||||
|
mysqlPublicPort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
service: { destinationDocker: { engine } }
|
||||||
|
},
|
||||||
select: { mysqlPublicPort: true }
|
select: { mysqlPublicPort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.mysqlPublicPort);
|
).map((a) => a.mysqlPublicPort);
|
||||||
const minioUsed = await (
|
const minioUsed = await (
|
||||||
await prisma.minio.findMany({
|
await prisma.minio.findMany({
|
||||||
where: { publicPort: { not: null }, id: { not: id }, service: { destinationDocker: { engine } } },
|
where: {
|
||||||
|
publicPort: { not: null },
|
||||||
|
id: { not: id },
|
||||||
|
service: { destinationDocker: { engine } }
|
||||||
|
},
|
||||||
select: { publicPort: true }
|
select: { publicPort: true }
|
||||||
})
|
})
|
||||||
).map((a) => a.publicPort);
|
).map((a) => a.publicPort);
|
||||||
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
|
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
|
||||||
const range = generateRangeArray(minPort, maxPort)
|
const range = generateRangeArray(minPort, maxPort);
|
||||||
const availablePorts = range.filter(port => !usedPorts.includes(port))
|
const availablePorts = range.filter((port) => !usedPorts.includes(port));
|
||||||
for (const port of availablePorts) {
|
for (const port of availablePorts) {
|
||||||
const found = await isReachable(port, { host: 'localhost' })
|
const found = await isReachable(port, { host: 'localhost' });
|
||||||
if (!found) {
|
if (!found) {
|
||||||
return port
|
return port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1502,11 +1586,11 @@ export async function getServiceFromDB({
|
|||||||
serviceSecret: true,
|
serviceSecret: true,
|
||||||
serviceSetting: true,
|
serviceSetting: true,
|
||||||
wordpress: true,
|
wordpress: true,
|
||||||
plausibleAnalytics: true,
|
plausibleAnalytics: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!body) {
|
if (!body) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
// body.type = fixType(body.type);
|
// body.type = fixType(body.type);
|
||||||
|
|
||||||
@ -1523,7 +1607,6 @@ export async function getServiceFromDB({
|
|||||||
return { ...body, settings };
|
return { ...body, settings };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function fixType(type) {
|
export function fixType(type) {
|
||||||
return type?.replaceAll(' ', '').toLowerCase() || null;
|
return type?.replaceAll(' ', '').toLowerCase() || null;
|
||||||
}
|
}
|
||||||
@ -1640,7 +1723,11 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
|
|||||||
|
|
||||||
images = images.trim();
|
images = images.trim();
|
||||||
if (images) {
|
if (images) {
|
||||||
await executeCommand({ dockerId, command: `docker rmi -f ${images}" -q | xargs -r`, shell: true });
|
await executeCommand({
|
||||||
|
dockerId,
|
||||||
|
command: `docker rmi -f ${images}" -q | xargs -r`,
|
||||||
|
shell: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
if (lowDiskSpace || force) {
|
if (lowDiskSpace || force) {
|
||||||
@ -1649,7 +1736,9 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
|
|||||||
await executeCommand({ dockerId, command: `docker image prune -f` });
|
await executeCommand({ dockerId, command: `docker image prune -f` });
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
|
|
||||||
const { numberOfDockerImagesKeptLocally } = await prisma.setting.findUnique({ where: { id: '0' } })
|
const { numberOfDockerImagesKeptLocally } = await prisma.setting.findUnique({
|
||||||
|
where: { id: '0' }
|
||||||
|
});
|
||||||
const { stdout: images } = await executeCommand({
|
const { stdout: images } = await executeCommand({
|
||||||
dockerId,
|
dockerId,
|
||||||
command: `docker images|grep -v "<none>"|grep -v REPOSITORY|awk '{print $1, $2}'`,
|
command: `docker images|grep -v "<none>"|grep -v REPOSITORY|awk '{print $1, $2}'`,
|
||||||
@ -1657,18 +1746,17 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
|
|||||||
});
|
});
|
||||||
const imagesArray = images.trim().replaceAll(' ', ':').split('\n');
|
const imagesArray = images.trim().replaceAll(' ', ':').split('\n');
|
||||||
const imagesSet = new Set(imagesArray.map((image) => image.split(':')[0]));
|
const imagesSet = new Set(imagesArray.map((image) => image.split(':')[0]));
|
||||||
let deleteImage = []
|
let deleteImage = [];
|
||||||
for (const image of imagesSet) {
|
for (const image of imagesSet) {
|
||||||
let keepImage = []
|
let keepImage = [];
|
||||||
for (const image2 of imagesArray) {
|
for (const image2 of imagesArray) {
|
||||||
if (image2.startsWith(image)) {
|
if (image2.startsWith(image)) {
|
||||||
if (keepImage.length >= numberOfDockerImagesKeptLocally) {
|
if (keepImage.length >= numberOfDockerImagesKeptLocally) {
|
||||||
deleteImage.push(image2)
|
deleteImage.push(image2);
|
||||||
} else {
|
} else {
|
||||||
keepImage.push(image2)
|
keepImage.push(image2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const image of deleteImage) {
|
for (const image of deleteImage) {
|
||||||
@ -1768,16 +1856,22 @@ export function decryptApplication(application: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function pushToRegistry(application: any, workdir: string, tag: string, imageName: string, customTag: string) {
|
export async function pushToRegistry(
|
||||||
const location = `${workdir}/.docker`
|
application: any,
|
||||||
const tagCommand = `docker tag ${application.id}:${tag} ${imageName}:${customTag}`
|
workdir: string,
|
||||||
const pushCommand = `docker --config ${location} push ${imageName}:${customTag}`
|
tag: string,
|
||||||
|
imageName: string,
|
||||||
|
customTag: string
|
||||||
|
) {
|
||||||
|
const location = `${workdir}/.docker`;
|
||||||
|
const tagCommand = `docker tag ${application.id}:${tag} ${imageName}:${customTag}`;
|
||||||
|
const pushCommand = `docker --config ${location} push ${imageName}:${customTag}`;
|
||||||
await executeCommand({
|
await executeCommand({
|
||||||
dockerId: application.destinationDockerId,
|
dockerId: application.destinationDockerId,
|
||||||
command: tagCommand
|
command: tagCommand
|
||||||
})
|
});
|
||||||
await executeCommand({
|
await executeCommand({
|
||||||
dockerId: application.destinationDockerId,
|
dockerId: application.destinationDockerId,
|
||||||
command: pushCommand
|
command: pushCommand
|
||||||
})
|
});
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "coolify",
|
"name": "coolify",
|
||||||
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
||||||
"version": "3.12.0",
|
"version": "3.12.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": "github:coollabsio/coolify",
|
"repository": "github:coollabsio/coolify",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
Loading…
Reference in New Issue
Block a user