From 2eeb4017acb4c454373e0c4d1845ae3aea12e59f Mon Sep 17 00:00:00 2001 From: DrMxrcy Date: Wed, 20 Nov 2024 11:12:31 -0500 Subject: [PATCH 1/3] feat(add): Twenty CRM --- apps/dokploy/public/templates/twenty.svg | 6 ++ apps/dokploy/templates/templates.ts | 15 +++ .../templates/twenty/docker-compose.yml | 98 +++++++++++++++++++ apps/dokploy/templates/twenty/index.ts | 37 +++++++ 4 files changed, 156 insertions(+) create mode 100644 apps/dokploy/public/templates/twenty.svg create mode 100644 apps/dokploy/templates/twenty/docker-compose.yml create mode 100644 apps/dokploy/templates/twenty/index.ts diff --git a/apps/dokploy/public/templates/twenty.svg b/apps/dokploy/public/templates/twenty.svg new file mode 100644 index 00000000..cf5223b9 --- /dev/null +++ b/apps/dokploy/public/templates/twenty.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/dokploy/templates/templates.ts b/apps/dokploy/templates/templates.ts index 46806a8a..b5a57dc5 100644 --- a/apps/dokploy/templates/templates.ts +++ b/apps/dokploy/templates/templates.ts @@ -867,4 +867,19 @@ export const templates: TemplateData[] = [ tags: ["support", "chat", "customer-service"], load: () => import("./chatwoot/index").then((m) => m.generate), }, + { + id: "twenty", + name: "Twenty CRM", + version: "latest", + description: + "Twenty is a modern CRM offering a powerful spreadsheet interface and open-source alternative to Salesforce.", + logo: "twenty.svg", + links: { + github: "https://github.com/twentyhq/twenty", + website: "https://twenty.com", + docs: "https://docs.twenty.com", + }, + tags: ["crm", "sales", "business"], + load: () => import("./twenty/index.ts").then((m) => m.generate), + }, ]; diff --git a/apps/dokploy/templates/twenty/docker-compose.yml b/apps/dokploy/templates/twenty/docker-compose.yml new file mode 100644 index 00000000..3a30e13b --- /dev/null +++ b/apps/dokploy/templates/twenty/docker-compose.yml @@ -0,0 +1,98 @@ +version: "3.9" + +services: + twenty-change-vol-ownership: + image: ubuntu + user: root + networks: + - dokploy-network + volumes: + - twenty-server-local-data:/tmp/server-local-data + - twenty-docker-data:/tmp/docker-data + command: > + bash -c " + chown -R 1000:1000 /tmp/server-local-data + && chown -R 1000:1000 /tmp/docker-data" + + twenty-server: + image: twentycrm/twenty:latest + networks: + - dokploy-network + volumes: + - twenty-server-local-data:/app/packages/twenty-server/${STORAGE_LOCAL_PATH:-.local-storage} + - twenty-docker-data:/app/docker-data + environment: + PORT: 3000 + PG_DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@twenty-db:5432/default + SERVER_URL: https://${TWENTY_HOST} + FRONT_BASE_URL: https://${TWENTY_HOST} + REDIS_URL: redis://twenty-redis:6379 + ENABLE_DB_MIGRATIONS: "true" + SIGN_IN_PREFILLED: "true" + STORAGE_TYPE: local + APP_SECRET: ${APP_SECRET} + depends_on: + twenty-change-vol-ownership: + condition: service_completed_successfully + twenty-db: + condition: service_healthy + healthcheck: + test: curl --fail http://localhost:3000/healthz + interval: 5s + timeout: 5s + retries: 10 + restart: always + + twenty-worker: + image: twentycrm/twenty:latest + networks: + - dokploy-network + command: ["yarn", "worker:prod"] + environment: + PG_DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@twenty-db:5432/default + SERVER_URL: https://${TWENTY_HOST} + FRONT_BASE_URL: https://${TWENTY_HOST} + REDIS_URL: redis://twenty-redis:6379 + ENABLE_DB_MIGRATIONS: "false" + STORAGE_TYPE: local + APP_SECRET: ${APP_SECRET} + depends_on: + twenty-db: + condition: service_healthy + twenty-server: + condition: service_healthy + restart: always + + twenty-db: + image: twentycrm/twenty-postgres-spilo:latest + networks: + - dokploy-network + volumes: + - twenty-db-data:/home/postgres/pgdata + environment: + PGUSER_SUPERUSER: ${PGUSER} + PGPASSWORD_SUPERUSER: ${PGPASSWORD} + ALLOW_NOSSL: "true" + SPILO_PROVIDER: "local" + healthcheck: + test: pg_isready -U ${PGUSER} -h localhost -d postgres + interval: 5s + timeout: 5s + retries: 10 + restart: always + + twenty-redis: + image: redis:latest + networks: + - dokploy-network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 10 + restart: always + +volumes: + twenty-docker-data: + twenty-db-data: + twenty-server-local-data: \ No newline at end of file diff --git a/apps/dokploy/templates/twenty/index.ts b/apps/dokploy/templates/twenty/index.ts new file mode 100644 index 00000000..932e98cd --- /dev/null +++ b/apps/dokploy/templates/twenty/index.ts @@ -0,0 +1,37 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateBase64, + generatePassword, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const mainDomain = generateRandomDomain(schema); + const pgPassword = generatePassword(); + const pgUser = "twenty"; + const appSecret = generateBase64(32); + + const domains: DomainSchema[] = [ + { + host: mainDomain, + port: 3000, + serviceName: "twenty-server", + }, + ]; + + const envs = [ + `TWENTY_HOST=${mainDomain}`, + `PGUSER=${pgUser}`, + `PGPASSWORD=${pgPassword}`, + `APP_SECRET=${appSecret}`, + "# Optional: Configure storage path", + "# STORAGE_LOCAL_PATH=.local-storage", + ]; + + return { + domains, + envs, + }; +} From e9956a66daaa1b904f867a2e07daebcb08e78094 Mon Sep 17 00:00:00 2001 From: DrMxrcy Date: Wed, 20 Nov 2024 11:18:33 -0500 Subject: [PATCH 2/3] fix(add): template.ts --- apps/dokploy/templates/templates.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/templates/templates.ts b/apps/dokploy/templates/templates.ts index b5a57dc5..41763a14 100644 --- a/apps/dokploy/templates/templates.ts +++ b/apps/dokploy/templates/templates.ts @@ -880,6 +880,6 @@ export const templates: TemplateData[] = [ docs: "https://docs.twenty.com", }, tags: ["crm", "sales", "business"], - load: () => import("./twenty/index.ts").then((m) => m.generate), + load: () => import("./twenty/index").then((m) => m.generate), }, ]; From d4b8985d71132597d00b22ad96b0daf2ce9487e3 Mon Sep 17 00:00:00 2001 From: DrMxrcy Date: Thu, 21 Nov 2024 10:18:38 -0500 Subject: [PATCH 3/3] fix(template): Twenty DB --- .../templates/twenty/docker-compose.yml | 34 +++++++++++-------- apps/dokploy/templates/twenty/index.ts | 8 ++--- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/apps/dokploy/templates/twenty/docker-compose.yml b/apps/dokploy/templates/twenty/docker-compose.yml index 3a30e13b..34c70aeb 100644 --- a/apps/dokploy/templates/twenty/docker-compose.yml +++ b/apps/dokploy/templates/twenty/docker-compose.yml @@ -23,7 +23,7 @@ services: - twenty-docker-data:/app/docker-data environment: PORT: 3000 - PG_DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@twenty-db:5432/default + PG_DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@twenty-postgres:5432/twenty SERVER_URL: https://${TWENTY_HOST} FRONT_BASE_URL: https://${TWENTY_HOST} REDIS_URL: redis://twenty-redis:6379 @@ -34,7 +34,7 @@ services: depends_on: twenty-change-vol-ownership: condition: service_completed_successfully - twenty-db: + twenty-postgres: condition: service_healthy healthcheck: test: curl --fail http://localhost:3000/healthz @@ -49,7 +49,7 @@ services: - dokploy-network command: ["yarn", "worker:prod"] environment: - PG_DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@twenty-db:5432/default + PG_DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@twenty-postgres:5432/twenty SERVER_URL: https://${TWENTY_HOST} FRONT_BASE_URL: https://${TWENTY_HOST} REDIS_URL: redis://twenty-redis:6379 @@ -57,25 +57,24 @@ services: STORAGE_TYPE: local APP_SECRET: ${APP_SECRET} depends_on: - twenty-db: + twenty-postgres: condition: service_healthy twenty-server: condition: service_healthy restart: always - twenty-db: - image: twentycrm/twenty-postgres-spilo:latest + twenty-postgres: + image: postgres:16-alpine networks: - dokploy-network volumes: - - twenty-db-data:/home/postgres/pgdata + - twenty-postgres-data:/var/lib/postgresql/data environment: - PGUSER_SUPERUSER: ${PGUSER} - PGPASSWORD_SUPERUSER: ${PGPASSWORD} - ALLOW_NOSSL: "true" - SPILO_PROVIDER: "local" + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: twenty healthcheck: - test: pg_isready -U ${PGUSER} -h localhost -d postgres + test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d twenty"] interval: 5s timeout: 5s retries: 10 @@ -85,6 +84,8 @@ services: image: redis:latest networks: - dokploy-network + volumes: + - twenty-redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s @@ -92,7 +93,12 @@ services: retries: 10 restart: always +networks: + dokploy-network: + external: true + volumes: twenty-docker-data: - twenty-db-data: - twenty-server-local-data: \ No newline at end of file + twenty-postgres-data: + twenty-server-local-data: + twenty-redis-data: \ No newline at end of file diff --git a/apps/dokploy/templates/twenty/index.ts b/apps/dokploy/templates/twenty/index.ts index 932e98cd..69bc5195 100644 --- a/apps/dokploy/templates/twenty/index.ts +++ b/apps/dokploy/templates/twenty/index.ts @@ -9,8 +9,8 @@ import { export function generate(schema: Schema): Template { const mainDomain = generateRandomDomain(schema); - const pgPassword = generatePassword(); - const pgUser = "twenty"; + const dbPassword = generatePassword(); + const dbUser = "twenty"; const appSecret = generateBase64(32); const domains: DomainSchema[] = [ @@ -23,8 +23,8 @@ export function generate(schema: Schema): Template { const envs = [ `TWENTY_HOST=${mainDomain}`, - `PGUSER=${pgUser}`, - `PGPASSWORD=${pgPassword}`, + `DB_USER=${dbUser}`, + `DB_PASSWORD=${dbPassword}`, `APP_SECRET=${appSecret}`, "# Optional: Configure storage path", "# STORAGE_LOCAL_PATH=.local-storage",