Skip to main content
Tutorials13 min read

How to Self-Host Kestra on a VPS: Complete 2026 Guide

Deploy Kestra workflow orchestration on your own VPS with Docker Compose. Build scheduled and event-driven workflows with a declarative YAML interface.

By AutomationVPS

Why Self-Host Kestra?

Kestra is an open-source orchestration platform for building scheduled and event-driven workflows using a declarative YAML interface. Unlike visual-only tools, Kestra lets you define workflows as code while providing a full web UI for monitoring, debugging, and manual triggers.

The current LTS release is Kestra v1.3 (March 2026), which introduced a Kill Switch for emergency workflow stops, centralized credential management, and the kestractl CLI for CI/CD integration. Kestra also includes an AI Copilot for generating workflows from natural language and supports AI agent integrations with OpenAI, Claude, and Gemini.

Self-hosting Kestra gives you unlimited workflow executions, full data ownership, and integration with 600+ plugins — all without per-task pricing.

What You'll Need

Before we start, make sure you have:

  • A VPS with at least 4 GB RAM and 2 vCPU (we recommend Hostinger VPS KVM 1 at $6.49/mo or Contabo at $4.50/mo for 8 GB RAM)
  • A domain name pointed to your VPS IP address
  • Basic familiarity with Linux command line
  • SSH access to your server

Kestra's official minimum requirements are 4 GB RAM and 2 vCPU. It runs as a Java application with PostgreSQL, so it needs more resources than lightweight tools. For production workloads with many concurrent workflows, 8 GB RAM is recommended.

Step 1: Prepare Your VPS

Connect to your VPS via SSH and update the system:

ssh root@your-server-ip
apt update && apt upgrade -y

Step 2: Install Docker and Docker Compose

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
apt install docker-compose-plugin -y

Step 3: Download the Official Docker Compose File

mkdir -p /opt/kestra && cd /opt/kestra
curl -o docker-compose.yml https://raw.githubusercontent.com/kestra-io/kestra/develop/docker-compose.yml

Step 4: Configure the Deployment

The official docker-compose.yml sets up two services: PostgreSQL (for state and queue storage) and Kestra (in standalone mode). Here's the key structure:

volumes:
  postgres-data: {}
  kestra-data: {}

services:
  postgres:
    image: postgres:18
    environment:
      POSTGRES_DB: kestra
      POSTGRES_USER: kestra
      POSTGRES_PASSWORD: k3str4
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d kestra -U kestra"]
      interval: 30s
      timeout: 10s
      retries: 10

  kestra:
    image: kestra/kestra:latest
    command: server standalone
    ports:
      - "8080:8080"
      - "8081:8081"
    environment:
      KESTRA_CONFIGURATION: |
        datasources:
          postgres:
            url: jdbc:postgresql://postgres:5432/kestra
            driver-class-name: org.postgresql.Driver
            username: kestra
            password: k3str4
        kestra:
          server:
            basic-auth:
              username: admin
              password: kestra
          repository:
            type: postgres
          storage:
            type: local
            local:
              base-path: "/app/storage"
          queue:
            type: postgres
    volumes:
      - kestra-data:/app/storage
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      postgres:
        condition: service_healthy

Before starting, update the default passwords:

  1. Change POSTGRES_PASSWORD (and the matching password in the JDBC URL)
  2. Change kestra.server.basic-auth.password to a strong password

Kestra runs on port 8080 (web UI + API) and port 8081 (metrics).

Step 5: Start Kestra

docker compose up -d

Monitor the startup:

docker compose logs -f kestra

Once you see the startup complete message, access Kestra at http://your-server-ip:8080.

Log in with the basic-auth username and password you configured.

Step 6: Set Up SSL with Nginx

Install Nginx and Certbot:

apt install nginx certbot python3-certbot-nginx -y

Create an Nginx configuration at /etc/nginx/sites-available/kestra:

server {
    listen 80;
    server_name kestra.yourdomain.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 600s;
        proxy_redirect off;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_buffering off;
        proxy_cache off;
    }
}

Important: The proxy_buffering off and proxy_cache off directives are required for Kestra's Server-Sent Events (SSE), which stream real-time execution logs. The 600s read timeout is needed for long-running SSE connections.

Enable and secure:

ln -s /etc/nginx/sites-available/kestra /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
certbot --nginx -d kestra.yourdomain.com

Restrict Docker to localhost:

ports:
  - "127.0.0.1:8080:8080"
  - "127.0.0.1:8081:8081"

Step 7: Create Your First Workflow

Kestra workflows are defined in YAML. Here's a simple example you can paste into the editor:

id: hello_world
namespace: tutorials

tasks:
  - id: greet
    type: io.kestra.plugin.core.log.Log
    message: "Hello from Kestra!"

  - id: run_python
    type: io.kestra.plugin.scripts.python.Script
    script: |
      import datetime
      print(f"Current time: {datetime.datetime.now()}")

triggers:
  - id: daily
    type: io.kestra.plugin.core.trigger.Schedule
    cron: "0 9 * * *"

This workflow runs a log message and a Python script every day at 9 AM. Kestra's plugin system supports hundreds of integrations including databases, cloud services, messaging platforms, and more.

Optimization Tips

  • Use the AI Copilot — Kestra's built-in AI can generate workflow YAML from natural language descriptions
  • Set up backups — Back up PostgreSQL regularly: docker exec kestra-postgres-1 pg_dump -U kestra kestra > /backups/kestra-$(date +%Y%m%d).sql
  • Configure external storage — For production, switch from local storage to S3, GCS, or MinIO by updating the kestra.storage configuration
  • Monitor with metrics — Port 8081 exposes Prometheus-compatible metrics for monitoring
  • Use the Kill Switch — Kestra v1.3's Kill Switch lets you emergency-stop workflows at the tenant, namespace, or flow level from the UI
  • Keep it updated — Pull the latest image: docker compose pull && docker compose up -d

Which VPS Should You Choose?

Based on our testing, here are our top recommendations for hosting Kestra:

  • Contabo — Best value for Kestra. 4 vCPU and 8 GB RAM at $4.50/mo gives you plenty of room for PostgreSQL and concurrent workflows.
  • Hostinger VPS — Great balance of price and ease of use. KVM 1 plan ($6.49/mo) with 4 GB RAM works for lighter workloads.
  • DigitalOcean — Best documentation and developer tools. The $24/mo Pro plan is comfortable for production use.

Conclusion

Kestra is a powerful orchestration platform that bridges the gap between code-based and visual workflow tools. Its YAML-first approach makes workflows version-controllable and CI/CD-friendly, while the web UI provides excellent observability.

Get started today with Contabo for maximum resources or Hostinger for the easiest setup. You'll have Kestra orchestrating workflows in under 30 minutes.

Ready to start automating? Get a VPS today.

Get started with Hostinger VPS hosting today. Special pricing available.

Get Hostinger VPS

* Affiliate link — we may earn a commission at no extra cost to you

#kestra#self-hosting#docker#orchestration