├── .gitignore ├── LICENSE ├── README.md ├── assets ├── temporal-shell.png └── worker-logs.png ├── render.yaml └── temporal-cluster ├── elasticsearch ├── Dockerfile └── elasticsearch.yml ├── server ├── .bashrc ├── Dockerfile ├── LICENSE ├── auto-setup │ ├── Dockerfile │ └── auto-setup-override.sh ├── config_template.yaml ├── dynamicconfig.yaml └── dynamicconfig_es.yaml └── web └── Dockerfile /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022, Render Developers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Temporal 2 | 3 | This is a template for running a production-ready Temporal cluster on Render. The setup supports independent autoscaling for each Temporal service (frontend, matching, history, worker), has [advanced visibility](https://docs.temporal.io/docs/content/what-is-advanced-visibility/) backed by Elasticsearch, and includes an example Go app to trigger and run workflows. Create a new repo using this template, and then click the button below to try it out: 4 | 5 | [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/render-examples/temporal) 6 | 7 | For deploy instructions, see our [Temporal guide](https://render.com/docs/deploy-temporal). 8 | 9 | # Acknowledgements 10 | 11 | [auto-setup-override.sh](temporal-cluster/server/auto-setup/auto-setup-override.sh) is based on Temporal's [auto-setup.sh script](https://github.com/temporalio/temporal/blob/077d39c775/docker/auto-setup.sh), with some modifications made to better accommodate Render's architecture. 12 | -------------------------------------------------------------------------------- /assets/temporal-shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/render-examples/temporal/9594ec21757c9e5893eefa7527a5da1eecdb748b/assets/temporal-shell.png -------------------------------------------------------------------------------- /assets/worker-logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/render-examples/temporal/9594ec21757c9e5893eefa7527a5da1eecdb748b/assets/worker-logs.png -------------------------------------------------------------------------------- /render.yaml: -------------------------------------------------------------------------------- 1 | databases: 2 | - name: temporal-db 3 | databaseName: temporal 4 | user: temporal 5 | plan: basic-256mb 6 | diskSizeGB: 1 7 | region: oregon 8 | 9 | envVarGroups: 10 | - name: temporal-shared 11 | envVars: 12 | - key: DYNAMIC_CONFIG_FILE_PATH 13 | value: /etc/temporal/dynamicconfig_es.yaml 14 | - key: ENABLE_ES 15 | value: true 16 | - key: ES_VERSION 17 | value: v7 18 | - key: ES_USER 19 | value: elastic 20 | - key: DB 21 | value: postgresql 22 | 23 | services: 24 | - type: pserv 25 | name: temporal-elasticsearch 26 | autoDeploy: false 27 | plan: Starter 28 | region: oregon 29 | env: docker 30 | dockerfilePath: ./temporal-cluster/elasticsearch/Dockerfile 31 | disk: 32 | name: esdata 33 | mountPath: /usr/share/elasticsearch/data 34 | sizeGB: 10 35 | envVars: 36 | - key: PORT 37 | value: 9200 38 | - key: ES_JAVA_OPTS 39 | value: "-Xms100m -Xmx100m" 40 | - key: xpack.security.enabled 41 | value: true 42 | - key: ELASTIC_PASSWORD 43 | generateValue: true 44 | - key: cluster.routing.allocation.disk.threshold_enabled 45 | value: true 46 | - key: cluster.routing.allocation.disk.watermark.low 47 | value: 512mb 48 | - key: cluster.routing.allocation.disk.watermark.high 49 | value: 256mb 50 | - key: cluster.routing.allocation.disk.watermark.flood_stage 51 | value: 128mb 52 | - key: discovery.type 53 | value: single-node 54 | - type: pserv 55 | name: temporal-frontend 56 | autoDeploy: false 57 | plan: Starter 58 | region: oregon 59 | env: docker 60 | dockerfilePath: ./temporal-cluster/server/auto-setup/Dockerfile 61 | scaling: 62 | minInstances: 1 63 | maxInstances: 3 64 | targetMemoryPercent: 80 65 | targetCPUPercent: 80 66 | envVars: 67 | - fromGroup: temporal-shared 68 | - key: SERVICES 69 | value: frontend 70 | - key: SKIP_POSTGRES_DB_CREATION 71 | value: true 72 | - key: SKIP_VISIBILITY_DB_SETUP 73 | value: true 74 | - key: ES_SEEDS 75 | fromService: 76 | name: temporal-elasticsearch 77 | type: pserv 78 | property: host 79 | - key: ES_PWD 80 | fromService: 81 | name: temporal-elasticsearch 82 | type: pserv 83 | envVarKey: ELASTIC_PASSWORD 84 | - key: DBNAME 85 | fromDatabase: 86 | name: temporal-db 87 | property: database 88 | - key: DB_PORT 89 | fromDatabase: 90 | name: temporal-db 91 | property: port 92 | - key: POSTGRES_USER 93 | fromDatabase: 94 | name: temporal-db 95 | property: user 96 | - key: POSTGRES_PWD 97 | fromDatabase: 98 | name: temporal-db 99 | property: password 100 | - key: POSTGRES_SEEDS 101 | fromDatabase: 102 | name: temporal-db 103 | property: host 104 | - type: pserv 105 | name: temporal-history 106 | autoDeploy: false 107 | plan: Starter 108 | region: oregon 109 | env: docker 110 | dockerfilePath: ./temporal-cluster/server/Dockerfile 111 | scaling: 112 | minInstances: 1 113 | maxInstances: 3 114 | targetMemoryPercent: 80 115 | targetCPUPercent: 80 116 | envVars: 117 | - fromGroup: temporal-shared 118 | - key: SERVICES 119 | value: history 120 | - key: TEMPORAL_FRONTEND_HOST 121 | fromService: 122 | name: temporal-frontend 123 | type: pserv 124 | property: host 125 | - key: ES_SEEDS 126 | fromService: 127 | name: temporal-elasticsearch 128 | type: pserv 129 | property: host 130 | - key: ES_PWD 131 | fromService: 132 | name: temporal-elasticsearch 133 | type: pserv 134 | envVarKey: ELASTIC_PASSWORD 135 | - key: DBNAME 136 | fromDatabase: 137 | name: temporal-db 138 | property: database 139 | - key: POSTGRES_USER 140 | fromDatabase: 141 | name: temporal-db 142 | property: user 143 | - key: POSTGRES_PWD 144 | fromDatabase: 145 | name: temporal-db 146 | property: password 147 | - key: POSTGRES_SEEDS 148 | fromDatabase: 149 | name: temporal-db 150 | property: host 151 | - type: pserv 152 | name: temporal-matching 153 | autoDeploy: false 154 | plan: Starter 155 | region: oregon 156 | env: docker 157 | dockerfilePath: ./temporal-cluster/server/Dockerfile 158 | scaling: 159 | minInstances: 1 160 | maxInstances: 3 161 | targetMemoryPercent: 80 162 | targetCPUPercent: 80 163 | envVars: 164 | - fromGroup: temporal-shared 165 | - key: SERVICES 166 | value: matching 167 | - key: TEMPORAL_FRONTEND_HOST 168 | fromService: 169 | name: temporal-frontend 170 | type: pserv 171 | property: host 172 | - key: ES_SEEDS 173 | fromService: 174 | name: temporal-elasticsearch 175 | type: pserv 176 | property: host 177 | - key: ES_PWD 178 | fromService: 179 | name: temporal-elasticsearch 180 | type: pserv 181 | envVarKey: ELASTIC_PASSWORD 182 | - key: DBNAME 183 | fromDatabase: 184 | name: temporal-db 185 | property: database 186 | - key: POSTGRES_USER 187 | fromDatabase: 188 | name: temporal-db 189 | property: user 190 | - key: POSTGRES_PWD 191 | fromDatabase: 192 | name: temporal-db 193 | property: password 194 | - key: POSTGRES_SEEDS 195 | fromDatabase: 196 | name: temporal-db 197 | property: host 198 | - type: pserv 199 | autoDeploy: false 200 | name: temporal-worker 201 | plan: Starter 202 | region: oregon 203 | env: docker 204 | dockerfilePath: ./temporal-cluster/server/Dockerfile 205 | scaling: 206 | minInstances: 1 207 | maxInstances: 3 208 | targetMemoryPercent: 80 209 | targetCPUPercent: 80 210 | envVars: 211 | - fromGroup: temporal-shared 212 | # The worker service needs to wait for the history service to be up first, 213 | # otherwise it will fail with "error starting scanner". 214 | - key: DEPENDS_ON_HISTORY 215 | fromService: 216 | name: temporal-history 217 | type: pserv 218 | property: host 219 | - key: SERVICES 220 | value: worker 221 | - key: TEMPORAL_FRONTEND_HOST 222 | fromService: 223 | name: temporal-frontend 224 | type: pserv 225 | property: host 226 | - key: ES_SEEDS 227 | fromService: 228 | name: temporal-elasticsearch 229 | type: pserv 230 | property: host 231 | - key: ES_PWD 232 | fromService: 233 | name: temporal-elasticsearch 234 | type: pserv 235 | envVarKey: ELASTIC_PASSWORD 236 | - key: DBNAME 237 | fromDatabase: 238 | name: temporal-db 239 | property: database 240 | - key: POSTGRES_USER 241 | fromDatabase: 242 | name: temporal-db 243 | property: user 244 | - key: POSTGRES_PWD 245 | fromDatabase: 246 | name: temporal-db 247 | property: password 248 | - key: POSTGRES_SEEDS 249 | fromDatabase: 250 | name: temporal-db 251 | property: host 252 | - type: pserv 253 | name: temporal-ui 254 | autoDeploy: false 255 | plan: Starter 256 | region: oregon 257 | env: docker 258 | dockerfilePath: ./temporal-cluster/web/Dockerfile 259 | envVars: 260 | - key: PORT 261 | value: 8088 262 | - key: TEMPORAL_PERMIT_WRITE_API 263 | value: true 264 | - key: TEMPORAL_GRPC_HOST 265 | fromService: 266 | name: temporal-frontend 267 | type: pserv 268 | property: host 269 | # For secure external access to the Temporal Workflow Service via REST 270 | # See https://github.com/render-examples/temporal-rest-proxy 271 | # - type: web 272 | # name: rest-to-grpc-proxy 273 | # repo: https://github.com/render-examples/temporal-rest-proxy 274 | # autoDeploy: false 275 | # plan: Starter 276 | # region: oregon 277 | # env: go 278 | # buildCommand: go build rest-proxy/main.go 279 | # startCommand: ./main 280 | # envVars: 281 | # - key: TEMPORAL_CLUSTER_HOST 282 | # fromService: 283 | # name: temporal-frontend 284 | # type: pserv 285 | # property: host 286 | # - key: AUTH_TOKEN 287 | # sync: false 288 | - type: web 289 | repo: https://github.com/render-examples/sample-temporal-app 290 | name: app-workflow-trigger 291 | plan: Starter 292 | region: oregon 293 | env: go 294 | buildCommand: go build start/main.go 295 | startCommand: ./main 296 | autoDeploy: false 297 | envVars: 298 | - key: TEMPORAL_CLUSTER_HOST 299 | fromService: 300 | name: temporal-frontend 301 | type: pserv 302 | property: host 303 | - type: worker 304 | repo: https://github.com/render-examples/sample-temporal-app 305 | name: app-worker 306 | plan: Starter 307 | region: oregon 308 | env: go 309 | buildCommand: go build worker/main.go 310 | startCommand: ./main 311 | autoDeploy: false 312 | envVars: 313 | - key: TEMPORAL_CLUSTER_HOST 314 | fromService: 315 | name: temporal-frontend 316 | type: pserv 317 | property: host 318 | -------------------------------------------------------------------------------- /temporal-cluster/elasticsearch/Dockerfile: -------------------------------------------------------------------------------- 1 | # The official Elasticsearch Docker image 2 | FROM docker.elastic.co/elasticsearch/elasticsearch:7.16.2 3 | 4 | # Copy our config file over 5 | COPY --chown=1000:0 temporal-cluster/elasticsearch/elasticsearch.yml /usr/share/elasticsearch/config/elasticsearch.yml 6 | 7 | # Allow Elasticsearch to create `elasticsearch.keystore` 8 | # to circumvent https://github.com/elastic/ansible-elasticsearch/issues/430 9 | RUN chmod g+ws /usr/share/elasticsearch/config 10 | 11 | USER 1000:0 12 | -------------------------------------------------------------------------------- /temporal-cluster/elasticsearch/elasticsearch.yml: -------------------------------------------------------------------------------- 1 | cluster.name: "elastic" 2 | # bind to all network interfaces 3 | network.host: 0.0.0.0 4 | -------------------------------------------------------------------------------- /temporal-cluster/server/.bashrc: -------------------------------------------------------------------------------- 1 | export TEMPORAL_CLI_ADDRESS=${TEMPORAL_FRONTEND_HOST:-$RENDER_SERVICE_NAME}:7233 2 | -------------------------------------------------------------------------------- /temporal-cluster/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM temporalio/server:1.14.3 2 | 3 | COPY temporal-cluster/server/dynamicconfig.yaml /etc/temporal/dynamicconfig.yaml 4 | COPY temporal-cluster/server/dynamicconfig_es.yaml /etc/temporal/dynamicconfig_es.yaml 5 | COPY temporal-cluster/server/config_template.yaml /etc/temporal/config/config_template.yaml 6 | COPY temporal-cluster/server/.bashrc /home/temporal/.bashrc 7 | 8 | ENTRYPOINT ["bash", "-c", "PUBLIC_FRONTEND_ADDRESS=$TEMPORAL_FRONTEND_HOST:7233 /etc/temporal/entrypoint.sh"] 9 | -------------------------------------------------------------------------------- /temporal-cluster/server/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 temporal.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /temporal-cluster/server/auto-setup/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM temporalio/auto-setup:1.14.3 2 | 3 | COPY temporal-cluster/server/dynamicconfig.yaml /etc/temporal/dynamicconfig.yaml 4 | COPY temporal-cluster/server/dynamicconfig_es.yaml /etc/temporal/dynamicconfig_es.yaml 5 | COPY temporal-cluster/server/config_template.yaml /etc/temporal/config/config_template.yaml 6 | COPY temporal-cluster/server/auto-setup/auto-setup-override.sh /etc/temporal/auto-setup.sh 7 | COPY temporal-cluster/server/.bashrc /home/temporal/.bashrc 8 | -------------------------------------------------------------------------------- /temporal-cluster/server/auto-setup/auto-setup-override.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux -o pipefail 4 | 5 | # === Auto setup defaults === 6 | 7 | DB="${DB:-cassandra}" 8 | SKIP_SCHEMA_SETUP="${SKIP_SCHEMA_SETUP:-false}" 9 | 10 | # Cassandra 11 | KEYSPACE="${KEYSPACE:-temporal}" 12 | VISIBILITY_KEYSPACE="${VISIBILITY_KEYSPACE:-temporal_visibility}" 13 | 14 | CASSANDRA_SEEDS="${CASSANDRA_SEEDS:-}" 15 | CASSANDRA_PORT="${CASSANDRA_PORT:-9042}" 16 | CASSANDRA_USER="${CASSANDRA_USER:-}" 17 | CASSANDRA_PASSWORD="${CASSANDRA_PASSWORD:-}" 18 | CASSANDRA_TLS_ENABLED="${CASSANDRA_TLS_ENABLED:-}" 19 | CASSANDRA_CERT="${CASSANDRA_CERT:-}" 20 | CASSANDRA_CERT_KEY="${CASSANDRA_CERT_KEY:-}" 21 | CASSANDRA_CA="${CASSANDRA_CA:-}" 22 | CASSANDRA_REPLICATION_FACTOR="${CASSANDRA_REPLICATION_FACTOR:-1}" 23 | 24 | # MySQL/PostgreSQL 25 | DBNAME="${DBNAME:-temporal}" 26 | VISIBILITY_DBNAME="${VISIBILITY_DBNAME:-temporal_visibility}" 27 | DB_PORT="${DB_PORT:-3306}" 28 | 29 | MYSQL_SEEDS="${MYSQL_SEEDS:-}" 30 | MYSQL_USER="${MYSQL_USER:-}" 31 | MYSQL_PWD="${MYSQL_PWD:-}" 32 | MYSQL_TX_ISOLATION_COMPAT="${MYSQL_TX_ISOLATION_COMPAT:-false}" 33 | 34 | POSTGRES_SEEDS="${POSTGRES_SEEDS:-}" 35 | POSTGRES_USER="${POSTGRES_USER:-}" 36 | POSTGRES_PWD="${POSTGRES_PWD:-}" 37 | # Don't create the DB instance 38 | SKIP_POSTGRES_DB_CREATION="${SKIP_POSTGRES_DB_CREATION:-false}" 39 | 40 | # Elasticsearch 41 | ENABLE_ES="${ENABLE_ES:-false}" 42 | ES_SCHEME="${ES_SCHEME:-http}" 43 | ES_SEEDS="${ES_SEEDS:-}" 44 | ES_PORT="${ES_PORT:-9200}" 45 | ES_USER="${ES_USER:-}" 46 | ES_PWD="${ES_PWD:-}" 47 | ES_VERSION="${ES_VERSION:-v7}" 48 | ES_VIS_INDEX="${ES_VIS_INDEX:-temporal_visibility_v1_dev}" 49 | ES_SCHEMA_SETUP_TIMEOUT_IN_SECONDS="${ES_SCHEMA_SETUP_TIMEOUT_IN_SECONDS:-0}" 50 | 51 | # Render-specific Server setup 52 | TEMPORAL_CLI_ADDRESS="$RENDER_SERVICE_NAME:${FRONTEND_GRPC_PORT:-7233}" 53 | 54 | SKIP_DEFAULT_NAMESPACE_CREATION="${SKIP_DEFAULT_NAMESPACE_CREATION:-false}" 55 | DEFAULT_NAMESPACE="${DEFAULT_NAMESPACE:-default}" 56 | DEFAULT_NAMESPACE_RETENTION=${DEFAULT_NAMESPACE_RETENTION:-1} 57 | 58 | SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES="${SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES:-false}" 59 | 60 | # === Main database functions === 61 | 62 | validate_db_env() { 63 | if [ "${DB}" == "mysql" ]; then 64 | if [ -z "${MYSQL_SEEDS}" ]; then 65 | echo "MYSQL_SEEDS env must be set if DB is ${DB}." 66 | exit 1 67 | fi 68 | elif [ "${DB}" == "postgresql" ]; then 69 | if [ -z "${POSTGRES_SEEDS}" ]; then 70 | echo "POSTGRES_SEEDS env must be set if DB is ${DB}." 71 | exit 1 72 | fi 73 | elif [ "${DB}" == "cassandra" ]; then 74 | if [ -z "${CASSANDRA_SEEDS}" ]; then 75 | echo "CASSANDRA_SEEDS env must be set if DB is ${DB}." 76 | exit 1 77 | fi 78 | else 79 | echo "Unsupported DB type: ${DB}." 80 | exit 1 81 | fi 82 | } 83 | 84 | wait_for_cassandra() { 85 | # TODO (alex): Remove exports 86 | export CASSANDRA_USER=${CASSANDRA_USER} 87 | export CASSANDRA_PORT=${CASSANDRA_PORT} 88 | export CASSANDRA_ENABLE_TLS=${CASSANDRA_TLS_ENABLED} 89 | export CASSANDRA_TLS_CERT=${CASSANDRA_CERT} 90 | export CASSANDRA_TLS_KEY=${CASSANDRA_CERT_KEY} 91 | export CASSANDRA_TLS_CA=${CASSANDRA_CA} 92 | 93 | { export CASSANDRA_PASSWORD=${CASSANDRA_PASSWORD}; } 2> /dev/null 94 | 95 | until temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" validate-health; do 96 | echo 'Waiting for Cassandra to start up.' 97 | sleep 1 98 | done 99 | echo 'Cassandra started.' 100 | } 101 | 102 | wait_for_mysql() { 103 | until nc -z "${MYSQL_SEEDS%%,*}" "${DB_PORT}"; do 104 | echo 'Waiting for MySQL to start up.' 105 | sleep 1 106 | done 107 | 108 | echo 'MySQL started.' 109 | } 110 | 111 | wait_for_postgres() { 112 | until nc -z "${POSTGRES_SEEDS%%,*}" "${DB_PORT}"; do 113 | echo 'Waiting for PostgreSQL to startup.' 114 | sleep 1 115 | done 116 | 117 | echo 'PostgreSQL started.' 118 | } 119 | 120 | wait_for_db() { 121 | if [ "${DB}" == "mysql" ]; then 122 | wait_for_mysql 123 | elif [ "${DB}" == "postgresql" ]; then 124 | wait_for_postgres 125 | elif [ "${DB}" == "cassandra" ]; then 126 | wait_for_cassandra 127 | else 128 | echo "Unsupported DB type: ${DB}." 129 | exit 1 130 | fi 131 | } 132 | 133 | setup_cassandra_schema() { 134 | # TODO (alex): Remove exports 135 | export CASSANDRA_USER=${CASSANDRA_USER} 136 | export CASSANDRA_PORT=${CASSANDRA_PORT} 137 | export CASSANDRA_ENABLE_TLS=${CASSANDRA_TLS_ENABLED} 138 | export CASSANDRA_TLS_CERT=${CASSANDRA_CERT} 139 | export CASSANDRA_TLS_KEY=${CASSANDRA_CERT_KEY} 140 | export CASSANDRA_TLS_CA=${CASSANDRA_CA} 141 | 142 | { export CASSANDRA_PASSWORD=${CASSANDRA_PASSWORD}; } 2> /dev/null 143 | 144 | SCHEMA_DIR=${TEMPORAL_HOME}/schema/cassandra/temporal/versioned 145 | temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" create -k "${KEYSPACE}" --rf "${CASSANDRA_REPLICATION_FACTOR}" 146 | temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" -k "${KEYSPACE}" setup-schema -v 0.0 147 | temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" -k "${KEYSPACE}" update-schema -d "${SCHEMA_DIR}" 148 | 149 | VISIBILITY_SCHEMA_DIR=${TEMPORAL_HOME}/schema/cassandra/visibility/versioned 150 | temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" create -k "${VISIBILITY_KEYSPACE}" --rf "${CASSANDRA_REPLICATION_FACTOR}" 151 | temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" -k "${VISIBILITY_KEYSPACE}" setup-schema -v 0.0 152 | temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" -k "${VISIBILITY_KEYSPACE}" update-schema -d "${VISIBILITY_SCHEMA_DIR}" 153 | } 154 | 155 | setup_mysql_schema() { 156 | # TODO (alex): Remove exports 157 | { export SQL_PASSWORD=${MYSQL_PWD}; } 2> /dev/null 158 | 159 | if [ "${MYSQL_TX_ISOLATION_COMPAT}" == "true" ]; then 160 | MYSQL_CONNECT_ATTR=(--connect-attributes "tx_isolation=READ-COMMITTED") 161 | else 162 | MYSQL_CONNECT_ATTR=() 163 | fi 164 | 165 | SCHEMA_DIR=${TEMPORAL_HOME}/schema/mysql/v57/temporal/versioned 166 | temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" create --db "${DBNAME}" 167 | temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" --db "${DBNAME}" setup-schema -v 0.0 168 | temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" --db "${DBNAME}" update-schema -d "${SCHEMA_DIR}" 169 | VISIBILITY_SCHEMA_DIR=${TEMPORAL_HOME}/schema/mysql/v57/visibility/versioned 170 | temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" create --db "${VISIBILITY_DBNAME}" 171 | temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" --db "${VISIBILITY_DBNAME}" setup-schema -v 0.0 172 | temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" --db "${VISIBILITY_DBNAME}" update-schema -d "${VISIBILITY_SCHEMA_DIR}" 173 | } 174 | 175 | setup_postgres_schema() { 176 | # TODO (alex): Remove exports 177 | { export SQL_PASSWORD=${POSTGRES_PWD}; } 2> /dev/null 178 | 179 | SCHEMA_DIR=${TEMPORAL_HOME}/schema/postgresql/v96/temporal/versioned 180 | # Create database only if its name is different from the user name. Otherwise PostgreSQL container itself will create database. 181 | if [[ "${DBNAME}" != "${POSTGRES_USER}" && "${SKIP_POSTGRES_DB_CREATION}" != true ]]; then 182 | temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" create --db "${DBNAME}" 183 | fi 184 | temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" --db "${DBNAME}" setup-schema -v 0.0 185 | temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" --db "${DBNAME}" update-schema -d "${SCHEMA_DIR}" 186 | 187 | if [[ "${SKIP_VISIBILITY_DB_SETUP}" != true ]]; then 188 | { export SQL_PASSWORD=${VISIBILITY_POSTGRES_PWD}; } 2> /dev/null 189 | VISIBILITY_SCHEMA_DIR=${TEMPORAL_HOME}/schema/postgresql/v96/visibility/versioned 190 | if [[ "${VISIBILITY_DBNAME}" != "${POSTGRES_USER}" && "${SKIP_POSTGRES_DB_CREATION}" != true ]]; then 191 | temporal-sql-tool --plugin postgres --ep "${VISIBILITY_POSTGRES_SEEDS}" -u "${VISIBILITY_POSTGRES_USER}" -p "${VISIBILITY_DB_PORT}" create --db "${VISIBILITY_DBNAME}" 192 | fi 193 | temporal-sql-tool --plugin postgres --ep "${VISIBILITY_POSTGRES_SEEDS}" -u "${VISIBILITY_POSTGRES_USER}" -p "${VISIBILITY_DB_PORT}" --db "${VISIBILITY_DBNAME}" setup-schema -v 0.0 194 | temporal-sql-tool --plugin postgres --ep "${VISIBILITY_POSTGRES_SEEDS}" -u "${VISIBILITY_POSTGRES_USER}" -p "${VISIBILITY_DB_PORT}" --db "${VISIBILITY_DBNAME}" update-schema -d "${VISIBILITY_SCHEMA_DIR}" 195 | fi 196 | } 197 | 198 | setup_schema() { 199 | if [ "${DB}" == "mysql" ]; then 200 | echo 'Setup MySQL schema.' 201 | setup_mysql_schema 202 | elif [ "${DB}" == "postgresql" ]; then 203 | echo 'Setup PostgreSQL schema.' 204 | setup_postgres_schema 205 | else 206 | echo 'Setup Cassandra schema.' 207 | setup_cassandra_schema 208 | fi 209 | } 210 | 211 | # === Elasticsearch functions === 212 | 213 | validate_es_env() { 214 | if [ "${ENABLE_ES}" == true ]; then 215 | if [ -z "${ES_SEEDS}" ]; then 216 | echo "ES_SEEDS env must be set if ENABLE_ES is ${ENABLE_ES}" 217 | exit 1 218 | fi 219 | fi 220 | } 221 | 222 | wait_for_es() { 223 | SECONDS=0 224 | 225 | ES_SERVER="${ES_SCHEME}://${ES_SEEDS%%,*}:${ES_PORT}" 226 | 227 | until curl --silent --fail --user "${ES_USER}":"${ES_PWD}" "${ES_SERVER}" > /dev/null 2>&1; do 228 | DURATION=${SECONDS} 229 | 230 | if [ "${ES_SCHEMA_SETUP_TIMEOUT_IN_SECONDS}" -gt 0 ] && [ ${DURATION} -ge "${ES_SCHEMA_SETUP_TIMEOUT_IN_SECONDS}" ]; then 231 | echo 'WARNING: timed out waiting for Elasticsearch to start up. Skipping index creation.' 232 | return; 233 | fi 234 | 235 | echo 'Waiting for Elasticsearch to start up.' 236 | sleep 1 237 | done 238 | 239 | echo 'Elasticsearch started.' 240 | } 241 | 242 | setup_es_index() { 243 | ES_SERVER="${ES_SCHEME}://${ES_SEEDS%%,*}:${ES_PORT}" 244 | # @@@SNIPSTART setup-es-template-commands 245 | # ES_SERVER is the URL of Elasticsearch server i.e. "http://localhost:9200". 246 | SETTINGS_URL="${ES_SERVER}/_cluster/settings" 247 | SETTINGS_FILE=${TEMPORAL_HOME}/schema/elasticsearch/visibility/cluster_settings_${ES_VERSION}.json 248 | TEMPLATE_URL="${ES_SERVER}/_template/temporal_visibility_v1_template" 249 | SCHEMA_FILE=${TEMPORAL_HOME}/schema/elasticsearch/visibility/index_template_${ES_VERSION}.json 250 | INDEX_URL="${ES_SERVER}/${ES_VIS_INDEX}" 251 | curl --fail --user "${ES_USER}":"${ES_PWD}" -X PUT "${SETTINGS_URL}" -H "Content-Type: application/json" --data-binary "@${SETTINGS_FILE}" --write-out "\n" 252 | curl --fail --user "${ES_USER}":"${ES_PWD}" -X PUT "${TEMPLATE_URL}" -H 'Content-Type: application/json' --data-binary "@${SCHEMA_FILE}" --write-out "\n" 253 | curl --user "${ES_USER}":"${ES_PWD}" -X PUT "${INDEX_URL}" --write-out "\n" 254 | # @@@SNIPEND 255 | } 256 | 257 | # === Server setup === 258 | 259 | register_default_namespace() { 260 | echo "Registering default namespace: ${DEFAULT_NAMESPACE}." 261 | if ! tctl --ns "${DEFAULT_NAMESPACE}" namespace describe; then 262 | echo "Default namespace ${DEFAULT_NAMESPACE} not found. Creating..." 263 | tctl --ns "${DEFAULT_NAMESPACE}" namespace register --rd "${DEFAULT_NAMESPACE_RETENTION}" --desc "Default namespace for Temporal Server." 264 | echo "Default namespace ${DEFAULT_NAMESPACE} registration complete." 265 | else 266 | echo "Default namespace ${DEFAULT_NAMESPACE} already registered." 267 | fi 268 | } 269 | 270 | add_custom_search_attributes() { 271 | echo "Adding Custom*Field search attributes." 272 | # TODO: Remove CustomStringField 273 | # @@@SNIPSTART add-custom-search-attributes-for-testing-command 274 | tctl --auto_confirm admin cluster add-search-attributes \ 275 | --name CustomKeywordField --type Keyword \ 276 | --name CustomStringField --type Text \ 277 | --name CustomTextField --type Text \ 278 | --name CustomIntField --type Int \ 279 | --name CustomDatetimeField --type Datetime \ 280 | --name CustomDoubleField --type Double \ 281 | --name CustomBoolField --type Bool 282 | # @@@SNIPEND 283 | } 284 | 285 | setup_server(){ 286 | echo "Temporal CLI address: ${TEMPORAL_CLI_ADDRESS}." 287 | 288 | until tctl cluster health | grep SERVING; do 289 | echo "Waiting for Temporal server to start..." 290 | sleep 1 291 | done 292 | echo "Temporal server started." 293 | 294 | if [ "${SKIP_DEFAULT_NAMESPACE_CREATION}" != true ]; then 295 | register_default_namespace 296 | fi 297 | 298 | if [ "${SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES}" != true ]; then 299 | add_custom_search_attributes 300 | fi 301 | } 302 | 303 | # === Main === 304 | 305 | if [ "${SKIP_SCHEMA_SETUP}" != true ]; then 306 | validate_db_env 307 | wait_for_db 308 | setup_schema 309 | fi 310 | 311 | if [ "${ENABLE_ES}" == true ]; then 312 | validate_es_env 313 | wait_for_es 314 | setup_es_index 315 | fi 316 | 317 | # Run this func in parallel process. It will wait for server to start and then run required steps. 318 | setup_server & 319 | -------------------------------------------------------------------------------- /temporal-cluster/server/config_template.yaml: -------------------------------------------------------------------------------- 1 | log: 2 | stdout: true 3 | level: {{ default .Env.LOG_LEVEL "info" }} 4 | 5 | persistence: 6 | numHistoryShards: {{ default .Env.NUM_HISTORY_SHARDS "4" }} 7 | defaultStore: default 8 | {{- $es := default .Env.ENABLE_ES "false" | lower -}} 9 | {{- if eq $es "true" }} 10 | advancedVisibilityStore: es-visibility 11 | {{- end }} 12 | datastores: 13 | {{- $db := default .Env.DB "cassandra" | lower -}} 14 | {{- if eq $db "cassandra" }} 15 | default: 16 | cassandra: 17 | hosts: "{{ default .Env.CASSANDRA_SEEDS "" }}" 18 | keyspace: "{{ default .Env.KEYSPACE "temporal" }}" 19 | user: "{{ default .Env.CASSANDRA_USER "" }}" 20 | password: "{{ default .Env.CASSANDRA_PASSWORD "" }}" 21 | port: {{ default .Env.CASSANDRA_PORT "9042" }} 22 | maxConns: {{ default .Env.CASSANDRA_MAX_CONNS "20" }} 23 | tls: 24 | enabled: {{ default .Env.CASSANDRA_TLS_ENABLED "false" }} 25 | caFile: {{ default .Env.CASSANDRA_CA "" }} 26 | certFile: {{ default .Env.CASSANDRA_CERT "" }} 27 | keyFile: {{ default .Env.CASSANDRA_CERT_KEY "" }} 28 | caData: {{ default .Env.CASSANDRA_CA_DATA "" }} 29 | certData: {{ default .Env.CASSANDRA_CERT_DATA "" }} 30 | keyData: {{ default .Env.CASSANDRA_CERT_KEY_DATA "" }} 31 | enableHostVerification: {{ default .Env.CASSANDRA_HOST_VERIFICATION "false" }} 32 | serverName: {{ default .Env.CASSANDRA_HOST_NAME "" }} 33 | visibility: 34 | cassandra: 35 | {{ $visibility_seeds_default := default .Env.CASSANDRA_SEEDS "" }} 36 | {{ $visibility_seeds := default .Env.VISIBILITY_CASSANDRA_SEEDS $visibility_seeds_default }} 37 | {{ $visibility_port_default := default .Env.CASSANDRA_PORT "9042" }} 38 | {{ $visibility_port := default .Env.VISIBILITY_CASSANDRA_PORT $visibility_port_default }} 39 | {{ $visibility_user_default := default .Env.CASSANDRA_USER "" }} 40 | {{ $visibility_user := default .Env.VISIBILITY_CASSANDRA_USER $visibility_user_default }} 41 | {{ $visibility_pwd_default := default .Env.CASSANDRA_PASSWORD "" }} 42 | {{ $visibility_pwd := default .Env.VISIBILITY_CASSANDRA_PASSWORD $visibility_pwd_default }} 43 | hosts: "{{ $visibility_seeds }}" 44 | keyspace: "{{ default .Env.VISIBILITY_KEYSPACE "temporal_visibility" }}" 45 | user: "{{ $visibility_user }}" 46 | password: "{{ $visibility_pwd }}" 47 | port: {{ $visibility_port }} 48 | maxConns: {{ default .Env.CASSANDRA_MAX_CONNS "10" }} 49 | tls: 50 | enabled: {{ default .Env.CASSANDRA_TLS_ENABLED "false" }} 51 | caFile: {{ default .Env.CASSANDRA_CA "" }} 52 | certFile: {{ default .Env.CASSANDRA_CERT "" }} 53 | keyFile: {{ default .Env.CASSANDRA_CERT_KEY "" }} 54 | caData: {{ default .Env.CASSANDRA_CA_DATA "" }} 55 | certData: {{ default .Env.CASSANDRA_CERT_DATA "" }} 56 | keyData: {{ default .Env.CASSANDRA_CERT_KEY_DATA "" }} 57 | enableHostVerification: {{ default .Env.CASSANDRA_HOST_VERIFICATION "false" }} 58 | serverName: {{ default .Env.CASSANDRA_HOST_NAME "" }} 59 | {{- else if eq $db "mysql" }} 60 | default: 61 | sql: 62 | pluginName: "mysql" 63 | databaseName: "{{ default .Env.DBNAME "temporal" }}" 64 | connectAddr: "{{ default .Env.MYSQL_SEEDS "" }}:{{ default .Env.DB_PORT "3306" }}" 65 | connectProtocol: "tcp" 66 | user: "{{ default .Env.MYSQL_USER "" }}" 67 | password: "{{ default .Env.MYSQL_PWD "" }}" 68 | {{- if .Env.MYSQL_TX_ISOLATION_COMPAT }} 69 | connectAttributes: 70 | tx_isolation: "'READ-COMMITTED'" 71 | {{- end }} 72 | maxConns: {{ default .Env.SQL_MAX_CONNS "20" }} 73 | maxIdleConns: {{ default .Env.SQL_MAX_IDLE_CONNS "20" }} 74 | maxConnLifetime: {{ default .Env.SQL_MAX_CONN_TIME "1h" }} 75 | tls: 76 | enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} 77 | сaFile: {{ default .Env.SQL_CA "" }} 78 | certFile: {{ default .Env.SQL_CERT "" }} 79 | keyFile: {{ default .Env.SQL_CERT_KEY "" }} 80 | enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} 81 | serverName: {{ default .Env.SQL_HOST_NAME "" }} 82 | visibility: 83 | sql: 84 | {{ $visibility_seeds_default := default .Env.MYSQL_SEEDS "" }} 85 | {{ $visibility_seeds := default .Env.VISIBILITY_MYSQL_SEEDS $visibility_seeds_default }} 86 | {{ $visibility_port_default := default .Env.DB_PORT "3306" }} 87 | {{ $visibility_port := default .Env.VISIBILITY_DB_PORT $visibility_port_default }} 88 | {{ $visibility_user_default := default .Env.MYSQL_USER "" }} 89 | {{ $visibility_user := default .Env.VISIBILITY_MYSQL_USER $visibility_user_default }} 90 | {{ $visibility_pwd_default := default .Env.MYSQL_PWD "" }} 91 | {{ $visibility_pwd := default .Env.VISIBILITY_MYSQL_PWD $visibility_pwd_default }} 92 | pluginName: "mysql" 93 | databaseName: "{{ default .Env.VISIBILITY_DBNAME "temporal_visibility" }}" 94 | connectAddr: "{{ $visibility_seeds }}:{{ $visibility_port }}" 95 | connectProtocol: "tcp" 96 | user: "{{ $visibility_user }}" 97 | password: "{{ $visibility_pwd }}" 98 | {{- if .Env.MYSQL_TX_ISOLATION_COMPAT }} 99 | connectAttributes: 100 | tx_isolation: "'READ-COMMITTED'" 101 | {{- end }} 102 | maxConns: {{ default .Env.SQL_VIS_MAX_CONNS "10" }} 103 | maxIdleConns: {{ default .Env.SQL_VIS_MAX_IDLE_CONNS "10" }} 104 | maxConnLifetime: {{ default .Env.SQL_VIS_MAX_CONN_TIME "1h" }} 105 | tls: 106 | enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} 107 | сaFile: {{ default .Env.SQL_CA "" }} 108 | certFile: {{ default .Env.SQL_CERT "" }} 109 | keyFile: {{ default .Env.SQL_CERT_KEY "" }} 110 | enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} 111 | serverName: {{ default .Env.SQL_HOST_NAME "" }} 112 | {{- else if eq $db "postgresql" }} 113 | default: 114 | sql: 115 | pluginName: "postgres" 116 | databaseName: "{{ default .Env.DBNAME "temporal" }}" 117 | connectAddr: "{{ default .Env.POSTGRES_SEEDS "" }}:{{ default .Env.DB_PORT "5432" }}" 118 | connectProtocol: "tcp" 119 | user: "{{ default .Env.POSTGRES_USER "" }}" 120 | password: "{{ default .Env.POSTGRES_PWD "" }}" 121 | maxConns: {{ default .Env.SQL_MAX_CONNS "20" }} 122 | maxIdleConns: {{ default .Env.SQL_MAX_IDLE_CONNS "20" }} 123 | maxConnLifetime: {{ default .Env.SQL_MAX_CONN_TIME "1h" }} 124 | tls: 125 | enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} 126 | сaFile: {{ default .Env.SQL_CA "" }} 127 | certFile: {{ default .Env.SQL_CERT "" }} 128 | keyFile: {{ default .Env.SQL_CERT_KEY "" }} 129 | enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} 130 | serverName: {{ default .Env.SQL_HOST_NAME "" }} 131 | visibility: 132 | {{- end }} 133 | {{- if eq $es "true" }} 134 | es-visibility: 135 | elasticsearch: 136 | version: {{ default .Env.ES_VERSION "" }} 137 | url: 138 | scheme: {{ default .Env.ES_SCHEME "http" }} 139 | host: "{{ default .Env.ES_SEEDS "" }}:{{ default .Env.ES_PORT "9200" }}" 140 | username: "{{ default .Env.ES_USER "" }}" 141 | password: "{{ default .Env.ES_PWD "" }}" 142 | indices: 143 | visibility: "{{ default .Env.ES_VIS_INDEX "temporal_visibility_v1_dev" }}" 144 | {{- end }} 145 | 146 | global: 147 | membership: 148 | maxJoinDuration: 30s 149 | broadcastAddress: "{{ default .Env.TEMPORAL_BROADCAST_ADDRESS "" }}" 150 | pprof: 151 | port: {{ default .Env.PPROF_PORT "0" }} 152 | tls: 153 | refreshInterval: {{ default .Env.TEMPORAL_TLS_REFRESH_INTERVAL "0s" }} 154 | expirationChecks: 155 | warningWindow: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_WARNING_WINDOW "0s" }} 156 | errorWindow: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_ERROR_WINDOW "0s" }} 157 | checkInterval: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_CHECK_INTERVAL "0s" }} 158 | internode: 159 | # This server section configures the TLS certificate that internal temporal 160 | # cluster nodes (history or matching) present to other clients within the Temporal Cluster. 161 | server: 162 | requireClientAuth: {{ default .Env.TEMPORAL_TLS_REQUIRE_CLIENT_AUTH "false" }} 163 | 164 | certFile: {{ default .Env.TEMPORAL_TLS_SERVER_CERT "" }} 165 | keyFile: {{ default .Env.TEMPORAL_TLS_SERVER_KEY "" }} 166 | {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} 167 | clientCaFiles: 168 | - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} 169 | {{- end }} 170 | 171 | certData: {{ default .Env.TEMPORAL_TLS_SERVER_CERT_DATA "" }} 172 | keyData: {{ default .Env.TEMPORAL_TLS_SERVER_KEY_DATA "" }} 173 | {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} 174 | clientCaData: 175 | - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} 176 | {{- end }} 177 | 178 | # This client section is used to configure the TLS clients within 179 | # the Temporal Cluster that connect to an Internode (history or matching) 180 | client: 181 | serverName: {{ default .Env.TEMPORAL_TLS_INTERNODE_SERVER_NAME "" }} 182 | disableHostVerification: {{ default .Env.TEMPORAL_TLS_INTERNODE_DISABLE_HOST_VERIFICATION "false"}} 183 | {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} 184 | rootCaFiles: 185 | - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} 186 | {{- end }} 187 | {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} 188 | rootCaData: 189 | - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} 190 | {{- end }} 191 | frontend: 192 | # This server section configures the TLS certificate that the Frontend 193 | # server presents to all clients (specifically the Worker role within 194 | # the Temporal Cluster and all External SDKs connecting to the Cluster) 195 | server: 196 | requireClientAuth: {{ default .Env.TEMPORAL_TLS_REQUIRE_CLIENT_AUTH "false" }} 197 | certFile: {{ default .Env.TEMPORAL_TLS_FRONTEND_CERT "" }} 198 | keyFile: {{ default .Env.TEMPORAL_TLS_FRONTEND_KEY "" }} 199 | {{- if .Env.TEMPORAL_TLS_CLIENT1_CA_CERT }} 200 | clientCaFiles: 201 | - {{ default .Env.TEMPORAL_TLS_CLIENT1_CA_CERT "" }} 202 | - {{ default .Env.TEMPORAL_TLS_CLIENT2_CA_CERT "" }} 203 | {{- end }} 204 | 205 | certData: {{ default .Env.TEMPORAL_TLS_FRONTEND_CERT_DATA "" }} 206 | keyData: {{ default .Env.TEMPORAL_TLS_FRONTEND_KEY_DATA "" }} 207 | {{- if .Env.TEMPORAL_TLS_CLIENT1_CA_CERT_DATA }} 208 | clientCaData: 209 | - {{ default .Env.TEMPORAL_TLS_CLIENT1_CA_CERT_DATA "" }} 210 | - {{ default .Env.TEMPORAL_TLS_CLIENT2_CA_CERT_DATA "" }} 211 | {{- end }} 212 | 213 | # This client section is used to configure the TLS clients within 214 | # the Temporal Cluster (specifically the Worker role) that connect to the Frontend service 215 | client: 216 | serverName: {{ default .Env.TEMPORAL_TLS_FRONTEND_SERVER_NAME "" }} 217 | disableHostVerification: {{ default .Env.TEMPORAL_TLS_FRONTEND_DISABLE_HOST_VERIFICATION "false"}} 218 | {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} 219 | rootCaFiles: 220 | - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} 221 | {{- end }} 222 | {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} 223 | rootCaData: 224 | - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} 225 | {{- end }} 226 | {{- if .Env.STATSD_ENDPOINT }} 227 | metrics: 228 | statsd: 229 | hostPort: {{ .Env.STATSD_ENDPOINT }} 230 | prefix: "temporal" 231 | {{- else if .Env.PROMETHEUS_ENDPOINT }} 232 | metrics: 233 | prometheus: 234 | timerType: {{ default .Env.PROMETHEUS_TIMER_TYPE "histogram" }} 235 | listenAddress: "{{ .Env.PROMETHEUS_ENDPOINT }}" 236 | {{- end }} 237 | authorization: 238 | jwtKeyProvider: 239 | keySourceURIs: 240 | {{- if .Env.TEMPORAL_JWT_KEY_SOURCE1 }} 241 | - {{ default .Env.TEMPORAL_JWT_KEY_SOURCE1 "" }} 242 | {{- end }} 243 | {{- if .Env.TEMPORAL_JWT_KEY_SOURCE2 }} 244 | - {{ default .Env.TEMPORAL_JWT_KEY_SOURCE2 "" }} 245 | {{- end }} 246 | refreshInterval: {{ default .Env.TEMPORAL_JWT_KEY_REFRESH "1m" }} 247 | permissionsClaimName: {{ default .Env.TEMPORAL_JWT_PERMISSIONS_CLAIM "permissions" }} 248 | authorizer: {{ default .Env.TEMPORAL_AUTH_AUTHORIZER "" }} 249 | claimMapper: {{ default .Env.TEMPORAL_AUTH_CLAIM_MAPPER "" }} 250 | 251 | {{- $temporalGrpcPort := default .Env.FRONTEND_GRPC_PORT "7233" }} 252 | services: 253 | frontend: 254 | rpc: 255 | grpcPort: {{ $temporalGrpcPort }} 256 | membershipPort: {{ default .Env.FRONTEND_MEMBERSHIP_PORT "6933" }} 257 | bindOnIP: {{ default .Env.BIND_ON_IP "127.0.0.1" }} 258 | 259 | matching: 260 | rpc: 261 | grpcPort: {{ default .Env.MATCHING_GRPC_PORT "7235" }} 262 | membershipPort: {{ default .Env.MATCHING_MEMBERSHIP_PORT "6935" }} 263 | bindOnIP: {{ default .Env.BIND_ON_IP "127.0.0.1" }} 264 | 265 | history: 266 | rpc: 267 | grpcPort: {{ default .Env.HISTORY_GRPC_PORT "7234" }} 268 | membershipPort: {{ default .Env.HISTORY_MEMBERSHIP_PORT "6934" }} 269 | bindOnIP: {{ default .Env.BIND_ON_IP "127.0.0.1" }} 270 | 271 | worker: 272 | rpc: 273 | grpcPort: {{ default .Env.WORKER_GRPC_PORT "7239" }} 274 | membershipPort: {{ default .Env.WORKER_MEMBERSHIP_PORT "6939" }} 275 | bindOnIP: {{ default .Env.BIND_ON_IP "127.0.0.1" }} 276 | 277 | clusterMetadata: 278 | enableGlobalNamespace: false 279 | failoverVersionIncrement: 10 280 | masterClusterName: "active" 281 | currentClusterName: "active" 282 | clusterInformation: 283 | active: 284 | enabled: true 285 | initialFailoverVersion: 1 286 | rpcName: "frontend" 287 | rpcAddress: {{ (print "127.0.0.1:" $temporalGrpcPort) }} 288 | 289 | dcRedirectionPolicy: 290 | policy: "noop" 291 | toDC: "" 292 | 293 | archival: 294 | history: 295 | state: "enabled" 296 | enableRead: true 297 | provider: 298 | filestore: 299 | fileMode: "0666" 300 | dirMode: "0766" 301 | visibility: 302 | state: "enabled" 303 | enableRead: true 304 | provider: 305 | filestore: 306 | fileMode: "0666" 307 | dirMode: "0766" 308 | 309 | namespaceDefaults: 310 | archival: 311 | history: 312 | state: "disabled" 313 | URI: "file:///tmp/temporal_archival/development" 314 | visibility: 315 | state: "disabled" 316 | URI: "file:///tmp/temporal_vis_archival/development" 317 | 318 | {{ $publicIp := default .Env.BIND_ON_IP "127.0.0.1" -}} 319 | {{- $defaultPublicHostPost := (print $publicIp ":" $temporalGrpcPort) -}} 320 | publicClient: 321 | hostPort: "{{ default .Env.PUBLIC_FRONTEND_ADDRESS $defaultPublicHostPost }}" 322 | 323 | dynamicConfigClient: 324 | filepath: "{{ default .Env.DYNAMIC_CONFIG_FILE_PATH "/etc/temporal/config/dynamicconfig" }}" 325 | pollInterval: "60s" 326 | -------------------------------------------------------------------------------- /temporal-cluster/server/dynamicconfig.yaml: -------------------------------------------------------------------------------- 1 | frontend.enableClientVersionCheck: 2 | - value: true 3 | constraints: {} 4 | history.persistenceMaxQPS: 5 | - value: 3000 6 | constraints: {} 7 | frontend.persistenceMaxQPS: 8 | - value: 3000 9 | constraints: {} 10 | frontend.throttledLogRPS: 11 | - value: 20 12 | constraints: {} 13 | history.defaultActivityRetryPolicy: 14 | - value: 15 | InitialIntervalInSeconds: 1 16 | MaximumIntervalCoefficient: 100.0 17 | BackoffCoefficient: 2.0 18 | MaximumAttempts: 0 19 | history.defaultWorkflowRetryPolicy: 20 | - value: 21 | InitialIntervalInSeconds: 1 22 | MaximumIntervalCoefficient: 100.0 23 | BackoffCoefficient: 2.0 24 | MaximumAttempts: 0 25 | system.advancedVisibilityWritingMode: 26 | - value: "off" 27 | constraints: {} 28 | -------------------------------------------------------------------------------- /temporal-cluster/server/dynamicconfig_es.yaml: -------------------------------------------------------------------------------- 1 | frontend.enableClientVersionCheck: 2 | - value: true 3 | constraints: {} 4 | history.persistenceMaxQPS: 5 | - value: 3000 6 | constraints: {} 7 | frontend.persistenceMaxQPS: 8 | - value: 3000 9 | constraints: {} 10 | frontend.throttledLogRPS: 11 | - value: 20 12 | constraints: {} 13 | history.defaultActivityRetryPolicy: 14 | - value: 15 | InitialIntervalInSeconds: 1 16 | MaximumIntervalCoefficient: 100.0 17 | BackoffCoefficient: 2.0 18 | MaximumAttempts: 0 19 | history.defaultWorkflowRetryPolicy: 20 | - value: 21 | InitialIntervalInSeconds: 1 22 | MaximumIntervalCoefficient: 100.0 23 | BackoffCoefficient: 2.0 24 | MaximumAttempts: 0 25 | system.advancedVisibilityWritingMode: 26 | - value: "on" 27 | constraints: {} 28 | system.enableReadVisibilityFromES: 29 | - value: true 30 | constraints: {} 31 | -------------------------------------------------------------------------------- /temporal-cluster/web/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM temporalio/web:1.13.0 2 | 3 | ENTRYPOINT ["/bin/sh", "-c", "TEMPORAL_GRPC_ENDPOINT=$TEMPORAL_GRPC_HOST:7233 node server.js"] 4 | --------------------------------------------------------------------------------