2022-02-10 14:47:44 +00:00
|
|
|
const dotEnvExtended = require('dotenv-extended');
|
|
|
|
dotEnvExtended.load();
|
|
|
|
const { PrismaClient } = require('@prisma/client');
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
const crypto = require('crypto');
|
|
|
|
const generator = require('generate-password');
|
|
|
|
const cuid = require('cuid');
|
2022-05-31 18:25:39 +00:00
|
|
|
const compare = require('compare-versions');
|
|
|
|
const { version } = require('../package.json');
|
|
|
|
const child = require('child_process');
|
|
|
|
const util = require('util');
|
|
|
|
|
|
|
|
const algorithm = 'aes-256-ctr';
|
2022-02-10 14:47:44 +00:00
|
|
|
|
|
|
|
function generatePassword(length = 24) {
|
|
|
|
return generator.generate({
|
|
|
|
length,
|
|
|
|
numbers: true,
|
|
|
|
strict: true
|
|
|
|
});
|
|
|
|
}
|
2022-05-31 18:25:39 +00:00
|
|
|
const asyncExecShell = util.promisify(child.exec);
|
2022-02-10 14:47:44 +00:00
|
|
|
|
|
|
|
async function main() {
|
|
|
|
// Enable registration for the first user
|
|
|
|
// Set initial HAProxy password
|
|
|
|
const settingsFound = await prisma.setting.findFirst({});
|
|
|
|
if (!settingsFound) {
|
|
|
|
await prisma.setting.create({
|
|
|
|
data: {
|
|
|
|
isRegistrationEnabled: true,
|
|
|
|
proxyPassword: encrypt(generatePassword()),
|
|
|
|
proxyUser: cuid()
|
|
|
|
}
|
|
|
|
});
|
2022-03-01 13:02:46 +00:00
|
|
|
} else {
|
|
|
|
await prisma.setting.update({
|
|
|
|
where: {
|
|
|
|
id: settingsFound.id
|
|
|
|
},
|
|
|
|
data: {
|
|
|
|
proxyHash: null
|
|
|
|
}
|
|
|
|
});
|
2022-02-10 14:47:44 +00:00
|
|
|
}
|
|
|
|
const localDocker = await prisma.destinationDocker.findFirst({
|
|
|
|
where: { engine: '/var/run/docker.sock' }
|
|
|
|
});
|
|
|
|
if (!localDocker) {
|
|
|
|
await prisma.destinationDocker.create({
|
|
|
|
data: {
|
|
|
|
engine: '/var/run/docker.sock',
|
|
|
|
name: 'Local Docker',
|
|
|
|
isCoolifyProxyUsed: true,
|
|
|
|
network: 'coolify'
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2022-04-25 07:54:28 +00:00
|
|
|
|
|
|
|
// Set auto-update based on env variable
|
|
|
|
const isAutoUpdateEnabled = process.env['COOLIFY_AUTO_UPDATE'] === 'true';
|
|
|
|
const settings = await prisma.setting.findFirst({});
|
|
|
|
if (settings) {
|
|
|
|
await prisma.setting.update({
|
|
|
|
where: {
|
|
|
|
id: settings.id
|
|
|
|
},
|
|
|
|
data: {
|
|
|
|
isAutoUpdateEnabled
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2022-05-31 20:29:50 +00:00
|
|
|
if (settings.isTraefikUsed) {
|
2022-05-31 18:25:39 +00:00
|
|
|
// Force stop Coolify Proxy, as it had a bug in < 2.9.2. TrustProxy + api.insecure
|
|
|
|
try {
|
2022-05-31 20:29:50 +00:00
|
|
|
const { stdout } = await asyncExecShell(
|
|
|
|
`docker inspect coolify-proxy --format '{{json .Config.Cmd}}'`
|
2022-05-31 18:50:28 +00:00
|
|
|
);
|
2022-05-31 20:29:50 +00:00
|
|
|
if (
|
|
|
|
!stdout
|
|
|
|
.replaceAll('[', '')
|
|
|
|
.replaceAll(']', '')
|
|
|
|
.replaceAll('"', '')
|
|
|
|
.replace('\n', '')
|
|
|
|
.split(',')
|
|
|
|
.includes('--entrypoints.web.forwardedHeaders.insecure=true')
|
|
|
|
) {
|
|
|
|
console.log('Reconfiguring Coolify Proxy (Traefik)...');
|
|
|
|
await asyncExecShell(`docker stop -t 0 coolify-proxy && docker rm coolify-proxy`);
|
|
|
|
const { stdout: Config } = await asyncExecShell(
|
|
|
|
`docker network inspect bridge --format '{{json .IPAM.Config }}'`
|
|
|
|
);
|
|
|
|
const ip = JSON.parse(Config)[0].Gateway;
|
|
|
|
await asyncExecShell(
|
|
|
|
`docker run --restart always \
|
2022-05-31 18:50:28 +00:00
|
|
|
--add-host 'host.docker.internal:host-gateway' \
|
|
|
|
--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 traefik:v2.6 \
|
|
|
|
--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=http://coolify:3000/webhooks/traefik/main.json \
|
|
|
|
--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`
|
2022-05-31 20:29:50 +00:00
|
|
|
);
|
|
|
|
}
|
2022-05-31 18:25:39 +00:00
|
|
|
} catch (error) {
|
|
|
|
console.log(error);
|
|
|
|
}
|
|
|
|
}
|
2022-02-10 14:47:44 +00:00
|
|
|
}
|
|
|
|
main()
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(e);
|
|
|
|
process.exit(1);
|
|
|
|
})
|
|
|
|
.finally(async () => {
|
|
|
|
await prisma.$disconnect();
|
|
|
|
});
|
|
|
|
|
|
|
|
const encrypt = (text) => {
|
|
|
|
if (text) {
|
|
|
|
const iv = crypto.randomBytes(16);
|
|
|
|
const cipher = crypto.createCipheriv(algorithm, process.env['COOLIFY_SECRET_KEY'], iv);
|
|
|
|
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]);
|
|
|
|
return JSON.stringify({
|
|
|
|
iv: iv.toString('hex'),
|
|
|
|
content: encrypted.toString('hex')
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const decrypt = (hashString) => {
|
|
|
|
if (hashString) {
|
|
|
|
const hash = JSON.parse(hashString);
|
|
|
|
const decipher = crypto.createDecipheriv(
|
|
|
|
algorithm,
|
|
|
|
process.env['COOLIFY_SECRET_KEY'],
|
|
|
|
Buffer.from(hash.iv, 'hex')
|
|
|
|
);
|
|
|
|
const decrpyted = Buffer.concat([
|
|
|
|
decipher.update(Buffer.from(hash.content, 'hex')),
|
|
|
|
decipher.final()
|
|
|
|
]);
|
|
|
|
return decrpyted.toString();
|
|
|
|
}
|
|
|
|
};
|