update all

This commit is contained in:
Andrei Canta
2024-12-04 15:21:36 +02:00
parent 9c2502c8d8
commit aa05d8edec
52 changed files with 1279 additions and 641 deletions
+6 -18
View File
@@ -1,32 +1,20 @@
TAG=v0.32.3
TAG=latest
POSTGRES_ADMIN_PASSWORD=replace_me_with_a_strong_password
#PGUSER_SUPERUSER=postgres
#PGPASSWORD_SUPERUSER=replace_me_with_a_strong_password
PG_DATABASE_HOST=db:5432
REDIS_URL=redis://redis:6379
SERVER_URL=https://$(PRIMARY_DOMAIN)
SERVER_URL=http://localhost:3000
# Use openssl rand -base64 32 for each secret - Please change these values
REFRESH_TOKEN_SECRET=IqPjqg9jCkrwp2KLS8k8mYRaOhvGtw3xmYF2dAkrkD0=
ACCESS_TOKEN_SECRET=IqPjqg9jCkrwp2KLS8k8mYRaOhvGtw3xmYF2dAkrkD0=
LOGIN_TOKEN_SECRET=IqPjqg9jCkrwp2KLS8k8mYRaOhvGtw3xmYF2dAkrkD0=
APP_SECRET=IqPjqg9jCkrwp2KLS8k8mYRaOhvGtw3xmYF2dAkrkD0=
# Use openssl rand -base64 32 for each secret
# APP_SECRET=replace_me_with_a_random_string
SIGN_IN_PREFILLED=true
STORAGE_TYPE=local
#S3 STORAGE
# STORAGE_S3_REGION=eu-west3
# STORAGE_S3_NAME=my-bucket
# STORAGE_S3_ENDPOINT=
#GOOGLE AUTH
# AUTH_GOOGLE_ENABLED=true
# AUTH_GOOGLE_CLIENT_ID=
# AUTH_GOOGLE_CLIENT_SECRET=
# AUTH_GOOGLE_CALLBACK_URL=
# AUTH_GOOGLE_APIS_CALLBACK_URL=
-36
View File
@@ -1,37 +1,9 @@
dev-build:
@docker compose -f dev/docker-compose.yml down -v
@docker compose -f dev/docker-compose.yml build
dev-up:
@docker compose -f dev/docker-compose.yml up -d
dev-start:
@docker compose -f dev/docker-compose.yml start
dev-stop:
@docker compose -f dev/docker-compose.yml stop
dev-down:
@docker compose -f dev/docker-compose.yml down -v
dev-sh:
@docker compose -f dev/docker-compose.yml exec twenty-dev sh
dev-postgres-build:
@docker stop twenty_postgres || true
@docker rm twenty_postgres || true
@docker volume rm twenty_db_data || true
@docker compose -f dev/docker-compose.yml up --build postgres -d
prod-build:
@cd ../.. && docker build -f ./packages/twenty-docker/twenty/Dockerfile --tag twenty . && cd -
prod-run:
@docker run -d -p 3000:3000 --name twenty twenty
prod-postgres-build:
@cd ../.. && docker build -f ./packages/twenty-docker/twenty-postgres/Dockerfile --tag twenty-postgres . && cd -
prod-postgres-run:
@docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres --name twenty-postgres twenty-postgres
@@ -40,11 +12,3 @@ prod-website-build:
prod-website-run:
@docker run -d -p 3000:3000 --name twenty-website twenty-website
release-postgres:
@cd ../.. && docker buildx build \
--push \
--no-cache \
--platform linux/amd64,linux/arm64 \
-f ./packages/twenty-docker/twenty-postgres/Dockerfile -t twentycrm/twenty-postgres:$(version) -t twentycrm/twenty-postgres:latest . \
&& cd -
+18 -28
View File
@@ -9,24 +9,21 @@ services:
- server-local-data:/tmp/server-local-data
- docker-data:/tmp/docker-data
command: >
bash -c "
chown -R 1000:1000 /tmp/server-local-data
&& chown -R 1000:1000 /tmp/docker-data"
bash -c " chown -R 1000:1000 /tmp/server-local-data && chown -R 1000:1000
/tmp/docker-data"
server:
image: twentycrm/twenty:${TAG}
volumes:
- server-local-data:/app/packages/twenty-server/${STORAGE_LOCAL_PATH:-.local-storage}
- docker-data:/app/docker-data
ports:
- "3000"
environment:
PORT: 3000
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
PG_DATABASE_URL: postgres://${PGUSER_SUPERUSER:-postgres}:${PGPASSWORD_SUPERUSER:-postgres}@${PG_DATABASE_HOST:-db:5432}/default
SERVER_URL: ${SERVER_URL}
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
REDIS_URL: ${REDIS_URL:-redis://localhost:6379}
REDIS_HOST: ${REDIS_HOST}
REDIS_URL: ${REDIS_URL:-redis://redis:6379}
ENABLE_DB_MIGRATIONS: "true"
SIGN_IN_PREFILLED: ${SIGN_IN_PREFILLED}
@@ -34,12 +31,8 @@ services:
STORAGE_S3_REGION: ${STORAGE_S3_REGION}
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
LOGIN_TOKEN_SECRET: ${LOGIN_TOKEN_SECRET}
REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}
APP_SECRET: ${APP_SECRET}
depends_on:
change-vol-ownership:
condition: service_completed_successfully
@@ -54,13 +47,13 @@ services:
worker:
image: twentycrm/twenty:${TAG}
command: ["yarn", "worker:prod"]
command: [ "yarn", "worker:prod" ]
environment:
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
PG_DATABASE_URL: postgres://${PGUSER_SUPERUSER:-postgres}:${PGPASSWORD_SUPERUSER:-postgres}@${PG_DATABASE_HOST:-db:5432}/default
SERVER_URL: ${SERVER_URL}
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
REDIS_URL: ${REDIS_URL:-redis://localhost:6379}
REDIS_HOST: redis
REDIS_URL: ${REDIS_URL:-redis://redis:6379}
ENABLE_DB_MIGRATIONS: "false" # it already runs on the server
STORAGE_TYPE: ${STORAGE_TYPE}
@@ -68,11 +61,7 @@ services:
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
LOGIN_TOKEN_SECRET: ${LOGIN_TOKEN_SECRET}
REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}
APP_SECRET: ${APP_SECRET}
depends_on:
db:
condition: service_healthy
@@ -81,13 +70,16 @@ services:
restart: always
db:
image: twentycrm/twenty-postgres:${TAG}
image: twentycrm/twenty-postgres-spilo:${TAG}
volumes:
- db-data:/bitnami/postgresql
- db-data:/home/postgres/pgdata
environment:
POSTGRES_PASSWORD: ${POSTGRES_ADMIN_PASSWORD}
PGUSER_SUPERUSER: ${PGUSER_SUPERUSER:-postgres}
PGPASSWORD_SUPERUSER: ${PGPASSWORD_SUPERUSER:-postgres}
ALLOW_NOSSL: "true"
SPILO_PROVIDER: "local"
healthcheck:
test: pg_isready -U twenty -d default
test: pg_isready -U ${PGUSER_SUPERUSER:-postgres} -h localhost -d postgres
interval: 5s
timeout: 5s
retries: 10
@@ -95,11 +87,9 @@ services:
redis:
image: redis
ports:
- "6379:6379"
restart: always
volumes:
docker-data:
db-data:
server-local-data:
server-local-data:
+27 -27
View File
@@ -22,33 +22,33 @@ spec:
app: twentycrm-db
spec:
volumes:
- name: twentycrm-db-data
persistentVolumeClaim:
claimName: twentycrm-db-pvc
- name: twentycrm-db-data
persistentVolumeClaim:
claimName: twentycrm-db-pvc
containers:
- env:
- name: POSTGRES_PASSWORD
value: "twenty"
- name: BITNAMI_DEBUG
value: "true"
- image: twentycrm/twenty-postgres:latest
imagePullPolicy: Always
name: twentycrm
ports:
- containerPort: 5432
name: tcp
protocol: TCP
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1024Mi"
cpu: "1000m"
stdin: true
tty: true
volumeMounts:
- mountPath: /bitnami/postgresql
name: twentycrm-db-data
- name: twentycrm
image: twentycrm/twenty-postgres:latest
imagePullPolicy: Always
env:
- name: PGUSER_SUPERUSER
value: "postgres"
- name: PGPASSWORD_SUPERUSER
value: "postgres"
ports:
- containerPort: 5432
name: tcp
protocol: TCP
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1024Mi"
cpu: "1000m"
stdin: true
tty: true
volumeMounts:
- mountPath: /home/postgres/pgdata
name: twentycrm-db-data
dnsPolicy: ClusterFirst
restartPolicy: Always
@@ -0,0 +1,44 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: twentycrm-redis
name: twentycrm-redis
namespace: twentycrm
spec:
progressDeadlineSeconds: 600
replicas: 1
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
selector:
matchLabels:
app: twentycrm-redis
template:
metadata:
labels:
app: twentycrm-redis
spec:
containers:
- name: redis
image: redis/redis-stack-server:latest
imagePullPolicy: Always
env:
- name: PORT
value: 6379
ports:
- containerPort: 6379
name: redis
protocol: TCP
resources:
requests:
memory: "1024Mi"
cpu: "250m"
limits:
memory: "2048Mi"
cpu: "500m"
dnsPolicy: ClusterFirst
restartPolicy: Always
@@ -22,67 +22,61 @@ spec:
app: twentycrm-server
spec:
volumes:
- name: twentycrm-server-data
persistentVolumeClaim:
claimName: twentycrm-server-pvc
- name: twentycrm-server-data
persistentVolumeClaim:
claimName: twentycrm-server-pvc
- name: twentycrm-docker-data
persistentVolumeClaim:
claimName: twentycrm-docker-data-pvc
containers:
- env:
- name: PORT
value: 3000
- name: SERVER_URL
value: "https://crm.example.com:443"
- name: FRONT_BASE_URL
value: "https://crm.example.com:443"
- name: PG_DATABASE_URL
value: "postgres://twenty:twenty@twenty-db.twentycrm.svc.cluster.local/default"
- name: ENABLE_DB_MIGRATIONS
value: "true"
- name: SIGN_IN_PREFILLED
value: "true"
- name: STORAGE_TYPE
value: "local"
- name: "MESSAGE_QUEUE_TYPE"
value: "pg-boss"
- name: ACCESS_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: accessToken
- name: LOGIN_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: loginToken
- name: REFRESH_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: refreshToken
- name: FILE_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: fileToken
- image: twentycrm/twenty:latest
imagePullPolicy: Always
name: twentycrm
ports:
- containerPort: 3000
name: http-tcp
protocol: TCP
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1024Mi"
cpu: "1000m"
stdin: true
tty: true
volumeMounts:
- mountPath: /app/docker-data
name: twentycrm-server-data
- mountPath: /app/.local-storage
name: twentycrm-server-data
- name: twentycrm
image: twentycrm/twenty:latest
imagePullPolicy: Always
env:
- name: PORT
value: 3000
- name: SERVER_URL
value: "https://crm.example.com:443"
- name: FRONT_BASE_URL
value: "https://crm.example.com:443"
- name: "PG_DATABASE_URL"
value: "postgres://postgres:postgres@twenty-db.twentycrm.svc.cluster.local/default"
- name: "REDIS_URL"
value: "redis://twentycrm-redis.twentycrm.svc.cluster.local:6379"
- name: ENABLE_DB_MIGRATIONS
value: "true"
- name: SIGN_IN_PREFILLED
value: "true"
- name: STORAGE_TYPE
value: "local"
- name: "MESSAGE_QUEUE_TYPE"
value: "bull-mq"
- name: "ACCESS_TOKEN_EXPIRES_IN"
value: "7d"
- name: "LOGIN_TOKEN_EXPIRES_IN"
value: "1h"
- name: APP_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: accessToken
ports:
- containerPort: 3000
name: http-tcp
protocol: TCP
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1024Mi"
cpu: "1000m"
stdin: true
tty: true
volumeMounts:
- mountPath: /app/docker-data
name: twentycrm-docker-data
- mountPath: /app/packages/twenty-server/.local-storage
name: twentycrm-server-data
dnsPolicy: ClusterFirst
restartPolicy: Always
@@ -21,58 +21,43 @@ spec:
labels:
app: twentycrm-worker
spec:
volumes:
- name: twentycrm-worker-data
persistentVolumeClaim:
claimName: twentycrm-worker-pvc
containers:
- env:
- name: SERVER_URL
value: "https://crm.example.com:443"
- name: FRONT_BASE_URL
value: "https://crm.example.com:443"
- name: PG_DATABASE_URL
value: "postgres://twenty:twenty@twenty-db.twentycrm.svc.cluster.local/default"
- name: ENABLE_DB_MIGRATIONS
value: "false" # it already runs on the server
- name: STORAGE_TYPE
value: "local"
- name: "MESSAGE_QUEUE_TYPE"
value: "pg-boss"
- name: ACCESS_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: accessToken
- name: LOGIN_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: loginToken
- name: REFRESH_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: refreshToken
- name: FILE_TOKEN_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: fileToken
- image: twentycrm/twenty:latest
imagePullPolicy: Always
name: twentycrm
command:
- yarn
- worker:prod
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1024Mi"
cpu: "1000m"
stdin: true
tty: true
- name: twentycrm
image: twentycrm/twenty:latest
imagePullPolicy: Always
env:
- name: SERVER_URL
value: "https://crm.example.com:443"
- name: FRONT_BASE_URL
value: "https://crm.example.com:443"
- name: PG_DATABASE_URL
value: "postgres://postgres:postgres@twenty-db.twentycrm.svc.cluster.local/default"
- name: ENABLE_DB_MIGRATIONS
value: "false" # it already runs on the server
- name: STORAGE_TYPE
value: "local"
- name: "MESSAGE_QUEUE_TYPE"
value: "bull-mq"
- name: "CACHE_STORAGE_TYPE"
value: "redis"
- name: "REDIS_URL"
value: "redis://twentycrm-redis.twentycrm.svc.cluster.local:6379"
- name: APP_SECRET
valueFrom:
secretKeyRef:
name: tokens
key: accessToken
command:
- yarn
- worker:prod
resources:
requests:
memory: "1024Mi"
cpu: "250m"
limits:
memory: "2048Mi"
cpu: "1000m"
stdin: true
tty: true
dnsPolicy: ClusterFirst
restartPolicy: Always
+14 -14
View File
@@ -4,21 +4,21 @@ metadata:
name: twentycrm
namespace: twentycrm
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "X-Forwarded-For $http_x_forwarded_for";
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
ingressClassName: nginx
rules:
- host: crm.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: twentycrm-server
port:
name: http-tcp
- host: crm.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: twentycrm-server
port:
name: http-tcp
@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: twentycrm-docker-data-pv
spec:
storageClassName: default
capacity:
storage: 100Mi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: twentycrm-docker-data-pvc
namespace: twentycrm
spec:
storageClassName: default
volumeName: twentycrm-docker-data-pv
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
+3 -3
View File
@@ -6,9 +6,9 @@ metadata:
spec:
internalTrafficPolicy: Cluster
ports:
- port: 5432
protocol: TCP
targetPort: 5432
- port: 5432
protocol: TCP
targetPort: 5432
selector:
app: twentycrm-db
sessionAffinity: ClientIP
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: twentycrm-redis
namespace: twentycrm
spec:
internalTrafficPolicy: Cluster
ports:
- port: 6379
protocol: TCP
targetPort: 6379
selector:
app: twentycrm-redis
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
type: ClusterIP
@@ -6,10 +6,10 @@ metadata:
spec:
internalTrafficPolicy: Cluster
ports:
- name: http-tcp
port: 3000
protocol: TCP
targetPort: 3000
- name: http-tcp
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: twentycrm-server
sessionAffinity: ClientIP
@@ -15,12 +15,12 @@ output:
<!-- BEGIN_TF_DOCS -->
# TwentyCRM Terraform Docs
This file was generated by [terraform-docs](https://terraform-docs.io/), for more information on how to install, configure and use visit their website.
This file was generated by [terraform-docs](https://terraform-docs.io/), for more information on how to install, configure, and use visit their website.
To update this `README.md` after changes to the Terraform code in this folder, run: `terraform-docs .`
To update this `README.md` after changes to the Terraform code in this folder, run: `terraform-docs -c `./.terraform-docs.yml .`
To make configuration changes to how this doc is generated, see `./.terraform-docs.yml`
{{ .Content }}
<!-- END_TF_DOCS -->
@@ -45,4 +45,4 @@ settings:
read-comments: true
required: true
sensitive: true
type: true
type: true
+20 -11
View File
@@ -1,9 +1,9 @@
<!-- BEGIN_TF_DOCS -->
# TwentyCRM Terraform Docs
This file was generated by [terraform-docs](https://terraform-docs.io/), for more information on how to install, configure and use visit their website.
This file was generated by [terraform-docs](https://terraform-docs.io/), for more information on how to install, configure, and use visit their website.
To update this `README.md` after changes to the Terraform code in this folder, run: `terraform-docs .`
To update this `README.md` after changes to the Terraform code in this folder, run: `terraform-docs -c `./.terraform-docs.yml .`
To make configuration changes to how this doc is generated, see `./.terraform-docs.yml`
@@ -12,30 +12,37 @@ To make configuration changes to how this doc is generated, see `./.terraform-do
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.2 |
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.31.0 |
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.32.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.6.3 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | >= 2.31.0 |
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | >= 2.32.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 3.6.3 |
## Resources
| Name | Type |
|------|------|
| [kubernetes_deployment.twentycrm_db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
| [kubernetes_deployment.twentycrm_redis](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
| [kubernetes_deployment.twentycrm_server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
| [kubernetes_deployment.twentycrm_worker](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
| [kubernetes_ingress.twentycrm](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/ingress) | resource |
| [kubernetes_namespace.twentycrm](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
| [kubernetes_persistent_volume.db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume) | resource |
| [kubernetes_persistent_volume.docker_data](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume) | resource |
| [kubernetes_persistent_volume.server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume) | resource |
| [kubernetes_persistent_volume_claim.db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim) | resource |
| [kubernetes_persistent_volume_claim.docker_data](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim) | resource |
| [kubernetes_persistent_volume_claim.server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim) | resource |
| [kubernetes_secret.twentycrm_tokens](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
| [kubernetes_service.twentycrm_db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
| [kubernetes_service.twentycrm_redis](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
| [kubernetes_service.twentycrm_server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
| [random_bytes.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/bytes) | resource |
## Inputs
@@ -43,22 +50,24 @@ To make configuration changes to how this doc is generated, see `./.terraform-do
|------|-------------|------|---------|:--------:|
| <a name="input_twentycrm_app_hostname"></a> [twentycrm\_app\_hostname](#input\_twentycrm\_app\_hostname) | The protocol, DNS fully qualified hostname, and port used to access TwentyCRM in your environment. Ex: https://crm.example.com:443 | `string` | n/a | yes |
| <a name="input_twentycrm_pgdb_admin_password"></a> [twentycrm\_pgdb\_admin\_password](#input\_twentycrm\_pgdb\_admin\_password) | TwentyCRM password for postgres database. | `string` | n/a | yes |
| <a name="input_twentycrm_token_accessToken"></a> [twentycrm\_token\_accessToken](#input\_twentycrm\_token\_accessToken) | TwentyCRM access Token | `string` | n/a | yes |
| <a name="input_twentycrm_token_fileToken"></a> [twentycrm\_token\_fileToken](#input\_twentycrm\_token\_fileToken) | TwentyCRM file Token | `string` | n/a | yes |
| <a name="input_twentycrm_token_loginToken"></a> [twentycrm\_token\_loginToken](#input\_twentycrm\_token\_loginToken) | TwentyCRM login Token | `string` | n/a | yes |
| <a name="input_twentycrm_token_refreshToken"></a> [twentycrm\_token\_refreshToken](#input\_twentycrm\_token\_refreshToken) | TwentyCRM refresh Token | `string` | n/a | yes |
| <a name="input_twentycrm_app_name"></a> [twentycrm\_app\_name](#input\_twentycrm\_app\_name) | A friendly name prefix to use for every component deployed. | `string` | `"twentycrm"` | no |
| <a name="input_twentycrm_db_image"></a> [twentycrm\_db\_image](#input\_twentycrm\_db\_image) | TwentyCRM image for database deployment. This defaults to latest. | `string` | `"twentycrm/twenty-postgres:latest"` | no |
| <a name="input_twentycrm_db_image"></a> [twentycrm\_db\_image](#input\_twentycrm\_db\_image) | TwentyCRM image for database deployment. This defaults to latest. | `string` | `"twentycrm/twenty-postgres-spilo:latest"` | no |
| <a name="input_twentycrm_db_pv_capacity"></a> [twentycrm\_db\_pv\_capacity](#input\_twentycrm\_db\_pv\_capacity) | Storage capacity provisioned for database persistent volume. | `string` | `"10Gi"` | no |
| <a name="input_twentycrm_db_pv_path"></a> [twentycrm\_db\_pv\_path](#input\_twentycrm\_db\_pv\_path) | Local path to use to store the physical volume if using local storage on nodes. | `string` | `""` | no |
| <a name="input_twentycrm_db_pvc_requests"></a> [twentycrm\_db\_pvc\_requests](#input\_twentycrm\_db\_pvc\_requests) | Storage capacity reservation for database persistent volume claim. | `string` | `"10Gi"` | no |
| <a name="input_twentycrm_db_replicas"></a> [twentycrm\_db\_replicas](#input\_twentycrm\_db\_replicas) | Number of replicas for the TwentyCRM database deployment. This defaults to 1. | `number` | `1` | no |
| <a name="input_twentycrm_docker_data_mount_path"></a> [twentycrm\_docker\_data\_mount\_path](#input\_twentycrm\_docker\_data\_mount\_path) | TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'. | `string` | `"/app/docker-data"` | no |
| <a name="input_twentycrm_docker_data_pv_capacity"></a> [twentycrm\_docker\_data\_pv\_capacity](#input\_twentycrm\_docker\_data\_pv\_capacity) | Storage capacity provisioned for server persistent volume. | `string` | `"10Gi"` | no |
| <a name="input_twentycrm_docker_data_pv_path"></a> [twentycrm\_docker\_data\_pv\_path](#input\_twentycrm\_docker\_data\_pv\_path) | Local path to use to store the physical volume if using local storage on nodes. | `string` | `""` | no |
| <a name="input_twentycrm_docker_data_pvc_requests"></a> [twentycrm\_docker\_data\_pvc\_requests](#input\_twentycrm\_docker\_data\_pvc\_requests) | Storage capacity reservation for server persistent volume claim. | `string` | `"10Gi"` | no |
| <a name="input_twentycrm_namespace"></a> [twentycrm\_namespace](#input\_twentycrm\_namespace) | Namespace for all TwentyCRM resources | `string` | `"twentycrm"` | no |
| <a name="input_twentycrm_server_data_mount_path"></a> [twentycrm\_server\_data\_mount\_path](#input\_twentycrm\_server\_data\_mount\_path) | TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'. | `string` | `"/app/docker-data"` | no |
| <a name="input_twentycrm_redis_image"></a> [twentycrm\_redis\_image](#input\_twentycrm\_redis\_image) | TwentyCRM image for Redis deployment. This defaults to latest. | `string` | `"redis/redis-stack-server:latest"` | no |
| <a name="input_twentycrm_redis_replicas"></a> [twentycrm\_redis\_replicas](#input\_twentycrm\_redis\_replicas) | Number of replicas for the TwentyCRM Redis deployment. This defaults to 1. | `number` | `1` | no |
| <a name="input_twentycrm_server_data_mount_path"></a> [twentycrm\_server\_data\_mount\_path](#input\_twentycrm\_server\_data\_mount\_path) | TwentyCRM mount path for servers application data. Defaults to '/app/packages/twenty-server/.local-storage'. | `string` | `"/app/packages/twenty-server/.local-storage"` | no |
| <a name="input_twentycrm_server_image"></a> [twentycrm\_server\_image](#input\_twentycrm\_server\_image) | TwentyCRM server image for the server deployment. This defaults to latest. This value is also used for the workers image. | `string` | `"twentycrm/twenty:latest"` | no |
| <a name="input_twentycrm_server_pv_capacity"></a> [twentycrm\_server\_pv\_capacity](#input\_twentycrm\_server\_pv\_capacity) | Storage capacity provisioned for server persistent volume. | `string` | `"10Gi"` | no |
| <a name="input_twentycrm_server_pv_path"></a> [twentycrm\_server\_pv\_path](#input\_twentycrm\_server\_pv\_path) | Local path to use to store the physical volume if using local storage on nodes. | `string` | `""` | no |
| <a name="input_twentycrm_server_pvc_requests"></a> [twentycrm\_server\_pvc\_requests](#input\_twentycrm\_server\_pvc\_requests) | Storage capacity reservation for server persistent volume claim. | `string` | `"10Gi"` | no |
| <a name="input_twentycrm_server_replicas"></a> [twentycrm\_server\_replicas](#input\_twentycrm\_server\_replicas) | Number of replicas for the TwentyCRM server deployment. This defaults to 1. | `number` | `1` | no |
| <a name="input_twentycrm_worker_replicas"></a> [twentycrm\_worker\_replicas](#input\_twentycrm\_worker\_replicas) | Number of replicas for the TwentyCRM worker deployment. This defaults to 1. | `number` | `1` | no |
<!-- END_TF_DOCS -->
<!-- END_TF_DOCS -->
@@ -0,0 +1,60 @@
resource "kubernetes_deployment" "twentycrm_redis" {
metadata {
name = "${var.twentycrm_app_name}-redis"
namespace = kubernetes_namespace.twentycrm.metadata.0.name
labels = {
app = "${var.twentycrm_app_name}-redis"
}
}
spec {
replicas = var.twentycrm_redis_replicas
selector {
match_labels = {
app = "${var.twentycrm_app_name}-redis"
}
}
strategy {
type = "RollingUpdate"
rolling_update {
max_surge = "1"
max_unavailable = "1"
}
}
template {
metadata {
labels = {
app = "${var.twentycrm_app_name}-redis"
}
}
spec {
container {
image = var.twentycrm_redis_image
name = "redis"
port {
container_port = 6379
protocol = "TCP"
}
resources {
requests = {
cpu = "250m"
memory = "1024Mi"
}
limits = {
cpu = "500m"
memory = "2048Mi"
}
}
}
dns_policy = "ClusterFirst"
restart_policy = "Always"
}
}
}
}
+33 -44
View File
@@ -37,20 +37,14 @@ resource "kubernetes_deployment" "twentycrm_server" {
stdin = true
tty = true
security_context {
allow_privilege_escalation = true
privileged = true
run_as_user = 1000
}
env {
name = "PORT"
value = "3000"
}
env {
name = "DEBUG_MODE"
value = false
}
# env {
# name = "DEBUG_MODE"
# value = false
# }
env {
name = "SERVER_URL"
@@ -64,9 +58,12 @@ resource "kubernetes_deployment" "twentycrm_server" {
env {
name = "PG_DATABASE_URL"
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${var.twentycrm_app_name}-db.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${kubernetes_service.twentycrm_db.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
}
env {
name = "REDIS_URL"
value = "redis://${kubernetes_service.twentycrm_redis.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local:6379"
}
env {
name = "ENABLE_DB_MIGRATIONS"
value = "true"
@@ -83,10 +80,18 @@ resource "kubernetes_deployment" "twentycrm_server" {
}
env {
name = "MESSAGE_QUEUE_TYPE"
value = "pg-boss"
value = "bull-mq"
}
env {
name = "ACCESS_TOKEN_SECRET"
name = "ACCESS_TOKEN_EXPIRES_IN"
value = "7d"
}
env {
name = "LOGIN_TOKEN_EXPIRES_IN"
value = "1h"
}
env {
name = "APP_SECRET"
value_from {
secret_key_ref {
name = "tokens"
@@ -95,36 +100,6 @@ resource "kubernetes_deployment" "twentycrm_server" {
}
}
env {
name = "LOGIN_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "loginToken"
}
}
}
env {
name = "REFRESH_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "refreshToken"
}
}
}
env {
name = "FILE_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "fileToken"
}
}
}
port {
container_port = 3000
protocol = "TCP"
@@ -145,6 +120,11 @@ resource "kubernetes_deployment" "twentycrm_server" {
name = "server-data"
mount_path = var.twentycrm_server_data_mount_path
}
volume_mount {
name = "docker-data"
mount_path = var.twentycrm_docker_data_mount_path
}
}
volume {
@@ -155,6 +135,14 @@ resource "kubernetes_deployment" "twentycrm_server" {
}
}
volume {
name = "docker-data"
persistent_volume_claim {
claim_name = kubernetes_persistent_volume_claim.docker_data.metadata.0.name
}
}
dns_policy = "ClusterFirst"
restart_policy = "Always"
}
@@ -162,6 +150,7 @@ resource "kubernetes_deployment" "twentycrm_server" {
}
depends_on = [
kubernetes_deployment.twentycrm_db,
kubernetes_deployment.twentycrm_redis,
kubernetes_secret.twentycrm_tokens
]
}
+18 -36
View File
@@ -50,7 +50,17 @@ resource "kubernetes_deployment" "twentycrm_worker" {
env {
name = "PG_DATABASE_URL"
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${var.twentycrm_app_name}-db.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${kubernetes_service.twentycrm_db.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
}
env {
name = "CACHE_STORAGE_TYPE"
value = "redis"
}
env {
name = "REDIS_URL"
value = "redis://${kubernetes_service.twentycrm_redis.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local:6379"
}
env {
@@ -64,11 +74,11 @@ resource "kubernetes_deployment" "twentycrm_worker" {
}
env {
name = "MESSAGE_QUEUE_TYPE"
value = "pg-boss"
value = "bull-mq"
}
env {
name = "ACCESS_TOKEN_SECRET"
name = "APP_SECRET"
value_from {
secret_key_ref {
name = "tokens"
@@ -77,44 +87,14 @@ resource "kubernetes_deployment" "twentycrm_worker" {
}
}
env {
name = "LOGIN_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "loginToken"
}
}
}
env {
name = "REFRESH_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "refreshToken"
}
}
}
env {
name = "FILE_TOKEN_SECRET"
value_from {
secret_key_ref {
name = "tokens"
key = "fileToken"
}
}
}
resources {
requests = {
cpu = "250m"
memory = "256Mi"
memory = "1024Mi"
}
limits = {
cpu = "1000m"
memory = "1024Mi"
memory = "2048Mi"
}
}
}
@@ -126,6 +106,8 @@ resource "kubernetes_deployment" "twentycrm_worker" {
}
depends_on = [
kubernetes_deployment.twentycrm_db,
kubernetes_secret.twentycrm_tokens
kubernetes_deployment.twentycrm_redis,
kubernetes_deployment.twentycrm_server,
kubernetes_secret.twentycrm_tokens,
]
}
+5 -1
View File
@@ -13,7 +13,11 @@ terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 2.31.0"
version = ">= 2.32.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.6.3"
}
}
}
@@ -0,0 +1,19 @@
resource "kubernetes_persistent_volume" "docker_data" {
metadata {
name = "${var.twentycrm_app_name}-docker-data-pv"
}
spec {
storage_class_name = "default"
capacity = {
storage = var.twentycrm_docker_data_pv_capacity
}
access_modes = ["ReadWriteOnce"]
# refer to Terraform Docs for your specific implementation requirements
# https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume
persistent_volume_source {
local {
path = var.twentycrm_docker_data_pv_path
}
}
}
}
@@ -0,0 +1,15 @@
resource "kubernetes_persistent_volume_claim" "docker_data" {
metadata {
name = "${var.twentycrm_app_name}-docker-data-pvc"
namespace = kubernetes_namespace.twentycrm.metadata.0.name
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = var.twentycrm_docker_data_pvc_requests
}
}
volume_name = kubernetes_persistent_volume.docker_data.metadata.0.name
}
}
+19 -6
View File
@@ -1,3 +1,18 @@
locals {
tokens = [
"accessToken",
"loginToken",
"refreshToken",
"fileToken"
]
}
resource "random_bytes" "this" {
for_each = toset(local.tokens)
length = 32
}
resource "kubernetes_secret" "twentycrm_tokens" {
metadata {
name = "tokens"
@@ -5,11 +20,9 @@ resource "kubernetes_secret" "twentycrm_tokens" {
}
data = {
accessToken = var.twentycrm_token_accessToken
loginToken = var.twentycrm_token_loginToken
refreshToken = var.twentycrm_token_refreshToken
fileToken = var.twentycrm_token_fileToken
accessToken = random_bytes.this["accessToken"].base64
loginToken = random_bytes.this["loginToken"].base64
refreshToken = random_bytes.this["refreshToken"].base64
fileToken = random_bytes.this["fileToken"].base64
}
# type = "kubernetes.io/basic-auth"
}
@@ -0,0 +1,18 @@
resource "kubernetes_service" "twentycrm_redis" {
metadata {
name = "${var.twentycrm_app_name}-redis"
namespace = kubernetes_namespace.twentycrm.metadata.0.name
}
spec {
selector = {
app = "${var.twentycrm_app_name}-redis"
}
session_affinity = "ClientIP"
port {
port = 6379
target_port = 6379
}
type = "ClusterIP"
}
}
+39 -27
View File
@@ -1,30 +1,6 @@
######################
# Required Variables #
######################
variable "twentycrm_token_accessToken" {
type = string
description = "TwentyCRM access Token"
sensitive = true
}
variable "twentycrm_token_loginToken" {
type = string
description = "TwentyCRM login Token"
sensitive = true
}
variable "twentycrm_token_refreshToken" {
type = string
description = "TwentyCRM refresh Token"
sensitive = true
}
variable "twentycrm_token_fileToken" {
type = string
description = "TwentyCRM file Token"
sensitive = true
}
variable "twentycrm_pgdb_admin_password" {
type = string
description = "TwentyCRM password for postgres database."
@@ -53,7 +29,7 @@ variable "twentycrm_server_image" {
variable "twentycrm_db_image" {
type = string
default = "twentycrm/twenty-postgres:latest"
default = "twentycrm/twenty-postgres-spilo:latest"
description = "TwentyCRM image for database deployment. This defaults to latest."
}
@@ -77,8 +53,8 @@ variable "twentycrm_db_replicas" {
variable "twentycrm_server_data_mount_path" {
type = string
default = "/app/docker-data"
description = "TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'."
default = "/app/packages/twenty-server/.local-storage"
description = "TwentyCRM mount path for servers application data. Defaults to '/app/packages/twenty-server/.local-storage'."
}
variable "twentycrm_db_pv_path" {
@@ -122,3 +98,39 @@ variable "twentycrm_namespace" {
default = "twentycrm"
description = "Namespace for all TwentyCRM resources"
}
variable "twentycrm_redis_replicas" {
type = number
default = 1
description = "Number of replicas for the TwentyCRM Redis deployment. This defaults to 1."
}
variable "twentycrm_redis_image" {
type = string
default = "redis/redis-stack-server:latest"
description = "TwentyCRM image for Redis deployment. This defaults to latest."
}
variable "twentycrm_docker_data_mount_path" {
type = string
default = "/app/docker-data"
description = "TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'."
}
variable "twentycrm_docker_data_pv_path" {
type = string
default = ""
description = "Local path to use to store the physical volume if using local storage on nodes."
}
variable "twentycrm_docker_data_pv_capacity" {
type = string
default = "100Mi"
description = "Storage capacity provisioned for server persistent volume."
}
variable "twentycrm_docker_data_pvc_requests" {
type = string
default = "100Mi"
description = "Storage capacity reservation for server persistent volume claim."
}
+22
View File
@@ -0,0 +1,22 @@
pull_version=${VERSION:-$(curl -s https://api.github.com/repos/twentyhq/twenty/tags | grep '"name":' | head -n 1 | cut -d '"' -f 4)}
if [[ -z "$pull_version" ]]; then
echo "Error: Unable to fetch the latest version tag. Please check your network connection or the GitHub API response."
exit 1
fi
pull_branch=${BRANCH:-$pull_version}
version_num=${pull_version#v}
target_version="0.32.4"
# We moved the install script to a different location in v0.32.4
if [[ -n "$BRANCH" ]] || [[ "$(printf '%s\n' "$target_version" "$version_num" | sort -V | head -n1)" != "$version_num" ]]; then
curl -sL "https://raw.githubusercontent.com/twentyhq/twenty/$pull_branch/packages/twenty-docker/scripts/install.sh" -o twenty_install.sh
else
curl -sL "https://raw.githubusercontent.com/twentyhq/twenty/$pull_branch/install.sh" -o twenty_install.sh
fi
chmod +x twenty_install.sh
VERSION="$VERSION" BRANCH="$BRANCH" ./twenty_install.sh
rm twenty_install.sh
+166
View File
@@ -0,0 +1,166 @@
#!/bin/bash
echo "🔧 Checking dependencies..."
if ! command -v docker &>/dev/null; then
echo -e "\t❌ Docker is not installed or not in PATH. Please install Docker first.\n\t\tSee https://docs.docker.com/get-docker/"
exit 1
fi
# Check if docker compose plugin is installed
if ! docker compose version &>/dev/null; then
echo -e "\t❌ Docker Compose is not installed or not in PATH (n.b. docker-compose is deprecated)\n\t\tUpdate docker or install docker-compose-plugin\n\t\tOn Linux: sudo apt-get install docker-compose-plugin\n\t\tSee https://docs.docker.com/compose/install/"
exit 1
fi
# Check if docker is started
if ! docker info &>/dev/null; then
echo -e "\t❌ Docker is not running.\n\t\tPlease start Docker Desktop, Docker or check documentation at https://docs.docker.com/config/daemon/start/"
exit 1
fi
if ! command -v curl &>/dev/null; then
echo -e "\t❌ Curl is not installed or not in PATH.\n\t\tOn macOS: brew install curl\n\t\tOn Linux: sudo apt install curl"
exit 1
fi
# Check if docker compose version is >= 2
if [ "$(docker compose version --short | cut -d' ' -f3 | cut -d'.' -f1)" -lt 2 ]; then
echo -e "\t❌ Docker Compose is outdated. Please update Docker Compose to version 2 or higher.\n\t\tSee https://docs.docker.com/compose/install/linux/"
exit 1
fi
# Check if docker-compose is installed, if so issue a warning if version is < 2
if command -v docker-compose &>/dev/null; then
if [ "$(docker-compose version --short | cut -d' ' -f3 | cut -d'.' -f1)" -lt 2 ]; then
echo -e "\n\t⚠️ 'docker-compose' is installed but outdated. Make sure to use 'docker compose' or to upgrade 'docker-compose' to version 2.\n\t\tSee https://docs.docker.com/compose/install/standalone/\n"
fi
fi
# Catch errors
set -e
function on_exit {
# $? is the exit status of the last command executed
local exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "❌ Something went wrong, exiting: $exit_status"
fi
}
trap on_exit EXIT
# Use environment variables VERSION and BRANCH, with defaults if not set
version=${VERSION:-$(curl -s https://api.github.com/repos/twentyhq/twenty/tags | grep '"name":' | head -n 1 | cut -d '"' -f 4)}
branch=${BRANCH:-$version}
echo "🚀 Using version $version and branch $branch"
dir_name="twenty"
function ask_directory {
read -p "📁 Enter the directory name to setup the project (default: $dir_name): " answer
if [ -n "$answer" ]; then
dir_name=$answer
fi
}
ask_directory
while [ -d "$dir_name" ]; do
read -p "🚫 Directory '$dir_name' already exists. Do you want to overwrite it? (y/N) " answer
if [ "$answer" = "y" ]; then
break
else
ask_directory
fi
done
# Create a directory named twenty
echo "📁 Creating directory '$dir_name'"
mkdir -p "$dir_name" && cd "$dir_name" || { echo "❌ Failed to create/access directory '$dir_name'"; exit 1; }
# Copy twenty/packages/twenty-docker/docker-compose.yml in it
echo -e "\t• Copying docker-compose.yml"
curl -sLo docker-compose.yml https://raw.githubusercontent.com/twentyhq/twenty/$branch/packages/twenty-docker/docker-compose.yml
# Copy twenty/packages/twenty-docker/.env.example to .env
echo -e "\t• Setting up .env file"
curl -sLo .env https://raw.githubusercontent.com/twentyhq/twenty/$branch/packages/twenty-docker/.env.example
# Replace TAG=latest by TAG=<latest_release or version input>
if [[ $(uname) == "Darwin" ]]; then
# Running on macOS
sed -i '' "s/TAG=latest/TAG=$version/g" .env
else
# Assuming Linux
sed -i'' "s/TAG=latest/TAG=$version/g" .env
fi
# Generate random strings for secrets
echo "# === Randomly generated secrets ===" >>.env
echo "APP_SECRET=$(openssl rand -base64 32)" >>.env
echo "" >>.env
echo "PGPASSWORD_SUPERUSER=$(openssl rand -hex 16)" >>.env
echo -e "\t• .env configuration completed"
port=3000
# Check if command nc is available
if command -v nc &> /dev/null; then
# Check if port 3000 is already in use, propose to change it
while nc -zv localhost $port &>/dev/null; do
read -p "🚫 Port $port is already in use. Do you want to use another port? (Y/n) " answer
if [ "$answer" = "n" ]; then
continue
fi
read -p "Enter a new port number: " new_port
if [[ $(uname) == "Darwin" ]]; then
sed -i '' "s/$port:$port/$new_port:$port/g" docker-compose.yml
sed -E -i '' "s|^SERVER_URL=http://localhost:[0-9]+|SERVER_URL=http://localhost:$new_port|g" .env
else
sed -i'' "s/$port:$port/$new_port:$port/g" docker-compose.yml
sed -E -i'' "s|^SERVER_URL=http://localhost:[0-9]+|SERVER_URL=http://localhost:$new_port|g" .env
fi
port=$new_port
done
fi
# Ask user if they want to start the project
read -p "🚀 Do you want to start the project now? (Y/n) " answer
if [ "$answer" = "n" ]; then
echo "✅ Project setup completed. Run 'docker compose up -d' to start."
exit 0
else
echo "🐳 Starting Docker containers..."
docker compose up -d
# Check if port is listening
echo "Waiting for server to be healthy, it might take a few minutes while we initialize the database..."
# Tail logs of the server until it's ready
docker compose logs -f server &
pid=$!
while [ ! $(docker inspect --format='{{.State.Health.Status}}' twenty-server-1) = "healthy" ]; do
sleep 1
done
kill $pid
echo ""
echo "✅ Server is up and running"
fi
function ask_open_browser {
read -p "🌐 Do you want to open the project in your browser? (Y/n) " answer
if [ "$answer" = "n" ]; then
echo "✅ Setup completed. Access your project at http://localhost:$port"
exit 0
fi
}
# Ask user if they want to open the project
# Running on macOS
if [[ $(uname) == "Darwin" ]]; then
ask_open_browser
open "http://localhost:$port"
# Assuming Linux
else
# xdg-open is not installed, we could be running in a non gui environment
if command -v xdg-open >/dev/null 2>&1; then
ask_open_browser
xdg-open "http://localhost:$port"
else
echo "✅ Setup completed. Your project is available at http://localhost:$port"
fi
fi
+6 -16
View File
@@ -1,13 +1,12 @@
ARG POSTGRES_VERSION=15
ARG SPILO_VERSION=3.2-p1
ARG PG_GRAPHQL_VERSION=1.5.6
ARG WRAPPERS_VERSION=0.2.0
# Build the mysql_fdw extension
FROM debian:bookworm as build-mysql_fdw
FROM debian:bookworm AS build-mysql_fdw
ARG POSTGRES_VERSION
ENV DEBIAN_FRONTEND noninteractive
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && \
apt install -y \
build-essential \
@@ -18,14 +17,14 @@ RUN apt update && \
# Install mysql_fdw
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
WORKDIR mysql_fdw
WORKDIR /mysql_fdw
RUN make USE_PGXS=1
# Build libssl for wrappers
FROM ubuntu:22.04 as build-libssl
FROM ubuntu:22.04 AS build-libssl
ENV DEBIAN_FRONTEND noninteractive
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && \
apt install -y \
build-essential \
@@ -38,10 +37,9 @@ WORKDIR /build/openssl
RUN ./config && make && make install
# Extend the Spilo image with the pg_graphql and mysql_fdw extensions
# Extend the Spilo image with the mysql_fdw extensions
FROM ghcr.io/zalando/spilo-${POSTGRES_VERSION}:${SPILO_VERSION}
ARG POSTGRES_VERSION
ARG PG_GRAPHQL_VERSION
ARG WRAPPERS_VERSION
ARG TARGETARCH
@@ -63,14 +61,6 @@ RUN curl -L "https://github.com/supabase/wrappers/releases/download/v${WRAPPERS_
COPY --from=build-libssl /usr/local/lib/libssl* /usr/local/lib/libcrypto* /usr/lib/
COPY --from=build-libssl /usr/local/lib/engines-1.1 /usr/lib/engines-1.1
# Copy pg_graphql
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql--${PG_GRAPHQL_VERSION}.sql \
/usr/share/postgresql/${POSTGRES_VERSION}/extension
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.control \
/usr/share/postgresql/${POSTGRES_VERSION}/extension
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.so \
/usr/lib/postgresql/${POSTGRES_VERSION}/lib/pg_graphql.so
# Copy mysql_fdw
COPY --from=build-mysql_fdw /mysql_fdw/mysql_fdw.so \
/usr/lib/postgresql/${POSTGRES_VERSION}/lib/mysql_fdw.so
-54
View File
@@ -1,54 +0,0 @@
ARG IMAGE_TAG='15.5.0-debian-11-r15'
FROM bitnami/postgresql:${IMAGE_TAG}
ARG PG_MAIN_VERSION=15
ARG PG_GRAPHQL_VERSION=1.5.6
ARG WRAPPERS_VERSION=0.2.0
ARG TARGETARCH
USER root
RUN set -eux; \
ARCH="$(dpkg --print-architecture)"; \
case "${ARCH}" in \
aarch64|arm64) \
TARGETARCH='arm64'; \
;; \
amd64|x86_64) \
TARGETARCH='amd64'; \
;; \
*) \
echo "Unsupported arch: ${ARCH}"; \
exit 1; \
;; \
esac;
RUN apt update && apt install build-essential git curl default-libmysqlclient-dev -y
# Install precompiled pg_graphql extensions
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql--${PG_GRAPHQL_VERSION}.sql \
/opt/bitnami/postgresql/share/extension/
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.control \
/opt/bitnami/postgresql/share/extension/
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.so \
/opt/bitnami/postgresql/lib/
# Install precompiled supabase wrappers extensions
RUN curl -L "https://github.com/supabase/wrappers/releases/download/v${WRAPPERS_VERSION}/wrappers-v${WRAPPERS_VERSION}-pg${PG_MAIN_VERSION}-${TARGETARCH}-linux-gnu.deb" -o wrappers.deb
RUN dpkg --install wrappers.deb
RUN cp /usr/share/postgresql/${PG_MAIN_VERSION}/extension/wrappers* /opt/bitnami/postgresql/share/extension/
RUN cp /usr/lib/postgresql/${PG_MAIN_VERSION}/lib/wrappers* /opt/bitnami/postgresql/lib/
RUN export PATH=/usr/local/pgsql/bin/:$PATH
RUN export PATH=/usr/local/mysql/bin/:$PATH
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
WORKDIR mysql_fdw
RUN make USE_PGXS=1
RUN make USE_PGXS=1 install
COPY ./packages/twenty-docker/twenty-postgres/init.sql /docker-entrypoint-initdb.d/
USER 1001
ENTRYPOINT ["/opt/bitnami/scripts/postgresql/entrypoint.sh"]
CMD ["/opt/bitnami/scripts/postgresql/run.sh"]
-4
View File
@@ -1,4 +0,0 @@
CREATE DATABASE "default";
CREATE DATABASE "test";
CREATE USER twenty PASSWORD 'twenty';
ALTER ROLE twenty superuser;
+2 -1
View File
@@ -52,9 +52,10 @@ RUN apk add --no-cache curl jq
RUN npm install -g tsx
RUN apk add --no-cache postgresql-client
COPY ./packages/twenty-docker/twenty/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
WORKDIR /app/packages/twenty-server
ARG REACT_APP_SERVER_BASE_URL
+9
View File
@@ -1,9 +1,18 @@
#!/bin/sh
set -e
# Check if the initialization has already been done and that we enabled automatic migration
if [ "${ENABLE_DB_MIGRATIONS}" = "true" ] && [ ! -f /app/docker-data/db_status ]; then
echo "Running database setup and migrations..."
# Creating the database if it doesn't exist
PGUSER=$(echo $PG_DATABASE_URL | awk -F '//' '{print $2}' | awk -F ':' '{print $1}')
PGPASS=$(echo $PG_DATABASE_URL | awk -F ':' '{print $3}' | awk -F '@' '{print $1}')
PGHOST=$(echo $PG_DATABASE_URL | awk -F '@' '{print $2}' | awk -F ':' '{print $1}')
PGPORT=$(echo $PG_DATABASE_URL | awk -F ':' '{print $4}' | awk -F '/' '{print $1}')
PGPASSWORD=${PGPASS} psql -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} -d postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'default'" | grep -q 1 || \
PGPASSWORD=${PGPASS} psql -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} -d postgres -c "CREATE DATABASE \"default\""
# Run setup and migration scripts
NODE_OPTIONS="--max-old-space-size=1500" tsx ./scripts/setup-db.ts
yarn database:migrate:prod