mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-21 12:33:13 +00:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac19ea5407 | ||
|
|
d19b05b970 | ||
|
|
a0795136ac | ||
|
|
d2566e345a | ||
|
|
66cd7cf90e | ||
|
|
9a599981ef | ||
|
|
f51f7bc82a | ||
|
|
dbcbac0137 | ||
|
|
e722f8a87c | ||
|
|
61679749eb | ||
|
|
23e12c9c44 | ||
|
|
6da78cd3e5 | ||
|
|
78ce8100a3 | ||
|
|
76ba338b45 | ||
|
|
823fe2deb2 | ||
|
|
cb90f692f2 | ||
|
|
0325343ede | ||
|
|
69d1556a1d | ||
|
|
2daa043840 | ||
|
|
f340ca9d05 | ||
|
|
02abd038fa | ||
|
|
b9da68ec28 | ||
|
|
88b3910d80 | ||
|
|
160412f6e4 | ||
|
|
59a86b25fc | ||
|
|
49e58b39f5 | ||
|
|
58e0757bbd | ||
|
|
5ff4197572 | ||
|
|
b56e28d27a | ||
|
|
c3d39e1dd4 | ||
|
|
716aa36bfd | ||
|
|
f01460170e | ||
|
|
a414ce282d | ||
|
|
6c32f3b130 | ||
|
|
4cf907c572 | ||
|
|
b28baaa5aa | ||
|
|
980dea64e0 | ||
|
|
c340f6436f | ||
|
|
54376fd105 | ||
|
|
ef006578b2 | ||
|
|
b0b1ee0c60 | ||
|
|
4e2026aa2d | ||
|
|
e0e50b4bd5 | ||
|
|
c9b52f1310 |
@@ -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": "2.0.21",
|
"version": "2.0.24",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "docker-compose -f docker-compose-dev.yaml up -d && NODE_ENV=development svelte-kit dev --host 0.0.0.0",
|
"dev": "docker-compose -f docker-compose-dev.yaml up -d && NODE_ENV=development svelte-kit dev --host 0.0.0.0",
|
||||||
@@ -74,6 +74,7 @@
|
|||||||
"js-cookie": "3.0.1",
|
"js-cookie": "3.0.1",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"jsonwebtoken": "8.5.1",
|
"jsonwebtoken": "8.5.1",
|
||||||
|
"mustache": "^4.2.0",
|
||||||
"node-forge": "1.2.1",
|
"node-forge": "1.2.1",
|
||||||
"svelte-kit-cookie-session": "2.1.2",
|
"svelte-kit-cookie-session": "2.1.2",
|
||||||
"tailwindcss-scrollbar": "^0.1.0",
|
"tailwindcss-scrollbar": "^0.1.0",
|
||||||
|
|||||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -35,6 +35,7 @@ specifiers:
|
|||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
jsonwebtoken: 8.5.1
|
jsonwebtoken: 8.5.1
|
||||||
lint-staged: 12.3.4
|
lint-staged: 12.3.4
|
||||||
|
mustache: ^4.2.0
|
||||||
node-forge: 1.2.1
|
node-forge: 1.2.1
|
||||||
postcss: 8.4.6
|
postcss: 8.4.6
|
||||||
prettier: 2.5.1
|
prettier: 2.5.1
|
||||||
@@ -70,6 +71,7 @@ dependencies:
|
|||||||
js-cookie: 3.0.1
|
js-cookie: 3.0.1
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
jsonwebtoken: 8.5.1
|
jsonwebtoken: 8.5.1
|
||||||
|
mustache: 4.2.0
|
||||||
node-forge: 1.2.1
|
node-forge: 1.2.1
|
||||||
svelte-kit-cookie-session: 2.1.2
|
svelte-kit-cookie-session: 2.1.2
|
||||||
tailwindcss-scrollbar: 0.1.0_tailwindcss@3.0.23
|
tailwindcss-scrollbar: 0.1.0_tailwindcss@3.0.23
|
||||||
@@ -4091,6 +4093,14 @@ packages:
|
|||||||
msgpackr-extract: 1.0.15
|
msgpackr-extract: 1.0.15
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/mustache/4.2.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==
|
||||||
|
}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/nan/2.15.0:
|
/nan/2.15.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
|||||||
2
prisma/migrations/20220301101928_proxyhash/migration.sql
Normal file
2
prisma/migrations/20220301101928_proxyhash/migration.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Setting" ADD COLUMN "proxyHash" TEXT;
|
||||||
@@ -16,6 +16,7 @@ model Setting {
|
|||||||
maxPort Int @default(9100)
|
maxPort Int @default(9100)
|
||||||
proxyPassword String
|
proxyPassword String
|
||||||
proxyUser String
|
proxyUser String
|
||||||
|
proxyHash String?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,15 @@ async function main() {
|
|||||||
proxyUser: cuid()
|
proxyUser: cuid()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
await prisma.setting.update({
|
||||||
|
where: {
|
||||||
|
id: settingsFound.id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
proxyHash: null
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const localDocker = await prisma.destinationDocker.findFirst({
|
const localDocker = await prisma.destinationDocker.findFirst({
|
||||||
where: { engine: '/var/run/docker.sock' }
|
where: { engine: '/var/run/docker.sock' }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const createDockerfile = async (data, imageforBuild): Promise<void> => {
|
|||||||
|
|
||||||
Dockerfile.push(`FROM ${imageforBuild}`);
|
Dockerfile.push(`FROM ${imageforBuild}`);
|
||||||
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${publishDirectory} ./`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${publishDirectory} ./`);
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
Dockerfile.push('CMD ["nginx", "-g", "daemon off;"]');
|
Dockerfile.push('CMD ["nginx", "-g", "daemon off;"]');
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /usr/src/app');
|
Dockerfile.push('WORKDIR /usr/src/app');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push(
|
Dockerfile.push(
|
||||||
`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${baseDirectory || ''} ./`
|
`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${baseDirectory || ''} ./`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /usr/src/app');
|
Dockerfile.push('WORKDIR /usr/src/app');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
if (secrets.length > 0) {
|
if (secrets.length > 0) {
|
||||||
secrets.forEach((secret) => {
|
secrets.forEach((secret) => {
|
||||||
if (secret.isBuildSecret) {
|
if (secret.isBuildSecret) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /usr/src/app');
|
Dockerfile.push('WORKDIR /usr/src/app');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
if (secrets.length > 0) {
|
if (secrets.length > 0) {
|
||||||
secrets.forEach((secret) => {
|
secrets.forEach((secret) => {
|
||||||
if (secret.isBuildSecret) {
|
if (secret.isBuildSecret) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /usr/src/app');
|
Dockerfile.push('WORKDIR /usr/src/app');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
if (secrets.length > 0) {
|
if (secrets.length > 0) {
|
||||||
secrets.forEach((secret) => {
|
secrets.forEach((secret) => {
|
||||||
if (secret.isBuildSecret) {
|
if (secret.isBuildSecret) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push('RUN a2enmod rewrite');
|
Dockerfile.push('RUN a2enmod rewrite');
|
||||||
Dockerfile.push('WORKDIR /var/www/html');
|
Dockerfile.push('WORKDIR /var/www/html');
|
||||||
Dockerfile.push(`COPY ./${baseDirectory || ''} /var/www/html`);
|
Dockerfile.push(`COPY ./${baseDirectory || ''} /var/www/html`);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${publishDirectory} ./`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${publishDirectory} ./`);
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const createDockerfile = async (data, image, name): Promise<void> => {
|
|||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /usr/src/app');
|
Dockerfile.push('WORKDIR /usr/src/app');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/target target`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/target target`);
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/local/cargo /usr/local/cargo`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/local/cargo /usr/local/cargo`);
|
||||||
Dockerfile.push(`COPY . .`);
|
Dockerfile.push(`COPY . .`);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
if (secrets.length > 0) {
|
if (secrets.length > 0) {
|
||||||
secrets.forEach((secret) => {
|
secrets.forEach((secret) => {
|
||||||
if (secret.isBuildSecret) {
|
if (secret.isBuildSecret) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${publishDirectory} ./`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${publishDirectory} ./`);
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
Dockerfile.push('CMD ["nginx", "-g", "daemon off;"]');
|
Dockerfile.push('CMD ["nginx", "-g", "daemon off;"]');
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const createDockerfile = async (data, image): Promise<void> => {
|
|||||||
|
|
||||||
Dockerfile.push(`FROM ${image}`);
|
Dockerfile.push(`FROM ${image}`);
|
||||||
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
Dockerfile.push('WORKDIR /usr/share/nginx/html');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${publishDirectory} ./`);
|
Dockerfile.push(`COPY --from=${applicationId}:${tag}-cache /usr/src/app/${publishDirectory} ./`);
|
||||||
Dockerfile.push(`EXPOSE 80`);
|
Dockerfile.push(`EXPOSE 80`);
|
||||||
Dockerfile.push('CMD ["nginx", "-g", "daemon off;"]');
|
Dockerfile.push('CMD ["nginx", "-g", "daemon off;"]');
|
||||||
|
|||||||
@@ -103,9 +103,14 @@ export const getUserDetails = async (event, isAdminRequired = true) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function getEngine(engine) {
|
export function getEngine(engine) {
|
||||||
return engine === '/var/run/docker.sock' ? 'unix:///var/run/docker.sock' : `tcp://${engine}:2375`;
|
return engine === '/var/run/docker.sock' ? 'unix:///var/run/docker.sock' : engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export async function saveSshKey(destination) {
|
||||||
|
// return await asyncExecShell(
|
||||||
|
// `echo '${destination.sshPrivateKey}' > /tmp/id_rsa_${destination.id} && chmod 600 /tmp/id_rsa_${destination.id}`
|
||||||
|
// );
|
||||||
|
// }
|
||||||
export async function removeContainer(id, engine) {
|
export async function removeContainer(id, engine) {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -15,3 +15,6 @@ export const notNodeDeployments = ['php', 'docker', 'rust'];
|
|||||||
export function getDomain(domain) {
|
export function getDomain(domain) {
|
||||||
return domain?.replace('https://', '').replace('http://', '');
|
return domain?.replace('https://', '').replace('http://', '');
|
||||||
}
|
}
|
||||||
|
export function generateRemoteEngine(destination) {
|
||||||
|
return `ssh://${destination.user}@${destination.ipAddress}:${destination.port}`;
|
||||||
|
}
|
||||||
|
|||||||
21
src/lib/components/svg/applications/Astro.svelte
Normal file
21
src/lib/components/svg/applications/Astro.svelte
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<svg
|
||||||
|
class="absolute top-0 left-0 -m-6 h-14 w-14"
|
||||||
|
viewBox="0 0 256 256"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
id="a"
|
||||||
|
fill="#302649"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="flame"
|
||||||
|
fill="#EF661E"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
6
src/lib/components/svg/applications/Eleventy.svelte
Normal file
6
src/lib/components/svg/applications/Eleventy.svelte
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg viewBox="0 0 128 128" class="absolute top-0 left-0 -m-8 h-16 w-16">
|
||||||
|
<path fill="transparent" d="M18 0h92v128H18z" /><path
|
||||||
|
d="M55.3 36.3h.4c1.1 0 1.5.9 1.5 2.3v41.8c0 1.8-.4 3-1.6 3l-4.8-.1c-1.2 0-1.6-1-1.6-3V45.5l-2.1.5c-1 0-1.5-.8-1.5-2.2v-3c0-1.2.4-2 1.4-2.2l8.3-2.2zm16 36.1l.1 3 .6 1.3.6.6.8.1h2.2c1 0 1.7.8 1.7 2v1.9c0 1.2-.6 2-1.8 2h-3.2l-2.3-.1c-.7-.2-1.4-.5-2.2-1a5.7 5.7 0 01-2-1.9c-.4-.8-.8-1.9-1-3.2-.4-1.4-.5-3-.5-4.8v-16h-1.5c-1.1 0-1.6-1-1.6-2.4v-1.7c0-1.4.5-2.3 1.6-2.3h1.5v-.1l.6-12.3c0-1.5.5-2.5 1.6-2.5h3.1c1.2 0 1.6 1 1.6 2.5v12.3h3.6c1.1 0 1.6 1 1.6 2.4V54c0 1.4-.5 2.3-1.6 2.3h-3.6v16.2zm9.4 15.7c0-2 .3-3.2 1.5-3.2.2 0 .4 0 1.4.4l1.1.3.2-.1.4-.7c.3-.6.4-1.6.4-3l-.6-3.3L79 52.7v-.9c0-1.2.3-2 1.2-2H84c.5 0 1 .3 1.3.6.3.4.5.9.6 1.6l3.4 18 2.6-17.8c.1-.8.3-1.3.6-1.7.3-.4.8-.6 1.3-.6h2.6c1 0 1.4.8 1.4 2l-.1.8L92 82.2c-.5 2.5-1 4.4-1.5 5.7a6.6 6.6 0 01-2 3c-.9.6-1.9.9-3.1.9h-.3c-2 0-3.3-.6-4.1-1.7-.3-.4-.4-1-.4-2zM31.3 38.8l8.2-2.1h.5c1 0 1.4.8 1.4 2.2v41.9c0 1.8-.4 2.9-1.6 2.9h-4.7c-1.2 0-1.6-1.1-1.6-3v-35l-2 .6c-1.2 0-1.6-.9-1.6-2.2v-3c0-1.2.4-2 1.4-2.3z"
|
||||||
|
fill="#FFF"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1,7 +1,7 @@
|
|||||||
function defaultBuildAndDeploy(packageManager) {
|
function defaultBuildAndDeploy(packageManager) {
|
||||||
return {
|
return {
|
||||||
installCommand:
|
installCommand:
|
||||||
packageManager === 'npm' ? `${packageManager} run install` : `${packageManager} install`,
|
packageManager === 'npm' ? `${packageManager} install` : `${packageManager} install`,
|
||||||
buildCommand:
|
buildCommand:
|
||||||
packageManager === 'npm' ? `${packageManager} run build` : `${packageManager} build`,
|
packageManager === 'npm' ? `${packageManager} run build` : `${packageManager} build`,
|
||||||
startCommand:
|
startCommand:
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { decrypt, encrypt } from '$lib/crypto';
|
import { decrypt, encrypt } from '$lib/crypto';
|
||||||
import { removeProxyConfiguration } from '$lib/haproxy';
|
|
||||||
import { asyncExecShell, getEngine } from '$lib/common';
|
import { asyncExecShell, getEngine } from '$lib/common';
|
||||||
|
|
||||||
import { getDomain, removeDestinationDocker } from '$lib/common';
|
import { getDomain, removeDestinationDocker } from '$lib/common';
|
||||||
@@ -119,7 +118,8 @@ export async function getApplicationWebhook({ projectId, branch }) {
|
|||||||
}
|
}
|
||||||
export async function getApplicationById({ id }) {
|
export async function getApplicationById({ id }) {
|
||||||
const body = await prisma.application.findFirst({
|
const body = await prisma.application.findFirst({
|
||||||
where: { id }
|
where: { id },
|
||||||
|
include: { destinationDocker: true }
|
||||||
});
|
});
|
||||||
|
|
||||||
return { ...body };
|
return { ...body };
|
||||||
@@ -135,13 +135,13 @@ export async function getApplication({ id, teamId }) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (body.gitSource?.githubApp?.clientSecret) {
|
if (body?.gitSource?.githubApp?.clientSecret) {
|
||||||
body.gitSource.githubApp.clientSecret = decrypt(body.gitSource.githubApp.clientSecret);
|
body.gitSource.githubApp.clientSecret = decrypt(body.gitSource.githubApp.clientSecret);
|
||||||
}
|
}
|
||||||
if (body.gitSource?.githubApp?.webhookSecret) {
|
if (body?.gitSource?.githubApp?.webhookSecret) {
|
||||||
body.gitSource.githubApp.webhookSecret = decrypt(body.gitSource.githubApp.webhookSecret);
|
body.gitSource.githubApp.webhookSecret = decrypt(body.gitSource.githubApp.webhookSecret);
|
||||||
}
|
}
|
||||||
if (body.gitSource?.githubApp?.privateKey) {
|
if (body?.gitSource?.githubApp?.privateKey) {
|
||||||
body.gitSource.githubApp.privateKey = decrypt(body.gitSource.githubApp.privateKey);
|
body.gitSource.githubApp.privateKey = decrypt(body.gitSource.githubApp.privateKey);
|
||||||
}
|
}
|
||||||
if (body?.gitSource?.gitlabApp?.appSecret) {
|
if (body?.gitSource?.gitlabApp?.appSecret) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { asyncExecShell, getEngine } from '$lib/common';
|
import { asyncExecShell, getEngine } from '$lib/common';
|
||||||
|
import { decrypt, encrypt } from '$lib/crypto';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { dockerInstance } from '$lib/docker';
|
||||||
import { startCoolifyProxy } from '$lib/haproxy';
|
import { startCoolifyProxy } from '$lib/haproxy';
|
||||||
import { getDatabaseImage } from '.';
|
import { getDatabaseImage } from '.';
|
||||||
@@ -47,7 +48,36 @@ export async function updateDestination({ id, name, engine, network }) {
|
|||||||
return await prisma.destinationDocker.update({ where: { id }, data: { name, engine, network } });
|
return await prisma.destinationDocker.update({ where: { id }, data: { name, engine, network } });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function newDestination({ name, teamId, engine, network, isCoolifyProxyUsed }) {
|
export async function newRemoteDestination({
|
||||||
|
name,
|
||||||
|
teamId,
|
||||||
|
engine,
|
||||||
|
network,
|
||||||
|
isCoolifyProxyUsed,
|
||||||
|
remoteEngine,
|
||||||
|
ipAddress,
|
||||||
|
user,
|
||||||
|
port,
|
||||||
|
sshPrivateKey
|
||||||
|
}) {
|
||||||
|
const encryptedPrivateKey = encrypt(sshPrivateKey);
|
||||||
|
const destination = await prisma.destinationDocker.create({
|
||||||
|
data: {
|
||||||
|
name,
|
||||||
|
teams: { connect: { id: teamId } },
|
||||||
|
engine,
|
||||||
|
network,
|
||||||
|
isCoolifyProxyUsed,
|
||||||
|
remoteEngine,
|
||||||
|
ipAddress,
|
||||||
|
user,
|
||||||
|
port,
|
||||||
|
sshPrivateKey: encryptedPrivateKey
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return destination.id;
|
||||||
|
}
|
||||||
|
export async function newLocalDestination({ name, teamId, engine, network, isCoolifyProxyUsed }) {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
const docker = dockerInstance({ destinationDocker: { engine, network } });
|
const docker = dockerInstance({ destinationDocker: { engine, network } });
|
||||||
const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } });
|
const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } });
|
||||||
@@ -94,9 +124,13 @@ export async function removeDestination({ id }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getDestination({ id, teamId }) {
|
export async function getDestination({ id, teamId }) {
|
||||||
return await prisma.destinationDocker.findFirst({
|
let destination = await prisma.destinationDocker.findFirst({
|
||||||
where: { id, teams: { some: { id: teamId } } }
|
where: { id, teams: { some: { id: teamId } } }
|
||||||
});
|
});
|
||||||
|
if (destination.remoteEngine) {
|
||||||
|
destination.sshPrivateKey = decrypt(destination.sshPrivateKey);
|
||||||
|
}
|
||||||
|
return destination;
|
||||||
}
|
}
|
||||||
export async function getDestinationByApplicationId({ id, teamId }) {
|
export async function getDestinationByApplicationId({ id, teamId }) {
|
||||||
return await prisma.destinationDocker.findFirst({
|
return await prisma.destinationDocker.findFirst({
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export async function buildCacheImageWithNode(data, imageForBuild) {
|
|||||||
const Dockerfile: Array<string> = [];
|
const Dockerfile: Array<string> = [];
|
||||||
Dockerfile.push(`FROM ${imageForBuild}`);
|
Dockerfile.push(`FROM ${imageForBuild}`);
|
||||||
Dockerfile.push('WORKDIR /usr/src/app');
|
Dockerfile.push('WORKDIR /usr/src/app');
|
||||||
|
Dockerfile.push(`LABEL coolify.image=true`);
|
||||||
if (secrets.length > 0) {
|
if (secrets.length > 0) {
|
||||||
secrets.forEach((secret) => {
|
secrets.forEach((secret) => {
|
||||||
if (secret.isBuildSecret) {
|
if (secret.isBuildSecret) {
|
||||||
|
|||||||
259
src/lib/haproxy/configuration.ts
Normal file
259
src/lib/haproxy/configuration.ts
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
import { dev } from '$app/env';
|
||||||
|
import got from 'got';
|
||||||
|
import mustache from 'mustache';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
|
import * as db from '$lib/database';
|
||||||
|
import { checkContainer, checkHAProxy } from '.';
|
||||||
|
import { asyncExecShell, getDomain, getEngine } from '$lib/common';
|
||||||
|
|
||||||
|
const url = dev ? 'http://localhost:5555' : 'http://coolify-haproxy:5555';
|
||||||
|
|
||||||
|
let template = `program api
|
||||||
|
command /usr/bin/dataplaneapi -f /usr/local/etc/haproxy/dataplaneapi.hcl --userlist haproxy-dataplaneapi
|
||||||
|
no option start-on-reload
|
||||||
|
|
||||||
|
global
|
||||||
|
stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners
|
||||||
|
log stdout format raw local0 debug
|
||||||
|
|
||||||
|
defaults
|
||||||
|
mode http
|
||||||
|
log global
|
||||||
|
timeout http-request 60s
|
||||||
|
timeout connect 10s
|
||||||
|
timeout client 60s
|
||||||
|
timeout server 60s
|
||||||
|
|
||||||
|
userlist haproxy-dataplaneapi
|
||||||
|
user admin insecure-password "\${HAPROXY_PASSWORD}"
|
||||||
|
|
||||||
|
frontend http
|
||||||
|
mode http
|
||||||
|
bind :80
|
||||||
|
bind :443 ssl crt /usr/local/etc/haproxy/ssl/ alpn h2,http/1.1
|
||||||
|
acl is_certbot path_beg /.well-known/acme-challenge/
|
||||||
|
{{#applications}}
|
||||||
|
{{#isHttps}}
|
||||||
|
http-request redirect scheme https code ${
|
||||||
|
dev ? 302 : 301
|
||||||
|
} if { hdr(host) -i {{domain}} } !{ ssl_fc }
|
||||||
|
{{/isHttps}}
|
||||||
|
http-request redirect location {{{redirectValue}}} code ${
|
||||||
|
dev ? 302 : 301
|
||||||
|
} if { req.hdr(host) -i {{redirectTo}} }
|
||||||
|
{{/applications}}
|
||||||
|
{{#services}}
|
||||||
|
{{#isHttps}}
|
||||||
|
http-request redirect scheme https code ${
|
||||||
|
dev ? 302 : 301
|
||||||
|
} if { hdr(host) -i {{domain}} } !{ ssl_fc }
|
||||||
|
{{/isHttps}}
|
||||||
|
http-request redirect location {{{redirectValue}}} code ${
|
||||||
|
dev ? 302 : 301
|
||||||
|
} if { req.hdr(host) -i {{redirectTo}} }
|
||||||
|
{{/services}}
|
||||||
|
{{#coolify}}
|
||||||
|
{{#isHttps}}
|
||||||
|
http-request redirect scheme https code ${
|
||||||
|
dev ? 302 : 301
|
||||||
|
} if { hdr(host) -i {{domain}} } !{ ssl_fc }
|
||||||
|
{{/isHttps}}
|
||||||
|
http-request redirect location {{{redirectValue}}} code ${
|
||||||
|
dev ? 302 : 301
|
||||||
|
} if { req.hdr(host) -i {{redirectTo}} }
|
||||||
|
{{/coolify}}
|
||||||
|
use_backend backend-certbot if is_certbot
|
||||||
|
use_backend %[req.hdr(host),lower]
|
||||||
|
|
||||||
|
frontend stats
|
||||||
|
bind *:8404
|
||||||
|
stats enable
|
||||||
|
stats uri /
|
||||||
|
stats admin if TRUE
|
||||||
|
stats auth "\${HAPROXY_USERNAME}:\${HAPROXY_PASSWORD}"
|
||||||
|
|
||||||
|
backend backend-certbot
|
||||||
|
mode http
|
||||||
|
server certbot host.docker.internal:9080
|
||||||
|
|
||||||
|
{{#applications}}
|
||||||
|
{{#isRunning}}
|
||||||
|
# updatedAt={{updatedAt}}
|
||||||
|
backend {{domain}}
|
||||||
|
option forwardfor
|
||||||
|
server {{id}} {{id}}:{{port}} check
|
||||||
|
{{/isRunning}}
|
||||||
|
{{/applications}}
|
||||||
|
|
||||||
|
{{#services}}
|
||||||
|
{{#isRunning}}
|
||||||
|
# updatedAt={{updatedAt}}
|
||||||
|
backend {{domain}}
|
||||||
|
option forwardfor
|
||||||
|
server {{id}} {{id}}:{{port}} check
|
||||||
|
{{/isRunning}}
|
||||||
|
{{/services}}
|
||||||
|
|
||||||
|
{{#coolify}}
|
||||||
|
backend {{domain}}
|
||||||
|
option forwardfor
|
||||||
|
option httpchk GET /undead.json
|
||||||
|
server {{id}} {{id}}:{{port}} check fall 10
|
||||||
|
{{/coolify}}
|
||||||
|
`;
|
||||||
|
export async function haproxyInstance() {
|
||||||
|
const { proxyPassword } = await db.listSettings();
|
||||||
|
return got.extend({
|
||||||
|
prefixUrl: url,
|
||||||
|
username: 'admin',
|
||||||
|
password: proxyPassword
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function configureHAProxy() {
|
||||||
|
try {
|
||||||
|
const haproxy = await haproxyInstance();
|
||||||
|
await checkHAProxy(haproxy);
|
||||||
|
const data = {
|
||||||
|
applications: [],
|
||||||
|
services: [],
|
||||||
|
coolify: []
|
||||||
|
};
|
||||||
|
const applications = await db.prisma.application.findMany({
|
||||||
|
include: { destinationDocker: true, settings: true }
|
||||||
|
});
|
||||||
|
for (const application of applications) {
|
||||||
|
const {
|
||||||
|
fqdn,
|
||||||
|
id,
|
||||||
|
port,
|
||||||
|
destinationDocker,
|
||||||
|
destinationDockerId,
|
||||||
|
settings: { previews },
|
||||||
|
updatedAt
|
||||||
|
} = application;
|
||||||
|
if (destinationDockerId) {
|
||||||
|
const { engine, network } = destinationDocker;
|
||||||
|
const isRunning = await checkContainer(engine, id);
|
||||||
|
if (fqdn) {
|
||||||
|
const domain = getDomain(fqdn);
|
||||||
|
const isHttps = fqdn.startsWith('https://');
|
||||||
|
const isWWW = fqdn.includes('www.');
|
||||||
|
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
||||||
|
if (isRunning) {
|
||||||
|
data.applications.push({
|
||||||
|
id,
|
||||||
|
port: port || 3000,
|
||||||
|
domain,
|
||||||
|
isRunning,
|
||||||
|
isHttps,
|
||||||
|
redirectValue,
|
||||||
|
redirectTo: isWWW ? domain : 'www.' + domain,
|
||||||
|
updatedAt: updatedAt.getTime()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (previews) {
|
||||||
|
const host = getEngine(engine);
|
||||||
|
const { stdout } = await asyncExecShell(
|
||||||
|
`DOCKER_HOST=${host} docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"`
|
||||||
|
);
|
||||||
|
const containers = stdout
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.filter((a) => a)
|
||||||
|
.map((c) => c.replace(/"/g, ''));
|
||||||
|
if (containers.length > 0) {
|
||||||
|
for (const container of containers) {
|
||||||
|
let previewDomain = `${container.split('-')[1]}.${domain}`;
|
||||||
|
data.applications.push({
|
||||||
|
id: container,
|
||||||
|
port: port || 3000,
|
||||||
|
domain: previewDomain,
|
||||||
|
isRunning,
|
||||||
|
isHttps,
|
||||||
|
redirectValue,
|
||||||
|
redirectTo: isWWW ? previewDomain : 'www.' + previewDomain,
|
||||||
|
updatedAt: updatedAt.getTime()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const services = await db.prisma.service.findMany({
|
||||||
|
include: {
|
||||||
|
destinationDocker: true,
|
||||||
|
minio: true,
|
||||||
|
plausibleAnalytics: true,
|
||||||
|
vscodeserver: true,
|
||||||
|
wordpress: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const service of services) {
|
||||||
|
const { fqdn, id, type, destinationDocker, destinationDockerId, updatedAt } = service;
|
||||||
|
if (destinationDockerId) {
|
||||||
|
const { engine } = destinationDocker;
|
||||||
|
const found = db.supportedServiceTypesAndVersions.find((a) => a.name === type);
|
||||||
|
if (found) {
|
||||||
|
const port = found.ports.main;
|
||||||
|
const publicPort = service[type]?.publicPort;
|
||||||
|
const isRunning = await checkContainer(engine, id);
|
||||||
|
if (fqdn) {
|
||||||
|
const domain = getDomain(fqdn);
|
||||||
|
const isHttps = fqdn.startsWith('https://');
|
||||||
|
const isWWW = fqdn.includes('www.');
|
||||||
|
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
||||||
|
if (isRunning) {
|
||||||
|
data.services.push({
|
||||||
|
id,
|
||||||
|
port,
|
||||||
|
publicPort,
|
||||||
|
domain,
|
||||||
|
isRunning,
|
||||||
|
isHttps,
|
||||||
|
redirectValue,
|
||||||
|
redirectTo: isWWW ? domain : 'www.' + domain,
|
||||||
|
updatedAt: updatedAt.getTime()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { fqdn } = await db.prisma.setting.findFirst();
|
||||||
|
if (fqdn) {
|
||||||
|
const domain = getDomain(fqdn);
|
||||||
|
const isHttps = fqdn.startsWith('https://');
|
||||||
|
const isWWW = fqdn.includes('www.');
|
||||||
|
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
||||||
|
data.coolify.push({
|
||||||
|
id: dev ? 'host.docker.internal' : 'coolify',
|
||||||
|
port: 3000,
|
||||||
|
domain,
|
||||||
|
isHttps,
|
||||||
|
redirectValue,
|
||||||
|
redirectTo: isWWW ? domain : 'www.' + domain
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const output = mustache.render(template, data);
|
||||||
|
const newHash = crypto.createHash('md5').update(output).digest('hex');
|
||||||
|
const { proxyHash, id } = await db.listSettings();
|
||||||
|
if (proxyHash !== newHash) {
|
||||||
|
await db.prisma.setting.update({ where: { id }, data: { proxyHash: newHash } });
|
||||||
|
await haproxy.post(`v2/services/haproxy/configuration/raw`, {
|
||||||
|
searchParams: {
|
||||||
|
skip_version: true
|
||||||
|
},
|
||||||
|
body: output,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'text/plain'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { dev } from '$app/env';
|
import { dev } from '$app/env';
|
||||||
import { asyncExecShell, getDomain, getEngine } from '$lib/common';
|
import { asyncExecShell, getEngine } from '$lib/common';
|
||||||
import got from 'got';
|
import got from 'got';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
|
|
||||||
@@ -47,113 +47,6 @@ export async function completeTransaction(transactionId) {
|
|||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
return await haproxy.put(`v2/services/haproxy/transactions/${transactionId}`);
|
return await haproxy.put(`v2/services/haproxy/transactions/${transactionId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeProxyConfiguration(fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
const backendFound = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/backends/${domain}`)
|
|
||||||
.json();
|
|
||||||
if (backendFound) {
|
|
||||||
const transactionId = await getNextTransactionId();
|
|
||||||
await haproxy
|
|
||||||
.delete(`v2/services/haproxy/configuration/backends/${domain}`, {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
await completeTransaction(transactionId);
|
|
||||||
}
|
|
||||||
await forceSSLOffApplication(domain);
|
|
||||||
await removeWwwRedirection(fqdn);
|
|
||||||
}
|
|
||||||
export async function forceSSLOffApplication(domain) {
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
let transactionId;
|
|
||||||
try {
|
|
||||||
const rules: any = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/http_request_rules`, {
|
|
||||||
searchParams: {
|
|
||||||
parent_name: 'http',
|
|
||||||
parent_type: 'frontend'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
if (rules.data.length > 0) {
|
|
||||||
const rule = rules.data.find((rule) =>
|
|
||||||
rule.cond_test.includes(`{ hdr(host) -i ${domain} } !{ ssl_fc }`)
|
|
||||||
);
|
|
||||||
if (rule) {
|
|
||||||
transactionId = await getNextTransactionId();
|
|
||||||
|
|
||||||
await haproxy
|
|
||||||
.delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId,
|
|
||||||
parent_name: 'http',
|
|
||||||
parent_type: 'frontend'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
if (transactionId) await completeTransaction(transactionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function forceSSLOnApplication(domain) {
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
let transactionId;
|
|
||||||
try {
|
|
||||||
const rules: any = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/http_request_rules`, {
|
|
||||||
searchParams: {
|
|
||||||
parent_name: 'http',
|
|
||||||
parent_type: 'frontend'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
let nextRule = 0;
|
|
||||||
if (rules.data.length > 0) {
|
|
||||||
const rule = rules.data.find((rule) =>
|
|
||||||
rule.cond_test.includes(`{ hdr(host) -i ${domain} } !{ ssl_fc }`)
|
|
||||||
);
|
|
||||||
if (rule) return;
|
|
||||||
nextRule = rules.data[rules.data.length - 1].index + 1;
|
|
||||||
}
|
|
||||||
transactionId = await getNextTransactionId();
|
|
||||||
|
|
||||||
await haproxy
|
|
||||||
.post(`v2/services/haproxy/configuration/http_request_rules`, {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId,
|
|
||||||
parent_name: 'http',
|
|
||||||
parent_type: 'frontend'
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
index: nextRule,
|
|
||||||
cond: 'if',
|
|
||||||
cond_test: `{ hdr(host) -i ${domain} } !{ ssl_fc }`,
|
|
||||||
type: 'redirect',
|
|
||||||
redir_type: 'scheme',
|
|
||||||
redir_value: 'https',
|
|
||||||
redir_code: dev ? 302 : 301
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
throw error;
|
|
||||||
} finally {
|
|
||||||
if (transactionId) await completeTransaction(transactionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deleteProxy({ id }) {
|
export async function deleteProxy({ id }) {
|
||||||
const haproxy = await haproxyInstance();
|
const haproxy = await haproxyInstance();
|
||||||
await checkHAProxy(haproxy);
|
await checkHAProxy(haproxy);
|
||||||
@@ -177,7 +70,7 @@ export async function deleteProxy({ id }) {
|
|||||||
})
|
})
|
||||||
.json();
|
.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error.response.body);
|
console.log(error.response?.body || error);
|
||||||
} finally {
|
} finally {
|
||||||
if (transactionId) await completeTransaction(transactionId);
|
if (transactionId) await completeTransaction(transactionId);
|
||||||
}
|
}
|
||||||
@@ -187,109 +80,6 @@ export async function reloadHaproxy(engine) {
|
|||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
return await asyncExecShell(`DOCKER_HOST=${host} docker exec coolify-haproxy kill -HUP 1`);
|
return await asyncExecShell(`DOCKER_HOST=${host} docker exec coolify-haproxy kill -HUP 1`);
|
||||||
}
|
}
|
||||||
export async function configureProxyForApplication({ domain, imageId, applicationId, port }) {
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
|
|
||||||
let serverConfigured = false;
|
|
||||||
let backendAvailable: any = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
backendAvailable = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/backends/${domain}`)
|
|
||||||
.json();
|
|
||||||
const server: any = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/servers/${imageId}`, {
|
|
||||||
searchParams: {
|
|
||||||
backend: domain
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
|
|
||||||
if (backendAvailable && server) {
|
|
||||||
// Very sophisticated way to check if the server is already configured in proxy
|
|
||||||
if (backendAvailable.data.forwardfor.enabled === 'enabled') {
|
|
||||||
if (backendAvailable.data.name === domain) {
|
|
||||||
if (server.data.check === 'enabled') {
|
|
||||||
if (server.data.address === imageId) {
|
|
||||||
if (server.data.port === port) {
|
|
||||||
serverConfigured = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
//console.log('error getting backend or server', error?.response?.body);
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serverConfigured) return;
|
|
||||||
const transactionId = await getNextTransactionId();
|
|
||||||
if (backendAvailable) {
|
|
||||||
await haproxy
|
|
||||||
.delete(`v2/services/haproxy/configuration/backends/${domain}`, {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await haproxy.post('v2/services/haproxy/configuration/backends', {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
'init-addr': 'last,libc,none',
|
|
||||||
forwardfor: { enabled: 'enabled' },
|
|
||||||
name: domain
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await haproxy.post('v2/services/haproxy/configuration/servers', {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId,
|
|
||||||
backend: domain
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
address: imageId,
|
|
||||||
check: 'enabled',
|
|
||||||
name: imageId,
|
|
||||||
port: port
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
throw error?.response?.body || error;
|
|
||||||
} finally {
|
|
||||||
await completeTransaction(transactionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function configureCoolifyProxyOff(fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json();
|
|
||||||
const transactionId = await getNextTransactionId();
|
|
||||||
await haproxy
|
|
||||||
.delete(`v2/services/haproxy/configuration/backends/${domain}`, {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
await completeTransaction(transactionId);
|
|
||||||
if (isHttps) await forceSSLOffApplication(domain);
|
|
||||||
await removeWwwRedirection(fqdn);
|
|
||||||
} catch (error) {
|
|
||||||
throw error?.response?.body || error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function checkHAProxy(haproxy?: any) {
|
export async function checkHAProxy(haproxy?: any) {
|
||||||
if (!haproxy) haproxy = await haproxyInstance();
|
if (!haproxy) haproxy = await haproxyInstance();
|
||||||
try {
|
try {
|
||||||
@@ -301,76 +91,6 @@ export async function checkHAProxy(haproxy?: any) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function configureCoolifyProxyOn(fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
let serverConfigured = false;
|
|
||||||
let backendAvailable: any = null;
|
|
||||||
try {
|
|
||||||
backendAvailable = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/backends/${domain}`)
|
|
||||||
.json();
|
|
||||||
const server: any = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/servers/coolify`, {
|
|
||||||
searchParams: {
|
|
||||||
backend: domain
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
if (backendAvailable && server) {
|
|
||||||
// Very sophisticated way to check if the server is already configured in proxy
|
|
||||||
if (backendAvailable.data.forwardfor.enabled === 'enabled') {
|
|
||||||
if (backendAvailable.data.name === domain) {
|
|
||||||
if (server.data.check === 'enabled') {
|
|
||||||
if (server.data.address === dev ? 'host.docker.internal' : 'coolify') {
|
|
||||||
if (server.data.port === 3000) {
|
|
||||||
serverConfigured = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {}
|
|
||||||
if (serverConfigured) return;
|
|
||||||
const transactionId = await getNextTransactionId();
|
|
||||||
try {
|
|
||||||
await haproxy.post('v2/services/haproxy/configuration/backends', {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
adv_check: 'httpchk',
|
|
||||||
httpchk_params: {
|
|
||||||
method: 'GET',
|
|
||||||
uri: '/undead.json'
|
|
||||||
},
|
|
||||||
'init-addr': 'last,libc,none',
|
|
||||||
forwardfor: { enabled: 'enabled' },
|
|
||||||
name: domain
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await haproxy.post('v2/services/haproxy/configuration/servers', {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId,
|
|
||||||
backend: domain
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
address: dev ? 'host.docker.internal' : 'coolify',
|
|
||||||
check: 'enabled',
|
|
||||||
fall: 10,
|
|
||||||
name: 'coolify',
|
|
||||||
port: 3000
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
throw error;
|
|
||||||
} finally {
|
|
||||||
await completeTransaction(transactionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function stopTcpHttpProxy(destinationDocker, publicPort) {
|
export async function stopTcpHttpProxy(destinationDocker, publicPort) {
|
||||||
const { engine } = destinationDocker;
|
const { engine } = destinationDocker;
|
||||||
@@ -434,7 +154,7 @@ export async function startHttpProxy(destinationDocker, id, publicPort, privateP
|
|||||||
export async function startCoolifyProxy(engine) {
|
export async function startCoolifyProxy(engine) {
|
||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
const found = await checkContainer(engine, 'coolify-haproxy');
|
const found = await checkContainer(engine, 'coolify-haproxy');
|
||||||
const { proxyPassword, proxyUser } = await db.listSettings();
|
const { proxyPassword, proxyUser, id } = await db.listSettings();
|
||||||
if (!found) {
|
if (!found) {
|
||||||
const { stdout: Config } = await asyncExecShell(
|
const { stdout: Config } = await asyncExecShell(
|
||||||
`DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'`
|
`DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'`
|
||||||
@@ -443,6 +163,7 @@ export async function startCoolifyProxy(engine) {
|
|||||||
await asyncExecShell(
|
await asyncExecShell(
|
||||||
`DOCKER_HOST="${host}" docker run -e HAPROXY_USERNAME=${proxyUser} -e HAPROXY_PASSWORD=${proxyPassword} --restart always --add-host 'host.docker.internal:host-gateway' --add-host 'host.docker.internal:${ip}' -v coolify-ssl-certs:/usr/local/etc/haproxy/ssl --network coolify-infra -p "80:80" -p "443:443" -p "8404:8404" -p "5555:5555" -p "5000:5000" --name coolify-haproxy -d coollabsio/${defaultProxyImage}`
|
`DOCKER_HOST="${host}" docker run -e HAPROXY_USERNAME=${proxyUser} -e HAPROXY_PASSWORD=${proxyPassword} --restart always --add-host 'host.docker.internal:host-gateway' --add-host 'host.docker.internal:${ip}' -v coolify-ssl-certs:/usr/local/etc/haproxy/ssl --network coolify-infra -p "80:80" -p "443:443" -p "8404:8404" -p "5555:5555" -p "5000:5000" --name coolify-haproxy -d coollabsio/${defaultProxyImage}`
|
||||||
);
|
);
|
||||||
|
await db.prisma.setting.update({ where: { id }, data: { proxyHash: null } });
|
||||||
}
|
}
|
||||||
await configureNetworkCoolifyProxy(engine);
|
await configureNetworkCoolifyProxy(engine);
|
||||||
}
|
}
|
||||||
@@ -475,6 +196,8 @@ export async function stopCoolifyProxy(engine) {
|
|||||||
const host = getEngine(engine);
|
const host = getEngine(engine);
|
||||||
const found = await checkContainer(engine, 'coolify-haproxy');
|
const found = await checkContainer(engine, 'coolify-haproxy');
|
||||||
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: false });
|
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: false });
|
||||||
|
const { id } = await db.prisma.setting.findFirst({});
|
||||||
|
await db.prisma.setting.update({ where: { id }, data: { proxyHash: null } });
|
||||||
try {
|
try {
|
||||||
if (found) {
|
if (found) {
|
||||||
await asyncExecShell(
|
await asyncExecShell(
|
||||||
@@ -499,168 +222,3 @@ export async function configureNetworkCoolifyProxy(engine) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configureSimpleServiceProxyOn({ id, domain, port }) {
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
let serverConfigured = false;
|
|
||||||
let backendAvailable: any = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
backendAvailable = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/backends/${domain}`)
|
|
||||||
.json();
|
|
||||||
const server: any = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/servers/${id}`, {
|
|
||||||
searchParams: {
|
|
||||||
backend: domain
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
if (backendAvailable && server) {
|
|
||||||
// Very sophisticated way to check if the server is already configured in proxy
|
|
||||||
if (backendAvailable.data.forwardfor.enabled === 'enabled') {
|
|
||||||
if (backendAvailable.data.name === domain) {
|
|
||||||
if (server.data.check === 'enabled') {
|
|
||||||
if (server.data.address === id) {
|
|
||||||
if (server.data.port === port) {
|
|
||||||
serverConfigured = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {}
|
|
||||||
if (serverConfigured) return;
|
|
||||||
const transactionId = await getNextTransactionId();
|
|
||||||
await haproxy.post('v2/services/haproxy/configuration/backends', {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
'init-addr': 'last,libc,none',
|
|
||||||
forwardfor: { enabled: 'enabled' },
|
|
||||||
name: domain
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await haproxy.post('v2/services/haproxy/configuration/servers', {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId,
|
|
||||||
backend: domain
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
address: id,
|
|
||||||
check: 'enabled',
|
|
||||||
name: id,
|
|
||||||
port: port
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await completeTransaction(transactionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function configureSimpleServiceProxyOff(fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
try {
|
|
||||||
await haproxy.get(`v2/services/haproxy/configuration/backends/${domain}`).json();
|
|
||||||
const transactionId = await getNextTransactionId();
|
|
||||||
await haproxy
|
|
||||||
.delete(`v2/services/haproxy/configuration/backends/${domain}`, {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
await completeTransaction(transactionId);
|
|
||||||
} catch (error) {}
|
|
||||||
await forceSSLOffApplication(domain);
|
|
||||||
await removeWwwRedirection(fqdn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeWwwRedirection(fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
|
||||||
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy();
|
|
||||||
const rules: any = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/http_request_rules`, {
|
|
||||||
searchParams: {
|
|
||||||
parent_name: 'http',
|
|
||||||
parent_type: 'frontend'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
if (rules.data.length > 0) {
|
|
||||||
const rule = rules.data.find((rule) => rule.redir_value.includes(redirectValue));
|
|
||||||
if (rule) {
|
|
||||||
const transactionId = await getNextTransactionId();
|
|
||||||
await haproxy
|
|
||||||
.delete(`v2/services/haproxy/configuration/http_request_rules/${rule.index}`, {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId,
|
|
||||||
parent_name: 'http',
|
|
||||||
parent_type: 'frontend'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
await completeTransaction(transactionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function setWwwRedirection(fqdn) {
|
|
||||||
const haproxy = await haproxyInstance();
|
|
||||||
await checkHAProxy(haproxy);
|
|
||||||
let transactionId;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
const isWWW = fqdn.includes('www.');
|
|
||||||
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
|
|
||||||
const contTest = `{ req.hdr(host) -i ${isWWW ? domain.replace('www.', '') : `www.${domain}`} }`;
|
|
||||||
const rules: any = await haproxy
|
|
||||||
.get(`v2/services/haproxy/configuration/http_request_rules`, {
|
|
||||||
searchParams: {
|
|
||||||
parent_name: 'http',
|
|
||||||
parent_type: 'frontend'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
let nextRule = 0;
|
|
||||||
if (rules.data.length > 0) {
|
|
||||||
const rule = rules.data.find((rule) => rule.redir_value.includes(redirectValue));
|
|
||||||
if (rule) return;
|
|
||||||
nextRule = rules.data[rules.data.length - 1].index + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionId = await getNextTransactionId();
|
|
||||||
await haproxy
|
|
||||||
.post(`v2/services/haproxy/configuration/http_request_rules`, {
|
|
||||||
searchParams: {
|
|
||||||
transaction_id: transactionId,
|
|
||||||
parent_name: 'http',
|
|
||||||
parent_type: 'frontend'
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
index: nextRule,
|
|
||||||
cond: 'if',
|
|
||||||
cond_test: contTest,
|
|
||||||
type: 'redirect',
|
|
||||||
redir_type: 'location',
|
|
||||||
redir_value: redirectValue,
|
|
||||||
redir_code: dev ? 302 : 301
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
throw error;
|
|
||||||
} finally {
|
|
||||||
if (transactionId) await completeTransaction(transactionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default async function ({
|
|||||||
buildId
|
buildId
|
||||||
}): Promise<any> {
|
}): Promise<any> {
|
||||||
try {
|
try {
|
||||||
saveBuildLog({ line: 'GitHub importer started', buildId, applicationId });
|
saveBuildLog({ line: 'GitHub importer started.', buildId, applicationId });
|
||||||
const { privateKey, appId, installationId } = await db.getUniqueGithubApp({ githubAppId });
|
const { privateKey, appId, installationId } = await db.getUniqueGithubApp({ githubAppId });
|
||||||
const githubPrivateKey = privateKey.replace(/\\n/g, '\n').replace(/"/g, '');
|
const githubPrivateKey = privateKey.replace(/\\n/g, '\n').replace(/"/g, '');
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { dev } from '$app/env';
|
import { asyncExecShell, getDomain, getEngine } from '$lib/common';
|
||||||
import { forceSSLOffApplication, forceSSLOnApplication } from '$lib/haproxy';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import { asyncExecShell, getEngine } from './common';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
|
import { dev } from '$app/env';
|
||||||
import cuid from 'cuid';
|
import cuid from 'cuid';
|
||||||
import getPort, { portNumbers } from 'get-port';
|
import getPort, { portNumbers } from 'get-port';
|
||||||
|
|
||||||
export async function letsEncrypt({ domain, isCoolify = false, id = null }) {
|
export async function letsEncrypt(domain, id = null, isCoolify = false) {
|
||||||
try {
|
try {
|
||||||
const data = await db.prisma.setting.findFirst();
|
const data = await db.prisma.setting.findFirst();
|
||||||
const { minPort, maxPort } = data;
|
const { minPort, maxPort } = data;
|
||||||
@@ -47,7 +47,6 @@ export async function letsEncrypt({ domain, isCoolify = false, id = null }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await forceSSLOffApplication(domain);
|
|
||||||
if (dualCerts) {
|
if (dualCerts) {
|
||||||
await asyncExecShell(
|
await asyncExecShell(
|
||||||
`DOCKER_HOST=${host} docker run --rm --name certbot-${randomCuid} -p 9080:${randomPort} -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs certonly --standalone --preferred-challenges http --http-01-address 0.0.0.0 --http-01-port ${randomPort} -d ${nakedDomain} -d ${wwwDomain} --expand --agree-tos --non-interactive --register-unsafely-without-email ${
|
`DOCKER_HOST=${host} docker run --rm --name certbot-${randomCuid} -p 9080:${randomPort} -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs certonly --standalone --preferred-challenges http --http-01-address 0.0.0.0 --http-01-port ${randomPort} -d ${nakedDomain} -d ${wwwDomain} --expand --agree-tos --non-interactive --register-unsafely-without-email ${
|
||||||
@@ -71,9 +70,85 @@ export async function letsEncrypt({ domain, isCoolify = false, id = null }) {
|
|||||||
if (error.code !== 0) {
|
if (error.code !== 0) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
} finally {
|
}
|
||||||
if (!isCoolify) {
|
}
|
||||||
await forceSSLOnApplication(domain);
|
|
||||||
|
export async function generateSSLCerts() {
|
||||||
|
const ssls = [];
|
||||||
|
const applications = await db.prisma.application.findMany({
|
||||||
|
include: { destinationDocker: true, settings: true }
|
||||||
|
});
|
||||||
|
for (const application of applications) {
|
||||||
|
const {
|
||||||
|
fqdn,
|
||||||
|
id,
|
||||||
|
destinationDocker: { engine, network },
|
||||||
|
settings: { previews }
|
||||||
|
} = application;
|
||||||
|
const isRunning = await checkContainer(engine, id);
|
||||||
|
const domain = getDomain(fqdn);
|
||||||
|
const isHttps = fqdn.startsWith('https://');
|
||||||
|
if (isRunning) {
|
||||||
|
if (isHttps) ssls.push({ domain, id, isCoolify: false });
|
||||||
|
}
|
||||||
|
if (previews) {
|
||||||
|
const host = getEngine(engine);
|
||||||
|
const { stdout } = await asyncExecShell(
|
||||||
|
`DOCKER_HOST=${host} docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"`
|
||||||
|
);
|
||||||
|
const containers = stdout
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.filter((a) => a)
|
||||||
|
.map((c) => c.replace(/"/g, ''));
|
||||||
|
if (containers.length > 0) {
|
||||||
|
for (const container of containers) {
|
||||||
|
let previewDomain = `${container.split('-')[1]}.${domain}`;
|
||||||
|
if (isHttps) ssls.push({ domain: previewDomain, id, isCoolify: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const services = await db.prisma.service.findMany({
|
||||||
|
include: {
|
||||||
|
destinationDocker: true,
|
||||||
|
minio: true,
|
||||||
|
plausibleAnalytics: true,
|
||||||
|
vscodeserver: true,
|
||||||
|
wordpress: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const service of services) {
|
||||||
|
const {
|
||||||
|
fqdn,
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
destinationDocker: { engine }
|
||||||
|
} = service;
|
||||||
|
const found = db.supportedServiceTypesAndVersions.find((a) => a.name === type);
|
||||||
|
if (found) {
|
||||||
|
const domain = getDomain(fqdn);
|
||||||
|
const isHttps = fqdn.startsWith('https://');
|
||||||
|
const isRunning = await checkContainer(engine, id);
|
||||||
|
if (isRunning) {
|
||||||
|
if (isHttps) ssls.push({ domain, id, isCoolify: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { fqdn } = await db.prisma.setting.findFirst();
|
||||||
|
if (fqdn) {
|
||||||
|
const domain = getDomain(fqdn);
|
||||||
|
const isHttps = fqdn.startsWith('https://');
|
||||||
|
if (isHttps) ssls.push({ domain, id: 'coolify', isCoolify: true });
|
||||||
|
}
|
||||||
|
if (ssls.length > 0) {
|
||||||
|
for (const ssl of ssls) {
|
||||||
|
if (!dev) {
|
||||||
|
await letsEncrypt(ssl.domain, ssl.id, ssl.isCoolify);
|
||||||
|
} else {
|
||||||
|
console.log('Generate ssl for', ssl.domain);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,6 @@ import * as buildpacks from '../buildPacks';
|
|||||||
import * as importers from '../importers';
|
import * as importers from '../importers';
|
||||||
import { dockerInstance } from '../docker';
|
import { dockerInstance } from '../docker';
|
||||||
import { asyncExecShell, createDirectories, getDomain, getEngine, saveBuildLog } from '../common';
|
import { asyncExecShell, createDirectories, getDomain, getEngine, saveBuildLog } from '../common';
|
||||||
import { configureProxyForApplication, reloadHaproxy, setWwwRedirection } from '../haproxy';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { decrypt } from '$lib/crypto';
|
import { decrypt } from '$lib/crypto';
|
||||||
import { sentry } from '$lib/common';
|
import { sentry } from '$lib/common';
|
||||||
@@ -234,10 +233,16 @@ export default async function (job) {
|
|||||||
baseDirectory,
|
baseDirectory,
|
||||||
publishDirectory
|
publishDirectory
|
||||||
});
|
});
|
||||||
|
let envFound = false;
|
||||||
|
try {
|
||||||
|
envFound = !!(await fs.stat(`${workdir}/.env`));
|
||||||
|
} catch (error) {
|
||||||
|
//
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
saveBuildLog({ line: 'Deployment started.', buildId, applicationId });
|
saveBuildLog({ line: 'Deployment started.', buildId, applicationId });
|
||||||
const { stderr } = await asyncExecShell(
|
const { stderr } = await asyncExecShell(
|
||||||
`DOCKER_HOST=${host} docker run --env-file=${workdir}/.env ${labels.join(
|
`DOCKER_HOST=${host} docker run ${envFound && `--env-file=${workdir}/.env`} ${labels.join(
|
||||||
' '
|
' '
|
||||||
)} --name ${imageId} --network ${
|
)} --name ${imageId} --network ${
|
||||||
docker.network
|
docker.network
|
||||||
@@ -250,25 +255,6 @@ export default async function (job) {
|
|||||||
sentry.captureException(error);
|
sentry.captureException(error);
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
try {
|
saveBuildLog({ line: 'Proxy will be updated shortly.', buildId, applicationId });
|
||||||
if (destinationDockerId && destinationDocker.isCoolifyProxyUsed) {
|
|
||||||
saveBuildLog({ line: 'Proxy configuration started!', buildId, applicationId });
|
|
||||||
await configureProxyForApplication({ domain, imageId, applicationId, port });
|
|
||||||
if (isHttps) await letsEncrypt({ domain, id: applicationId });
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
await reloadHaproxy(destinationDocker.engine);
|
|
||||||
saveBuildLog({ line: 'Proxy configuration successful!', buildId, applicationId });
|
|
||||||
} else {
|
|
||||||
saveBuildLog({
|
|
||||||
line: 'Coolify Proxy is not configured for this destination. Nothing else to do.',
|
|
||||||
buildId,
|
|
||||||
applicationId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
saveBuildLog({ line: error.stdout || error, buildId, applicationId });
|
|
||||||
sentry.captureException(error);
|
|
||||||
throw new Error(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,48 +8,53 @@ export default async function () {
|
|||||||
for (const destinationDocker of destinationDockers) {
|
for (const destinationDocker of destinationDockers) {
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
// Tagging images with labels
|
// Tagging images with labels
|
||||||
try {
|
// try {
|
||||||
const images = [
|
// const images = [
|
||||||
`coollabsio/${defaultProxyImageTcp}`,
|
// `coollabsio/${defaultProxyImageTcp}`,
|
||||||
`coollabsio/${defaultProxyImageHttp}`,
|
// `coollabsio/${defaultProxyImageHttp}`,
|
||||||
'certbot/certbot:latest',
|
// 'certbot/certbot:latest',
|
||||||
'node:16.14.0-alpine',
|
// 'node:16.14.0-alpine',
|
||||||
'alpine:latest',
|
// 'alpine:latest',
|
||||||
'nginx:stable-alpine',
|
// 'nginx:stable-alpine',
|
||||||
'node:lts',
|
// 'node:lts',
|
||||||
'php:apache',
|
// 'php:apache',
|
||||||
'rust:latest'
|
// 'rust:latest'
|
||||||
];
|
// ];
|
||||||
for (const image of images) {
|
// for (const image of images) {
|
||||||
try {
|
// try {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker image inspect ${image}`);
|
// await asyncExecShell(`DOCKER_HOST=${host} docker image inspect ${image}`);
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
await asyncExecShell(
|
// await asyncExecShell(
|
||||||
`DOCKER_HOST=${host} docker pull ${image} && echo "FROM ${image}" | docker build --label coolify.image="true" -t "${image}" -`
|
// `DOCKER_HOST=${host} docker pull ${image} && echo "FROM ${image}" | docker build --label coolify.image="true" -t "${image}" -`
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} catch (error) {}
|
// } catch (error) {}
|
||||||
try {
|
try {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker container prune -f`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker container prune -f`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
if (!dev) {
|
|
||||||
//Cleanup images that are not managed by coolify
|
|
||||||
try {
|
|
||||||
await asyncExecShell(
|
|
||||||
`DOCKER_HOST=${host} docker image prune --filter 'label!=coolify.image=true' -a -f`
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Cleanup dangling images
|
|
||||||
try {
|
try {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker image prune -f`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker image prune -f`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
// if (!dev) {
|
||||||
|
// // Cleanup images that are not managed by coolify
|
||||||
|
// try {
|
||||||
|
// await asyncExecShell(
|
||||||
|
// `DOCKER_HOST=${host} docker image prune --filter 'label!=coolify.image=true' -a -f`
|
||||||
|
// );
|
||||||
|
// } catch (error) {
|
||||||
|
// console.log(error);
|
||||||
|
// }
|
||||||
|
// // Cleanup old images >3 days
|
||||||
|
// try {
|
||||||
|
// await asyncExecShell(`DOCKER_HOST=${host} docker image prune --filter "until=72h" -a -f`);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.log(error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ const cron = async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await queue.proxy.add('proxy', {}, { repeat: { every: 10000 } });
|
await queue.proxy.add('proxy', {}, { repeat: { every: 10000 } });
|
||||||
// await queue.ssl.add('ssl', {}, { repeat: { every: 10000 } });
|
await queue.ssl.add('ssl', {}, { repeat: { every: 60000 } });
|
||||||
await queue.cleanup.add('cleanup', {}, { repeat: { every: 600000 } });
|
await queue.cleanup.add('cleanup', {}, { repeat: { every: 600000 } });
|
||||||
await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } });
|
await queue.sslRenew.add('sslRenew', {}, { repeat: { every: 1800000 } });
|
||||||
|
|
||||||
|
|||||||
@@ -1,106 +1,12 @@
|
|||||||
import { getDomain } from '$lib/common';
|
import { dev } from '$app/env';
|
||||||
import { getApplicationById, prisma, supportedServiceTypesAndVersions } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { configureHAProxy } from '$lib/haproxy/configuration';
|
||||||
import {
|
|
||||||
checkContainer,
|
|
||||||
configureCoolifyProxyOn,
|
|
||||||
configureProxyForApplication,
|
|
||||||
configureSimpleServiceProxyOn,
|
|
||||||
forceSSLOnApplication,
|
|
||||||
reloadHaproxy,
|
|
||||||
setWwwRedirection,
|
|
||||||
startCoolifyProxy,
|
|
||||||
startHttpProxy
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import * as db from '$lib/database';
|
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
try {
|
try {
|
||||||
// Check destination containers and configure proxy if needed
|
return await configureHAProxy();
|
||||||
const destinationDockers = await prisma.destinationDocker.findMany({});
|
|
||||||
for (const destination of destinationDockers) {
|
|
||||||
if (destination.isCoolifyProxyUsed) {
|
|
||||||
const docker = dockerInstance({ destinationDocker: destination });
|
|
||||||
const containers = await docker.engine.listContainers();
|
|
||||||
const configurations = containers.filter(
|
|
||||||
(container) => container.Labels['coolify.managed']
|
|
||||||
);
|
|
||||||
for (const configuration of configurations) {
|
|
||||||
if (configuration.Labels['coolify.configuration']) {
|
|
||||||
const parsedConfiguration = JSON.parse(
|
|
||||||
Buffer.from(configuration.Labels['coolify.configuration'], 'base64').toString()
|
|
||||||
);
|
|
||||||
if (
|
|
||||||
parsedConfiguration &&
|
|
||||||
configuration.Labels['coolify.type'] === 'standalone-application'
|
|
||||||
) {
|
|
||||||
const { fqdn, applicationId, port, pullmergeRequestId } = parsedConfiguration;
|
|
||||||
if (fqdn) {
|
|
||||||
const found = await getApplicationById({ id: applicationId });
|
|
||||||
if (found) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
await configureProxyForApplication({
|
|
||||||
domain,
|
|
||||||
imageId: pullmergeRequestId
|
|
||||||
? `${applicationId}-${pullmergeRequestId}`
|
|
||||||
: applicationId,
|
|
||||||
applicationId,
|
|
||||||
port
|
|
||||||
});
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
if (isHttps) await forceSSLOnApplication(domain);
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const container of containers) {
|
|
||||||
const image = container.Image.split(':')[0];
|
|
||||||
const found = supportedServiceTypesAndVersions.find((a) => a.baseImage === image);
|
|
||||||
if (found) {
|
|
||||||
const type = found.name;
|
|
||||||
const mainPort = found.ports.main;
|
|
||||||
const id = container.Names[0].replace('/', '');
|
|
||||||
const service = await db.prisma.service.findUnique({
|
|
||||||
where: { id },
|
|
||||||
include: {
|
|
||||||
destinationDocker: true,
|
|
||||||
minio: true,
|
|
||||||
plausibleAnalytics: true,
|
|
||||||
vscodeserver: true,
|
|
||||||
wordpress: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const { fqdn } = service;
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
await configureSimpleServiceProxyOn({ id, domain, port: mainPort });
|
|
||||||
const publicPort = service[type]?.publicPort;
|
|
||||||
if (publicPort) {
|
|
||||||
const containerFound = await checkContainer(
|
|
||||||
destination.engine,
|
|
||||||
`haproxy-for-${publicPort}`
|
|
||||||
);
|
|
||||||
if (!containerFound) {
|
|
||||||
await startHttpProxy(destination, id, publicPort, 9000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const services = await prisma.service.findMany({});
|
|
||||||
// Check Coolify FQDN and configure proxy if needed
|
|
||||||
const { fqdn } = await db.listSettings();
|
|
||||||
if (fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
await startCoolifyProxy('/var/run/docker.sock');
|
|
||||||
await configureCoolifyProxyOn(fqdn);
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
if (isHttps) await forceSSLOnApplication(domain);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
console.log(error.response?.body || error);
|
||||||
|
return ErrorHandler(error.response?.body || error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,9 @@
|
|||||||
import { asyncExecShell, getDomain, getEngine } from '$lib/common';
|
import { generateSSLCerts } from '$lib/letsencrypt';
|
||||||
import { prisma } from '$lib/database';
|
|
||||||
import { dockerInstance } from '$lib/docker';
|
|
||||||
import { forceSSLOnApplication } from '$lib/haproxy';
|
|
||||||
import * as db from '$lib/database';
|
|
||||||
import { dev } from '$app/env';
|
|
||||||
import getPort, { portNumbers } from 'get-port';
|
|
||||||
import cuid from 'cuid';
|
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
try {
|
try {
|
||||||
const data = await db.prisma.setting.findFirst();
|
return await generateSSLCerts();
|
||||||
const { minPort, maxPort } = data;
|
|
||||||
|
|
||||||
const publicPort = await getPort({ port: portNumbers(minPort, maxPort) });
|
|
||||||
const randomCuid = cuid();
|
|
||||||
const destinationDockers = await prisma.destinationDocker.findMany({});
|
|
||||||
for (const destination of destinationDockers) {
|
|
||||||
if (destination.isCoolifyProxyUsed) {
|
|
||||||
const docker = dockerInstance({ destinationDocker: destination });
|
|
||||||
const containers = await docker.engine.listContainers();
|
|
||||||
const configurations = containers.filter(
|
|
||||||
(container) => container.Labels['coolify.managed']
|
|
||||||
);
|
|
||||||
for (const configuration of configurations) {
|
|
||||||
const parsedConfiguration = JSON.parse(
|
|
||||||
Buffer.from(configuration.Labels['coolify.configuration'], 'base64').toString()
|
|
||||||
);
|
|
||||||
if (configuration.Labels['coolify.type'] === 'standalone-application') {
|
|
||||||
const { fqdn } = parsedConfiguration;
|
|
||||||
if (fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
if (isHttps) {
|
|
||||||
if (dev) {
|
|
||||||
console.log('DEV MODE: SSL is enabled');
|
|
||||||
} else {
|
|
||||||
const host = getEngine(destination.engine);
|
|
||||||
await asyncExecShell(
|
|
||||||
`DOCKER_HOST=${host} docker run --rm --name certbot-${randomCuid} -p 9080:${publicPort} -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs certonly --standalone --preferred-challenges http --http-01-address 0.0.0.0 --http-01-port ${publicPort} -d ${domain} --agree-tos --non-interactive --register-unsafely-without-email`
|
|
||||||
);
|
|
||||||
const { stderr } = await asyncExecShell(
|
|
||||||
`DOCKER_HOST=${host} docker run --rm -v "coolify-letsencrypt:/etc/letsencrypt" -v "coolify-ssl-certs:/app/ssl" alpine:latest cat /etc/letsencrypt/live/${domain}/fullchain.pem /etc/letsencrypt/live/${domain}/privkey.pem > /app/ssl/${domain}.pem`
|
|
||||||
);
|
|
||||||
if (stderr) throw new Error(stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const { fqdn } = await db.listSettings();
|
|
||||||
if (fqdn) {
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
if (isHttps) {
|
|
||||||
if (dev) {
|
|
||||||
console.log('DEV MODE: SSL is enabled');
|
|
||||||
} else {
|
|
||||||
await asyncExecShell(
|
|
||||||
`docker run --rm --name certbot-${randomCuid} -p 9080:${publicPort} -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs certonly --standalone --preferred-challenges http --http-01-address 0.0.0.0 --http-01-port ${publicPort} -d ${domain} --agree-tos --non-interactive --register-unsafely-without-email`
|
|
||||||
);
|
|
||||||
|
|
||||||
const { stderr } = await asyncExecShell(
|
|
||||||
`docker run --rm -v "coolify-letsencrypt:/etc/letsencrypt" -v "coolify-ssl-certs:/app/ssl" alpine:latest cat /etc/letsencrypt/live/${domain}/fullchain.pem /etc/letsencrypt/live/${domain}/privkey.pem > /app/ssl/${domain}.pem`
|
|
||||||
);
|
|
||||||
if (stderr) throw new Error(stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
<script>
|
<script>
|
||||||
export let teams;
|
export let teams;
|
||||||
export let selectedTeamId;
|
export let selectedTeamId;
|
||||||
import { fade } from 'svelte/transition';
|
|
||||||
|
|
||||||
import '../tailwind.css';
|
import '../tailwind.css';
|
||||||
import { SvelteToast, toast } from '@zerodevx/svelte-toast';
|
import { SvelteToast, toast } from '@zerodevx/svelte-toast';
|
||||||
@@ -39,12 +38,13 @@
|
|||||||
import { errorNotification } from '$lib/form';
|
import { errorNotification } from '$lib/form';
|
||||||
import { asyncSleep } from '$lib/components/common';
|
import { asyncSleep } from '$lib/components/common';
|
||||||
import { del, get, post } from '$lib/api';
|
import { del, get, post } from '$lib/api';
|
||||||
import { browser } from '$app/env';
|
import { browser, dev } from '$app/env';
|
||||||
|
|
||||||
let isUpdateAvailable = false;
|
let isUpdateAvailable = false;
|
||||||
|
|
||||||
let updateStatus = {
|
let updateStatus = {
|
||||||
|
found: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
checking: false,
|
|
||||||
success: null
|
success: null
|
||||||
};
|
};
|
||||||
let latestVersion = 'latest';
|
let latestVersion = 'latest';
|
||||||
@@ -59,17 +59,20 @@
|
|||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
}
|
}
|
||||||
if ($session.teamId === '0') {
|
if ($session.teamId === '0') {
|
||||||
updateStatus.checking = true;
|
|
||||||
try {
|
try {
|
||||||
const data = await get(`/update.json`);
|
const data = await get(`/update.json`);
|
||||||
if (overrideVersion || data?.isUpdateAvailable) {
|
if (overrideVersion || data?.isUpdateAvailable) {
|
||||||
latestVersion = overrideVersion || data.latestVersion;
|
latestVersion = overrideVersion || data.latestVersion;
|
||||||
isUpdateAvailable = overrideVersion ? true : data?.isUpdateAvailable;
|
console.log('checking update');
|
||||||
await post(`/update.json`, { type: 'pull', latestVersion });
|
const { exists } = await post(`/update.json`, {
|
||||||
|
type: 'check',
|
||||||
|
latestVersion,
|
||||||
|
overrideVersion
|
||||||
|
});
|
||||||
|
isUpdateAvailable = exists;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
} finally {
|
} finally {
|
||||||
updateStatus.checking = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,26 +100,32 @@
|
|||||||
async function update() {
|
async function update() {
|
||||||
updateStatus.loading = true;
|
updateStatus.loading = true;
|
||||||
try {
|
try {
|
||||||
await post(`/update.json`, { type: 'update', latestVersion });
|
if (dev) {
|
||||||
toast.push('Update completed.<br><br>Waiting for the new version to start...');
|
console.log(`updating to ${latestVersion}`);
|
||||||
let reachable = false;
|
|
||||||
let tries = 0;
|
|
||||||
do {
|
|
||||||
await asyncSleep(4000);
|
await asyncSleep(4000);
|
||||||
try {
|
return window.location.reload();
|
||||||
await get(`/undead.json`);
|
} else {
|
||||||
reachable = true;
|
await post(`/update.json`, { type: 'update', latestVersion });
|
||||||
} catch (error) {
|
toast.push('Update completed.<br><br>Waiting for the new version to start...');
|
||||||
reachable = false;
|
let reachable = false;
|
||||||
}
|
let tries = 0;
|
||||||
if (reachable) break;
|
do {
|
||||||
tries++;
|
await asyncSleep(4000);
|
||||||
} while (!reachable || tries < 120);
|
try {
|
||||||
toast.push('New version reachable. Reloading...');
|
await get(`/undead.json`);
|
||||||
updateStatus.loading = false;
|
reachable = true;
|
||||||
updateStatus.success = true;
|
} catch (error) {
|
||||||
await asyncSleep(3000);
|
reachable = false;
|
||||||
return window.location.reload();
|
}
|
||||||
|
if (reachable) break;
|
||||||
|
tries++;
|
||||||
|
} while (!reachable || tries < 120);
|
||||||
|
toast.push('New version reachable. Reloading...');
|
||||||
|
updateStatus.loading = false;
|
||||||
|
updateStatus.success = true;
|
||||||
|
await asyncSleep(3000);
|
||||||
|
return window.location.reload();
|
||||||
|
}
|
||||||
} catch ({ error }) {
|
} catch ({ error }) {
|
||||||
updateStatus.success = false;
|
updateStatus.success = false;
|
||||||
updateStatus.loading = false;
|
updateStatus.loading = false;
|
||||||
@@ -311,42 +320,17 @@
|
|||||||
|
|
||||||
<div class="flex flex-col space-y-4 py-2">
|
<div class="flex flex-col space-y-4 py-2">
|
||||||
{#if $session.teamId === '0'}
|
{#if $session.teamId === '0'}
|
||||||
{#if updateStatus.checking}
|
{#if isUpdateAvailable}
|
||||||
<button
|
|
||||||
disabled
|
|
||||||
in:fade={{ duration: 150 }}
|
|
||||||
class="icons tooltip-right bg-gradient-to-r from-purple-500 via-pink-500 to-red-500 text-white duration-75 hover:scale-105"
|
|
||||||
data-tooltip="Checking for updates..."
|
|
||||||
><svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-9 w-8 animate-spin"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
fill="none"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
||||||
<path d="M9 4.55a8 8 0 0 1 6 14.9m0 -4.45v5h5" />
|
|
||||||
<line x1="5.63" y1="7.16" x2="5.63" y2="7.17" />
|
|
||||||
<line x1="4.06" y1="11" x2="4.06" y2="11.01" />
|
|
||||||
<line x1="4.63" y1="15.1" x2="4.63" y2="15.11" />
|
|
||||||
<line x1="7.16" y1="18.37" x2="7.16" y2="18.38" />
|
|
||||||
<line x1="11" y1="19.94" x2="11" y2="19.95" />
|
|
||||||
</svg></button
|
|
||||||
>
|
|
||||||
{:else if isUpdateAvailable}
|
|
||||||
<button
|
<button
|
||||||
disabled={updateStatus.success === false}
|
disabled={updateStatus.success === false}
|
||||||
data-tooltip="Update available"
|
title="Update available"
|
||||||
on:click={update}
|
on:click={update}
|
||||||
class="icons tooltip-right bg-gradient-to-r from-purple-500 via-pink-500 to-red-500 text-white duration-75 hover:scale-105"
|
class="icons tooltip-right bg-gradient-to-r from-purple-500 via-pink-500 to-red-500 text-white duration-75 hover:scale-105"
|
||||||
>
|
>
|
||||||
{#if updateStatus.loading}
|
{#if updateStatus.loading}
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="w-8 h-9 lds-heart"
|
class="lds-heart h-9 w-8"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
stroke-width="1.5"
|
stroke-width="1.5"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
async function handleDeploySubmit() {
|
async function handleDeploySubmit() {
|
||||||
try {
|
try {
|
||||||
const { buildId } = await post(`/applications/${id}/deploy.json`, { ...application });
|
const { buildId } = await post(`/applications/${id}/deploy.json`, { ...application });
|
||||||
return await goto(`/applications/${id}/logs/build?buildId=${buildId}`);
|
return window.location.assign(`/applications/${id}/logs/build?buildId=${buildId}`);
|
||||||
} catch ({ error }) {
|
} catch ({ error }) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
title="Stop application"
|
title="Stop application"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!$session.isAdmin}
|
disabled={!$session.isAdmin}
|
||||||
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:bg-green-600 hover:text-white"
|
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-red-500"
|
||||||
data-tooltip={$session.isAdmin
|
data-tooltip={$session.isAdmin
|
||||||
? 'Stop application'
|
? 'Stop application'
|
||||||
: 'You do not have permission to stop the application.'}
|
: 'You do not have permission to stop the application.'}
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
title="Rebuild application"
|
title="Rebuild application"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!$session.isAdmin}
|
disabled={!$session.isAdmin}
|
||||||
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:bg-green-600 hover:text-white"
|
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:text-green-500"
|
||||||
data-tooltip={$session.isAdmin
|
data-tooltip={$session.isAdmin
|
||||||
? 'Rebuild application'
|
? 'Rebuild application'
|
||||||
: 'You do not have permission to rebuild application.'}
|
: 'You do not have permission to rebuild application.'}
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
title="Build and start application"
|
title="Build and start application"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!$session.isAdmin}
|
disabled={!$session.isAdmin}
|
||||||
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:bg-green-600 hover:text-white"
|
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-green-500"
|
||||||
data-tooltip={$session.isAdmin
|
data-tooltip={$session.isAdmin
|
||||||
? 'Build and start application'
|
? 'Build and start application'
|
||||||
: 'You do not have permission to Build and start application.'}
|
: 'You do not have permission to Build and start application.'}
|
||||||
|
|||||||
@@ -105,6 +105,8 @@
|
|||||||
foundConfig = findBuildPack('static', packageManager);
|
foundConfig = findBuildPack('static', packageManager);
|
||||||
} else if (indexPHP) {
|
} else if (indexPHP) {
|
||||||
foundConfig = findBuildPack('php');
|
foundConfig = findBuildPack('php');
|
||||||
|
} else {
|
||||||
|
foundConfig = findBuildPack('node', packageManager);
|
||||||
}
|
}
|
||||||
} else if (type === 'github') {
|
} else if (type === 'github') {
|
||||||
const files = await get(`${apiUrl}/repos/${repository}/contents?ref=${branch}`, {
|
const files = await get(`${apiUrl}/repos/${repository}/contents?ref=${branch}`, {
|
||||||
@@ -146,6 +148,8 @@
|
|||||||
foundConfig = findBuildPack('static', packageManager);
|
foundConfig = findBuildPack('static', packageManager);
|
||||||
} else if (indexPHP) {
|
} else if (indexPHP) {
|
||||||
foundConfig = findBuildPack('php');
|
foundConfig = findBuildPack('php');
|
||||||
|
} else {
|
||||||
|
foundConfig = findBuildPack('node', packageManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -183,9 +187,10 @@
|
|||||||
browser && window.location.reload();
|
browser && window.location.reload();
|
||||||
}
|
}
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
|
} finally {
|
||||||
|
if (!foundConfig) foundConfig = findBuildPack('node', packageManager);
|
||||||
|
scanning = false;
|
||||||
}
|
}
|
||||||
if (!foundConfig) foundConfig = findBuildPack('node', packageManager);
|
|
||||||
scanning = false;
|
|
||||||
}
|
}
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await scanRepository();
|
await scanRepository();
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
.digest('hex');
|
.digest('hex');
|
||||||
await db.prisma.application.update({ where: { id }, data: { configHash } });
|
await db.prisma.application.update({ where: { id }, data: { configHash } });
|
||||||
}
|
}
|
||||||
|
await db.prisma.application.update({ where: { id }, data: { updatedAt: new Date() } });
|
||||||
await buildQueue.add(buildId, { build_id: buildId, type: 'manual', ...applicationFound });
|
await buildQueue.add(buildId, { build_id: buildId, type: 'manual', ...applicationFound });
|
||||||
return {
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
build.took = data.builds[0].took;
|
build.took = data.builds[0].took;
|
||||||
build.since = data.builds[0].since;
|
build.since = data.builds[0].since;
|
||||||
}
|
}
|
||||||
window.location.reload();
|
|
||||||
return build;
|
return build;
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -43,53 +43,41 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mx-auto max-w-6xl rounded-xl px-6 pt-4">
|
{#if applicationSecrets.length !== 0}
|
||||||
<table class="mx-auto">
|
<div class="mx-auto max-w-6xl rounded-xl px-6 pt-4">
|
||||||
<thead class=" rounded-xl border-b border-coolgray-500">
|
<table class="mx-auto border-separate text-left">
|
||||||
<tr>
|
<thead>
|
||||||
<th
|
<tr class="h-12">
|
||||||
scope="col"
|
<th scope="col">Name</th>
|
||||||
class="px-6 py-3 text-left text-xs font-bold uppercase tracking-wider text-white">Name</th
|
<th scope="col">Value</th>
|
||||||
>
|
<th scope="col" class="w-64 text-center">Need during buildtime?</th>
|
||||||
<th
|
<th scope="col" class="w-96 text-center">Action</th>
|
||||||
scope="col"
|
</tr>
|
||||||
class="px-6 py-3 text-left text-xs font-bold uppercase tracking-wider text-white"
|
</thead>
|
||||||
>Value</th
|
<tbody>
|
||||||
>
|
{#each applicationSecrets as secret}
|
||||||
<th
|
{#key secret.id}
|
||||||
scope="col"
|
<tr>
|
||||||
class="px-6 py-3 text-left text-xs font-bold uppercase tracking-wider text-white"
|
<Secret
|
||||||
>Need during buildtime?</th
|
PRMRSecret={PRMRSecrets.find((s) => s.name === secret.name)}
|
||||||
>
|
isPRMRSecret
|
||||||
<th
|
name={secret.name}
|
||||||
scope="col"
|
value={secret.value}
|
||||||
class="px-6 py-3 text-left text-xs font-bold uppercase tracking-wider text-white"
|
isBuildSecret={secret.isBuildSecret}
|
||||||
/>
|
on:refresh={refreshSecrets}
|
||||||
</tr>
|
/>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody class="">
|
{/key}
|
||||||
{#each applicationSecrets as secret}
|
{/each}
|
||||||
{#key secret.id}
|
</tbody>
|
||||||
<tr class="h-20 transition duration-100 hover:bg-coolgray-400">
|
</table>
|
||||||
<Secret
|
</div>
|
||||||
PRMRSecret={PRMRSecrets.find((s) => s.name === secret.name)}
|
{/if}
|
||||||
isPRMRSecret
|
|
||||||
name={secret.name}
|
|
||||||
value={secret.value}
|
|
||||||
isBuildSecret={secret.isBuildSecret}
|
|
||||||
on:refresh={refreshSecrets}
|
|
||||||
/>
|
|
||||||
</tr>
|
|
||||||
{/key}
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-center py-4 text-center">
|
<div class="flex justify-center py-4 text-center">
|
||||||
<Explainer
|
<Explainer
|
||||||
customClass="w-full"
|
customClass="w-full"
|
||||||
text={applicationSecrets.length === 0
|
text={applicationSecrets.length === 0
|
||||||
? "<span class='font-bold text-white text-xl'>Please add secrets to the application first.</span> <br><br>These values overwrite application secrets in PR/MR deployments. Useful for creating <span class='text-green-500 font-bold'>staging</span> environments."
|
? "You can add secrets to PR/MR deployments. Please add secrets to the application first. <br>Useful for creating <span class='text-green-500 font-bold'>staging</span> environments."
|
||||||
: "These values overwrite application secrets in PR/MR deployments. Useful for creating <span class='text-green-500 font-bold'>staging</span> environments."}
|
: "These values overwrite application secrets in PR/MR deployments. Useful for creating <span class='text-green-500 font-bold'>staging</span> environments."}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { getDomain, getUserDetails } from '$lib/common';
|
import { asyncExecShell, getEngine, getUserDetails, removeDestinationDocker } from '$lib/common';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import { removeProxyConfiguration } from '$lib/haproxy';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
@@ -17,10 +16,12 @@ export const post: RequestHandler = async (event) => {
|
|||||||
teamId
|
teamId
|
||||||
});
|
});
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const docker = dockerInstance({ destinationDocker });
|
const { engine } = destinationDocker;
|
||||||
await docker.engine.getContainer(id).stop();
|
const found = await checkContainer(engine, id);
|
||||||
|
if (found) {
|
||||||
|
await removeDestinationDocker({ id, engine });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await removeProxyConfiguration(fqdn);
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
import Nextjs from '$lib/components/svg/applications/Nextjs.svelte';
|
import Nextjs from '$lib/components/svg/applications/Nextjs.svelte';
|
||||||
import Gatsby from '$lib/components/svg/applications/Gatsby.svelte';
|
import Gatsby from '$lib/components/svg/applications/Gatsby.svelte';
|
||||||
import Docker from '$lib/components/svg/applications/Docker.svelte';
|
import Docker from '$lib/components/svg/applications/Docker.svelte';
|
||||||
|
import Astro from '$lib/components/svg/applications/Astro.svelte';
|
||||||
|
import Eleventy from '$lib/components/svg/applications/Eleventy.svelte';
|
||||||
|
|
||||||
const buildPack = application?.buildPack?.toLowerCase();
|
const buildPack = application?.buildPack?.toLowerCase();
|
||||||
</script>
|
</script>
|
||||||
@@ -45,6 +47,10 @@
|
|||||||
<Gatsby />
|
<Gatsby />
|
||||||
{:else if buildPack === 'docker'}
|
{:else if buildPack === 'docker'}
|
||||||
<Docker />
|
<Docker />
|
||||||
|
{:else if buildPack === 'astro'}
|
||||||
|
<Astro />
|
||||||
|
{:else if buildPack === 'eleventy'}
|
||||||
|
<Eleventy />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="truncate text-center text-xl font-bold">{application.name}</div>
|
<div class="truncate text-center text-xl font-bold">{application.name}</div>
|
||||||
|
|||||||
@@ -120,7 +120,7 @@
|
|||||||
title="Stop database"
|
title="Stop database"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!$session.isAdmin}
|
disabled={!$session.isAdmin}
|
||||||
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:bg-purple-600 hover:text-white"
|
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-red-500"
|
||||||
data-tooltip={$session.isAdmin
|
data-tooltip={$session.isAdmin
|
||||||
? 'Stop database'
|
? 'Stop database'
|
||||||
: 'You do not have permission to stop the database.'}
|
: 'You do not have permission to stop the database.'}
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
title="Start database"
|
title="Start database"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!$session.isAdmin}
|
disabled={!$session.isAdmin}
|
||||||
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:bg-purple-600 hover:text-white"
|
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-green-500"
|
||||||
data-tooltip={$session.isAdmin
|
data-tooltip={$session.isAdmin
|
||||||
? 'Start database'
|
? 'Start database'
|
||||||
: 'You do not have permission to start the database.'}
|
: 'You do not have permission to start the database.'}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
export let state;
|
export let state;
|
||||||
|
|
||||||
import { toast } from '@zerodevx/svelte-toast';
|
import { toast } from '@zerodevx/svelte-toast';
|
||||||
import { page } from '$app/stores';
|
import { page, session } from '$app/stores';
|
||||||
import Setting from '$lib/components/Setting.svelte';
|
import Setting from '$lib/components/Setting.svelte';
|
||||||
import { errorNotification } from '$lib/form';
|
import { errorNotification } from '$lib/form';
|
||||||
import { post } from '$lib/api';
|
import { post } from '$lib/api';
|
||||||
@@ -117,6 +117,8 @@
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
} finally {
|
||||||
|
restarting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,27 +127,35 @@
|
|||||||
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
||||||
<div class="flex space-x-1 pb-5">
|
<div class="flex space-x-1 pb-5">
|
||||||
<div class="title font-bold">Configuration</div>
|
<div class="title font-bold">Configuration</div>
|
||||||
<button
|
{#if $session.isAdmin}
|
||||||
type="submit"
|
<button
|
||||||
class="bg-sky-600 hover:bg-sky-500"
|
type="submit"
|
||||||
class:bg-sky-600={!loading}
|
class="bg-sky-600 hover:bg-sky-500"
|
||||||
class:hover:bg-sky-500={!loading}
|
class:bg-sky-600={!loading}
|
||||||
disabled={loading}
|
class:hover:bg-sky-500={!loading}
|
||||||
>{loading ? 'Saving...' : 'Save'}
|
disabled={loading}
|
||||||
</button>
|
>{loading ? 'Saving...' : 'Save'}
|
||||||
<button
|
</button>
|
||||||
class={restarting ? '' : 'bg-red-600 hover:bg-red-500'}
|
<button
|
||||||
disabled={restarting}
|
class={restarting ? '' : 'bg-red-600 hover:bg-red-500'}
|
||||||
on:click|preventDefault={forceRestartProxy}
|
disabled={restarting}
|
||||||
>{restarting ? 'Restarting... please wait...' : 'Force restart proxy'}</button
|
on:click|preventDefault={forceRestartProxy}
|
||||||
>
|
>{restarting ? 'Restarting... please wait...' : 'Force restart proxy'}</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
<!-- <button type="button" class="bg-coollabs hover:bg-coollabs-100" on:click={scanApps}
|
<!-- <button type="button" class="bg-coollabs hover:bg-coollabs-100" on:click={scanApps}
|
||||||
>Scan for applications</button
|
>Scan for applications</button
|
||||||
> -->
|
> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 items-center px-10 ">
|
<div class="grid grid-cols-2 items-center px-10 ">
|
||||||
<label for="name" class="text-base font-bold text-stone-100">Name</label>
|
<label for="name" class="text-base font-bold text-stone-100">Name</label>
|
||||||
<input name="name" placeholder="name" bind:value={destination.name} />
|
<input
|
||||||
|
name="name"
|
||||||
|
placeholder="name"
|
||||||
|
disabled={!$session.isAdmin}
|
||||||
|
readonly={!$session.isAdmin}
|
||||||
|
bind:value={destination.name}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 items-center px-10">
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
|
|||||||
225
src/routes/destinations/[id]/_RemoteDocker.svelte
Normal file
225
src/routes/destinations/[id]/_RemoteDocker.svelte
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let destination;
|
||||||
|
export let settings;
|
||||||
|
export let state;
|
||||||
|
|
||||||
|
import { toast } from '@zerodevx/svelte-toast';
|
||||||
|
import { page, session } from '$app/stores';
|
||||||
|
import Setting from '$lib/components/Setting.svelte';
|
||||||
|
import { errorNotification } from '$lib/form';
|
||||||
|
import { post } from '$lib/api';
|
||||||
|
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { generateRemoteEngine } from '$lib/components/common';
|
||||||
|
const { id } = $page.params;
|
||||||
|
let cannotDisable = settings.fqdn && destination.engine === '/var/run/docker.sock';
|
||||||
|
// let scannedApps = [];
|
||||||
|
let loading = false;
|
||||||
|
let restarting = false;
|
||||||
|
async function handleSubmit() {
|
||||||
|
loading = true;
|
||||||
|
try {
|
||||||
|
return await post(`/destinations/${id}.json`, { ...destination });
|
||||||
|
} catch ({ error }) {
|
||||||
|
return errorNotification(error);
|
||||||
|
} finally {
|
||||||
|
loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// async function scanApps() {
|
||||||
|
// scannedApps = [];
|
||||||
|
// const data = await fetch(`/destinations/${id}/scan.json`);
|
||||||
|
// const { containers } = await data.json();
|
||||||
|
// scannedApps = containers;
|
||||||
|
// }
|
||||||
|
onMount(async () => {
|
||||||
|
if (state === false && destination.isCoolifyProxyUsed === true) {
|
||||||
|
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
|
||||||
|
try {
|
||||||
|
await post(`/destinations/${id}/settings.json`, {
|
||||||
|
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
|
||||||
|
engine: destination.engine
|
||||||
|
});
|
||||||
|
await stopProxy();
|
||||||
|
} catch ({ error }) {
|
||||||
|
return errorNotification(error);
|
||||||
|
}
|
||||||
|
} else if (state === true && destination.isCoolifyProxyUsed === false) {
|
||||||
|
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
|
||||||
|
try {
|
||||||
|
await post(`/destinations/${id}/settings.json`, {
|
||||||
|
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
|
||||||
|
engine: destination.engine
|
||||||
|
});
|
||||||
|
await startProxy();
|
||||||
|
} catch ({ error }) {
|
||||||
|
return errorNotification(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
async function changeProxySetting() {
|
||||||
|
if (!cannotDisable) {
|
||||||
|
const isProxyActivated = destination.isCoolifyProxyUsed;
|
||||||
|
if (isProxyActivated) {
|
||||||
|
const sure = confirm(
|
||||||
|
`Are you sure you want to ${
|
||||||
|
destination.isCoolifyProxyUsed ? 'disable' : 'enable'
|
||||||
|
} Coolify proxy? It will remove the proxy for all configured networks and all deployments on '${
|
||||||
|
destination.engine
|
||||||
|
}'! Nothing will be reachable if you do it!`
|
||||||
|
);
|
||||||
|
if (!sure) return;
|
||||||
|
}
|
||||||
|
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
|
||||||
|
try {
|
||||||
|
await post(`/destinations/${id}/settings.json`, {
|
||||||
|
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
|
||||||
|
engine: destination.engine
|
||||||
|
});
|
||||||
|
if (isProxyActivated) {
|
||||||
|
await stopProxy();
|
||||||
|
} else {
|
||||||
|
await startProxy();
|
||||||
|
}
|
||||||
|
} catch ({ error }) {
|
||||||
|
return errorNotification(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function stopProxy() {
|
||||||
|
try {
|
||||||
|
const engine = generateRemoteEngine(destination);
|
||||||
|
await post(`/destinations/${id}/stop.json`, { engine });
|
||||||
|
return toast.push('Coolify Proxy stopped!');
|
||||||
|
} catch ({ error }) {
|
||||||
|
return errorNotification(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function startProxy() {
|
||||||
|
try {
|
||||||
|
const engine = generateRemoteEngine(destination);
|
||||||
|
await post(`/destinations/${id}/start.json`, { engine });
|
||||||
|
return toast.push('Coolify Proxy started!');
|
||||||
|
} catch ({ error }) {
|
||||||
|
return errorNotification(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function forceRestartProxy() {
|
||||||
|
const sure = confirm(
|
||||||
|
'Are you sure you want to restart the proxy? Everyting will be reconfigured in ~10 sec.'
|
||||||
|
);
|
||||||
|
if (sure) {
|
||||||
|
try {
|
||||||
|
restarting = true;
|
||||||
|
toast.push('Coolify Proxy restarting...');
|
||||||
|
await post(`/destinations/${id}/restart.json`, {
|
||||||
|
engine: destination.engine,
|
||||||
|
fqdn: settings.fqdn
|
||||||
|
});
|
||||||
|
} catch ({ error }) {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
||||||
|
<div class="flex space-x-1 pb-5">
|
||||||
|
<div class="title font-bold">Configuration</div>
|
||||||
|
{#if $session.isAdmin}
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="bg-sky-600 hover:bg-sky-500"
|
||||||
|
class:bg-sky-600={!loading}
|
||||||
|
class:hover:bg-sky-500={!loading}
|
||||||
|
disabled={loading}
|
||||||
|
>{loading ? 'Saving...' : 'Save'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={restarting ? '' : 'bg-red-600 hover:bg-red-500'}
|
||||||
|
disabled={restarting}
|
||||||
|
on:click|preventDefault={forceRestartProxy}
|
||||||
|
>{restarting ? 'Restarting... please wait...' : 'Force restart proxy'}</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
<!-- <button type="button" class="bg-coollabs hover:bg-coollabs-100" on:click={scanApps}
|
||||||
|
>Scan for applications</button
|
||||||
|
> -->
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 items-center px-10 ">
|
||||||
|
<label for="name" class="text-base font-bold text-stone-100">Name</label>
|
||||||
|
<input
|
||||||
|
name="name"
|
||||||
|
placeholder="name"
|
||||||
|
disabled={!$session.isAdmin}
|
||||||
|
readonly={!$session.isAdmin}
|
||||||
|
bind:value={destination.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
|
<label for="engine" class="text-base font-bold text-stone-100">Engine</label>
|
||||||
|
<CopyPasswordField
|
||||||
|
id="engine"
|
||||||
|
readonly
|
||||||
|
disabled
|
||||||
|
name="engine"
|
||||||
|
placeholder="eg: /var/run/docker.sock"
|
||||||
|
value={destination.engine}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="flex items-center">
|
||||||
|
<label for="remoteEngine">Remote Engine?</label>
|
||||||
|
<input name="remoteEngine" type="checkbox" bind:checked={payload.remoteEngine} />
|
||||||
|
</div> -->
|
||||||
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
|
<label for="network" class="text-base font-bold text-stone-100">Network</label>
|
||||||
|
<CopyPasswordField
|
||||||
|
id="network"
|
||||||
|
readonly
|
||||||
|
disabled
|
||||||
|
name="network"
|
||||||
|
placeholder="default: coolify"
|
||||||
|
value={destination.network}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 items-center">
|
||||||
|
<Setting
|
||||||
|
disabled={cannotDisable}
|
||||||
|
bind:setting={destination.isCoolifyProxyUsed}
|
||||||
|
on:click={changeProxySetting}
|
||||||
|
title="Use Coolify Proxy?"
|
||||||
|
description={`This will install a proxy on the destination to allow you to access your applications and services without any manual configuration. Databases will have their own proxy. <br><br>${
|
||||||
|
cannotDisable
|
||||||
|
? '<span class="font-bold text-white">You cannot disable this proxy as FQDN is configured for Coolify.</span>'
|
||||||
|
: ''
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<!-- <div class="flex justify-center">
|
||||||
|
{#if payload.isCoolifyProxyUsed}
|
||||||
|
{#if state}
|
||||||
|
<button on:click={stopProxy}>Stop proxy</button>
|
||||||
|
{:else}
|
||||||
|
<button on:click={startProxy}>Start proxy</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- {#if scannedApps.length > 0}
|
||||||
|
<div class="flex justify-center px-6 pb-10">
|
||||||
|
<div class="flex space-x-2 h-8 items-center">
|
||||||
|
<div class="font-bold text-xl text-white">Found applications</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="max-w-4xl mx-auto px-6">
|
||||||
|
<div class="flex space-x-2 justify-center">
|
||||||
|
{#each scannedApps as app}
|
||||||
|
<FoundApp {app} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if} -->
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { asyncExecShell, getEngine, getTeam, getUserDetails } from '$lib/common';
|
import { asyncExecShell, getUserDetails } from '$lib/common';
|
||||||
|
import { generateRemoteEngine } from '$lib/components/common';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { checkContainer } from '$lib/haproxy';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
@@ -12,15 +13,26 @@ export const get: RequestHandler = async (event) => {
|
|||||||
try {
|
try {
|
||||||
const destination = await db.getDestination({ id, teamId });
|
const destination = await db.getDestination({ id, teamId });
|
||||||
const settings = await db.listSettings();
|
const settings = await db.listSettings();
|
||||||
const state =
|
let payload = {
|
||||||
destination?.engine && (await checkContainer(destination.engine, 'coolify-haproxy'));
|
destination,
|
||||||
|
settings,
|
||||||
|
state: false
|
||||||
|
};
|
||||||
|
if (destination.remoteEngine) {
|
||||||
|
// const { stdout } = await asyncExecShell(
|
||||||
|
// `ssh -p ${destination.port} ${destination.user}@${destination.ipAddress} "docker ps -a"`
|
||||||
|
// );
|
||||||
|
// console.log(stdout)
|
||||||
|
// const engine = await generateRemoteEngine(destination);
|
||||||
|
// // await saveSshKey(destination);
|
||||||
|
// payload.state = await checkContainer(engine, 'coolify-haproxy');
|
||||||
|
} else {
|
||||||
|
payload.state =
|
||||||
|
destination?.engine && (await checkContainer(destination.engine, 'coolify-haproxy'));
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
body: {
|
body: { ...payload }
|
||||||
destination,
|
|
||||||
settings,
|
|
||||||
state
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorHandler(error);
|
return ErrorHandler(error);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
import type Prisma from '@prisma/client';
|
import type Prisma from '@prisma/client';
|
||||||
import LocalDocker from './_LocalDocker.svelte';
|
import LocalDocker from './_LocalDocker.svelte';
|
||||||
|
import RemoteDocker from './_RemoteDocker.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex space-x-1 p-6 text-2xl font-bold">
|
<div class="flex space-x-1 p-6 text-2xl font-bold">
|
||||||
@@ -42,6 +43,11 @@
|
|||||||
<span class="arrow-right-applications px-1">></span>
|
<span class="arrow-right-applications px-1">></span>
|
||||||
<span class="pr-2">{destination.name}</span>
|
<span class="pr-2">{destination.name}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mx-auto max-w-4xl px-6">
|
<div class="mx-auto max-w-4xl px-6">
|
||||||
<LocalDocker bind:destination {settings} {state} />
|
{#if destination.remoteEngine}
|
||||||
|
<RemoteDocker bind:destination {settings} {state} />
|
||||||
|
{:else}
|
||||||
|
<LocalDocker bind:destination {settings} {state} />
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,30 +1,19 @@
|
|||||||
import { getDomain, getUserDetails } from '$lib/common';
|
import { getUserDetails } from '$lib/common';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import {
|
import { startCoolifyProxy, stopCoolifyProxy } from '$lib/haproxy';
|
||||||
configureCoolifyProxyOn,
|
|
||||||
forceSSLOnApplication,
|
|
||||||
setWwwRedirection,
|
|
||||||
startCoolifyProxy,
|
|
||||||
stopCoolifyProxy
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
const { teamId, status, body } = await getUserDetails(event);
|
const { teamId, status, body } = await getUserDetails(event);
|
||||||
if (status === 401) return { status, body };
|
if (status === 401) return { status, body };
|
||||||
|
|
||||||
const { engine, fqdn } = await event.request.json();
|
const { engine } = await event.request.json();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
await stopCoolifyProxy(engine);
|
await stopCoolifyProxy(engine);
|
||||||
await startCoolifyProxy(engine);
|
await startCoolifyProxy(engine);
|
||||||
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: true });
|
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: true });
|
||||||
await configureCoolifyProxyOn(fqdn);
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
if (isHttps) await forceSSLOnApplication(domain);
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -71,12 +71,14 @@
|
|||||||
class:text-stone-600={loading}
|
class:text-stone-600={loading}
|
||||||
class:bg-coollabs={!loading}>{loading ? 'Authenticating...' : 'Login'}</button
|
class:bg-coollabs={!loading}>{loading ? 'Authenticating...' : 'Login'}</button
|
||||||
>
|
>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
on:click|preventDefault={() => goto('/register')}
|
on:click|preventDefault={() => goto('/register')}
|
||||||
class="hover:opacity-90 text-white">Register</button
|
class="bg-transparent hover:bg-coolgray-300 text-white ">Register</button
|
||||||
>
|
>
|
||||||
<button class="bg-transparent" on:click|preventDefault={() => goto('/reset')}
|
<button
|
||||||
>Reset password</button
|
class="bg-transparent hover:bg-coolgray-300"
|
||||||
|
on:click|preventDefault={() => goto('/reset')}>Reset password</button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -51,26 +51,7 @@
|
|||||||
placeholder="eg: /var/run/docker.sock"
|
placeholder="eg: /var/run/docker.sock"
|
||||||
bind:value={payload.engine}
|
bind:value={payload.engine}
|
||||||
/>
|
/>
|
||||||
<!-- <Explainer text="You can use remote Docker Engine with over SSH." /> -->
|
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="flex items-center">
|
|
||||||
<label for="remoteEngine">Remote Docker Engine?</label>
|
|
||||||
<input name="remoteEngine" type="checkbox" bind:checked={payload.remoteEngine} />
|
|
||||||
</div>
|
|
||||||
{#if payload.remoteEngine}
|
|
||||||
<div class="grid grid-cols-3 items-center">
|
|
||||||
<label for="user">User</label>
|
|
||||||
<div class="col-span-2">
|
|
||||||
<input required name="user" placeholder="eg: root" bind:value={payload.user} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-3 items-center">
|
|
||||||
<label for="port">Port</label>
|
|
||||||
<div class="col-span-2">
|
|
||||||
<input required name="port" placeholder="eg: 22" bind:value={payload.port} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if} -->
|
|
||||||
<div class="grid grid-cols-2 items-center px-10">
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
<label for="network" class="text-base font-bold text-stone-100">Network</label>
|
<label for="network" class="text-base font-bold text-stone-100">Network</label>
|
||||||
<input required name="network" placeholder="default: coolify" bind:value={payload.network} />
|
<input required name="network" placeholder="default: coolify" bind:value={payload.network} />
|
||||||
90
src/routes/new/destination/_RemoteDocker.svelte
Normal file
90
src/routes/new/destination/_RemoteDocker.svelte
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
|
export let payload;
|
||||||
|
|
||||||
|
import { post } from '$lib/api';
|
||||||
|
import Explainer from '$lib/components/Explainer.svelte';
|
||||||
|
import Setting from '$lib/components/Setting.svelte';
|
||||||
|
import { errorNotification } from '$lib/form';
|
||||||
|
|
||||||
|
let loading = false;
|
||||||
|
|
||||||
|
async function handleSubmit() {
|
||||||
|
try {
|
||||||
|
const { id } = await post('/new/destination/docker.json', {
|
||||||
|
...payload
|
||||||
|
});
|
||||||
|
return await goto(`/destinations/${id}`);
|
||||||
|
} catch ({ error }) {
|
||||||
|
return errorNotification(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex justify-center px-6 pb-8">
|
||||||
|
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
||||||
|
<div class="flex items-center space-x-2 pb-5">
|
||||||
|
<div class="title font-bold">Configuration</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class:bg-sky-600={!loading}
|
||||||
|
class:hover:bg-sky-500={!loading}
|
||||||
|
disabled={loading}
|
||||||
|
>{loading
|
||||||
|
? payload.isCoolifyProxyUsed
|
||||||
|
? 'Saving and configuring proxy...'
|
||||||
|
: 'Saving...'
|
||||||
|
: 'Save'}</button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 grid grid-cols-2 items-center px-10">
|
||||||
|
<label for="name" class="text-base font-bold text-stone-100">Name</label>
|
||||||
|
<input required name="name" placeholder="name" bind:value={payload.name} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
|
<label for="ipAddress" class="text-base font-bold text-stone-100">IP Address</label>
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
name="ipAddress"
|
||||||
|
placeholder="eg: 192.168..."
|
||||||
|
bind:value={payload.ipAddress}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
|
<label for="user" class="text-base font-bold text-stone-100">User</label>
|
||||||
|
<input required name="user" placeholder="eg: root" bind:value={payload.user} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
|
<label for="port" class="text-base font-bold text-stone-100">Port</label>
|
||||||
|
<input required name="port" placeholder="eg: 22" bind:value={payload.port} />
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
|
<label for="sshPrivateKey" class="text-base font-bold text-stone-100">SSH Private Key</label>
|
||||||
|
<textarea
|
||||||
|
rows="10"
|
||||||
|
class="resize-none"
|
||||||
|
required
|
||||||
|
name="sshPrivateKey"
|
||||||
|
placeholder="eg: -----BEGIN...."
|
||||||
|
bind:value={payload.sshPrivateKey}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 items-center px-10">
|
||||||
|
<label for="network" class="text-base font-bold text-stone-100">Network</label>
|
||||||
|
<input required name="network" placeholder="default: coolify" bind:value={payload.network} />
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 items-center">
|
||||||
|
<Setting
|
||||||
|
bind:setting={payload.isCoolifyProxyUsed}
|
||||||
|
on:click={() => (payload.isCoolifyProxyUsed = !payload.isCoolifyProxyUsed)}
|
||||||
|
title="Use Coolify Proxy?"
|
||||||
|
description="This will install a proxy on the destination to allow you to access your applications and services without any manual configuration (recommended for Docker).<br><br>Databases will have their own proxy."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -8,10 +8,36 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { teamId, status, body } = await getUserDetails(event);
|
const { teamId, status, body } = await getUserDetails(event);
|
||||||
if (status === 401) return { status, body };
|
if (status === 401) return { status, body };
|
||||||
|
|
||||||
const { name, engine, network, isCoolifyProxyUsed } = await event.request.json();
|
const {
|
||||||
|
name,
|
||||||
|
engine,
|
||||||
|
network,
|
||||||
|
isCoolifyProxyUsed,
|
||||||
|
remoteEngine,
|
||||||
|
ipAddress,
|
||||||
|
user,
|
||||||
|
port,
|
||||||
|
sshPrivateKey
|
||||||
|
} = await event.request.json();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const id = await db.newDestination({ name, teamId, engine, network, isCoolifyProxyUsed });
|
let id = null;
|
||||||
|
if (remoteEngine) {
|
||||||
|
id = await db.newRemoteDestination({
|
||||||
|
name,
|
||||||
|
teamId,
|
||||||
|
engine,
|
||||||
|
network,
|
||||||
|
isCoolifyProxyUsed,
|
||||||
|
remoteEngine,
|
||||||
|
ipAddress,
|
||||||
|
user,
|
||||||
|
port,
|
||||||
|
sshPrivateKey
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
id = await db.newLocalDestination({ name, teamId, engine, network, isCoolifyProxyUsed });
|
||||||
|
}
|
||||||
return { status: 200, body: { id } };
|
return { status: 200, body: { id } };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorHandler(error);
|
return ErrorHandler(error);
|
||||||
|
|||||||
@@ -1,25 +1,34 @@
|
|||||||
<script>
|
<script>
|
||||||
import Docker from './_Docker.svelte';
|
import LocalDocker from './_LocalDocker.svelte';
|
||||||
import cuid from 'cuid';
|
import cuid from 'cuid';
|
||||||
|
import RemoteDocker from './_RemoteDocker.svelte';
|
||||||
let payload = {};
|
let payload = {};
|
||||||
let selected = 'docker';
|
let selected = 'localDocker';
|
||||||
|
|
||||||
function setPredefined(type) {
|
function setPredefined(type) {
|
||||||
selected = type;
|
selected = type;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'docker':
|
case 'localDocker':
|
||||||
payload = {
|
payload = {
|
||||||
name: 'Local Docker',
|
name: 'Local Docker',
|
||||||
engine: '/var/run/docker.sock',
|
engine: '/var/run/docker.sock',
|
||||||
remoteEngine: false,
|
remoteEngine: false,
|
||||||
user: 'root',
|
|
||||||
port: 22,
|
|
||||||
privateKey: null,
|
|
||||||
network: cuid(),
|
network: cuid(),
|
||||||
isCoolifyProxyUsed: true
|
isCoolifyProxyUsed: true
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case 'remoteDocker':
|
||||||
|
payload = {
|
||||||
|
name: 'Remote Docker',
|
||||||
|
remoteEngine: true,
|
||||||
|
ipAddress: null,
|
||||||
|
user: 'root',
|
||||||
|
port: 22,
|
||||||
|
sshPrivateKey: null,
|
||||||
|
network: cuid(),
|
||||||
|
isCoolifyProxyUsed: true
|
||||||
|
};
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -32,12 +41,15 @@
|
|||||||
<div class="flex-col space-y-2 pb-10 text-center">
|
<div class="flex-col space-y-2 pb-10 text-center">
|
||||||
<div class="text-xl font-bold text-white">Predefined destinations</div>
|
<div class="text-xl font-bold text-white">Predefined destinations</div>
|
||||||
<div class="flex justify-center space-x-2">
|
<div class="flex justify-center space-x-2">
|
||||||
<button class="w-32" on:click={() => setPredefined('docker')}>Docker</button>
|
<button class="w-32" on:click={() => setPredefined('localDocker')}>Local Docker</button>
|
||||||
|
<!-- <button class="w-32" on:click={() => setPredefined('remoteDocker')}>Remote Docker</button> -->
|
||||||
<button class="w-32" on:click={() => setPredefined('kubernetes')}>Kubernetes</button>
|
<button class="w-32" on:click={() => setPredefined('kubernetes')}>Kubernetes</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if selected === 'docker'}
|
{#if selected === 'localDocker'}
|
||||||
<Docker {payload} />
|
<LocalDocker {payload} />
|
||||||
|
{:else if selected === 'remoteDocker'}
|
||||||
|
<RemoteDocker {payload} />
|
||||||
{:else}
|
{:else}
|
||||||
<div class="text-center font-bold text-4xl py-10">Not implemented yet</div>
|
<div class="text-center font-bold text-4xl py-10">Not implemented yet</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@
|
|||||||
title="Stop Service"
|
title="Stop Service"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!$session.isAdmin}
|
disabled={!$session.isAdmin}
|
||||||
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:bg-pink-600 hover:text-white"
|
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-red-500"
|
||||||
data-tooltip={$session.isAdmin
|
data-tooltip={$session.isAdmin
|
||||||
? 'Stop Service'
|
? 'Stop Service'
|
||||||
: 'You do not have permission to stop the service.'}
|
: 'You do not have permission to stop the service.'}
|
||||||
@@ -166,7 +166,7 @@
|
|||||||
title="Start Service"
|
title="Start Service"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!$session.isAdmin}
|
disabled={!$session.isAdmin}
|
||||||
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 hover:bg-pink-600 hover:text-white"
|
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-green-500"
|
||||||
data-tooltip={$session.isAdmin
|
data-tooltip={$session.isAdmin
|
||||||
? 'Start Service'
|
? 'Start Service'
|
||||||
: 'You do not have permission to start the service.'}
|
: 'You do not have permission to start the service.'}
|
||||||
|
|||||||
@@ -3,14 +3,7 @@ import * as db from '$lib/database';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
import { startHttpProxy } from '$lib/haproxy';
|
||||||
import {
|
|
||||||
checkHAProxy,
|
|
||||||
configureSimpleServiceProxyOn,
|
|
||||||
reloadHaproxy,
|
|
||||||
setWwwRedirection,
|
|
||||||
startHttpProxy
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import getPort, { portNumbers } from 'get-port';
|
import getPort, { portNumbers } from 'get-port';
|
||||||
import { getDomain } from '$lib/components/common';
|
import { getDomain } from '$lib/components/common';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
@@ -23,7 +16,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await checkHAProxy();
|
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
@@ -37,9 +29,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const data = await db.prisma.setting.findFirst();
|
const data = await db.prisma.setting.findFirst();
|
||||||
const { minPort, maxPort } = data;
|
const { minPort, maxPort } = data;
|
||||||
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
|
|
||||||
const network = destinationDockerId && destinationDocker.network;
|
const network = destinationDockerId && destinationDocker.network;
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
|
|
||||||
@@ -95,15 +84,8 @@ export const post: RequestHandler = async (event) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
||||||
await configureSimpleServiceProxyOn({ id, domain, port: consolePort });
|
|
||||||
await db.updateMinioService({ id, publicPort });
|
await db.updateMinioService({ id, publicPort });
|
||||||
await startHttpProxy(destinationDocker, id, publicPort, apiPort);
|
await startHttpProxy(destinationDocker, id, publicPort, apiPort);
|
||||||
|
|
||||||
if (isHttps) {
|
|
||||||
await letsEncrypt({ domain, id });
|
|
||||||
}
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
await reloadHaproxy(destinationDocker.engine);
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { getEngine, getUserDetails, removeDestinationDocker } from '$lib/common';
|
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { checkContainer, stopTcpHttpProxy } from '$lib/haproxy';
|
||||||
import { checkContainer, configureSimpleServiceProxyOff, stopTcpHttpProxy } from '$lib/haproxy';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
@@ -21,7 +19,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
minio: { publicPort }
|
minio: { publicPort }
|
||||||
} = service;
|
} = service;
|
||||||
await db.updateMinioService({ id, publicPort: null });
|
await db.updateMinioService({ id, publicPort: null });
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const engine = destinationDocker.engine;
|
const engine = destinationDocker.engine;
|
||||||
|
|
||||||
@@ -35,7 +32,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await stopTcpHttpProxy(destinationDocker, publicPort);
|
await stopTcpHttpProxy(destinationDocker, publicPort);
|
||||||
await configureSimpleServiceProxyOff(fqdn);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,6 @@ import * as db from '$lib/database';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
|
||||||
import {
|
|
||||||
checkHAProxy,
|
|
||||||
configureSimpleServiceProxyOn,
|
|
||||||
reloadHaproxy,
|
|
||||||
setWwwRedirection
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { makeLabelForServices } from '$lib/buildPacks/common';
|
import { makeLabelForServices } from '$lib/buildPacks/common';
|
||||||
|
|
||||||
@@ -21,13 +13,8 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await checkHAProxy();
|
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { type, version, fqdn, destinationDockerId, destinationDocker } = service;
|
const { type, version, destinationDockerId, destinationDocker } = service;
|
||||||
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
|
|
||||||
const network = destinationDockerId && destinationDocker.network;
|
const network = destinationDockerId && destinationDocker.network;
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
|
|
||||||
@@ -55,13 +42,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
||||||
await configureSimpleServiceProxyOn({ id, domain, port: 8080 });
|
|
||||||
|
|
||||||
if (isHttps) {
|
|
||||||
await letsEncrypt({ domain, id });
|
|
||||||
}
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
await reloadHaproxy(destinationDocker.engine);
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
@@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
try {
|
try {
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { destinationDockerId, destinationDocker, fqdn } = service;
|
const { destinationDockerId, destinationDocker, fqdn } = service;
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const engine = destinationDocker.engine;
|
const engine = destinationDocker.engine;
|
||||||
|
|
||||||
@@ -27,11 +24,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
await configureSimpleServiceProxyOff(fqdn);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -3,14 +3,6 @@ import * as db from '$lib/database';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
|
||||||
import {
|
|
||||||
checkHAProxy,
|
|
||||||
configureSimpleServiceProxyOn,
|
|
||||||
reloadHaproxy,
|
|
||||||
setWwwRedirection
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { makeLabelForServices } from '$lib/buildPacks/common';
|
import { makeLabelForServices } from '$lib/buildPacks/common';
|
||||||
|
|
||||||
@@ -21,7 +13,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await checkHAProxy();
|
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
@@ -41,9 +32,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
}
|
}
|
||||||
} = service;
|
} = service;
|
||||||
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
plausibleAnalytics: {
|
plausibleAnalytics: {
|
||||||
image: `plausible/analytics:${version}`,
|
image: `plausible/analytics:${version}`,
|
||||||
@@ -82,7 +70,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
};
|
};
|
||||||
const network = destinationDockerId && destinationDocker.network;
|
const network = destinationDockerId && destinationDocker.network;
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
const engine = destinationDocker.engine;
|
|
||||||
|
|
||||||
const { workdir } = await createDirectories({ repository: type, buildId: id });
|
const { workdir } = await createDirectories({ repository: type, buildId: id });
|
||||||
|
|
||||||
@@ -186,13 +173,7 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`;
|
|||||||
await asyncExecShell(
|
await asyncExecShell(
|
||||||
`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up --build -d`
|
`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up --build -d`
|
||||||
);
|
);
|
||||||
await configureSimpleServiceProxyOn({ id, domain, port: 8000 });
|
|
||||||
|
|
||||||
if (isHttps) {
|
|
||||||
await letsEncrypt({ domain, id });
|
|
||||||
}
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
await reloadHaproxy(destinationDocker.engine);
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
@@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
try {
|
try {
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { destinationDockerId, destinationDocker, fqdn } = service;
|
const { destinationDockerId, destinationDocker, fqdn } = service;
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
|
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const engine = destinationDocker.engine;
|
const engine = destinationDocker.engine;
|
||||||
@@ -36,12 +33,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
await configureSimpleServiceProxyOff(fqdn);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -3,14 +3,6 @@ import * as db from '$lib/database';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
|
||||||
import {
|
|
||||||
checkHAProxy,
|
|
||||||
configureSimpleServiceProxyOn,
|
|
||||||
reloadHaproxy,
|
|
||||||
setWwwRedirection
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import { getServiceImage, ErrorHandler } from '$lib/database';
|
import { getServiceImage, ErrorHandler } from '$lib/database';
|
||||||
import { makeLabelForServices } from '$lib/buildPacks/common';
|
import { makeLabelForServices } from '$lib/buildPacks/common';
|
||||||
|
|
||||||
@@ -21,12 +13,8 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await checkHAProxy();
|
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { type, version, fqdn, destinationDockerId, destinationDocker } = service;
|
const { type, version, destinationDockerId, destinationDocker } = service;
|
||||||
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
|
|
||||||
const network = destinationDockerId && destinationDocker.network;
|
const network = destinationDockerId && destinationDocker.network;
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
@@ -73,13 +61,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
||||||
await configureSimpleServiceProxyOn({ id, domain, port: 80 });
|
|
||||||
|
|
||||||
if (isHttps) {
|
|
||||||
await letsEncrypt({ domain, id });
|
|
||||||
}
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
await reloadHaproxy(destinationDocker.engine);
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
@@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
try {
|
try {
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { destinationDockerId, destinationDocker, fqdn } = service;
|
const { destinationDockerId, destinationDocker, fqdn } = service;
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const engine = destinationDocker.engine;
|
const engine = destinationDocker.engine;
|
||||||
|
|
||||||
@@ -27,13 +24,7 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
await configureSimpleServiceProxyOff(fqdn);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,14 +3,6 @@ import * as db from '$lib/database';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
|
||||||
import {
|
|
||||||
checkHAProxy,
|
|
||||||
configureSimpleServiceProxyOn,
|
|
||||||
reloadHaproxy,
|
|
||||||
setWwwRedirection
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { makeLabelForServices } from '$lib/buildPacks/common';
|
import { makeLabelForServices } from '$lib/buildPacks/common';
|
||||||
|
|
||||||
@@ -21,20 +13,15 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await checkHAProxy();
|
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
version,
|
version,
|
||||||
fqdn,
|
|
||||||
destinationDockerId,
|
destinationDockerId,
|
||||||
destinationDocker,
|
destinationDocker,
|
||||||
vscodeserver: { password }
|
vscodeserver: { password }
|
||||||
} = service;
|
} = service;
|
||||||
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
|
|
||||||
const network = destinationDockerId && destinationDocker.network;
|
const network = destinationDockerId && destinationDocker.network;
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
|
|
||||||
@@ -83,13 +70,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
||||||
await configureSimpleServiceProxyOn({ id, domain, port: 8080 });
|
|
||||||
|
|
||||||
if (isHttps) {
|
|
||||||
await letsEncrypt({ domain, id });
|
|
||||||
}
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
await reloadHaproxy(destinationDocker.engine);
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
@@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
try {
|
try {
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { destinationDockerId, destinationDocker, fqdn } = service;
|
const { destinationDockerId, destinationDocker, fqdn } = service;
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const engine = destinationDocker.engine;
|
const engine = destinationDocker.engine;
|
||||||
|
|
||||||
@@ -27,11 +24,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
await configureSimpleServiceProxyOff(fqdn);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
|
|||||||
@@ -3,14 +3,6 @@ import * as db from '$lib/database';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
|
||||||
import {
|
|
||||||
checkHAProxy,
|
|
||||||
configureSimpleServiceProxyOn,
|
|
||||||
reloadHaproxy,
|
|
||||||
setWwwRedirection
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { makeLabelForServices } from '$lib/buildPacks/common';
|
import { makeLabelForServices } from '$lib/buildPacks/common';
|
||||||
|
|
||||||
@@ -21,7 +13,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
const { id } = event.params;
|
const { id } = event.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await checkHAProxy();
|
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
@@ -39,9 +30,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
}
|
}
|
||||||
} = service;
|
} = service;
|
||||||
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
|
|
||||||
const network = destinationDockerId && destinationDocker.network;
|
const network = destinationDockerId && destinationDocker.network;
|
||||||
const host = getEngine(destinationDocker.engine);
|
const host = getEngine(destinationDocker.engine);
|
||||||
|
|
||||||
@@ -120,13 +108,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`);
|
||||||
await configureSimpleServiceProxyOn({ id, domain, port: 80 });
|
|
||||||
|
|
||||||
if (isHttps) {
|
|
||||||
await letsEncrypt({ domain, id });
|
|
||||||
}
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
await reloadHaproxy(destinationDocker.engine);
|
|
||||||
return {
|
return {
|
||||||
status: 200
|
status: 200
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
import { getUserDetails, removeDestinationDocker } from '$lib/common';
|
||||||
import { getDomain } from '$lib/components/common';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { ErrorHandler } from '$lib/database';
|
import { ErrorHandler } from '$lib/database';
|
||||||
import { dockerInstance } from '$lib/docker';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import { checkContainer, configureSimpleServiceProxyOff } from '$lib/haproxy';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
@@ -15,7 +13,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
try {
|
try {
|
||||||
const service = await db.getService({ id, teamId });
|
const service = await db.getService({ id, teamId });
|
||||||
const { destinationDockerId, destinationDocker, fqdn } = service;
|
const { destinationDockerId, destinationDocker, fqdn } = service;
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const engine = destinationDocker.engine;
|
const engine = destinationDocker.engine;
|
||||||
try {
|
try {
|
||||||
@@ -30,11 +27,6 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
await configureSimpleServiceProxyOff(fqdn);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,17 +1,6 @@
|
|||||||
import { dev } from '$app/env';
|
import { getUserDetails } from '$lib/common';
|
||||||
import { getDomain, getUserDetails } from '$lib/common';
|
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import { listSettings, ErrorHandler } from '$lib/database';
|
import { listSettings, ErrorHandler } from '$lib/database';
|
||||||
import {
|
|
||||||
configureCoolifyProxyOff,
|
|
||||||
configureCoolifyProxyOn,
|
|
||||||
forceSSLOnApplication,
|
|
||||||
reloadHaproxy,
|
|
||||||
removeWwwRedirection,
|
|
||||||
setWwwRedirection,
|
|
||||||
startCoolifyProxy
|
|
||||||
} from '$lib/haproxy';
|
|
||||||
import { letsEncrypt } from '$lib/letsencrypt';
|
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import { promises as dns } from 'dns';
|
import { promises as dns } from 'dns';
|
||||||
|
|
||||||
@@ -51,10 +40,7 @@ export const del: RequestHandler = async (event) => {
|
|||||||
// Do not care.
|
// Do not care.
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
await db.prisma.setting.update({ where: { fqdn }, data: { fqdn: null } });
|
await db.prisma.setting.update({ where: { fqdn }, data: { fqdn: null } });
|
||||||
await configureCoolifyProxyOff(fqdn);
|
|
||||||
await removeWwwRedirection(domain);
|
|
||||||
return {
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
body: {
|
body: {
|
||||||
@@ -79,49 +65,19 @@ export const post: RequestHandler = async (event) => {
|
|||||||
|
|
||||||
const { fqdn, isRegistrationEnabled, dualCerts, minPort, maxPort } = await event.request.json();
|
const { fqdn, isRegistrationEnabled, dualCerts, minPort, maxPort } = await event.request.json();
|
||||||
try {
|
try {
|
||||||
const {
|
const { id } = await db.listSettings();
|
||||||
id,
|
if (isRegistrationEnabled) {
|
||||||
fqdn: oldFqdn,
|
|
||||||
isRegistrationEnabled: oldIsRegistrationEnabled,
|
|
||||||
dualCerts: oldDualCerts
|
|
||||||
} = await db.listSettings();
|
|
||||||
if (oldIsRegistrationEnabled !== isRegistrationEnabled) {
|
|
||||||
await db.prisma.setting.update({ where: { id }, data: { isRegistrationEnabled } });
|
await db.prisma.setting.update({ where: { id }, data: { isRegistrationEnabled } });
|
||||||
}
|
}
|
||||||
if (oldDualCerts !== dualCerts) {
|
|
||||||
await db.prisma.setting.update({ where: { id }, data: { dualCerts } });
|
|
||||||
}
|
|
||||||
if (oldFqdn && oldFqdn !== fqdn) {
|
|
||||||
if (oldFqdn) {
|
|
||||||
const oldDomain = getDomain(oldFqdn);
|
|
||||||
await configureCoolifyProxyOff(oldFqdn);
|
|
||||||
await removeWwwRedirection(oldDomain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fqdn) {
|
if (fqdn) {
|
||||||
await startCoolifyProxy('/var/run/docker.sock');
|
|
||||||
const domain = getDomain(fqdn);
|
|
||||||
const isHttps = fqdn.startsWith('https://');
|
|
||||||
if (domain) {
|
|
||||||
await configureCoolifyProxyOn(fqdn);
|
|
||||||
await setWwwRedirection(fqdn);
|
|
||||||
if (isHttps) {
|
|
||||||
await letsEncrypt({ domain, isCoolify: true });
|
|
||||||
await forceSSLOnApplication(domain);
|
|
||||||
await reloadHaproxy('/var/run/docker.sock');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.prisma.setting.update({ where: { id }, data: { fqdn } });
|
await db.prisma.setting.update({ where: { id }, data: { fqdn } });
|
||||||
await db.prisma.destinationDocker.updateMany({
|
}
|
||||||
where: { engine: '/var/run/docker.sock' },
|
if (dualCerts) {
|
||||||
data: { isCoolifyProxyUsed: true }
|
await db.prisma.setting.update({ where: { id }, data: { dualCerts } });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (minPort && maxPort) {
|
if (minPort && maxPort) {
|
||||||
await db.prisma.setting.update({ where: { id }, data: { minPort, maxPort } });
|
await db.prisma.setting.update({ where: { id }, data: { minPort, maxPort } });
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 201
|
status: 201
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -78,6 +78,7 @@
|
|||||||
if (fqdn !== settings.fqdn) {
|
if (fqdn !== settings.fqdn) {
|
||||||
await post(`/settings/check.json`, { fqdn });
|
await post(`/settings/check.json`, { fqdn });
|
||||||
await post(`/settings.json`, { fqdn });
|
await post(`/settings.json`, { fqdn });
|
||||||
|
return window.location.reload();
|
||||||
}
|
}
|
||||||
if (minPort !== settings.minPort || maxPort !== settings.maxPort) {
|
if (minPort !== settings.minPort || maxPort !== settings.maxPort) {
|
||||||
await post(`/settings.json`, { minPort, maxPort });
|
await post(`/settings.json`, { minPort, maxPort });
|
||||||
@@ -98,7 +99,7 @@
|
|||||||
{#if $session.teamId === '0'}
|
{#if $session.teamId === '0'}
|
||||||
<div class="mx-auto max-w-4xl px-6">
|
<div class="mx-auto max-w-4xl px-6">
|
||||||
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
||||||
<div class="flex space-x-1 py-6">
|
<div class="flex space-x-1 pb-6">
|
||||||
<div class="title font-bold">Global Settings</div>
|
<div class="title font-bold">Global Settings</div>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const get: RequestHandler = async () => {
|
|||||||
const versions = await got
|
const versions = await got
|
||||||
.get(`https://get.coollabs.io/versions.json?appId=${process.env['COOLIFY_APP_ID']}`)
|
.get(`https://get.coollabs.io/versions.json?appId=${process.env['COOLIFY_APP_ID']}`)
|
||||||
.json();
|
.json();
|
||||||
const latestVersion = dev ? '10.0.0' : versions['coolify'].main.version;
|
const latestVersion = versions['coolify'].main.version;
|
||||||
const isUpdateAvailable = compare(latestVersion, currentVersion);
|
const isUpdateAvailable = compare(latestVersion, currentVersion);
|
||||||
return {
|
return {
|
||||||
body: {
|
body: {
|
||||||
@@ -26,27 +26,11 @@ export const get: RequestHandler = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const post: RequestHandler = async (event) => {
|
export const post: RequestHandler = async (event) => {
|
||||||
const { type, latestVersion } = await event.request.json();
|
const { type, latestVersion, overrideVersion } = await event.request.json();
|
||||||
if (type === 'pull') {
|
if (type === 'update') {
|
||||||
try {
|
try {
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
await asyncExecShell(`docker pull coollabsio/coolify:${latestVersion}`);
|
await asyncExecShell(`docker pull coollabsio/coolify:${latestVersion}`);
|
||||||
return {
|
|
||||||
status: 200,
|
|
||||||
body: {}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
status: 200,
|
|
||||||
body: {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return ErrorHandler(error);
|
|
||||||
}
|
|
||||||
} else if (type === 'update') {
|
|
||||||
try {
|
|
||||||
if (!dev) {
|
|
||||||
await asyncExecShell(`env | grep COOLIFY > .env`);
|
await asyncExecShell(`env | grep COOLIFY > .env`);
|
||||||
await asyncExecShell(
|
await asyncExecShell(
|
||||||
`docker run --rm -tid --env-file .env -v /var/run/docker.sock:/var/run/docker.sock -v coolify-db coollabsio/coolify:${latestVersion} /bin/sh -c "env | grep COOLIFY > .env && echo 'TAG=${latestVersion}' >> .env && docker stop -t 0 coolify coolify-redis && docker rm coolify coolify-redis && docker compose up -d --force-recreate"`
|
`docker run --rm -tid --env-file .env -v /var/run/docker.sock:/var/run/docker.sock -v coolify-db coollabsio/coolify:${latestVersion} /bin/sh -c "env | grep COOLIFY > .env && echo 'TAG=${latestVersion}' >> .env && docker stop -t 0 coolify coolify-redis && docker rm coolify coolify-redis && docker compose up -d --force-recreate"`
|
||||||
@@ -66,6 +50,31 @@ export const post: RequestHandler = async (event) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
return ErrorHandler(error);
|
return ErrorHandler(error);
|
||||||
}
|
}
|
||||||
|
} else if (type === 'check') {
|
||||||
|
try {
|
||||||
|
if (overrideVersion) {
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: {
|
||||||
|
exists: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
await asyncExecShell(`docker image inspect coollabsio/coolify:${latestVersion}`);
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: {
|
||||||
|
exists: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: {
|
||||||
|
exists: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
status: 500
|
status: 500
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { RequestHandler } from '@sveltejs/kit';
|
|||||||
import cuid from 'cuid';
|
import cuid from 'cuid';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { buildQueue } from '$lib/queues';
|
import { buildQueue } from '$lib/queues';
|
||||||
import { checkContainer, removeProxyConfiguration } from '$lib/haproxy';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import { dev } from '$app/env';
|
import { dev } from '$app/env';
|
||||||
|
|
||||||
export const options: RequestHandler = async () => {
|
export const options: RequestHandler = async () => {
|
||||||
@@ -84,6 +84,10 @@ export const post: RequestHandler = async (event) => {
|
|||||||
data: { configHash }
|
data: { configHash }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
await db.prisma.application.update({
|
||||||
|
where: { id: applicationFound.id },
|
||||||
|
data: { updatedAt: new Date() }
|
||||||
|
});
|
||||||
await buildQueue.add(buildId, {
|
await buildQueue.add(buildId, {
|
||||||
build_id: buildId,
|
build_id: buildId,
|
||||||
type: 'webhook_commit',
|
type: 'webhook_commit',
|
||||||
@@ -128,6 +132,10 @@ export const post: RequestHandler = async (event) => {
|
|||||||
pullmergeRequestAction === 'reopened' ||
|
pullmergeRequestAction === 'reopened' ||
|
||||||
pullmergeRequestAction === 'synchronize'
|
pullmergeRequestAction === 'synchronize'
|
||||||
) {
|
) {
|
||||||
|
await db.prisma.application.update({
|
||||||
|
where: { id: applicationFound.id },
|
||||||
|
data: { updatedAt: new Date() }
|
||||||
|
});
|
||||||
await buildQueue.add(buildId, {
|
await buildQueue.add(buildId, {
|
||||||
build_id: buildId,
|
build_id: buildId,
|
||||||
type: 'webhook_pr',
|
type: 'webhook_pr',
|
||||||
@@ -143,18 +151,9 @@ export const post: RequestHandler = async (event) => {
|
|||||||
};
|
};
|
||||||
} else if (pullmergeRequestAction === 'closed') {
|
} else if (pullmergeRequestAction === 'closed') {
|
||||||
if (applicationFound.destinationDockerId) {
|
if (applicationFound.destinationDockerId) {
|
||||||
const domain = getDomain(applicationFound.fqdn);
|
|
||||||
const isHttps = applicationFound.fqdn.startsWith('https://');
|
|
||||||
const isWWW = applicationFound.fqdn.includes('www.');
|
|
||||||
const fqdn = `${isHttps ? 'https://' : 'http://'}${
|
|
||||||
isWWW ? 'www.' : ''
|
|
||||||
}${pullmergeRequestId}.${domain}`;
|
|
||||||
|
|
||||||
const id = `${applicationFound.id}-${pullmergeRequestId}`;
|
const id = `${applicationFound.id}-${pullmergeRequestId}`;
|
||||||
const engine = applicationFound.destinationDocker.engine;
|
const engine = applicationFound.destinationDocker.engine;
|
||||||
|
|
||||||
await removeDestinationDocker({ id, engine });
|
await removeDestinationDocker({ id, engine });
|
||||||
await removeProxyConfiguration(fqdn);
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getTeam, getUserDetails, getDomain, removeDestinationDocker } from '$lib/common';
|
import { getTeam, getUserDetails, getDomain, removeDestinationDocker } from '$lib/common';
|
||||||
import { checkContainer, removeProxyConfiguration } from '$lib/haproxy';
|
import { checkContainer } from '$lib/haproxy';
|
||||||
import * as db from '$lib/database';
|
import * as db from '$lib/database';
|
||||||
import type { RequestHandler } from '@sveltejs/kit';
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
import cuid from 'cuid';
|
import cuid from 'cuid';
|
||||||
@@ -48,6 +48,10 @@ export const post: RequestHandler = async (event) => {
|
|||||||
data: { configHash }
|
data: { configHash }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
await db.prisma.application.update({
|
||||||
|
where: { id: applicationFound.id },
|
||||||
|
data: { updatedAt: new Date() }
|
||||||
|
});
|
||||||
await buildQueue.add(buildId, {
|
await buildQueue.add(buildId, {
|
||||||
build_id: buildId,
|
build_id: buildId,
|
||||||
type: 'webhook_commit',
|
type: 'webhook_commit',
|
||||||
@@ -125,6 +129,10 @@ export const post: RequestHandler = async (event) => {
|
|||||||
action === 'open' ||
|
action === 'open' ||
|
||||||
action === 'update'
|
action === 'update'
|
||||||
) {
|
) {
|
||||||
|
await db.prisma.application.update({
|
||||||
|
where: { id: applicationFound.id },
|
||||||
|
data: { updatedAt: new Date() }
|
||||||
|
});
|
||||||
await buildQueue.add(buildId, {
|
await buildQueue.add(buildId, {
|
||||||
build_id: buildId,
|
build_id: buildId,
|
||||||
type: 'webhook_mr',
|
type: 'webhook_mr',
|
||||||
@@ -140,18 +148,9 @@ export const post: RequestHandler = async (event) => {
|
|||||||
};
|
};
|
||||||
} else if (action === 'close') {
|
} else if (action === 'close') {
|
||||||
if (applicationFound.destinationDockerId) {
|
if (applicationFound.destinationDockerId) {
|
||||||
const domain = getDomain(applicationFound.fqdn);
|
|
||||||
const isHttps = applicationFound.fqdn.startsWith('https://');
|
|
||||||
const isWWW = applicationFound.fqdn.includes('www.');
|
|
||||||
const fqdn = `${isHttps ? 'https://' : 'http://'}${
|
|
||||||
isWWW ? 'www.' : ''
|
|
||||||
}${pullmergeRequestId}.${domain}`;
|
|
||||||
|
|
||||||
const id = `${applicationFound.id}-${pullmergeRequestId}`;
|
const id = `${applicationFound.id}-${pullmergeRequestId}`;
|
||||||
const engine = applicationFound.destinationDocker.engine;
|
const engine = applicationFound.destinationDocker.engine;
|
||||||
|
|
||||||
await removeDestinationDocker({ id, engine });
|
await removeDestinationDocker({ id, engine });
|
||||||
await removeProxyConfiguration(fqdn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user