From 5f047e4adf4a52252d0548204dc947d0110dee13 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 16 Apr 2022 22:16:47 +0200 Subject: [PATCH 01/16] docs: How to add new services --- CONTRIBUTING.md | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8a21ec10a..db04c9de0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,3 +42,76 @@ If the schema is finalized, you need to create a migration file with `pnpm db:mi ## Tricky parts - BullMQ, the queue system Coolify is using, cannot be hot reloaded. So if you change anything in the files related to it, you need to restart the development process. I'm actively looking of a different queue/scheduler library. I'm open for discussion! + +# Adding new services + +You can add any open-source and self-hostable softwares (service / application) to Coolify, if the following statements are true: + +- Self-hostable (obviously) +- Open-source +- Maintained (do not want to host softwares with full of bugs) + +## Example MinIO + +### Backend + +(Lots of the code are duplicated, I know.) + +I use MinIO as an example, as that is the simplest. + +You need to add a new folder to [src/routes/services/[id]/](src/routes/services/[id]/) with the low-capital name of the service. + +1. A POST endpoint that updates Coolify's database about the service. + + Basic services only requires to update the URL(fqdn) and the name of the service. + +2. A start endpoint that setups the docker-compose file (for Local Docker Engines) and starts the service. + + - To start a service, you need to know Coolify supported images and tags of the service. For that you need to update `supportedServiceTypesAndVersions` function at [src/lib/components/common.ts](src/lib/components/common.ts). + + Example JSON: + + ```json + { + // Name used to identify the service in Coolify + name: 'minio', + // Fancier name to show to the user + fancyName: 'MinIO', + // Docker base image for the service + baseImage: 'minio/minio', + // Usable tags + versions: ['latest'], + // Which tag is the recommended + recommendedVersion: 'latest', + // Application's default port, MinIO listens on 9001 (and 9000, more details later on) + ports: { + main: 9001 + } + }, + ``` + + - Then you need to define a compose file as `const composeFile: ComposeFile` found in [src/routes/services/[id]/minio/start.json.ts](src/routes/services/[id]/minio/start.json.ts) + + IMPORTANT: It should contain `all the default environment variables` that is required for the service to function properly and `all the volumes to persist data` in restarts. + + - You could also define a `HTTP` or `TCP` proxy for every other ports that should be proxied to your server. (See `startHttpProxy` and `startTcpProxy` functions) + +3. A stop endpoints that stops the service. + + It needs stop all the services by their container name and all proxies started. + +4. You need to add the automatically generated variables (passwords, users, etc.) for the new service you are adding at [src/lib/database/services.ts](src/lib/database/services.ts) `configureServiceType` function. + +### Frontend + +1. Need to add a custom logo at [src/lib/components/svg/services/](src/lib/components/svg/services/) as a svelte component. + + SVG is recommended, but you can use PNG as well. It should have the `isAbsolute` variable with the right CSS classes, mostly for sizing and positioning. + +2. Need to include it the logo at [src/routes/services/index.svelte](src/routes/services/index.svelte) with `isAbsolute` and [src/lib/components/ServiceLinks.svelte](src/lib/components/ServiceLinks.svelte) with a link to the docs/main site of the service. + +3. By default the URL and the name frontend forms are included in [src/routes/services/[id]/\_Services/\_Services.svelte](src/routes/services/[id]/_Services/_Services.svelte). + + If you need to show more details on the frontend, like users/passwords, you need to add Svelte component to [src/routes/services/[id]/\_Services](src/routes/services/[id]/_Services) with an underscore. For examples, see other files in that folder. + + You also need to add the new inputs to the `index.json.ts` file of the specific service, like for MinIO here: [src/routes/services/[id]/minio/index.json.ts](src/routes/services/[id]/minio/index.json.ts) From 5eeb519ed653c97cee601bc8a08d98a1248ed3d7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 16 Apr 2022 22:19:41 +0200 Subject: [PATCH 02/16] docs: update --- CONTRIBUTING.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index db04c9de0..d813df53b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,6 +43,8 @@ If the schema is finalized, you need to create a migration file with `pnpm db:mi - BullMQ, the queue system Coolify is using, cannot be hot reloaded. So if you change anything in the files related to it, you need to restart the development process. I'm actively looking of a different queue/scheduler library. I'm open for discussion! +--- + # Adding new services You can add any open-source and self-hostable softwares (service / application) to Coolify, if the following statements are true: @@ -51,21 +53,17 @@ You can add any open-source and self-hostable softwares (service / application) - Open-source - Maintained (do not want to host softwares with full of bugs) -## Example MinIO +## Backend -### Backend +I use MinIO as an example. -(Lots of the code are duplicated, I know.) +You need to add a new folder to [src/routes/services/[id]](src/routes/services/[id]) with the low-capital name of the service. It should have three files with the following properties: -I use MinIO as an example, as that is the simplest. - -You need to add a new folder to [src/routes/services/[id]/](src/routes/services/[id]/) with the low-capital name of the service. - -1. A POST endpoint that updates Coolify's database about the service. +1. `index.json.ts`: A POST endpoint that updates Coolify's database about the service. Basic services only requires to update the URL(fqdn) and the name of the service. -2. A start endpoint that setups the docker-compose file (for Local Docker Engines) and starts the service. +2. `start.json.ts`: A start endpoint that setups the docker-compose file (for Local Docker Engines) and starts the service. - To start a service, you need to know Coolify supported images and tags of the service. For that you need to update `supportedServiceTypesAndVersions` function at [src/lib/components/common.ts](src/lib/components/common.ts). @@ -96,13 +94,13 @@ You need to add a new folder to [src/routes/services/[id]/](src/routes/services/ - You could also define a `HTTP` or `TCP` proxy for every other ports that should be proxied to your server. (See `startHttpProxy` and `startTcpProxy` functions) -3. A stop endpoints that stops the service. +3. `stop.json.ts` A stop endpoints that stops the service. It needs stop all the services by their container name and all proxies started. 4. You need to add the automatically generated variables (passwords, users, etc.) for the new service you are adding at [src/lib/database/services.ts](src/lib/database/services.ts) `configureServiceType` function. -### Frontend +## Frontend 1. Need to add a custom logo at [src/lib/components/svg/services/](src/lib/components/svg/services/) as a svelte component. From d70672ba4be2c2ac791b80d2a42954e46e014b3c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 16 Apr 2022 22:21:42 +0200 Subject: [PATCH 03/16] switch example type --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d813df53b..1dade2a2f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ You need to add a new folder to [src/routes/services/[id]](src/routes/services/[ Example JSON: - ```json + ```js { // Name used to identify the service in Coolify name: 'minio', From bf01e9e29fb72dbde420de442f24790036b27c23 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 16 Apr 2022 22:28:17 +0200 Subject: [PATCH 04/16] Grammar things --- CONTRIBUTING.md | 30 +++++++++++++++--------------- README.md | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1dade2a2f..0b9aaf7bd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Welcome -First of all, thank you for considering to contribute to my project! It means a lot 💜. +First of all, thank you for considering contributing to my project! It means a lot 💜. # Technical skills required @@ -20,7 +20,7 @@ First of all, thank you for considering to contribute to my project! It means a # How to start after you set up your local fork? -This repository best with [pnpm](https://pnpm.io) due to the lock file. I recommend you should try and use `pnpm` as well, because it is cool and efficient! +Due to the lock file, this repository is best with [pnpm](https://pnpm.io). I recommend you try and use `pnpm` because it is cool and efficient! You need to have [Docker Engine](https://docs.docker.com/engine/install/) installed locally. @@ -41,17 +41,17 @@ If the schema is finalized, you need to create a migration file with `pnpm db:mi ## Tricky parts -- BullMQ, the queue system Coolify is using, cannot be hot reloaded. So if you change anything in the files related to it, you need to restart the development process. I'm actively looking of a different queue/scheduler library. I'm open for discussion! +- BullMQ, the queue system Coolify uses, cannot be hot reloaded. So if you change anything in the files related to it, you need to restart the development process. I'm actively looking for a different queue/scheduler library. I'm open to discussion! --- # Adding new services -You can add any open-source and self-hostable softwares (service / application) to Coolify, if the following statements are true: +You can add any open-source and self-hostable software (service/application) to Coolify if the following statements are true: - Self-hostable (obviously) - Open-source -- Maintained (do not want to host softwares with full of bugs) +- Maintained (I do not want to add software full of bugs) ## Backend @@ -61,7 +61,7 @@ You need to add a new folder to [src/routes/services/[id]](src/routes/services/[ 1. `index.json.ts`: A POST endpoint that updates Coolify's database about the service. - Basic services only requires to update the URL(fqdn) and the name of the service. + Basic services only require updating the URL(fqdn) and the name of the service. 2. `start.json.ts`: A start endpoint that setups the docker-compose file (for Local Docker Engines) and starts the service. @@ -88,28 +88,28 @@ You need to add a new folder to [src/routes/services/[id]](src/routes/services/[ }, ``` - - Then you need to define a compose file as `const composeFile: ComposeFile` found in [src/routes/services/[id]/minio/start.json.ts](src/routes/services/[id]/minio/start.json.ts) + - You need to define a compose file as `const composeFile: ComposeFile` found in [src/routes/services/[id]/minio/start.json.ts](src/routes/services/[id]/minio/start.json.ts) - IMPORTANT: It should contain `all the default environment variables` that is required for the service to function properly and `all the volumes to persist data` in restarts. + IMPORTANT: It should contain `all the default environment variables` that are required for the service to function correctly and `all the volumes to persist data` in restarts. - - You could also define a `HTTP` or `TCP` proxy for every other ports that should be proxied to your server. (See `startHttpProxy` and `startTcpProxy` functions) + - You could also define an `HTTP` or `TCP` proxy for every other port that should be proxied to your server. (See `startHttpProxy` and `startTcpProxy` functions) -3. `stop.json.ts` A stop endpoints that stops the service. +3. `stop.json.ts` A stop endpoint that stops the service. - It needs stop all the services by their container name and all proxies started. + It needs to stop all the services by their container name, and all proxies started. 4. You need to add the automatically generated variables (passwords, users, etc.) for the new service you are adding at [src/lib/database/services.ts](src/lib/database/services.ts) `configureServiceType` function. ## Frontend -1. Need to add a custom logo at [src/lib/components/svg/services/](src/lib/components/svg/services/) as a svelte component. +1. You need to add a custom logo at [src/lib/components/svg/services/](src/lib/components/svg/services/) as a svelte component. - SVG is recommended, but you can use PNG as well. It should have the `isAbsolute` variable with the right CSS classes, mostly for sizing and positioning. + SVG is recommended, but you can use PNG as well. It should have the `isAbsolute` variable with the suitable CSS classes, primarily for sizing and positioning. -2. Need to include it the logo at [src/routes/services/index.svelte](src/routes/services/index.svelte) with `isAbsolute` and [src/lib/components/ServiceLinks.svelte](src/lib/components/ServiceLinks.svelte) with a link to the docs/main site of the service. +2. You need to include it the logo at [src/routes/services/index.svelte](src/routes/services/index.svelte) with `isAbsolute` and [src/lib/components/ServiceLinks.svelte](src/lib/components/ServiceLinks.svelte) with a link to the docs/main site of the service. 3. By default the URL and the name frontend forms are included in [src/routes/services/[id]/\_Services/\_Services.svelte](src/routes/services/[id]/_Services/_Services.svelte). - If you need to show more details on the frontend, like users/passwords, you need to add Svelte component to [src/routes/services/[id]/\_Services](src/routes/services/[id]/_Services) with an underscore. For examples, see other files in that folder. + If you need to show more details on the frontend, such as users/passwords, you need to add Svelte component to [src/routes/services/[id]/\_Services](src/routes/services/[id]/_Services) with an underscore. For example, see other files in that folder. You also need to add the new inputs to the `index.json.ts` file of the specific service, like for MinIO here: [src/routes/services/[id]/minio/index.json.ts](src/routes/services/[id]/minio/index.json.ts) diff --git a/README.md b/README.md index 2cb2d5bf6..d214d42b7 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ If you would like no questions during installation ### Git Sources -You can use the following Git Sources to be auto-deployed to your Coolifyt instance! (Self hosted versions also supported.) +You can use the following Git Sources to be auto-deployed to your Coolifyt instance! (Self-hosted versions are also supported.) - Github - GitLab @@ -38,7 +38,7 @@ You can deploy your applications to the following destinations: ### Applications -These are the predefined build packs, but with the Docker build pack, you can host basically anything that is hostable with a single Dockerfile. +These are the predefined build packs, but with the Docker build pack, you can host anything that is hostable with a single Dockerfile. - Static sites - NodeJS From 07aa285b279696f5bd4d886b2c6d5fcc38e4783c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 16 Apr 2022 22:31:30 +0200 Subject: [PATCH 05/16] updates on docs --- CONTRIBUTING.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0b9aaf7bd..4122aab7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ First of all, thank you for considering contributing to my project! It means a l - Node.js / Javascript - Svelte / SvelteKit -- Prisma.io +- Prisma.io / SQL # Recommended Pull Request Guideline @@ -18,6 +18,8 @@ First of all, thank you for considering contributing to my project! It means a l - Write a proper description - Open the pull request to review +--- + # How to start after you set up your local fork? Due to the lock file, this repository is best with [pnpm](https://pnpm.io). I recommend you try and use `pnpm` because it is cool and efficient! @@ -45,7 +47,7 @@ If the schema is finalized, you need to create a migration file with `pnpm db:mi --- -# Adding new services +# How to add new services You can add any open-source and self-hostable software (service/application) to Coolify if the following statements are true: @@ -90,7 +92,7 @@ You need to add a new folder to [src/routes/services/[id]](src/routes/services/[ - You need to define a compose file as `const composeFile: ComposeFile` found in [src/routes/services/[id]/minio/start.json.ts](src/routes/services/[id]/minio/start.json.ts) - IMPORTANT: It should contain `all the default environment variables` that are required for the service to function correctly and `all the volumes to persist data` in restarts. + **IMPORTANT:** It should contain `all the default environment variables` that are required for the service to function correctly and `all the volumes to persist data` in restarts. - You could also define an `HTTP` or `TCP` proxy for every other port that should be proxied to your server. (See `startHttpProxy` and `startTcpProxy` functions) From 93a6518974081c9fd70f58dd00e3d6c67aabe785 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sat, 16 Apr 2022 23:04:29 +0200 Subject: [PATCH 06/16] docs: update --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4122aab7d..68f432132 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -94,13 +94,13 @@ You need to add a new folder to [src/routes/services/[id]](src/routes/services/[ **IMPORTANT:** It should contain `all the default environment variables` that are required for the service to function correctly and `all the volumes to persist data` in restarts. - - You could also define an `HTTP` or `TCP` proxy for every other port that should be proxied to your server. (See `startHttpProxy` and `startTcpProxy` functions) + - You could also define an `HTTP` or `TCP` proxy for every other port that should be proxied to your server. (See `startHttpProxy` and `startTcpProxy` functions in [src/lib/haproxy/index.ts](src/lib/haproxy/index.ts)) 3. `stop.json.ts` A stop endpoint that stops the service. - It needs to stop all the services by their container name, and all proxies started. + It needs to stop all the services by their container name and proxies (if applicable). -4. You need to add the automatically generated variables (passwords, users, etc.) for the new service you are adding at [src/lib/database/services.ts](src/lib/database/services.ts) `configureServiceType` function. +4. You need to add the automatically generated variables (passwords, users, etc.) for the new service at [src/lib/database/services.ts](src/lib/database/services.ts), `configureServiceType` function. ## Frontend From 591ee29e0d33c6fe9c51ab962eec4375139b88c6 Mon Sep 17 00:00:00 2001 From: lichtscheu Date: Tue, 19 Apr 2022 22:08:42 +0200 Subject: [PATCH 07/16] feat: initial deno support --- src/lib/buildPacks/deno.ts | 41 +++++++++++++++++++ src/lib/buildPacks/index.ts | 4 +- src/lib/components/common.ts | 2 +- .../components/svg/applications/Deno.svelte | 24 +++++++++++ src/lib/components/templates.ts | 16 ++++++++ src/routes/applications/[id]/index.svelte | 12 ++++++ src/routes/applications/index.svelte | 5 +++ 7 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/lib/buildPacks/deno.ts create mode 100644 src/lib/components/svg/applications/Deno.svelte diff --git a/src/lib/buildPacks/deno.ts b/src/lib/buildPacks/deno.ts new file mode 100644 index 000000000..ac06cc177 --- /dev/null +++ b/src/lib/buildPacks/deno.ts @@ -0,0 +1,41 @@ +import { buildImage } from '$lib/docker'; +import { promises as fs } from 'fs'; + +const createDockerfile = async (data, image): Promise => { + const { workdir, port, startCommand, baseDirectory, secrets, pullmergeRequestId } = data; + const Dockerfile: Array = []; + + Dockerfile.push(`FROM ${image}`); + Dockerfile.push('WORKDIR /app'); + Dockerfile.push(`LABEL coolify.image=true`); + if (secrets.length > 0) { + secrets.forEach((secret) => { + if (secret.isBuildSecret) { + if (pullmergeRequestId) { + if (secret.isPRMRSecret) { + Dockerfile.push(`ARG ${secret.name}=${secret.value}`); + } + } else { + if (!secret.isPRMRSecret) { + Dockerfile.push(`ARG ${secret.name}=${secret.value}`); + } + } + } + }); + } + Dockerfile.push(`COPY .${baseDirectory || ''} ./`); + Dockerfile.push(`ENV NO_COLOR true`); + Dockerfile.push(`EXPOSE ${port}`); + Dockerfile.push(`CMD ${startCommand}`); + await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile.join('\n')); +}; + +export default async function (data) { + try { + const image = 'denoland/deno:latest'; + await createDockerfile(data, image); + await buildImage(data); + } catch (error) { + throw error; + } +} diff --git a/src/lib/buildPacks/index.ts b/src/lib/buildPacks/index.ts index babbe8f17..ac31afc16 100644 --- a/src/lib/buildPacks/index.ts +++ b/src/lib/buildPacks/index.ts @@ -13,6 +13,7 @@ import rust from './rust'; import astro from './static'; import eleventy from './static'; import python from './python'; +import deno from './deno'; export { node, @@ -29,5 +30,6 @@ export { rust, astro, eleventy, - python + python, + deno }; diff --git a/src/lib/components/common.ts b/src/lib/components/common.ts index 2bd962c4c..6bc60202d 100644 --- a/src/lib/components/common.ts +++ b/src/lib/components/common.ts @@ -19,7 +19,7 @@ export const staticDeployments = [ 'astro', 'eleventy' ]; -export const notNodeDeployments = ['php', 'docker', 'rust', 'python']; +export const notNodeDeployments = ['php', 'docker', 'rust', 'python', 'deno']; export function getDomain(domain) { return domain?.replace('https://', '').replace('http://', ''); diff --git a/src/lib/components/svg/applications/Deno.svelte b/src/lib/components/svg/applications/Deno.svelte new file mode 100644 index 000000000..4e1794226 --- /dev/null +++ b/src/lib/components/svg/applications/Deno.svelte @@ -0,0 +1,24 @@ + diff --git a/src/lib/components/templates.ts b/src/lib/components/templates.ts index b82b12f51..99aceabfe 100644 --- a/src/lib/components/templates.ts +++ b/src/lib/components/templates.ts @@ -153,6 +153,16 @@ export function findBuildPack(pack, packageManager = 'npm') { port: 8000 }; } + if (pack === 'deno') { + return { + ...metaData, + installCommand: `yarn install`, + buildCommand: `yarn build`, + startCommand: null, + publishDirectory: `_site`, + port: 80 + }; + } return { name: 'node', fancyName: 'Node.js', @@ -262,6 +272,12 @@ export const buildPacks = [ fancyName: 'Python', hoverColor: 'hover:bg-green-700', color: 'bg-green-700' + }, + { + name: 'deno', + fancyName: 'Deno', + hoverColor: 'hover:bg-green-700', + color: 'bg-green-700' } ]; export const scanningTemplates = { diff --git a/src/routes/applications/[id]/index.svelte b/src/routes/applications/[id]/index.svelte index 4b7d6b497..f4ca842e0 100644 --- a/src/routes/applications/[id]/index.svelte +++ b/src/routes/applications/[id]/index.svelte @@ -420,6 +420,18 @@ /> {/if} + {#if application.buildPack === 'deno'} +
+ + +
+ {/if}