tva
← Insights

Self-Hosting do Windmill no Ubuntu: Tutorial Completo de Configuração Docker com Resolução de Problemas PostgreSQL

Plataformas de automação de fluxos de trabalho são essenciais para equipes modernas de desenvolvimento, mas soluções em nuvem como o Windmill Cloud podem se tornar caras conforme o uso cresce. Vamos mostrar como configurar sua própria instância Windmill no Ubuntu com Docker Compose e integração Traefik, superando problemas críticos de autenticação PostgreSQL que podem inviabilizar sua instalação.

O Que Você Vai Construir

Ao final deste tutorial, você terá:

  • Instalação Windmill totalmente funcional com HTTPS
  • Certificados SSL automáticos via Let's Encrypt através do Traefik
  • Banco de dados PostgreSQL pronto para produção com autenticação adequada
  • Configuração de worker otimizada para recursos
  • Integrado com infraestrutura Docker existente
  • Configuração pronta para produção para automação profissional de fluxos de trabalho

Custo mensal: €4,51 (servidor CX11) + custos de domínio -- mesma infraestrutura que pode lidar com múltiplas ferramentas de automação

Pré-requisitos

  • Servidor Ubuntu 24.04 LTS com Docker e Docker Compose instalados
  • Configuração existente de proxy reverso Traefik (veja nosso guia de configuração n8n para configuração do Traefik)
  • Nome de domínio apontando para o IP do seu servidor
  • Mínimo de 4GB de RAM e 2 vCPUs recomendados
  • Acesso SSH e conhecimento básico de linha de comando

Entendendo o Windmill

Windmill é um motor de fluxos de trabalho de código aberto que oferece:

  • Editor visual de fluxos de trabalho com suporte a TypeScript/Python/Go
  • Agendamento de tarefas e gestão de execução
  • Capacidades de integração via API
  • Recursos de colaboração em equipe
  • Auto-hospedável sem limites de uso

Diferentemente da abordagem baseada em nós do n8n, o Windmill foca em fluxos de trabalho orientados a código com um poderoso ambiente de desenvolvimento.

Passo 1: Preparação do Servidor e Estrutura de Diretórios

Primeiro, vamos preparar nosso ambiente de servidor. Usaremos uma convenção de nomenclatura baseada em alimentos para instâncias Windmill para evitar conflitos:

# 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

Convenção de Nomenclatura: Use nomes simples de alimentos para múltiplas instâncias Windmill:

  • Primeira instância: pizza
  • Instâncias adicionais: pasta, salad, soup, burger, etc.
  • Isso evita conflitos e facilita a gestão

Passo 2: Configuração do Ambiente

Crie um arquivo de ambiente seguro com credenciais adequadas:

# 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: Substitua windmill.yourdomain.com pelo seu domínio real!

Passo 3: Configuração do Docker Compose

Crie a configuração principal do 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: Atualize o domínio nas labels do Traefik para corresponder à sua configuração!

Passo 4: O Problema de Senha do PostgreSQL (Questão Crítica)

Aqui é onde a maioria das instalações Windmill falha, e foi necessária considerável resolução de problemas para identificar a causa raiz:

O Problema: Caracteres Especiais em Senhas

Ao usar openssl rand -base64 32 para gerar senhas, frequentemente surgem caracteres especiais como =@#%, etc. Esses caracteres causam falhas de autenticação PostgreSQL em ambientes Docker, mesmo quando devidamente escapados.

Exemplo de senha problemática:

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

A Solução: Senhas Apenas em Hexadecimal

Use senhas apenas em hexadecimal que não contêm caracteres especiais:

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

Problemas Adicionais de Configuração PostgreSQL

  1. Configuração de Usuário: Use postgres como usuário padrão, não usuários personalizados como windmill_user
  2. Persistência de Volume: O PostgreSQL ignora variáveis de ambiente POSTGRES_PASSWORD quando volumes de dados existentes contêm credenciais diferentes
  3. Formato da URL: Inclua ?sslmode=disable na URL do banco de dados para ambientes Docker

Passo 5: Instalação e Inicialização

Agora vamos instalar o Windmill com nossa configuração corrigida:

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

Você deve ver uma saída como:

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

Passo 6: Resolução de Problemas Comuns

Problema 1: Falhas de Autenticação PostgreSQL

Sintomas:

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

Solução:

# 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: Contêiner Não Inicia

Sintomas:

  • Contêiner encerra imediatamente
  • Erros de alocação de recursos

Solução:

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

# Check system resources
docker stats
free -h

Problema 3: Problemas de Certificado SSL

Sintomas:

  • HTTPS não funciona
  • Erros de certificado

Solução:

# Check Traefik logs
docker logs traefik

# Verify DNS resolution
nslookup windmill.yourdomain.com

# Restart Traefik if needed
docker restart traefik

Passo 7: Acesso e Configuração Inicial

Após a instalação ser concluída:

  1. Acesse o Windmill: https://windmill.yourdomain.com
  2. Credenciais padrão:
    • E-mail: admin@windmill.dev
    • Senha: changeme
  3. Complete a configuração:
    • Altere a senha do administrador
    • Configure a URL base
    • Configure contas de usuário

Passo 8: Otimização de Recursos

Alocação de Memória (para servidor de 8GB)

Nossa configuração aloca recursos de forma eficiente:

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

