tva
← Artigos

Auto-hospedagem do Windmill no Ubuntu: tutorial completo de configuração com Docker com resolução de problemas do 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 do Windmill no Ubuntu com Docker Compose e integração com o Traefik, superando problemas críticos de autenticação do PostgreSQL que podem inviabilizar sua instalação.

O que você vai construir

Ao final deste tutorial, você terá:

  • Instalação do 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
  • Integração com a infraestrutura Docker existente
  • Configuração pronta para produção voltada à automação profissional de fluxos de trabalho

Custo mensal: a partir de €5,99 sem IVA, incluindo um endereço IPv4 primário (Hetzner CX23, 4 GB RAM, em outubro de 2026) + 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 do n8n para configuração do Traefik)
  • Nome de domínio apontando para o IP do seu servidor
  • Pelo menos 4GB de RAM e 2 vCPUs recomendados
  • Acesso SSH e conhecimento básico de linha de comando

Entendendo o Windmill

O Windmill é um mecanismo 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 gerenciamento de execução
  • Recursos de integração via API
  • Recursos de colaboração em equipe
  • Auto-hospedável, com execuções ilimitadas na Community Edition gratuita

Diferentemente da abordagem baseada em nós do n8n, o Windmill se concentra 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 do 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 do Windmill:

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

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-pizza-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
chmod 600 /opt/windmill-pizza/.env

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 nos rótulos 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 do Windmill falha, e foi necessário um trabalho considerável de diagnóstico para identificar a causa raiz:

O problema: caracteres especiais em senhas

Ao usar openssl rand -base64 32 para gerar senhas, a saída pode conter +, / e =. Em DATABASE_URL, esses caracteres devem ser codificados com codificação percentual; sem codificação, podem comprometer a interpretação da URL e se manifestar como falhas de autenticação do PostgreSQL. Senhas hexadecimais dispensam totalmente essa etapa de codificação.

Exemplo de senha problemática:

# This WILL cause authentication failures:
PASSWORD="305t6m9KrC/kvbyNEF+EYQ6pqAGlApn9rbJPH3D5y9g="

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 do PostgreSQL

  1. Configuração de usuário: Use o superusuário postgres, como na configuração de exemplo do Windmill. Um usuário personalizado só funciona após receber os papéis windmill_admin e windmill_user exigidos pelas migrações do Windmill (consulte a documentação de auto-hospedagem do Windmill)
  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 quando ele for acessível apenas pela rede interna do Docker, como na configuração de exemplo do Windmill; use um modo SSL como require para bancos de dados acessados por outras redes

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 do PostgreSQL

Sintomas:

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

Solução: Isso exclui todos os dados do banco de dados do Windmill. Use este procedimento apenas em uma instalação nova ou após um backup verificado. Os dois comandos sed gravam a nova senha em POSTGRES_PASSWORD e em DATABASE_URL.

# 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#postgresql://postgres:[^@]*@#postgresql://postgres:$NEW_PASSWORD@#" .env

# Restart
docker compose up -d

Problema 2: contêiner não inicia

Sintomas:

  • O contêiner é encerrado 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:
  3. Conclua 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
set -euo pipefail
cd /opt/windmill-pizza
DATE=$(date +%Y%m%d_%H%M%S)
FILE=/opt/backups/windmill_pizza_${DATE}.sql
mkdir -p /opt/backups
if ! docker compose exec -T windmill-db pg_dump -U postgres windmill_pizza > "$FILE"; then
  rm -f "$FILE"
  echo "Backup failed" >&2
  exit 1
fi
echo "Backup created: $FILE"
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 o do nosso tutorial de configuração do n8n), integre-o:

# Add to docker-compose.yml environment for windmill-server:
- SMTP_HOST=mailserver
- SMTP_PORT=25
- SMTP_USERNAME=
- SMTP_PASSWORD=
- [email protected]

Múltiplas instâncias do Windmill

Para equipes que necessitam de ambientes isolados, a segunda instância recebe seus próprios diretórios de dados vazios, banco de dados e senha:

# Create second instance with its own empty data directories
mkdir -p /opt/windmill-pasta/postgres-data /opt/windmill-pasta/windmill-data /opt/windmill-pasta/lsp-cache
cp /opt/windmill-pizza/.env /opt/windmill-pizza/docker-compose.yml /opt/windmill-pasta/
chmod 600 /opt/windmill-pasta/.env

# 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
sed -i "s#postgresql://postgres:[^@]*@#postgresql://postgres:$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

  • O PostgreSQL só é acessível a partir de contêineres na rede Docker compartilhada proxy; use uma rede interna separada para um isolamento mais rigoroso
  • Nenhuma porta de banco de dados externa exposta
  • Terminação HTTPS no nível do Traefik

Limites de recursos

  • Contêineres de workers têm limites de CPU e memória
  • Os limites de recursos reduzem o impacto de tarefas fora de controle e de tentativas 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

# Backup database first
cd /opt/windmill-pizza
./backup.sh

# Update containers
./update.sh

# Clean old data
docker system prune -f

Detalhamento de custos e comparação

Custos mensais

Configuração auto-hospedada:

  • Hetzner CX23 (4 GB RAM): €5,99/mês sem IVA, incluindo um endereço IPv4 primário (em outubro de 2026)
  • Custos de domínio: ~€1/mês
  • Total: ~€7/mês sem IVA

Comparação com Windmill Cloud:

  • Cloud: $20/mês por licença de desenvolvedor, $10/mês por operador (em outubro de 2026)
  • Economia: $250+ por ano quando dois ou mais desenvolvedores precisam de licenças

Benefícios de desempenho

Vantagens da auto-hospedagem:

  • Execuções de fluxos de trabalho ilimitadas
  • Sem limites externos de requisições
  • 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; esvazie os volumes apenas após um backup ou em uma instalação nova
  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 (preços da Hetzner sem IVA, incluindo um endereço IPv4 primário em outubro de 2026):

  • CX33 (8 GB RAM): €8,99/mês para cargas de trabalho pesadas
  • CX43 (16 GB RAM): €16,49/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 evitam 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: Registros de logs e métricas unificados
  • Backups: Estratégia centralizada de backup

Conclusão

A auto-hospedagem 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 como as credenciais do PostgreSQL são transmitidas e persistidas e usar senhas apenas em hexadecimal para evitar problemas de codificação de URL que podem inviabilizar instalações.

Principais benefícios desta configuração

  • Econômico: Economize centenas por ano em comparação com soluções em nuvem
  • Pronto para produção: Lida com cargas de trabalho empresariais de forma confiável
  • Seguro: HTTPS, nenhuma porta do banco de dados exposta e limites de recursos (a montagem do socket Docker ainda concede ao worker acesso ao host)
  • Escalável: Fácil adicionar workers e recursos conforme necessário
  • Privado: Seu código e dados permanecem na sua infraestrutura, a menos que seus fluxos de trabalho os enviem a serviços externos

Esta configuração foi testada em ambientes de produção e fornece a confiabilidade necessária para a automação de fluxos de trabalho essenciais aos negócios. Os passos de resolução de problemas abordam questões reais encontradas durante a implantação, particularmente os problemas de autenticação do 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 uma alocação ideal de recursos.

Próximos passos


Sobre a tva

A tva assegura o gerenciamento 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 recursos digitais e ativos físicos — mantendo os mais altos padrões de excelência operacional e conformidade em todos os projetos.

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

Artigos relacionados

Leitura complementar