tva
← Insights

Autoalojamiento de Windmill en Ubuntu: Tutorial Completo de Configuración con Docker y Resolución de Problemas de PostgreSQL

Las plataformas de automatización de flujos de trabajo son esenciales para los equipos de desarrollo modernos, pero las soluciones en la nube como Windmill Cloud pueden resultar costosas a medida que crece el uso. Le mostraremos cómo configurar su propia instancia de Windmill en Ubuntu con Docker Compose e integración con Traefik, superando los problemas críticos de autenticación de PostgreSQL que pueden descarrilar su instalación.

Lo que Construirá

Al finalizar este tutorial, tendrá:

  • Instalación de Windmill completamente funcional con HTTPS
  • Certificados SSL automáticos mediante Let's Encrypt a través de Traefik
  • Base de datos PostgreSQL lista para producción con autenticación adecuada
  • Configuración de workers optimizada en recursos
  • Integrada con la infraestructura Docker existente
  • Configuración lista para producción para automatización profesional de flujos de trabajo

Costo mensual: 4,51EUR (servidor CX11) + costos de dominio -- la misma infraestructura que puede manejar múltiples herramientas de automatización

Requisitos Previos

  • Servidor Ubuntu 24.04 LTS con Docker y Docker Compose instalados
  • Configuración existente de proxy inverso Traefik (consulte nuestra guía de configuración de n8n para la configuración de Traefik)
  • Nombre de dominio apuntando a la IP de su servidor
  • Al menos 4GB de RAM y 2 vCPUs recomendados
  • Acceso SSH y conocimientos básicos de línea de comandos

Comprendiendo Windmill

Windmill es un motor de flujos de trabajo de código abierto que proporciona:

  • Editor visual de flujos de trabajo con soporte para TypeScript/Python/Go
  • Programación de tareas y gestión de ejecución
  • Capacidades de integración con APIs
  • Funciones de colaboración en equipo
  • Autoalojable sin límites de uso

A diferencia del enfoque basado en nodos de n8n, Windmill se centra en flujos de trabajo orientados al código con un potente entorno de desarrollo.

Paso 1: Preparación del Servidor y Estructura de Directorios

Primero, preparemos nuestro entorno de servidor. Usaremos una convención de nombres basada en comidas para las instancias de Windmill para evitar conflictos:

# Create Windmill directory (first instance: "pizza")
mkdir -p /opt/windmill-pizza
cd /opt/windmill-pizza

# Create required subdirectories
mkdir -p postgres-data windmill-data lsp-cache

# Verify directory structure
ls -la

Convención de Nombres: Use nombres simples de comidas para múltiples instancias de Windmill:

  • Primera instancia: pizza
  • Instancias adicionales: pasta, salad, soup, burger, etc.
  • Esto evita conflictos y facilita la gestión

Paso 2: Configuración del Entorno

Cree un archivo de entorno seguro con credenciales adecuadas:

# Generate a secure hex password (no special characters!)
SECURE_PASSWORD=$(openssl rand -hex 16)
echo "Generated password: $SECURE_PASSWORD"

# Create environment file
cat > /opt/windmill-pizza/.env << EOF
# Windmill Image Version
WM_IMAGE=ghcr.io/windmill-labs/windmill:main

# Database Configuration - SECURE PASSWORDS
DATABASE_URL=postgresql://postgres:${SECURE_PASSWORD}@windmill-db:5432/windmill_pizza?sslmode=disable
POSTGRES_PASSWORD=${SECURE_PASSWORD}
POSTGRES_DB=windmill_pizza
POSTGRES_USER=postgres

# Windmill Configuration
BASE_URL=https://windmill.yourdomain.com
RUST_LOG=info

# Worker Configuration
WORKER_GROUP=default
KEEP_JOB_DIR=false

# Instance Identifier
INSTANCE_NAME=pizza
EOF

Crítico: Reemplace windmill.yourdomain.com con su dominio real.

Paso 3: Configuración de Docker Compose

Cree la configuración principal de Docker Compose:

cat > /opt/windmill-pizza/docker-compose.yml << 'EOF'
version: "3.8"