Alocação de CPU (para servidor de 4 vCPU)

  • Worker: 1 vCPU (limitado)
  • Outros serviços: 3 vCPUs (compartilhados)

Regra de escala: 1 worker por vCPU com 1-2GB de RAM cada

Passo 9: Preparação para Produção

Criar Script de Backup

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 Monitoramento

# Monitor container health
docker compose ps

# Check resource usage
docker stats

# Monitor logs
docker compose logs -f windmill-server

Configurar Atualizações 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

Passo 10: Configuração Avançada

Integração com SMTP Existente

Se você tem um servidor de e-mail (como do nosso tutorial de configuração n8n), integre-o:

# 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últiplas Instâncias Windmill

Para equipes que necessitam de ambientes isolados:

# 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

Considerações de Segurança

Isolamento de Rede

  • PostgreSQL acessível apenas dentro da rede Docker
  • Nenhuma porta de banco de dados externa exposta
  • Terminação HTTPS no nível do Traefik

Limites de Recursos

  • Contêineres worker têm limites de CPU e memória
  • Previne ataques de esgotamento de recursos
  • Configurável com base na capacidade do servidor

Segurança SSL

  • Certificados automáticos Let's Encrypt
  • Redirecionamentos HTTP para HTTPS
  • Configuração TLS moderna

Monitoramento e Manutenção

Verificações Semanais de Saúde

# Container status
docker compose ps

# Resource usage
docker stats --no-stream

# Log analysis
docker compose logs | grep -i error

Manutenção Mensal

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

# Clean old data
docker system prune -f

# Backup database
./backup.sh

Detalhamento de Custos e Comparação

Custos Mensais

Configuração auto-hospedada:

  • Hetzner CX21 (4GB RAM): €8,46/mês
  • Custos de domínio: ~€1/mês
  • Total: ~€9,50/mês

Comparação com Windmill Cloud:

  • Plano Team: $30/mês por usuário
  • Economia: $250+ anualmente para equipes pequenas

Benefícios de Desempenho

Vantagens do auto-hospedamento:

  • Execuções de fluxos de trabalho ilimitadas
  • Sem limites de taxa externos
  • Controle total dos dados
  • Integrações personalizadas
  • Flexibilidade de escala de recursos

Referência de Resolução 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)"

Padrões Comuns de Erro

  1. "password authentication failed" → Use senhas hexadecimais, limpe volumes
  2. "connection refused" → Verifique configuração de rede
  3. "certificate errors" → Verifique DNS e configuração do Traefik
  4. "out of memory" → Ajuste limites de recursos do worker

Escalando Sua Infraestrutura Windmill

Escalabilidade Horizontal

Para ambientes de alto volume:

# 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

Escalabilidade Vertical

Faça upgrade dos recursos do servidor:

  • CX31 (8GB RAM): €16,07/mês para cargas de trabalho pesadas
  • CX41 (16GB RAM): €29,75/mês para uso empresarial

Integração com Infraestrutura Existente

Trabalhando com n8n

Se você já está executando n8n (dos nossos tutoriais anteriores):

  • Windmill lida com fluxos de trabalho orientados a código
  • n8n lida com automações visuais e simples
  • Ambos compartilham o mesmo proxy Traefik
  • Bancos de dados separados previnem conflitos

Serviços Compartilhados

Aproveite a infraestrutura existente:

  • Traefik: Gerencia SSL para todos os serviços
  • Servidor de E-mail: SMTP compartilhado para notificações
  • Monitoramento: Logging e métricas unificados
  • Backups: Estratégia centralizada de backup

Conclusão

O auto-hospedamento do Windmill fornece automação de fluxos de trabalho de nível empresarial a uma fração dos custos de hospedagem em nuvem. A chave para o sucesso é entender os requisitos de autenticação do PostgreSQL e usar senhas apenas em hexadecimal para evitar problemas com caracteres especiais que podem inviabilizar instalações.

Principais Benefícios Desta Configuração

  • Econômico: Economize centenas anualmente comparado a soluções em nuvem
  • Pronto para produção: Lida com cargas de trabalho empresariais de forma confiável
  • Seguro: HTTPS, redes isoladas e limites de recursos
  • Escalável: Fácil adicionar workers e recursos conforme necessário
  • Privado: Seu código e dados nunca saem da sua infraestrutura

Esta configuração foi testada em ambientes de produção e fornece a confiabilidade necessária para automação de fluxos de trabalho críticos para os negócios. Os passos de resolução de problemas abordam questões reais encontradas durante a implantação, particularmente os problemas de autenticação PostgreSQL que afetam muitas instalações auto-hospedadas.

Para requisitos complexos de fluxos de trabalho ou implantações empresariais, considere consultoria profissional para otimizar seu caso de uso específico e garantir alocação otimizada de recursos.

Próximos Passos


Sobre a tva

A tva assegura a gestão abrangente de infraestrutura de sistemas de banco de dados, ambientes em nuvem e cadeias de suprimentos globais. Nossa abordagem metódica combina protocolos rigorosos de segurança com otimização de desempenho, enquanto os serviços de consultoria estratégica permitem a coordenação precisa de capacidades digitais e ativos físicos -- mantendo os mais altos padrões de excelência operacional e conformidade em todos os engajamentos.

Visite tva.sg para mais informações sobre nossos serviços e tutoriais adicionais de automação.