feat(postiz): add temporal server for workflow orchestration

add temporal and temporal-ui services to the postiz profile for
workflow orchestration. includes caddy reverse proxy with basic
auth, secret generation, and welcome page integration.
This commit is contained in:
Yury Kossakovsky
2026-01-16 18:42:54 -07:00
parent 19cd6b6f91
commit 4a6f1c0e01
8 changed files with 105 additions and 5 deletions

View File

@@ -314,14 +314,16 @@ ${SERVICE_NAME_UPPER}_PASSWORD=
${SERVICE_NAME_UPPER}_PASSWORD_HASH=
```
### 3.3 GOST_NO_PROXY (if using proxy-env)
### 3.3 GOST_NO_PROXY (REQUIRED for ALL services)
Add service to comma-separated list:
**CRITICAL:** Add ALL new service container names to the comma-separated list to prevent internal Docker traffic from going through the proxy:
```dotenv
GOST_NO_PROXY=localhost,127.0.0.1,...existing...,$ARGUMENTS
```
This applies to ALL services, not just those using `<<: *proxy-env`. Internal service-to-service communication must bypass the proxy.
---
## STEP 4: scripts/03_generate_secrets.sh
@@ -706,6 +708,7 @@ bash -n scripts/07_final_report.sh
- [ ] `docker-compose.yml`: caddy environment vars (if external)
- [ ] `Caddyfile`: reverse proxy block (if external)
- [ ] `.env.example`: hostname added
- [ ] `.env.example`: service added to `GOST_NO_PROXY` (ALL internal services must be listed)
- [ ] `scripts/03_generate_secrets.sh`: password in `VARS_TO_GENERATE`
- [ ] `scripts/04_wizard.sh`: service in `base_services_data`
- [ ] `scripts/generate_welcome_page.sh`: `SERVICES_ARRAY` entry
@@ -722,7 +725,6 @@ bash -n scripts/07_final_report.sh
### If Outbound Proxy (AI API calls)
- [ ] `docker-compose.yml`: `<<: *proxy-env` in environment
- [ ] `.env.example`: service added to `GOST_NO_PROXY`
- [ ] `docker-compose.yml`: healthcheck bypasses proxy
### If Database Required

View File

@@ -164,6 +164,7 @@ NOCODB_HOSTNAME=nocodb.yourdomain.com
PADDLEOCR_HOSTNAME=paddleocr.yourdomain.com
PORTAINER_HOSTNAME=portainer.yourdomain.com
POSTIZ_HOSTNAME=postiz.yourdomain.com
TEMPORAL_UI_HOSTNAME=temporal.yourdomain.com
PROMETHEUS_HOSTNAME=prometheus.yourdomain.com
QDRANT_HOSTNAME=qdrant.yourdomain.com
RAGAPP_HOSTNAME=ragapp.yourdomain.com
@@ -433,7 +434,7 @@ GOST_UPSTREAM_PROXY=
# Internal services bypass list (prevents internal Docker traffic from going through proxy)
# Includes: Docker internal networks (172.16-31.*, 10.*), Docker DNS (127.0.0.11), and all service hostnames
GOST_NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.local,postgres,postgres:5432,redis,redis:6379,caddy,ollama,neo4j,qdrant,weaviate,clickhouse,minio,searxng,crawl4ai,gotenberg,langfuse-web,langfuse-worker,flowise,n8n,n8n-import,n8n-worker-1,n8n-worker-2,n8n-worker-3,n8n-worker-4,n8n-worker-5,n8n-worker-6,n8n-worker-7,n8n-worker-8,n8n-worker-9,n8n-worker-10,n8n-runner-1,n8n-runner-2,n8n-runner-3,n8n-runner-4,n8n-runner-5,n8n-runner-6,n8n-runner-7,n8n-runner-8,n8n-runner-9,n8n-runner-10,letta,lightrag,docling,postiz,ragflow,ragflow-mysql,ragflow-minio,ragflow-redis,ragflow-elasticsearch,ragapp,open-webui,comfyui,waha,libretranslate,paddleocr,nocodb,db,studio,kong,auth,rest,realtime,storage,imgproxy,meta,functions,analytics,vector,supavisor,gost
GOST_NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.local,postgres,postgres:5432,redis,redis:6379,caddy,ollama,neo4j,qdrant,weaviate,clickhouse,minio,searxng,crawl4ai,gotenberg,langfuse-web,langfuse-worker,flowise,n8n,n8n-import,n8n-worker-1,n8n-worker-2,n8n-worker-3,n8n-worker-4,n8n-worker-5,n8n-worker-6,n8n-worker-7,n8n-worker-8,n8n-worker-9,n8n-worker-10,n8n-runner-1,n8n-runner-2,n8n-runner-3,n8n-runner-4,n8n-runner-5,n8n-runner-6,n8n-runner-7,n8n-runner-8,n8n-runner-9,n8n-runner-10,letta,lightrag,docling,postiz,temporal,temporal-ui,ragflow,ragflow-mysql,ragflow-minio,ragflow-redis,ragflow-elasticsearch,ragapp,open-webui,comfyui,waha,libretranslate,paddleocr,nocodb,db,studio,kong,auth,rest,realtime,storage,imgproxy,meta,functions,analytics,vector,supavisor,gost
############
# Functions - Configuration for Functions
@@ -489,6 +490,13 @@ RAGAPP_PASSWORD_HASH=
POSTIZ_DISABLE_REGISTRATION=false
############
# Temporal UI credentials (for Caddy basic auth)
############
TEMPORAL_UI_USERNAME=
TEMPORAL_UI_PASSWORD=
TEMPORAL_UI_PASSWORD_HASH=
############
# Postiz Social Media Integrations
# Leave blank if not used. Provide credentials from each platform.
@@ -539,6 +547,7 @@ MASTODON_URL=https://mastodon.social
MASTODON_CLIENT_ID=
MASTODON_CLIENT_SECRET=
############
# WAHA (WhatsApp HTTP API) configuration
# Engine: NOWEB | WEBJS | GOWS

View File

@@ -1,5 +1,12 @@
# Changelog
## [Unreleased]
## [1.2.1] - 2026-01-16
### Added
- **Temporal** - Temporal server and UI for Postiz workflow orchestration (#33)
## [1.2.0] - 2026-01-12
### Added

View File

@@ -81,6 +81,14 @@
reverse_proxy postiz:5000
}
# Temporal UI (workflow orchestration for Postiz)
{$TEMPORAL_UI_HOSTNAME} {
basic_auth {
{$TEMPORAL_UI_USERNAME} {$TEMPORAL_UI_PASSWORD_HASH}
}
reverse_proxy temporal-ui:8080
}
# Databasus
{$DATABASUS_HOSTNAME} {
reverse_proxy databasus:4005

View File

@@ -339,6 +339,9 @@ services:
PORTAINER_HOSTNAME: ${PORTAINER_HOSTNAME}
DATABASUS_HOSTNAME: ${DATABASUS_HOSTNAME}
POSTIZ_HOSTNAME: ${POSTIZ_HOSTNAME}
TEMPORAL_UI_HOSTNAME: ${TEMPORAL_UI_HOSTNAME}
TEMPORAL_UI_USERNAME: ${TEMPORAL_UI_USERNAME}
TEMPORAL_UI_PASSWORD_HASH: ${TEMPORAL_UI_PASSWORD_HASH}
PROMETHEUS_HOSTNAME: ${PROMETHEUS_HOSTNAME}
PROMETHEUS_PASSWORD_HASH: ${PROMETHEUS_PASSWORD_HASH}
PROMETHEUS_USERNAME: ${PROMETHEUS_USERNAME}
@@ -778,6 +781,50 @@ services:
- portainer_data:/data
- ${DOCKER_SOCKET_LOCATION:-/var/run/docker.sock}:/var/run/docker.sock
temporal:
image: temporalio/auto-setup:latest
container_name: temporal
profiles: ["postiz"]
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
environment:
DB: postgres12
POSTGRES_USER: postgres
POSTGRES_PWD: ${POSTGRES_PASSWORD}
POSTGRES_SEEDS: postgres
DB_PORT: 5432
TEMPORAL_UINAMESPACE: default
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "tctl cluster health | grep -q SERVING || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
temporal-ui:
image: temporalio/ui:latest
container_name: temporal-ui
profiles: ["postiz"]
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
environment:
TEMPORAL_UIADDRESS: temporal:7233
TEMPORAL_UICORS_ORIGINS: http://localhost:3000
depends_on:
temporal:
condition: service_healthy
postiz:
image: ghcr.io/gitroomhq/postiz-app:latest
container_name: postiz
@@ -796,6 +843,7 @@ services:
NEXT_PUBLIC_UPLOAD_DIRECTORY: "/uploads"
REDIS_URL: "redis://redis:6379"
STORAGE_PROVIDER: "local"
TEMPORAL_UIADDRESS: temporal:7233
UPLOAD_DIRECTORY: "/uploads"
# Social Media API Settings
X_API_KEY: ${X_API_KEY}
@@ -837,6 +885,8 @@ services:
condition: service_healthy
redis:
condition: service_healthy
temporal:
condition: service_healthy
databasus:
image: databasus/databasus:latest

View File

@@ -55,6 +55,7 @@ EMAIL_VARS=(
"PROMETHEUS_USERNAME"
"RAGAPP_USERNAME"
"SEARXNG_USERNAME"
"TEMPORAL_UI_USERNAME"
"WAHA_DASHBOARD_USERNAME"
"WEAVIATE_USERNAME"
"WELCOME_USERNAME"
@@ -114,6 +115,7 @@ declare -A VARS_TO_GENERATE=(
["RAGFLOW_REDIS_PASSWORD"]="password:32"
["SEARXNG_PASSWORD"]="password:32" # Added SearXNG admin password
["SECRET_KEY_BASE"]="base64:64" # 48 bytes -> 64 chars
["TEMPORAL_UI_PASSWORD"]="password:32" # Temporal UI basic auth password
["VAULT_ENC_KEY"]="alphanum:32"
["WAHA_DASHBOARD_PASSWORD"]="password:32"
["WEAVIATE_API_KEY"]="secret:48" # API Key for Weaviate service (36 bytes -> 48 chars base64)
@@ -564,7 +566,7 @@ if [[ -n "$template_no_proxy" ]]; then
fi
# Hash passwords using caddy with bcrypt (consolidated loop)
SERVICES_NEEDING_HASH=("PROMETHEUS" "SEARXNG" "COMFYUI" "PADDLEOCR" "RAGAPP" "LT" "DOCLING" "WELCOME")
SERVICES_NEEDING_HASH=("PROMETHEUS" "SEARXNG" "COMFYUI" "PADDLEOCR" "RAGAPP" "LT" "DOCLING" "TEMPORAL_UI" "WELCOME")
for service in "${SERVICES_NEEDING_HASH[@]}"; do
password_var="${service}_PASSWORD"

View File

@@ -327,6 +327,20 @@ if is_profile_active "postiz"; then
}")
fi
# Temporal UI
if is_profile_active "postiz"; then
SERVICES_ARRAY+=(" \"temporal-ui\": {
\"hostname\": \"$(json_escape "$TEMPORAL_UI_HOSTNAME")\",
\"credentials\": {
\"username\": \"$(json_escape "$TEMPORAL_UI_USERNAME")\",
\"password\": \"$(json_escape "$TEMPORAL_UI_PASSWORD")\"
},
\"extra\": {
\"note\": \"Workflow orchestration admin for Postiz\"
}
}")
fi
# WAHA
if is_profile_active "waha"; then
SERVICES_ARRAY+=(" \"waha\": {

View File

@@ -340,6 +340,14 @@
category: 'tools',
docsUrl: 'https://docs.postiz.com'
},
'temporal-ui': {
name: 'Temporal UI',
description: 'Postiz Workflow Orchestration',
icon: 'TM',
color: 'bg-violet-500',
category: 'tools',
docsUrl: 'https://docs.temporal.io/'
},
'waha': {
name: 'WAHA',
description: 'WhatsApp HTTP API',