services:
  # PostgreSQL Database for Windmill
  windmill-db:
    image: postgres:16
    container_name: windmill-pizza-db
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    networks:
      - proxy
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Windmill Server
  windmill-server:
    image: ${WM_IMAGE}
    container_name: windmill-pizza-server
    restart: unless-stopped
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - BASE_URL=${BASE_URL}
      - RUST_LOG=${RUST_LOG}
      - MODE=server
    networks:
      - proxy
    depends_on:
      windmill-db:
        condition: service_healthy
    volumes:
      - ./windmill-data:/tmp/windmill
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.windmill-pizza.rule=Host(`windmill.yourdomain.com`)"
      - "traefik.http.routers.windmill-pizza.entrypoints=https"
      - "traefik.http.routers.windmill-pizza.tls.certresolver=letsencrypt"
      - "traefik.http.services.windmill-pizza.loadbalancer.server.port=8000"

  # Windmill Worker
  windmill-worker:
    image: ${WM_IMAGE}
    container_name: windmill-pizza-worker
    restart: unless-stopped
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - BASE_URL=${BASE_URL}
      - RUST_LOG=${RUST_LOG}
      - MODE=worker
      - WORKER_GROUP=${WORKER_GROUP}
      - KEEP_JOB_DIR=${KEEP_JOB_DIR}
    networks:
      - proxy
    depends_on:
      windmill-db:
        condition: service_healthy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./windmill-data:/tmp/windmill
      - worker_dependency_cache:/tmp/windmill/cache
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 2G

networks:
  proxy:
    external: true

volumes:
  worker_dependency_cache:
    driver: local
EOF

Importante: Actualice el dominio en las etiquetas de Traefik para que coincida con su configuración.

Paso 4: El Problema de Contraseñas de PostgreSQL (Problema Crítico)

Aquí es donde la mayoría de las instalaciones de Windmill fallan, y requirió una considerable resolución de problemas para identificar la causa raíz:

El Problema: Caracteres Especiales en las Contraseñas

Al usar openssl rand -base64 32 para generar contraseñas, frecuentemente se obtienen caracteres especiales como =@#%, etc. Estos caracteres causan fallos de autenticación de PostgreSQL en entornos Docker, incluso cuando se escapan correctamente.

Ejemplo de una contraseña problemática:

# This WILL cause authentication failures:
PASSWORD="305t6m9KrChkvbyNEFLEYQ6pqAGlApn9rbJPH3D5y9g="

La Solución: Contraseñas Solo Hexadecimales

Use contraseñas solo hexadecimales que no contengan caracteres especiales:

# This WORKS reliably:
PASSWORD=$(openssl rand -hex 16)
# Example result: 5781b14ec0ec1bc184653ffa5e379411

Problemas Adicionales de Configuración de PostgreSQL

  1. Configuración de Usuario: Use postgres como usuario predeterminado, no usuarios personalizados como windmill_user
  2. Persistencia de Volúmenes: PostgreSQL ignora las variables de entorno POSTGRES_PASSWORD cuando los volúmenes de datos existentes contienen credenciales diferentes
  3. Formato de URL: Incluya ?sslmode=disable en la URL de la base de datos para entornos Docker

Paso 5: Instalación e Inicio

Ahora instalemos Windmill con nuestra configuración corregida:

cd /opt/windmill-pizza

# Verify configuration syntax
docker compose config --quiet

# Pull images
docker compose pull

# Start services
docker compose up -d

# Check status
docker compose ps

Debería ver una salida como:

NAME                    STATUS                    PORTS
windmill-pizza-db       Up (healthy)              5432/tcp
windmill-pizza-server   Up                        8000/tcp
windmill-pizza-worker   Up                        8000/tcp

Paso 6: Resolución de Problemas Comunes

Problema 1: Fallos de Autenticación de PostgreSQL

Síntomas:

windmill-pizza-server | Error: password authentication failed for user "postgres"

Solución:

# Stop containers
docker compose down --volumes

