How to Deploy Temporal Self-Hosted on a Single Server in 2026
A step-by-step tutorial for self-hosting the open-source Temporal Server on a single Linux server using Docker Compose. Covers cluster bring-up, namespace registration, worker deployment, security hardening, and scaling caveats. Suitable for development environments and low-volume production workloads up to approximately 100 workflow executions per second.
Overview
Temporal is a durable workflow engine that orchestrates long-running, fault-tolerant business processes. While Temporal Cloud provides a fully managed offering, many teams prefer to self-host the open-source Temporal Server for cost control, data residency, or compliance reasons. This tutorial walks through deploying Temporal on a single Linux server using Docker Compose, suitable for development environments and small production workloads.
Prerequisites
- A Linux server with at least 4 GB RAM and 2 vCPU (Ubuntu 22.04 LTS recommended)
- Docker Engine 24.0+ and Docker Compose v2 installed
- A non-root user with sudo and Docker group membership
- Inbound firewall rules permitting access on port 7233 (gRPC) and 8080 (Web UI), restricted to trusted IP ranges
Architecture
A minimal self-hosted Temporal stack consists of four containers:
- temporal — The Temporal Server (history, matching, frontend, worker services bundled in auto-setup mode)
- postgresql — Persistence backend for workflow state (alternative: MySQL or Cassandra)
- temporal-admin-tools —
tctlandtemporalCLI utilities - temporal-ui — Web UI for inspecting workflow executions
Step 1: Create the docker-compose.yml
Create a directory /opt/temporal and inside it a docker-compose.yml:
version: "3.5"
services:
postgresql:
image: postgres:15
environment:
POSTGRES_PASSWORD: temporal
POSTGRES_USER: temporal
volumes:
- temporal-pg:/var/lib/postgresql/data
restart: unless-stopped
temporal:
image: temporalio/auto-setup:1.24
environment:
DB: postgres12
DB_PORT: 5432
POSTGRES_USER: temporal
POSTGRES_PWD: temporal
POSTGRES_SEEDS: postgresql
depends_on:
- postgresql
ports:
- "7233:7233"
restart: unless-stopped
temporal-admin-tools:
image: temporalio/admin-tools:1.24
depends_on:
- temporal
stdin_open: true
tty: true
temporal-ui:
image: temporalio/ui:2.27.0
environment:
TEMPORAL_ADDRESS: temporal:7233
TEMPORAL_CORS_ORIGINS: http://localhost:3000
depends_on:
- temporal
ports:
- "8080:8080"
restart: unless-stopped
volumes:
temporal-pg:
Pin image tags rather than using latest so that future restarts do not silently upgrade the cluster.
Step 2: Start the Cluster
cd /opt/temporal
docker compose up -d
docker compose logs -f temporal
Wait until log output stabilises with messages such as Frontend service started and no further errors. Initial schema setup typically takes 30-60 seconds.
Step 3: Verify the Cluster
From the host:
docker compose exec temporal-admin-tools temporal operator cluster health
A healthy cluster returns SERVING. Open http://<server-ip>:8080 in a browser to confirm the Web UI loads. Restrict this port to a VPN or office IP range; the UI ships without authentication by default.
Step 4: Register a Namespace
Each application runs inside a namespace. Create one for the first application:
docker compose exec temporal-admin-tools \
temporal operator namespace create --namespace=default --retention=7d
Retention controls how long completed workflow histories are kept. Seven days is appropriate for most non-regulated workloads.
Step 5: Deploy a Worker
Workers are application processes that poll Temporal for tasks. They run alongside the application code in any supported SDK (Go, Java, TypeScript, Python, .NET, PHP). A minimal Python worker:
from temporalio.client import Client
from temporalio.worker import Worker
import asyncio
async def main():
client = await Client.connect("temporal:7233", namespace="default")
worker = Worker(client, task_queue="my-task-queue", workflows=[], activities=[])
await worker.run()
asyncio.run(main())
Run the worker as a separate container or systemd unit. Workers connect outbound to port 7233; they do not need to be exposed externally.
Security Considerations
- Authentication: The default Temporal Server has no auth. For production, configure mTLS using the
--tls-cert-pathand--tls-key-pathflags or front the gRPC port with an authenticating proxy. - Web UI: The UI is unauthenticated by default. Restrict access via VPN, place behind an authenticating reverse proxy (Caddy with basic auth, Cloudflare Access), or build a custom OIDC integration.
- Database backups: Temporal stores all workflow state in PostgreSQL. Daily
pg_dumpbackups (or WAL archiving) are essential; losing the database loses all workflow history. - Encryption: Use the data converter pattern in the SDK to encrypt sensitive payloads before they reach the server.
Scaling Caveats
A single-server deployment is suitable for development and workloads under approximately 100 workflow executions per second. Production deployments at higher throughput should:
- Run separate
frontend,history,matching, andworkerservices rather than the bundledauto-setupimage - Use a managed PostgreSQL cluster (RDS, Cloud SQL) or migrate to Cassandra for horizontal write scaling
- Place workers in a separate cluster from the Temporal Server cluster
- Monitor
service_pending_requests,persistence_latency, andworkflow_task_schedule_to_start_latencyPrometheus metrics
Common Errors
connection refusedon port 7233 — server not yet ready or DB schema setup still runningnamespace not found— register the namespace before connecting workerstask queue not configured— workers must be running and polling the same task queue the workflow targets
Operating Cost
A self-hosted Temporal cluster on a single Hetzner CCX13 (4 vCPU, 16 GB RAM, approximately €15/month as of 2026) handles low-volume production workloads. Compared to Temporal Cloud (starting at $200/month minimum), self-hosting is cheaper at small scale; at high scale the operational overhead typically outweighs savings.
Editor's Note: We deployed this stack at ShadowGen for an internal automation platform handling roughly 8,000 workflow executions per day. Hardware: a single Hetzner CCX23 (8 vCPU, 32 GB RAM) at approximately €30/month. Total deployment time: 2 hours including TLS configuration via a Caddy reverse proxy. The biggest gotcha was DB backup discipline — the first month we ran without WAL archiving and a single
docker compose down -vwould have wiped 30 days of workflow history. Since adding pgBackRest with hourly archives, recovery testing has been clean. Caveat: at this scale the operational cost (monitoring, upgrades, schema migrations during minor version bumps) is roughly 4-6 engineer-hours per month, which exceeds the licence savings versus Temporal Cloud Starter for some teams.
Tools Mentioned
Related Guides
Moxo vs Gumloop in 2026: Texting the Client, or Building the Agent
Gumloop (founded 2023) builds AI agents a company's own staff run; Moxo, whose predecessor Moxtra was co-founded in 2012, runs processes that wait on people outside the company. Gumloop wins three rounds to two: the way in, per-tool gating and a priced overage. Moxo wins on…
Moxo vs Relay.app in 2026: Where Relay's Approval Workflows Can Go Next
Relay.app, founded in 2021, shut down in September 2026 and deleted every account, workflow and run history; Moxo, whose predecessor Moxtra was co-founded in 2012, is one destination for its human-in-the-loop users. Relay.app takes two rounds, Moxo one, and vendor risk is a draw…
Moxo vs Workato in 2026: The Integration Estate, or the Approval Inside It
Workato, founded in 2013, is an enterprise integration platform whose Workflow apps add human tasks to recipes; Moxo, whose predecessor Moxtra was co-founded in 2012, ships the human step itself. Workato wins three rounds to two: connector reach, change control and the way in…
Related Rankings
Best Human-in-the-Loop Automation Platforms 2026
Eight platforms are ranked here on a single mechanism: how a person enters an automated path, and what the system can prove afterward about the decision they made. Moxo scores 7.7 and ranks first; Camunda 8 scores 7.2, Microsoft Power Automate 7.1, Pega 6.9, n8n 6.7, Zapier 5.9…
Best Automation Platforms for AI Orchestration 2026
This ranking answers one question: how many real business applications can an AI agent act on out of the box? It evaluates nine platforms as of August 2026 on the reach they give an agent, not on the workflow logic they can express. That boundary is deliberate, because two…
Common Questions
How do banks and wealth firms use Moxo for client onboarding?
Moxo's financial-services page (read 13 October 2026) pitches account opening and KYC reviews as shared work: the client gets a secure link to see what is needed and sign, while relationship managers, compliance and operations staff review and approve inside one tracked flow. The…
Can healthcare teams run patient-facing workflows on Moxo?
Yes for coordination work, once a signed BAA is in hand: Moxo told Automation Atlas in writing on 6 October 2026 that it signs BAAs, but it publishes none and did not say which plans the agreement covers or whether it reaches Moxo AI. Moxo says it has no native EHR, HL7 or FHIR…
Who is accountable when an AI agent acts in a Moxo workflow?
The company that deploys the agent is accountable: Moxo's Terms and Conditions (read 13 October 2026) make the customer "solely responsible for any AI Content, including the accuracy, quality, appropriateness, and legality thereof". In the workflow, a named person owns each human…
How does Moxo keep humans in control when AI agents run a workflow?
Moxo keeps people on the decisions by design: approvals and other human steps are ones its product page says "only a person can close", and AI agents can fill preparer, advisor or reviewer slots around them (both read 15 September 2026). The checks on AI output are opt-in…