Kestra is an open-source workflow orchestration platform that runs YAML-defined pipelines on schedules, triggers, or events, with a web UI for managing executions, logs, and metadata. This guide deploys Kestra using Docker Compose with a PostgreSQL backend and Traefik handling automatic HTTPS. By the end, you'll have Kestra running a sample workflow with a SUCCESS execution at your domain.
Set Up the Directory Structure
1. Create the project directories:
$ mkdir -p ~/kestra/data/{postgres,kestra,traefik}
$ cd ~/kestra
postgres/ holds the database, kestra/ holds execution artifacts, traefik/ holds Let's Encrypt certificates.
2. Create the environment file:
$ nano .env
POSTGRES_DB=kestra
POSTGRES_USER=kestra
POSTGRES_PASSWORD=STRONG-PASSWORD
DOMAIN=kestra.example.com
LETSENCRYPT_EMAIL=admin@example.com
Deploy with Docker Compose
1. Create the Compose manifest:
$ nano docker-compose.yml
services:
traefik:
image: traefik:v3.6
restart: unless-stopped
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik:/letsencrypt
postgres:
image: postgres:15
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ./data/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
kestra:
image: kestra/kestra:v1.3.6
restart: unless-stopped
command: server standalone
environment:
KESTRA_CONFIGURATION: |
datasources:
postgres:
url: jdbc:postgresql://postgres:5432/${POSTGRES_DB}
driverClassName: org.postgresql.Driver
username: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
kestra:
repository:
type: postgres
storage:
type: local
local:
basePath: /app/storage
queue:
type: postgres
volumes:
- ./data/kestra:/app/storage
depends_on:
postgres:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.kestra.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.kestra.entrypoints=websecure"
- "traefik.http.routers.kestra.tls.certresolver=letsencrypt"
- "traefik.http.services.kestra.loadbalancer.server.port=8080"
2. Start the services:
$ docker compose up -d
3. Verify the services are running:
$ docker compose ps
$ docker compose logs
Create the Admin Account
- Open
https://kestra.example.com. - On the Create an admin user page, fill in email and a password with ≥8 characters, ≥1 uppercase, ≥1 number.
- Click Create admin user, then Start Kestra UI.
Create and Run a Sample Workflow
1. Click **Flows → Create in the sidebar, then paste:**
id: hello_world
namespace: demo
tasks:
- id: log_message
type: io.kestra.core.tasks.log.Log
message: "Hello from Kestra!"
2. Click **Save, then Execute in the top right.**
3. Open **Executions and select the run** — the status should read SUCCESS.
Next Steps
Kestra is running and served securely over HTTPS. From here you can:
- Add schedules, webhook triggers, and event-based triggers to your flows
- Install plugins for AWS, GCP, Kubernetes, dbt, and Python tasks
- Wire RBAC for multi-team usage and store secrets via the secret manager
For the full guide with additional tips, visit the original article on Vultr Docs.
Top comments (0)