# Remove old data
rm -rf postgres-data/*

# Regenerate hex password
NEW_PASSWORD=$(openssl rand -hex 16)
sed -i "s/POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$NEW_PASSWORD/" .env
sed -i "s/:.*@/:$NEW_PASSWORD@/" .env

# Restart
docker compose up -d

Problema 2: El Contenedor No Inicia

Síntomas:

  • El contenedor se cierra inmediatamente
  • Errores de asignación de recursos

Solución:

# Check container logs
docker logs windmill-pizza-server
docker logs windmill-pizza-db

# Check system resources
docker stats
free -h

Problema 3: Problemas con Certificados SSL

Síntomas:

  • HTTPS no funciona
  • Errores de certificado

Solución:

# Check Traefik logs
docker logs traefik

# Verify DNS resolution
nslookup windmill.yourdomain.com

# Restart Traefik if needed
docker restart traefik

Paso 7: Acceso y Configuración Inicial

Una vez completada la instalación:

  1. Acceda a Windmill: https://windmill.yourdomain.com
  2. Credenciales predeterminadas:
    • Email: admin@windmill.dev
    • Contraseña: changeme
  3. Complete la configuración:
    • Cambie la contraseña de administrador
    • Configure la URL base
    • Configure las cuentas de usuario

Paso 8: Optimización de Recursos

Asignación de Memoria (para servidor de 8GB)

Nuestra configuración asigna recursos de manera eficiente:

  • Servidor Windmill: ~800MB
  • Worker Windmill: 2GB (limitado)
  • PostgreSQL: ~500MB
  • Reserva del Sistema: ~4,7GB

Asignación de CPU (para servidor de 4 vCPU)

  • Worker: 1 vCPU (limitado)
  • Otros servicios: 3 vCPUs (compartidos)

Regla de escalado: 1 worker por vCPU con 1-2GB de RAM cada uno

Paso 9: Endurecimiento para Producción

Crear Script de Copia de Seguridad

cat > /opt/windmill-pizza/backup.sh << 'EOF'
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p /opt/backups
docker compose exec windmill-db pg_dump -U postgres windmill_pizza > /opt/backups/windmill_pizza_${DATE}.sql
echo "Backup created: windmill_pizza_${DATE}.sql"
EOF

chmod +x /opt/windmill-pizza/backup.sh

Configurar Monitoreo

# Monitor container health
docker compose ps

# Check resource usage
docker stats

# Monitor logs
docker compose logs -f windmill-server

Configurar Actualizaciones Automatizadas

cat > /opt/windmill-pizza/update.sh << 'EOF'
#!/bin/bash
cd /opt/windmill-pizza
docker compose pull
docker compose up -d --force-recreate
EOF

chmod +x /opt/windmill-pizza/update.sh

Paso 10: Configuración Avanzada

Integración con SMTP Existente

Si tiene un servidor de correo (como el de nuestra configuración de n8n), intégrelo:

# Add to docker-compose.yml environment for windmill-server:
- SMTP_HOST=mailserver
- SMTP_PORT=25
- SMTP_USERNAME=
- SMTP_PASSWORD=
- SMTP_FROM=noreply@yourdomain.com

Múltiples Instancias de Windmill

Para equipos que requieren entornos aislados:

# Create second instance
cp -r /opt/windmill-pizza /opt/windmill-pasta

# Update configuration
sed -i 's/pizza/pasta/g' /opt/windmill-pasta/.env
sed -i 's/windmill.yourdomain.com/pasta.yourdomain.com/g' /opt/windmill-pasta/.env

# Generate new password
NEW_PASSWORD=$(openssl rand -hex 16)
sed -i "s/POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$NEW_PASSWORD/" /opt/windmill-pasta/.env

# Update docker-compose.yml
sed -i 's/pizza/pasta/g' /opt/windmill-pasta/docker-compose.yml
sed -i 's/windmill.yourdomain.com/pasta.yourdomain.com/g' /opt/windmill-pasta/docker-compose.yml

Consideraciones de Seguridad

Aislamiento de Red

  • PostgreSQL solo accesible dentro de la red Docker
  • Sin puertos de base de datos externos expuestos
  • Terminación HTTPS a nivel de Traefik

Límites de Recursos

  • Los contenedores de workers tienen límites de CPU y memoria
  • Previene ataques de agotamiento de recursos
  • Configurable según la capacidad del servidor

Seguridad SSL

  • Certificados automáticos de Let's Encrypt
  • Redirecciones de HTTP a HTTPS
  • Configuración TLS moderna

Monitoreo y Mantenimiento

Verificaciones Semanales de Salud

# Container status
docker compose ps

# Resource usage
docker stats --no-stream

# Log analysis
docker compose logs | grep -i error

Mantenimiento Mensual

# Update containers
cd /opt/windmill-pizza
./update.sh

# Clean old data
docker system prune -f

# Backup database
./backup.sh

Desglose de Costos y Comparación

Costos Mensuales

Configuración autoalojada:

  • Hetzner CX21 (4GB RAM): 8,46EUR/mes
  • Costos de dominio: ~1EUR/mes
  • Total: ~9,50EUR/mes

Comparación con Windmill Cloud:

  • Plan de equipo: $30/mes por usuario
  • Ahorro: $250+ anuales para equipos pequeños

Beneficios de Rendimiento

Ventajas del autoalojamiento:

  • Ejecuciones de flujos de trabajo ilimitadas
  • Sin límites de velocidad externos
  • Control total de los datos
  • Integraciones personalizadas
  • Flexibilidad de escalado de recursos

Referencia de Resolución de Problemas

Diagnóstico Rápido

# Container health
docker compose ps | grep -E "(healthy|Up)"

# Network connectivity
docker network inspect proxy

# Database connection
docker compose exec windmill-db psql -U postgres -d windmill_pizza -c "SELECT version();"

# Log analysis
docker compose logs --tail 50 windmill-server | grep -E "(ERROR|WARN)"

Patrones de Error Comunes

  1. "password authentication failed" -- Use contraseñas hexadecimales, limpie los volúmenes
  2. "connection refused" -- Verifique la configuración de red
  3. "certificate errors" -- Verifique DNS y la configuración de Traefik
  4. "out of memory" -- Ajuste los límites de recursos del worker

Escalando su Infraestructura Windmill

Escalado Horizontal

Para entornos de alto volumen:

# Add additional workers
windmill-worker-2:
  image: ${WM_IMAGE}
  container_name: windmill-pizza-worker-2
  environment:
    - DATABASE_URL=${DATABASE_URL}
    - MODE=worker
    - WORKER_GROUP=heavy
  deploy:
    resources:
      limits:
        cpus: '2'
        memory: 4G

Escalado Vertical

Actualice los recursos del servidor:

  • CX31 (8GB RAM): 16,07EUR/mes para cargas pesadas
  • CX41 (16GB RAM): 29,75EUR/mes para uso empresarial

Integración con Infraestructura Existente

Trabajando con n8n

Si ya está ejecutando n8n (de nuestros tutoriales anteriores):

  • Windmill maneja flujos de trabajo orientados al código
  • n8n maneja automatizaciones visuales y simples
  • Ambos comparten el mismo proxy Traefik
  • Bases de datos separadas previenen conflictos

Servicios Compartidos

Aproveche la infraestructura existente:

  • Traefik: Gestiona SSL para todos los servicios
  • Servidor de correo: SMTP compartido para notificaciones
  • Monitoreo: Registro y métricas unificados
  • Copias de seguridad: Estrategia de respaldo centralizada

Conclusión

El autoalojamiento de Windmill proporciona automatización de flujos de trabajo de nivel empresarial a una fracción de los costos de alojamiento en la nube. La clave del éxito es comprender los requisitos de autenticación de PostgreSQL y usar contraseñas solo hexadecimales para evitar problemas de caracteres especiales que pueden descarrilar las instalaciones.

Beneficios Clave de esta Configuración

  • Rentable: Ahorre cientos anualmente comparado con soluciones en la nube
  • Listo para producción: Maneja cargas de trabajo empresariales de manera fiable
  • Seguro: HTTPS, redes aisladas y límites de recursos
  • Escalable: Fácil de agregar workers y recursos según sea necesario
  • Privado: Su código y datos nunca abandonan su infraestructura

Esta configuración ha sido probada en entornos de producción y proporciona la fiabilidad necesaria para la automatización de flujos de trabajo críticos de negocio. Los pasos de resolución de problemas abordan problemas del mundo real encontrados durante la implementación, particularmente los problemas de autenticación de PostgreSQL que afectan a muchas instalaciones autoalojadas.

Para requisitos complejos de flujos de trabajo o implementaciones empresariales, considere la consulta profesional para optimizar su caso de uso específico y asegurar una asignación óptima de recursos del servidor.

Próximos Pasos


Acerca de tva

tva garantiza la gestión integral de infraestructura de sistemas de bases de datos, entornos en la nube y cadenas de suministro globales. Nuestro enfoque metódico combina protocolos de seguridad rigurosos con optimización del rendimiento, mientras que los servicios de asesoría estratégica permiten la coordinación precisa tanto de capacidades digitales como de activos físicos, manteniendo los más altos estándares de excelencia operativa y cumplimiento normativo en todos los compromisos.

Visite tva.sg para más información sobre nuestros servicios y tutoriales adicionales de automatización.