twenty and dify
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
TAG=latest
|
||||
|
||||
# POSTGRES_ADMIN_PASSWORD=replace_me_with_a_strong_password
|
||||
|
||||
PG_DATABASE_HOST=db:5432
|
||||
|
||||
SERVER_URL=http://localhost:3000
|
||||
# Uncoment if you are serving your front on another server than the API (eg. bucket)
|
||||
# FRONT_BASE_URL=http://localhost:3000
|
||||
|
||||
# Use openssl rand -base64 32 for each secret
|
||||
# ACCESS_TOKEN_SECRET=replace_me_with_a_random_string_access
|
||||
# LOGIN_TOKEN_SECRET=replace_me_with_a_random_string_login
|
||||
# REFRESH_TOKEN_SECRET=replace_me_with_a_random_string_refresh
|
||||
# FILE_TOKEN_SECRET=replace_me_with_a_random_string_refresh
|
||||
|
||||
SIGN_IN_PREFILLED=true
|
||||
|
||||
STORAGE_TYPE=local
|
||||
|
||||
# STORAGE_S3_REGION=eu-west3
|
||||
# STORAGE_S3_NAME=my-bucket
|
||||
# STORAGE_S3_ENDPOINT=
|
||||
|
||||
MESSAGE_QUEUE_TYPE=pg-boss
|
||||
@@ -0,0 +1,50 @@
|
||||
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
|
||||
|
||||
prod-website-build:
|
||||
@cd ../.. && docker build -f ./packages/twenty-docker/twenty-website/Dockerfile --tag twenty-website . && cd -
|
||||
|
||||
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 -
|
||||
@@ -0,0 +1,93 @@
|
||||
version: "3.9"
|
||||
name: twenty
|
||||
|
||||
services:
|
||||
change-vol-ownership:
|
||||
image: ubuntu
|
||||
user: root
|
||||
volumes:
|
||||
- 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"
|
||||
|
||||
server:
|
||||
image: twentycrm/twenty:${TAG}
|
||||
volumes:
|
||||
- server-local-data:/app/packages/twenty-server/${STORAGE_LOCAL_PATH:-.local-storage}
|
||||
- docker-data:/app/docker-data
|
||||
environment:
|
||||
PORT: 3000
|
||||
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
|
||||
SERVER_URL: ${SERVER_URL}
|
||||
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
|
||||
MESSAGE_QUEUE_TYPE: ${MESSAGE_QUEUE_TYPE}
|
||||
|
||||
ENABLE_DB_MIGRATIONS: "true"
|
||||
|
||||
SIGN_IN_PREFILLED: ${SIGN_IN_PREFILLED}
|
||||
STORAGE_TYPE: ${STORAGE_TYPE}
|
||||
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}
|
||||
FILE_TOKEN_SECRET: ${FILE_TOKEN_SECRET}
|
||||
depends_on:
|
||||
change-vol-ownership:
|
||||
condition: service_completed_successfully
|
||||
db:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: curl --fail http://localhost:3000/healthz
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
restart: always
|
||||
|
||||
worker:
|
||||
image: twentycrm/twenty:${TAG}
|
||||
command: ["yarn", "worker:prod"]
|
||||
environment:
|
||||
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
|
||||
SERVER_URL: ${SERVER_URL}
|
||||
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
|
||||
MESSAGE_QUEUE_TYPE: ${MESSAGE_QUEUE_TYPE}
|
||||
|
||||
ENABLE_DB_MIGRATIONS: "false" # it already runs on the server
|
||||
|
||||
STORAGE_TYPE: ${STORAGE_TYPE}
|
||||
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}
|
||||
FILE_TOKEN_SECRET: ${FILE_TOKEN_SECRET}
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
server:
|
||||
condition: service_healthy
|
||||
restart: always
|
||||
|
||||
db:
|
||||
image: twentycrm/twenty-postgres:${TAG}
|
||||
volumes:
|
||||
- db-data:/bitnami/postgresql
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${POSTGRES_ADMIN_PASSWORD}
|
||||
healthcheck:
|
||||
test: pg_isready -U twenty -d default
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
docker-data:
|
||||
db-data:
|
||||
server-local-data:
|
||||
@@ -0,0 +1,113 @@
|
||||
# README
|
||||
|
||||
## Overview
|
||||
|
||||
This repository contains Kubernetes manifests and Terraform files to help you deploy and manage the TwentyCRM application. The files are located in the `packages/twenty-docker/k8s` directory.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before using these files, ensure you have the following installed and configured on your system:
|
||||
|
||||
- Kubernetes cluster (e.g., Minikube, EKS, GKE)
|
||||
- kubectl
|
||||
- Terraform
|
||||
- Docker
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
### Step 1: Clone the Repository
|
||||
|
||||
Clone the repository to your local machine:
|
||||
|
||||
``` bash
|
||||
git clone https://github.com/twentyhq/twenty.git
|
||||
cd twentycrm/packages/twenty-docker/k8s
|
||||
```
|
||||
|
||||
### Step 2: Customize the Manifests and Terraform Files
|
||||
|
||||
**Important:** These files require customization for your specific implementation. Update the placeholders and configurations according to your environment and requirements.
|
||||
|
||||
### Step 3: Deploy with Terraform
|
||||
|
||||
1. Navigate to the Terraform directory:
|
||||
|
||||
```bash
|
||||
cd terraform
|
||||
```
|
||||
|
||||
2. Initialize Terraform:
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
```
|
||||
|
||||
3. Plan the deployment:
|
||||
|
||||
```bash
|
||||
terraform plan
|
||||
```
|
||||
|
||||
4. Apply the deployment:
|
||||
|
||||
```bash
|
||||
terraform apply
|
||||
```
|
||||
|
||||
## OR
|
||||
|
||||
### Step 3: Deploy with Kubernetes Manifests
|
||||
|
||||
1. Navigate to the Kubernetes manifests directory:
|
||||
|
||||
```bash
|
||||
cd ../k8s
|
||||
```
|
||||
|
||||
2. Create Server Secret
|
||||
|
||||
``` bash
|
||||
kubectl create secret generic -n twentycrm tokens --from-literal accessToken=changeme --from-literal loginToken="changeme" --from-literal refreshToken="changeme" --from-literal fileToken="changeme"
|
||||
```
|
||||
|
||||
3. Apply the manifests:
|
||||
|
||||
```bash
|
||||
kubectl apply -f .
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
### Kubernetes Manifests
|
||||
|
||||
- **Namespace:** Update the `namespace` in the manifests as needed.
|
||||
- **Resource Limits:** Adjust the resource limits and requests according to your application's requirements.
|
||||
- **Environment Variables:** Configure server tokens in the `Secret` command above.
|
||||
|
||||
### Terraform Files
|
||||
|
||||
- **Variables:** Update the variables in the `variables.tf` file to match your environment.
|
||||
- **Locals:** Update the locals in the `main.tf` file to match your environment.
|
||||
- **Providers:** Ensure the provider configurations (e.g., AWS, GCP) are correct for your setup.
|
||||
- **Resources:** Modify the resource definitions as needed to fit your infrastructure.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
- **Connectivity:** Ensure your Kubernetes cluster is accessible and configured correctly.
|
||||
- **Permissions:** Verify that you have the necessary permissions to deploy resources in your cloud provider.
|
||||
- **Resource Limits:** Adjust resource limits if you encounter issues related to insufficient resources.
|
||||
|
||||
### Logs and Debugging
|
||||
|
||||
- Use `kubectl logs` to check the logs of your Kubernetes pods.
|
||||
- Use `terraform show` and `terraform state` to inspect your Terraform state and configurations.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This setup provides a basic structure for deploying the TwentyCRM application using Kubernetes and Terraform. Ensure you thoroughly customize the manifests and Terraform files to suit your specific needs. For any issues or questions, please refer to the official documentation of Kubernetes and Terraform or seek support from your cloud provider.
|
||||
|
||||
---
|
||||
|
||||
Feel free to contribute and improve this repository by submitting pull requests or opening issues. Happy deploying!
|
||||
@@ -0,0 +1,54 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: twentycrm-db
|
||||
name: twentycrm-db
|
||||
namespace: twentycrm
|
||||
spec:
|
||||
progressDeadlineSeconds: 600
|
||||
replicas: 1
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 1
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: twentycrm-db
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: twentycrm-db
|
||||
spec:
|
||||
volumes:
|
||||
- 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
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
@@ -0,0 +1,82 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: twentycrm-server
|
||||
name: twentycrm-server
|
||||
namespace: twentycrm
|
||||
spec:
|
||||
progressDeadlineSeconds: 600
|
||||
replicas: 1
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 1
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: twentycrm-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: twentycrm-server
|
||||
spec:
|
||||
volumes:
|
||||
- name: twentycrm-server-data
|
||||
persistentVolumeClaim:
|
||||
claimName: twentycrm-server-pvc
|
||||
containers:
|
||||
- env:
|
||||
- name: PORT
|
||||
value: 3000
|
||||
- name: SERVER_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: 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/.local-storage
|
||||
name: twentycrm-server-data
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
@@ -0,0 +1,24 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: twentycrm
|
||||
namespace: twentycrm
|
||||
annotations:
|
||||
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"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- 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-db-pv
|
||||
spec:
|
||||
storageClassName: default
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: twentycrm-server-pv
|
||||
namespace: twentycrm
|
||||
spec:
|
||||
storageClassName: default
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: twentycrm-db-pvc
|
||||
namespace: twentycrm
|
||||
spec:
|
||||
storageClassName: default
|
||||
volumeName: twentycrm-db-pv
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: twentycrm-server-pvc
|
||||
namespace: twentycrm
|
||||
spec:
|
||||
storageClassName: default
|
||||
volumeName: twentycrm-server-pv
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: twentycrm-db
|
||||
namespace: twentycrm
|
||||
spec:
|
||||
internalTrafficPolicy: Cluster
|
||||
ports:
|
||||
- port: 5432
|
||||
protocol: TCP
|
||||
targetPort: 5432
|
||||
selector:
|
||||
app: twentycrm-db
|
||||
sessionAffinity: ClientIP
|
||||
sessionAffinityConfig:
|
||||
clientIP:
|
||||
timeoutSeconds: 10800
|
||||
type: ClusterIP
|
||||
@@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: twentycrm-server
|
||||
namespace: twentycrm
|
||||
spec:
|
||||
internalTrafficPolicy: Cluster
|
||||
ports:
|
||||
- name: http-tcp
|
||||
port: 3000
|
||||
protocol: TCP
|
||||
targetPort: 3000
|
||||
selector:
|
||||
app: twentycrm-server
|
||||
sessionAffinity: ClientIP
|
||||
sessionAffinityConfig:
|
||||
clientIP:
|
||||
timeoutSeconds: 10800
|
||||
type: ClusterIP
|
||||
@@ -0,0 +1,90 @@
|
||||
resource "kubernetes_deployment" "twentycrm_db" {
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-db"
|
||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||
labels = {
|
||||
app = "${local.twentycrm_app_name}-db"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 1
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "${local.twentycrm_app_name}-db"
|
||||
}
|
||||
}
|
||||
|
||||
strategy {
|
||||
type = "RollingUpdate"
|
||||
rolling_update {
|
||||
max_surge = "1"
|
||||
max_unavailable = "1"
|
||||
}
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "${local.twentycrm_app_name}-db"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
# security_context {
|
||||
# fs_group = 0
|
||||
# }
|
||||
container {
|
||||
image = local.twentycrm_db_image
|
||||
name = local.twentycrm_app_name
|
||||
stdin = true
|
||||
tty = true
|
||||
security_context {
|
||||
allow_privilege_escalation = true
|
||||
}
|
||||
|
||||
env {
|
||||
name = "POSTGRES_PASSWORD"
|
||||
value = "twenty"
|
||||
}
|
||||
env {
|
||||
name = "BITNAMI_DEBUG"
|
||||
value = true
|
||||
}
|
||||
|
||||
port {
|
||||
container_port = 5432
|
||||
protocol = "TCP"
|
||||
}
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
cpu = "250m"
|
||||
memory = "256Mi"
|
||||
}
|
||||
limits = {
|
||||
cpu = "1000m"
|
||||
memory = "1024Mi"
|
||||
}
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "nfs-twentycrm-db-data"
|
||||
mount_path = "/bitnami/postgresql"
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "nfs-twentycrm-db-data"
|
||||
|
||||
persistent_volume_claim {
|
||||
claim_name = "nfs-twentycrm-db-data-pvc"
|
||||
}
|
||||
}
|
||||
|
||||
dns_policy = "ClusterFirst"
|
||||
restart_policy = "Always"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
resource "kubernetes_deployment" "twentycrm_server" {
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-server"
|
||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||
labels = {
|
||||
app = "${local.twentycrm_app_name}-server"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 1
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "${local.twentycrm_app_name}-server"
|
||||
}
|
||||
}
|
||||
|
||||
strategy {
|
||||
type = "RollingUpdate"
|
||||
rolling_update {
|
||||
max_surge = "1"
|
||||
max_unavailable = "1"
|
||||
}
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "${local.twentycrm_app_name}-server"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
container {
|
||||
image = local.twentycrm_server_image
|
||||
name = local.twentycrm_app_name
|
||||
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 = "SERVER_URL"
|
||||
value = "https://crm.example.com:443"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "FRONT_BASE_URL"
|
||||
value = "https://crm.example.com:443"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "BACKEND_SERVER_URL"
|
||||
value = "https://crm.example.com:443"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "PG_DATABASE_URL"
|
||||
value = "postgres://twenty:twenty@twentycrm-db.twentycrm.svc.cluster.local/default"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "ENABLE_DB_MIGRATIONS"
|
||||
value = "true"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "SIGN_IN_PREFILLED"
|
||||
value = "true"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "STORAGE_TYPE"
|
||||
value = "local"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "ACCESS_TOKEN_SECRET"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = "tokens"
|
||||
key = "accessToken"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
cpu = "250m"
|
||||
memory = "256Mi"
|
||||
}
|
||||
limits = {
|
||||
cpu = "1000m"
|
||||
memory = "1024Mi"
|
||||
}
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "nfs-twentycrm-server-data"
|
||||
mount_path = "/app/.local-storage"
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "nfs-twentycrm-server-data"
|
||||
|
||||
persistent_volume_claim {
|
||||
claim_name = "nfs-twentycrm-server-data-pvc"
|
||||
}
|
||||
}
|
||||
|
||||
dns_policy = "ClusterFirst"
|
||||
restart_policy = "Always"
|
||||
}
|
||||
}
|
||||
}
|
||||
depends_on = [
|
||||
kubernetes_deployment.twentycrm_db,
|
||||
kubernetes_secret.twentycrm_tokens
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
resource "kubernetes_ingress" "twentycrm" {
|
||||
wait_for_load_balancer = true
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-ingress"
|
||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||
annotations = {
|
||||
"kubernetes.io/ingress.class" = "nginx"
|
||||
"nginx.ingress.kubernetes.io/configuration-snippet" = <<EOF
|
||||
more_set_headers "X-Forwarded-For $http_x_forwarded_for";
|
||||
EOF
|
||||
"nginx.ingress.kubernetes.io/force-ssl-redirect" = "false"
|
||||
"nginx.ingress.kubernetes.io/backend-protocol" = "HTTP"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
ingress_class_name = "nginx"
|
||||
rule {
|
||||
host = local.twentycrm_app_hostname
|
||||
http {
|
||||
path {
|
||||
path = "/*"
|
||||
backend {
|
||||
service_name = kubernetes_service.twentycrm_server.metadata.0.name
|
||||
service_port = kubernetes_service.twentycrm_server.spec.0.port.0.port
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#############
|
||||
# Providers #
|
||||
#############
|
||||
provider "kubernetes" {
|
||||
config_path = "~/.kube/config"
|
||||
}
|
||||
|
||||
#################
|
||||
# Global Locals #
|
||||
#################
|
||||
locals {
|
||||
twentycrm_app_name = "twentycrm"
|
||||
twentycrm_app_hostname = "crm.example.com"
|
||||
twentycrm_server_image = "twentycrm/twenty:v0.10.4"
|
||||
twentycrm_db_image = "twentycrm/twenty-postgres:v0.10.4"
|
||||
twentycrm_db_pv_path = "/path/to/mystorage"
|
||||
twentycrm_db_pv_capacity = "10Gi"
|
||||
twentycrm_db_pvc_requests = "10Gi"
|
||||
twentycrm_server_pv_path = "/path/to/mystorage"
|
||||
twentycrm_server_pv_capacity = "10Gi"
|
||||
twentycrm_server_pvc_requests = "10Gi"
|
||||
}
|
||||
|
||||
####################
|
||||
# Terraform Config #
|
||||
####################
|
||||
terraform {
|
||||
required_version = ">= 1.7.4"
|
||||
required_providers {
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = ">= 2.23.0"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
resource "kubernetes_namespace" "twentycrm" {
|
||||
metadata {
|
||||
annotations = {
|
||||
name = "twentycrm"
|
||||
}
|
||||
|
||||
name = "twentycrm"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
resource "kubernetes_persistent_volume" "db" {
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-db-pv"
|
||||
}
|
||||
spec {
|
||||
storage_class_name = "default"
|
||||
capacity = {
|
||||
storage = local.twentycrm_db_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 = local.twentycrm_db_pv_path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
resource "kubernetes_persistent_volume" "server" {
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-server-pv"
|
||||
}
|
||||
spec {
|
||||
storage_class_name = "default"
|
||||
capacity = {
|
||||
storage = local.twentycrm_server_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 = local.twentycrm_server_pv_path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
resource "kubernetes_persistent_volume_claim" "db" {
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-db-pvc"
|
||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||
}
|
||||
spec {
|
||||
access_modes = ["ReadWriteOnce"]
|
||||
resources {
|
||||
requests = {
|
||||
storage = local.twentycrm_db_pvc_requests
|
||||
}
|
||||
}
|
||||
volume_name = kubernetes_persistent_volume.db.metadata.0.name
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
resource "kubernetes_persistent_volume_claim" "server" {
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-server-pvc"
|
||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||
}
|
||||
spec {
|
||||
access_modes = ["ReadWriteOnce"]
|
||||
resources {
|
||||
requests = {
|
||||
storage = local.twentycrm_server_pvc_requests
|
||||
}
|
||||
}
|
||||
volume_name = kubernetes_persistent_volume.server.metadata.0.name
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
resource "kubernetes_secret" "twentycrm_tokens" {
|
||||
metadata {
|
||||
name = "tokens"
|
||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||
}
|
||||
|
||||
data = {
|
||||
accessToken = var.twentycrm_token_accessToken
|
||||
loginToken = var.twentycrm_token_loginToken
|
||||
refreshToken = var.twentycrm_token_refreshToken
|
||||
fileToken = var.twentycrm_token_fileToken
|
||||
}
|
||||
|
||||
# type = "kubernetes.io/basic-auth"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
resource "kubernetes_service" "twentycrm_db" {
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-db"
|
||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||
}
|
||||
spec {
|
||||
selector = {
|
||||
app = "${local.twentycrm_app_name}-db"
|
||||
}
|
||||
session_affinity = "ClientIP"
|
||||
port {
|
||||
port = 5432
|
||||
target_port = 5432
|
||||
}
|
||||
|
||||
type = "ClusterIP"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
resource "kubernetes_service" "twentycrm_server" {
|
||||
metadata {
|
||||
name = "${local.twentycrm_app_name}-server"
|
||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||
}
|
||||
spec {
|
||||
selector = {
|
||||
app = "${local.twentycrm_app_name}-server"
|
||||
}
|
||||
session_affinity = "ClientIP"
|
||||
port {
|
||||
name = "http-tcp"
|
||||
port = 3000
|
||||
target_port = 3000
|
||||
}
|
||||
|
||||
type = "ClusterIP"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
variable "twentycrm_token_accessToken" {
|
||||
type = string
|
||||
description = "TwentyCRM access Token"
|
||||
}
|
||||
|
||||
variable "twentycrm_token_loginToken" {
|
||||
type = string
|
||||
description = "TwentyCRM login Token"
|
||||
}
|
||||
|
||||
variable "twentycrm_token_refreshToken" {
|
||||
type = string
|
||||
description = "TwentyCRM refresh Token"
|
||||
}
|
||||
|
||||
variable "twentycrm_token_fileToken" {
|
||||
type = string
|
||||
description = "TwentyCRM file Token"
|
||||
}
|
||||
|
||||
variable "twentycrm_pgdb_admin_password" {
|
||||
type = string
|
||||
description = "TwentyCRM password for postgres database"
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
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
|
||||
ARG POSTGRES_VERSION
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt update && \
|
||||
apt install -y \
|
||||
build-essential \
|
||||
git \
|
||||
postgresql-server-dev-${POSTGRES_VERSION} \
|
||||
default-libmysqlclient-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install mysql_fdw
|
||||
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
|
||||
WORKDIR mysql_fdw
|
||||
RUN make USE_PGXS=1
|
||||
|
||||
|
||||
# Build libssl for wrappers
|
||||
FROM ubuntu:22.04 as build-libssl
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt update && \
|
||||
apt install -y \
|
||||
build-essential \
|
||||
git && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /build
|
||||
RUN git clone --branch OpenSSL_1_1_1-stable https://github.com/openssl/openssl.git
|
||||
WORKDIR /build/openssl
|
||||
RUN ./config && make && make install
|
||||
|
||||
|
||||
# Extend the Spilo image with the pg_graphql and mysql_fdw extensions
|
||||
FROM ghcr.io/zalando/spilo-${POSTGRES_VERSION}:${SPILO_VERSION}
|
||||
ARG POSTGRES_VERSION
|
||||
ARG PG_GRAPHQL_VERSION
|
||||
ARG WRAPPERS_VERSION
|
||||
ARG TARGETARCH
|
||||
|
||||
# Install precompiled supabase wrappers extensions
|
||||
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 default-libmysqlclient-dev -y && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -L "https://github.com/supabase/wrappers/releases/download/v${WRAPPERS_VERSION}/wrappers-v${WRAPPERS_VERSION}-pg${POSTGRES_VERSION}-${TARGETARCH}-linux-gnu.deb" -o wrappers.deb && \
|
||||
dpkg --install wrappers.deb && \
|
||||
rm wrappers.deb
|
||||
|
||||
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
|
||||
COPY --from=build-mysql_fdw /mysql_fdw/mysql_fdw*.sql /mysql_fdw/mysql_fdw.control /mysql_fdw/mysql_fdw_pushdown.config \
|
||||
/usr/share/postgresql/${POSTGRES_VERSION}/extension/
|
||||
@@ -0,0 +1,54 @@
|
||||
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"]
|
||||
@@ -0,0 +1,4 @@
|
||||
CREATE DATABASE "default";
|
||||
CREATE DATABASE "test";
|
||||
CREATE USER twenty PASSWORD 'twenty';
|
||||
ALTER ROLE twenty superuser;
|
||||
@@ -0,0 +1,29 @@
|
||||
FROM node:18.17.1-alpine as twenty-website-build
|
||||
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./package.json .
|
||||
COPY ./yarn.lock .
|
||||
COPY ./.yarnrc.yml .
|
||||
COPY ./.yarn/releases /app/.yarn/releases
|
||||
COPY ./tools/eslint-rules /app/tools/eslint-rules
|
||||
COPY ./packages/twenty-website/package.json /app/packages/twenty-website/package.json
|
||||
|
||||
RUN yarn
|
||||
|
||||
COPY ./packages/twenty-website /app/packages/twenty-website
|
||||
RUN npx nx build twenty-website
|
||||
|
||||
FROM node:18.17.1-alpine as twenty-website
|
||||
|
||||
WORKDIR /app/packages/twenty-website
|
||||
|
||||
COPY --from=twenty-website-build /app /app
|
||||
|
||||
WORKDIR /app/packages/twenty-website
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
|
||||
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the website."
|
||||
|
||||
CMD ["/bin/sh", "-c", "npx nx start"]
|
||||
@@ -0,0 +1,79 @@
|
||||
# Base image for common dependencies
|
||||
FROM node:18.17.1-alpine as common-deps
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy only the necessary files for dependency resolution
|
||||
COPY ./package.json ./yarn.lock ./.yarnrc.yml ./tsconfig.base.json ./nx.json /app/
|
||||
COPY ./.yarn/releases /app/.yarn/releases
|
||||
|
||||
COPY ./packages/twenty-emails/package.json /app/packages/twenty-emails/
|
||||
COPY ./packages/twenty-server/package.json /app/packages/twenty-server/
|
||||
COPY ./packages/twenty-server/patches /app/packages/twenty-server/patches
|
||||
COPY ./packages/twenty-ui/package.json /app/packages/twenty-ui/
|
||||
COPY ./packages/twenty-front/package.json /app/packages/twenty-front/
|
||||
|
||||
# Install all dependencies
|
||||
RUN yarn && yarn cache clean && npx nx reset
|
||||
|
||||
|
||||
# Build the back
|
||||
FROM common-deps as twenty-server-build
|
||||
|
||||
# Copy sourcecode after installing dependences to accelerate subsequents builds
|
||||
COPY ./packages/twenty-emails /app/packages/twenty-emails
|
||||
COPY ./packages/twenty-server /app/packages/twenty-server
|
||||
|
||||
RUN npx nx run twenty-server:build
|
||||
RUN mv /app/packages/twenty-server/dist /app/packages/twenty-server/build
|
||||
RUN npx nx run twenty-server:build:packageJson
|
||||
RUN mv /app/packages/twenty-server/dist/package.json /app/packages/twenty-server/package.json
|
||||
RUN rm -rf /app/packages/twenty-server/dist
|
||||
RUN mv /app/packages/twenty-server/build /app/packages/twenty-server/dist
|
||||
|
||||
RUN yarn workspaces focus --production twenty-emails twenty-server
|
||||
|
||||
|
||||
# Build the front
|
||||
FROM common-deps as twenty-front-build
|
||||
|
||||
ARG REACT_APP_SERVER_BASE_URL
|
||||
|
||||
COPY ./packages/twenty-front /app/packages/twenty-front
|
||||
COPY ./packages/twenty-ui /app/packages/twenty-ui
|
||||
RUN npx nx build twenty-front
|
||||
|
||||
|
||||
# Final stage: Run the application
|
||||
FROM node:18.17.1-alpine as twenty
|
||||
|
||||
# Used to run healthcheck in docker
|
||||
RUN apk add --no-cache curl jq
|
||||
|
||||
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
|
||||
ENV REACT_APP_SERVER_BASE_URL $REACT_APP_SERVER_BASE_URL
|
||||
ARG SENTRY_RELEASE
|
||||
ENV SENTRY_RELEASE $SENTRY_RELEASE
|
||||
|
||||
# Copy built applications from previous stages
|
||||
COPY --chown=1000 --from=twenty-server-build /app /app
|
||||
COPY --chown=1000 --from=twenty-server-build /app/packages/twenty-server /app/packages/twenty-server
|
||||
COPY --chown=1000 --from=twenty-front-build /app/packages/twenty-front/build /app/packages/twenty-server/dist/front
|
||||
|
||||
# Set metadata and labels
|
||||
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
|
||||
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the backend and frontend, ensuring it deploys faster and runs the same way regardless of the deployment environment."
|
||||
|
||||
RUN mkdir /app/.local-storage
|
||||
RUN chown -R 1000 /app
|
||||
|
||||
# Use non root user with uid 1000
|
||||
USER 1000
|
||||
|
||||
CMD ["node", "dist/src/main"]
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 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..."
|
||||
|
||||
# Run setup and migration scripts
|
||||
NODE_OPTIONS="--max-old-space-size=1500" npx ts-node ./scripts/setup-db.ts
|
||||
yarn database:migrate:prod
|
||||
|
||||
# Mark initialization as done
|
||||
echo "Successfuly migrated DB!"
|
||||
touch /app/docker-data/db_status
|
||||
fi
|
||||
|
||||
# Continue with the original Docker command
|
||||
exec "$@"
|
||||
Reference in New Issue
Block a user