From 138fa2e93c3aad221bdc3a6c5deb7eec27831105 Mon Sep 17 00:00:00 2001 From: Renan Bastos Date: Mon, 9 Nov 2026 12:10:58 -0300 Subject: [PATCH 1/3] Temporal: add new script Temporal Server on PostgreSQL 17, the Temporal UI (temporalio/ui-server) and the temporal CLI (temporalio/cli), all from the official release tarballs. Config lives in /etc/temporal, the schema is applied with the embedded temporal-sql-tool schemas, and the default namespace is created at install. Ports: 7233 (gRPC), 7243 (HTTP API), 8080 (UI). --- ct/temporal.sh | 82 +++++++++++++++ install/temporal-install.sh | 205 ++++++++++++++++++++++++++++++++++++ json/temporal.json | 49 +++++++++ 3 files changed, 336 insertions(+) create mode 100644 ct/temporal.sh create mode 100644 install/temporal-install.sh create mode 100644 json/temporal.json diff --git a/ct/temporal.sh b/ct/temporal.sh new file mode 100644 index 0000000000..e3304ec57a --- /dev/null +++ b/ct/temporal.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/DevScripts/main" +_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func" +source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func") +# Copyright (c) 2021-2026 community-scripts ORG +# Author: Renan Bastos (renanbastos93) +# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE +# Source: https://github.com/temporalio/temporal + +APP="Temporal" +var_tags="${var_tags:-workflow;automation}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-2048}" +var_disk="${var_disk:-8}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +#var_arm64="${var_arm64:-yes}" # unset = ask the user; server, UI and CLI all ship linux_arm64 assets, but not yet run on arm64 +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d /opt/temporal ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "temporal" "temporalio/temporal"; then + msg_info "Stopping Temporal" + systemctl stop temporal-ui temporal + msg_ok "Stopped Temporal" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "temporal" "temporalio/temporal" "prebuild" "latest" "/opt/temporal" "temporal_*_linux_$(arch_resolve).tar.gz" + + msg_info "Migrating Temporal Database" + set -a && source /etc/temporal/temporal.env && set +a + $STD /opt/temporal/temporal-sql-tool --db temporal update-schema --schema-name postgresql/v12/temporal + $STD /opt/temporal/temporal-sql-tool --db temporal_visibility update-schema --schema-name postgresql/v12/visibility + msg_ok "Migrated Temporal Database" + + msg_info "Starting Temporal" + systemctl start temporal temporal-ui + msg_ok "Started Temporal" + msg_ok "Updated Temporal successfully!" + fi + + if check_for_gh_release "temporal-ui" "temporalio/ui-server"; then + msg_info "Stopping Temporal UI" + systemctl stop temporal-ui + msg_ok "Stopped Temporal UI" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "temporal-ui" "temporalio/ui-server" "prebuild" "latest" "/opt/temporal-ui" "ui-server_*_linux_$(arch_resolve).tar.gz" + + msg_info "Starting Temporal UI" + systemctl start temporal-ui + msg_ok "Started Temporal UI" + msg_ok "Updated Temporal UI successfully!" + fi + + if check_for_gh_release "temporal-cli" "temporalio/cli"; then + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "temporal-cli" "temporalio/cli" "prebuild" "latest" "/opt/temporal-cli" "temporal_cli_*_linux_$(arch_resolve).tar.gz" + msg_ok "Updated Temporal CLI successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW}Access it using the following URL:${CL}" +echo -e "${GATEWAY}${BGN}http://${IP}:8080${CL}" +echo -e "${INFO}${YW}gRPC endpoint for workers and SDKs: ${IP}:7233${CL}" diff --git a/install/temporal-install.sh b/install/temporal-install.sh new file mode 100644 index 0000000000..afd4d82db7 --- /dev/null +++ b/install/temporal-install.sh @@ -0,0 +1,205 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2026 community-scripts ORG +# Author: Renan Bastos (renanbastos93) +# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE +# Source: https://github.com/temporalio/temporal + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +PG_VERSION="17" setup_postgresql +PG_DB_NAME="temporal" PG_DB_USER="temporal" setup_postgresql_db + +fetch_and_deploy_gh_release "temporal" "temporalio/temporal" "prebuild" "latest" "/opt/temporal" "temporal_*_linux_$(arch_resolve).tar.gz" +fetch_and_deploy_gh_release "temporal-ui" "temporalio/ui-server" "prebuild" "latest" "/opt/temporal-ui" "ui-server_*_linux_$(arch_resolve).tar.gz" +fetch_and_deploy_gh_release "temporal-cli" "temporalio/cli" "prebuild" "latest" "/opt/temporal-cli" "temporal_cli_*_linux_$(arch_resolve).tar.gz" + +msg_info "Configuring Temporal" +mkdir -p /etc/temporal/config/dynamicconfig /etc/temporal/ui +ln -sf /opt/temporal-cli/temporal /usr/local/bin/temporal +cat </etc/temporal/temporal.env +SQL_PLUGIN=postgres12 +SQL_HOST=127.0.0.1 +SQL_PORT=5432 +SQL_USER=temporal +SQL_PASSWORD=${PG_DB_PASS} +EOF +chmod 600 /etc/temporal/temporal.env +cat <<'EOF' >/etc/temporal/config/production.yaml +# enable-template +log: + stdout: true + level: info + +persistence: + defaultStore: postgres-default + visibilityStore: postgres-visibility + numHistoryShards: 4 + datastores: + postgres-default: + sql: + pluginName: {{ env "SQL_PLUGIN" | quote }} + databaseName: "temporal" + connectAddr: {{ printf "%s:%s" (env "SQL_HOST") (env "SQL_PORT") | quote }} + connectProtocol: "tcp" + user: {{ env "SQL_USER" | quote }} + password: {{ env "SQL_PASSWORD" | quote }} + maxConns: 20 + maxIdleConns: 20 + maxConnLifetime: "1h" + postgres-visibility: + sql: + pluginName: {{ env "SQL_PLUGIN" | quote }} + databaseName: "temporal_visibility" + connectAddr: {{ printf "%s:%s" (env "SQL_HOST") (env "SQL_PORT") | quote }} + connectProtocol: "tcp" + user: {{ env "SQL_USER" | quote }} + password: {{ env "SQL_PASSWORD" | quote }} + maxConns: 10 + maxIdleConns: 10 + maxConnLifetime: "1h" + +global: + membership: + maxJoinDuration: 30s + broadcastAddress: "127.0.0.1" + +services: + frontend: + rpc: + grpcPort: 7233 + membershipPort: 6933 + bindOnIP: "0.0.0.0" + httpPort: 7243 + + matching: + rpc: + grpcPort: 7235 + membershipPort: 6935 + bindOnLocalHost: true + + history: + rpc: + grpcPort: 7234 + membershipPort: 6934 + bindOnLocalHost: true + + worker: + rpc: + grpcPort: 7239 + membershipPort: 6939 + bindOnLocalHost: true + +clusterMetadata: + enableGlobalNamespace: false + failoverVersionIncrement: 10 + masterClusterName: "active" + currentClusterName: "active" + clusterInformation: + active: + enabled: true + initialFailoverVersion: 1 + rpcName: "frontend" + rpcAddress: "127.0.0.1:7233" + httpAddress: "127.0.0.1:7243" + +dcRedirectionPolicy: + policy: "noop" + +archival: + history: + state: "disabled" + visibility: + state: "disabled" + +namespaceDefaults: + archival: + history: + state: "disabled" + visibility: + state: "disabled" + +dynamicConfigClient: + filepath: "/etc/temporal/config/dynamicconfig/production.yaml" + pollInterval: "60s" +EOF +cat </etc/temporal/config/dynamicconfig/production.yaml +limit.maxIDLength: + - value: 255 + constraints: {} +EOF +cat </etc/temporal/ui/production.yaml +temporalGrpcAddress: 127.0.0.1:7233 +port: 8080 +enableUi: true +defaultNamespace: default +cors: + cookieInsecure: true + allowOrigins: + - http://${LOCAL_IP}:8080 +EOF +msg_ok "Configured Temporal" + +msg_info "Initializing Temporal Database" +set -a && source /etc/temporal/temporal.env && set +a +$STD sudo -u postgres psql -c "CREATE DATABASE temporal_visibility WITH OWNER temporal ENCODING 'UTF8' TEMPLATE template0;" +$STD /opt/temporal/temporal-sql-tool --db temporal setup-schema -v 0.0 +$STD /opt/temporal/temporal-sql-tool --db temporal update-schema --schema-name postgresql/v12/temporal +$STD /opt/temporal/temporal-sql-tool --db temporal_visibility setup-schema -v 0.0 +$STD /opt/temporal/temporal-sql-tool --db temporal_visibility update-schema --schema-name postgresql/v12/visibility +msg_ok "Initialized Temporal Database" + +msg_info "Creating Services" +cat </etc/systemd/system/temporal.service +[Unit] +Description=Temporal Server +After=network.target postgresql.service +Requires=postgresql.service + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/temporal +EnvironmentFile=/etc/temporal/temporal.env +ExecStart=/opt/temporal/temporal-server --root /etc/temporal --env production --allow-no-auth start +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF + +cat </etc/systemd/system/temporal-ui.service +[Unit] +Description=Temporal UI +After=network.target temporal.service +Wants=temporal.service + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/temporal-ui +ExecStart=/opt/temporal-ui/ui-server --root /etc/temporal --config ui --env production start +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now temporal temporal-ui +msg_ok "Created Services" + +msg_info "Creating Default Namespace" +until temporal operator cluster health &>/dev/null; do sleep 1; done +$STD temporal operator namespace create --namespace default +msg_ok "Created Default Namespace" + +motd_ssh +customize +cleanup_lxc diff --git a/json/temporal.json b/json/temporal.json new file mode 100644 index 0000000000..c364a88042 --- /dev/null +++ b/json/temporal.json @@ -0,0 +1,49 @@ +{ + "name": "Temporal", + "slug": "temporal", + "categories": [ + 20 + ], + "date_created": "2026-11-09", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 8080, + "documentation": "https://docs.temporal.io/", + "website": "https://temporal.io/", + "repository": "https://github.com/temporalio/temporal", + "logo": "https://cdn.jsdelivr.net/gh/temporalio/ui@main/src/lib/vendor/apple-touch-icon.png", + "description": "Temporal is an open-source durable execution platform. Workflows written in Go, Java, Python, TypeScript, .NET, PHP or Ruby keep their state across crashes, restarts and retries, and the server handles timers, retries, signals and schedules so application code does not have to.", + "install_methods": [ + { + "type": "default", + "script": "ct/temporal.sh", + "config_path": "/etc/temporal/config/production.yaml", + "resources": { + "cpu": 2, + "ram": 2048, + "hdd": 8, + "os": "Debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "The gRPC endpoint on port 7233, the HTTP API on 7243 and the UI on 8080 have no authentication. Keep the container on a trusted network or put it behind a firewall and a TLS proxy.", + "type": "warning" + }, + { + "text": "Point workers and SDK clients at :7233. The temporal CLI is installed in the container and already talks to the local server; the default namespace is created with a 72h retention.", + "type": "info" + }, + { + "text": "The database password lives in /etc/temporal/temporal.env; the server config in /etc/temporal/config/production.yaml reads it from there. Restart temporal after changing either file.", + "type": "info" + } + ] +} From a0ab5f6d3f38e93dd90bfc01bc7dc65d56465593 Mon Sep 17 00:00:00 2001 From: Renan Bastos Date: Wed, 11 Nov 2026 13:57:16 -0300 Subject: [PATCH 2/3] Temporal: create the visibility database without sudo The temporal role gets CREATEDB through PG_DB_SCHEMA_PERMS and temporal-sql-tool creates temporal_visibility itself, the way the upstream setup does it. --- install/temporal-install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install/temporal-install.sh b/install/temporal-install.sh index afd4d82db7..09e7c8a462 100644 --- a/install/temporal-install.sh +++ b/install/temporal-install.sh @@ -14,7 +14,7 @@ network_check update_os PG_VERSION="17" setup_postgresql -PG_DB_NAME="temporal" PG_DB_USER="temporal" setup_postgresql_db +PG_DB_NAME="temporal" PG_DB_USER="temporal" PG_DB_SCHEMA_PERMS="true" setup_postgresql_db fetch_and_deploy_gh_release "temporal" "temporalio/temporal" "prebuild" "latest" "/opt/temporal" "temporal_*_linux_$(arch_resolve).tar.gz" fetch_and_deploy_gh_release "temporal-ui" "temporalio/ui-server" "prebuild" "latest" "/opt/temporal-ui" "ui-server_*_linux_$(arch_resolve).tar.gz" @@ -148,7 +148,7 @@ msg_ok "Configured Temporal" msg_info "Initializing Temporal Database" set -a && source /etc/temporal/temporal.env && set +a -$STD sudo -u postgres psql -c "CREATE DATABASE temporal_visibility WITH OWNER temporal ENCODING 'UTF8' TEMPLATE template0;" +$STD /opt/temporal/temporal-sql-tool --db temporal_visibility create-database $STD /opt/temporal/temporal-sql-tool --db temporal setup-schema -v 0.0 $STD /opt/temporal/temporal-sql-tool --db temporal update-schema --schema-name postgresql/v12/temporal $STD /opt/temporal/temporal-sql-tool --db temporal_visibility setup-schema -v 0.0 From b90e91b22c4372c948e73e9f341c3a5aedc9394c Mon Sep 17 00:00:00 2001 From: Renan Bastos Date: Wed, 11 Nov 2026 14:44:32 -0300 Subject: [PATCH 3/3] Temporal: drop the HTTP API port, bound the health wait Nothing in the container uses the frontend HTTP API on 7243: SDKs, the CLI and the UI all talk gRPC on 7233. The wait for cluster health now gives up after 60 seconds, so a server that does not start fails the install instead of hanging it. --- install/temporal-install.sh | 7 ++++--- json/temporal.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/install/temporal-install.sh b/install/temporal-install.sh index 09e7c8a462..dbf7667dc8 100644 --- a/install/temporal-install.sh +++ b/install/temporal-install.sh @@ -76,7 +76,6 @@ services: grpcPort: 7233 membershipPort: 6933 bindOnIP: "0.0.0.0" - httpPort: 7243 matching: rpc: @@ -107,7 +106,6 @@ clusterMetadata: initialFailoverVersion: 1 rpcName: "frontend" rpcAddress: "127.0.0.1:7233" - httpAddress: "127.0.0.1:7243" dcRedirectionPolicy: policy: "noop" @@ -196,7 +194,10 @@ systemctl enable -q --now temporal temporal-ui msg_ok "Created Services" msg_info "Creating Default Namespace" -until temporal operator cluster health &>/dev/null; do sleep 1; done +for _ in {1..60}; do + temporal operator cluster health &>/dev/null && break + sleep 1 +done $STD temporal operator namespace create --namespace default msg_ok "Created Default Namespace" diff --git a/json/temporal.json b/json/temporal.json index c364a88042..6ff0e5b312 100644 --- a/json/temporal.json +++ b/json/temporal.json @@ -34,7 +34,7 @@ }, "notes": [ { - "text": "The gRPC endpoint on port 7233, the HTTP API on 7243 and the UI on 8080 have no authentication. Keep the container on a trusted network or put it behind a firewall and a TLS proxy.", + "text": "The gRPC endpoint on port 7233 and the UI on 8080 have no authentication. Keep the container on a trusted network or put it behind a firewall and a TLS proxy.", "type": "warning" }, {