✓ Verified 💻 Development ✓ Enhanced Data

Setuporion Byimpa

Setup completo de VPS Ubuntu/Debian para produção com Docker Swarm, Traefik v3 (SSL/HTTPS automático

Rating
3.9 (222 reviews)
Downloads
1,119 downloads
Version
1.0.0

Overview

Setup completo de VPS Ubuntu/Debian para produção com Docker Swarm, Traefik v3 (SSL/HTTPS automático), Portainer CE.

Complete Documentation

View Source →


name: vps-setup description: Setup completo de VPS Ubuntu/Debian para produção com Docker Swarm, Traefik v3 (SSL/HTTPS automático), Portainer CE e rede overlay. Baseado no SetupOrion v2.8.0. Executa todos os comandos automaticamente. metadata: openclaw: requires: bins: [] env: VPS_HOSTNAME: "Nome do servidor (ex: Orion)" VPS_NETWORK: "Nome da rede overlay Docker (ex: Impasevid)" VPS_EMAIL_SSL: "Email para certificados Let's Encrypt (ex: [email protected])" VPS_PORTAINER_DOMAIN: "Domínio do Portainer (ex: portainer.seudominio.com)" VPS_PORTAINER_USER: "Usuário admin do Portainer (ex: admin)" VPS_PORTAINER_PASS: "Senha admin do Portainer (mínimo 12 caracteres)" VPS_POSTGRES_PASS: "Senha do PostgreSQL (auto-gerada se vazia). Use openssl rand -hex 16" VPS_EVOLUTION_DOMAIN: "Domínio da Evolution API (ex: api.seudominio.com)" VPS_EVOLUTION_API_KEY: "Global API Key da Evolution (auto-gerada se vazia). Use openssl rand -hex 16"

VPS Setup - Docker Swarm + Traefik + Portainer

Setup automatizado de VPS para produção. Instala Docker, inicia Swarm, cria rede overlay, deploya Traefik v3 com SSL automático e Portainer CE. Requisitos: Ubuntu 20.04+ ou Debian 11+ com acesso root/sudo.

Execução Completa (todos os passos em ordem)

Execute cada etapa na ordem. Todas as etapas são idempotentes (seguro re-executar).

Etapa 1 - Atualizar Sistema e Configurar Servidor

``bash

Atualizar sistema

sudo apt-get update && sudo apt-get upgrade -y

Instalar utilitários essenciais

sudo apt-get install -y apt-utils apparmor-utils curl jq htpasswd ca-certificates gnupg lsb-release

Configurar timezone

sudo timedatectl set-timezone America/Sao_Paulo

Definir hostname do servidor

sudo hostnamectl set-hostname $VPS_HOSTNAME sudo sed -i "s/127.0.0.1[[:space:]]localhost/127.0.0.1 $VPS_HOSTNAME/g" /etc/hosts
` Verificação: `bash timedatectl | grep "Time zone"

Esperado: America/Sao_Paulo

hostname

Esperado: $VPS_HOSTNAME

`

Etapa 2 - Instalar Docker

`bash

Instalar Docker via script oficial

curl -fsSL https://get.docker.com | bash

Habilitar e iniciar Docker

sudo systemctl enable docker sudo systemctl start docker

Fix: garantir compatibilidade com API mínima

sudo mkdir -p /etc/systemd/system/docker.service.d sudo bash -c 'cat > /etc/systemd/system/docker.service.d/override.conf <` Se falhar, instalar manualmente: `bash sudo install -m 0755 -d /etc/apt/keyrings OS_ID=$(source /etc/os-release && echo "$ID") OS_CODENAME=$(source /etc/os-release && echo "$VERSION_CODENAME") curl -fsSL https://download.docker.com/linux/$OS_ID/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$OS_ID $OS_CODENAME stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl enable docker sudo systemctl start docker ` Verificação: `bash docker --version

Esperado: Docker version 2X.x.x

docker info --format '{{.Swarm.LocalNodeState}}'

Esperado: inactive (ainda não iniciamos o Swarm)

`

Etapa 3 - Iniciar Docker Swarm

`bash

Obter IP público da VPS (ignora loopback e IPs internos)

IP=$(hostname -I | tr ' ' '\n' | grep -v '^127\.' | grep -v '^10\.0\.0\.' | head -n1)

Iniciar Swarm

docker swarm init --advertise-addr $IP
` Verificação: `bash docker info --format '{{.Swarm.LocalNodeState}}'

Esperado: active

docker node ls

Esperado: 1 node com STATUS=Ready, MANAGER STATUS=Leader

`

Etapa 4 - Criar Rede Overlay e Volumes

`bash

Criar rede overlay para comunicação entre containers

docker network create --driver=overlay $VPS_NETWORK

Criar volumes necessários

docker volume create volume_swarm_shared docker volume create volume_swarm_certificates docker volume create portainer_data docker volume create postgres_data docker volume create evolution_instances docker volume create evolution_redis
` Verificação: `bash docker network ls | grep $VPS_NETWORK

Esperado: linha com $VPS_NETWORK, DRIVER=overlay, SCOPE=swarm

docker volume ls | grep -E "shared|certificates|portainer|postgres|evolution"

Esperado: 6 volumes listados

`

Etapa 5 - Deploy do Traefik v3 (Proxy Reverso + SSL)

Criar o arquivo
traefik.yaml e fazer deploy: `bash cat > /root/traefik.yaml << 'TRAEFIKEOF' version: "3.7" services: traefik: image: traefik:v3.5.3 command:
  • "--api.dashboard=true"
  • "--providers.swarm=true"
  • "--providers.docker.endpoint=unix:///var/run/docker.sock"
  • "--providers.docker.exposedbydefault=false"
  • "--providers.docker.network=NETWORK_PLACEHOLDER"
  • "--entrypoints.web.address=:80"
  • "--entrypoints.web.http.redirections.entryPoint.to=websecure"
  • "--entrypoints.web.http.redirections.entryPoint.scheme=https"
  • "--entrypoints.web.http.redirections.entrypoint.permanent=true"
  • "--entrypoints.websecure.address=:443"
  • "--entrypoints.web.transport.respondingTimeouts.idleTimeout=3600"
  • "--certificatesresolvers.letsencryptresolver.acme.httpchallenge=true"
  • "--certificatesresolvers.letsencryptresolver.acme.httpchallenge.entrypoint=web"
  • "--certificatesresolvers.letsencryptresolver.acme.storage=/etc/traefik/letsencrypt/acme.json"
  • "--certificatesresolvers.letsencryptresolver.acme.email=EMAIL_PLACEHOLDER"
  • "--log.level=DEBUG"
  • "--log.format=common"
  • "--log.filePath=/var/log/traefik/traefik.log"
  • "--accesslog=true"
  • "--accesslog.filepath=/var/log/traefik/access-log"
volumes:
  • "vol_certificates:/etc/traefik/letsencrypt"
  • "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
  • network_overlay
ports:
  • target: 80
published: 80 mode: host
  • target: 443
published: 443 mode: host deploy: placement: constraints:
  • node.role == manager
labels:
  • "traefik.enable=true"
  • "traefik.http.middlewares.redirect-https.redirectscheme.scheme=https"
  • "traefik.http.middlewares.redirect-https.redirectscheme.permanent=true"
  • "traefik.http.routers.http-catchall.rule=Host({host:.+})"
  • "traefik.http.routers.http-catchall.entrypoints=web"
  • "traefik.http.routers.http-catchall.middlewares=redirect-https@docker"
  • "traefik.http.routers.http-catchall.priority=1"
volumes: vol_shared: external: true name: volume_swarm_shared vol_certificates: external: true name: volume_swarm_certificates networks: network_overlay: external: true attachable: true name: NETWORK_PLACEHOLDER TRAEFIKEOF

Substituir placeholders pelas variáveis reais

sed -i "s/NETWORK_PLACEHOLDER/$VPS_NETWORK/g" /root/traefik.yaml sed -i "s/EMAIL_PLACEHOLDER/$VPS_EMAIL_SSL/g" /root/traefik.yaml

Deploy

docker stack deploy --prune --resolve-image always -c /root/traefik.yaml traefik
` Aguardar Traefik ficar online: `bash

Verificar a cada 10s até o serviço mostrar 1/1

while ! docker service ls --filter name='traefik_traefik' --format '{{.Replicas}}' | grep -q '1/1'; do echo "Aguardando Traefik..." sleep 10 done echo "Traefik online!"
` Verificação: `bash docker service ls --filter name=traefik

Esperado: traefik_traefik 1/1

curl -sI http://localhost:80 | head -3

Esperado: HTTP redirect ou resposta do Traefik

`

Etapa 6 - Deploy do Portainer CE (Gerenciador Docker)

Criar o arquivo
portainer.yaml e fazer deploy: `bash cat > /root/portainer.yaml << 'PORTAINEREOF' version: "3.7" services: agent: image: portainer/agent:latest volumes:
  • /var/run/docker.sock:/var/run/docker.sock
  • /var/lib/docker/volumes:/var/lib/docker/volumes
networks:
  • network_overlay
deploy: mode: global placement: constraints: [node.platform.os == linux] portainer: image: portainer/portainer-ce:latest command: -H tcp://tasks.agent:9001 --tlsskipverify volumes:
  • portainer_data:/data
networks:
  • network_overlay
deploy: mode: replicated replicas: 1 placement: constraints: [node.role == manager] labels:
  • "traefik.enable=true"
  • "traefik.http.routers.portainer.rule=Host(PORTAINER_DOMAIN_PLACEHOLDER)"
  • "traefik.http.services.portainer.loadbalancer.server.port=9000"
  • "traefik.http.routers.portainer.tls.certresolver=letsencryptresolver"
  • "traefik.http.routers.portainer.service=portainer"
  • "traefik.docker.network=NETWORK_PLACEHOLDER"
  • "traefik.http.routers.portainer.entrypoints=websecure"
  • "traefik.http.routers.portainer.priority=1"
volumes: portainer_data: external: true name: portainer_data networks: network_overlay: external: true attachable: true name: NETWORK_PLACEHOLDER PORTAINEREOF

Substituir placeholders

sed -i "s/NETWORK_PLACEHOLDER/$VPS_NETWORK/g" /root/portainer.yaml sed -i "s/PORTAINER_DOMAIN_PLACEHOLDER/$VPS_PORTAINER_DOMAIN/g" /root/portainer.yaml

Deploy

docker stack deploy --prune --resolve-image always -c /root/portainer.yaml portainer
` Aguardar Portainer ficar online: `bash

Aguardar agent + portainer

while ! docker service ls --filter name='portainer_portainer' --format '{{.Replicas}}' | grep -q '1/1'; do echo "Aguardando Portainer..." sleep 10 done echo "Portainer online!"
` Verificação: `bash docker service ls --filter name=portainer

Esperado: portainer_agent 1/1 (global), portainer_portainer 1/1

`

Etapa 7 - Criar Conta Admin no Portainer

`bash

Aguardar API do Portainer estar pronta (30s após container online)

sleep 30

Criar usuário admin (tentativa com retry)

for i in 1 2 3 4; do RESPONSE=$(curl -k -s -X POST "https://$VPS_PORTAINER_DOMAIN/api/users/admin/init" \ -H "Content-Type: application/json" \ -d "{\"Username\": \"$VPS_PORTAINER_USER\", \"Password\": \"$VPS_PORTAINER_PASS\"}") if echo "$RESPONSE" | jq -e '.Id' > /dev/null 2>&1; then echo "Admin criado com sucesso!" break fi echo "Tentativa $i falhou, aguardando 15s..." sleep 15 done

Obter token JWT para validar

TOKEN=$(curl -k -s -X POST "https://$VPS_PORTAINER_DOMAIN/api/auth" \ -H "Content-Type: application/json" \ -d "{\"username\":\"$VPS_PORTAINER_USER\",\"password\":\"$VPS_PORTAINER_PASS\"}" | jq -r .jwt) echo "Token: $TOKEN"
` Verificação: `bash curl -k -s "https://$VPS_PORTAINER_DOMAIN/api/status" | jq .

Esperado: JSON com Version e InstanceID

echo "Portainer acessível em: https://$VPS_PORTAINER_DOMAIN" echo "Usuário: $VPS_PORTAINER_USER"
`

Etapa 8 - Deploy do PostgreSQL 14 (Banco de Dados)

O PostgreSQL é necessário para a Evolution API e outros serviços.
`bash

Gerar senha do Postgres (ou usar VPS_POSTGRES_PASS se definida)

POSTGRES_PASS="${VPS_POSTGRES_PASS:-$(openssl rand -hex 16)}" echo "Senha do PostgreSQL: $POSTGRES_PASS"

Criar volume para dados do Postgres

docker volume create postgres_data

Criar stack postgres.yaml

cat > /root/postgres.yaml << POSTGRESEOF version: "3.7" services: postgres: image: postgres:14 command: > postgres -c max_connections=500 -c shared_buffers=512MB -c timezone=America/Sao_Paulo volumes:
  • postgres_data:/var/lib/postgresql/data
networks:
  • network_overlay
environment:
  • POSTGRES_PASSWORD=${POSTGRES_PASS}
  • TZ=America/Sao_Paulo
deploy: mode: replicated replicas: 1 placement: constraints:
  • node.role == manager
resources: limits: cpus: "1" memory: 1024M volumes: postgres_data: external: true name: postgres_data networks: network_overlay: external: true name: NETWORK_PLACEHOLDER POSTGRESEOF

Substituir placeholder da rede

sed -i "s/NETWORK_PLACEHOLDER/$VPS_NETWORK/g" /root/postgres.yaml

Deploy

docker stack deploy --prune --resolve-image always -c /root/postgres.yaml postgres
` Aguardar PostgreSQL ficar online: `bash while ! docker service ls --filter name='postgres_postgres' --format '{{.Replicas}}' | grep -q '1/1'; do echo "Aguardando PostgreSQL..." sleep 10 done echo "PostgreSQL online!" ` Verificação: `bash docker service ls --filter name=postgres

Esperado: postgres_postgres 1/1

Testar conexão

CONTAINER_ID=$(docker ps -q --filter "name=^postgres_postgres") docker exec "$CONTAINER_ID" psql -U postgres -c "SELECT version();"

Esperado: PostgreSQL 14.x

echo "" echo "=== DADOS DO POSTGRESQL ===" echo "Host: postgres (interno Docker)" echo "Porta: 5432" echo "Usuário: postgres" echo "Senha: $POSTGRES_PASS"
`

Etapa 9 - Deploy da Evolution API v2 (WhatsApp)

Instala a Evolution API com Redis para cache e PostgreSQL como banco de dados.
`bash

Obter senha do Postgres (já deve estar definida na Etapa 8)

POSTGRES_PASS="${VPS_POSTGRES_PASS:-$(grep 'POSTGRES_PASSWORD' /root/postgres.yaml | awk -F '=' '{print $2}')}"

Gerar Global API Key (ou usar VPS_EVOLUTION_API_KEY se definida)

EVOLUTION_API_KEY="${VPS_EVOLUTION_API_KEY:-$(openssl rand -hex 16)}" echo "Evolution Global API Key: $EVOLUTION_API_KEY"

Criar banco de dados para a Evolution no PostgreSQL

CONTAINER_ID=$(docker ps -q --filter "name=^postgres_postgres") docker exec "$CONTAINER_ID" psql -U postgres -c "CREATE DATABASE evolution;" 2>/dev/null || echo "Banco 'evolution' já existe"

Criar volumes

docker volume create evolution_instances docker volume create evolution_redis

Criar stack evolution.yaml

cat > /root/evolution.yaml << 'EVOLUTIONEOF' version: "3.7" services: evolution_api: image: evoapicloud/evolution-api:latest volumes:
  • evolution_instances:/evolution/instances
networks:
  • network_overlay
environment: ## Configuracoes Gerais
  • SERVER_URL=https://EVOLUTION_DOMAIN_PLACEHOLDER
  • AUTHENTICATION_API_KEY=EVOLUTION_APIKEY_PLACEHOLDER
  • AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true
  • DEL_INSTANCE=false
  • QRCODE_LIMIT=1902
  • LANGUAGE=pt-BR
## Configuracao do Cliente
  • CONFIG_SESSION_PHONE_CLIENT=OpenClaw
  • CONFIG_SESSION_PHONE_NAME=Chrome
## Banco de Dados
  • DATABASE_ENABLED=true
  • DATABASE_PROVIDER=postgresql
  • DATABASE_CONNECTION_URI=postgresql://postgres:POSTGRES_PASS_PLACEHOLDER@postgres:5432/evolution
  • DATABASE_CONNECTION_CLIENT_NAME=evolution
  • DATABASE_SAVE_DATA_INSTANCE=true
  • DATABASE_SAVE_DATA_NEW_MESSAGE=true
  • DATABASE_SAVE_MESSAGE_UPDATE=true
  • DATABASE_SAVE_DATA_CONTACTS=true
  • DATABASE_SAVE_DATA_CHATS=true
  • DATABASE_SAVE_DATA_LABELS=true
  • DATABASE_SAVE_DATA_HISTORIC=true
## Integracoes (chatbots)
  • N8N_ENABLED=true
  • EVOAI_ENABLED=true
  • OPENAI_ENABLED=true
  • DIFY_ENABLED=true
  • TYPEBOT_ENABLED=true
  • TYPEBOT_API_VERSION=latest
## Chatwoot
  • CHATWOOT_ENABLED=true
  • CHATWOOT_MESSAGE_READ=true
  • CHATWOOT_MESSAGE_DELETE=true
  • CHATWOOT_IMPORT_PLACEHOLDER_MEDIA_MESSAGE=false
## Cache Redis
  • CACHE_REDIS_ENABLED=true
  • CACHE_REDIS_URI=redis://evolution_redis:6379/1
  • CACHE_REDIS_PREFIX_KEY=evolution
  • CACHE_REDIS_SAVE_INSTANCES=false
  • CACHE_LOCAL_ENABLED=false
## S3 (desabilitado por padrao)
  • S3_ENABLED=false
## WhatsApp Business (Cloud API)
  • WA_BUSINESS_TOKEN_WEBHOOK=evolution
  • WA_BUSINESS_URL=https://graph.facebook.com
  • WA_BUSINESS_VERSION=v23.0
  • WA_BUSINESS_LANGUAGE=pt_BR
## Telemetria
  • TELEMETRY=false
## WebSocket
  • WEBSOCKET_ENABLED=false
  • WEBSOCKET_GLOBAL_EVENTS=false
## RabbitMQ (desabilitado por padrao)
  • RABBITMQ_ENABLED=false
## Webhook (desabilitado por padrao)
  • WEBHOOK_GLOBAL_ENABLED=false
## SQS (desabilitado por padrao)
  • SQS_ENABLED=false
## Provider
  • PROVIDER_ENABLED=false
deploy: mode: replicated replicas: 1 placement: constraints:
  • node.role == manager
labels:
  • traefik.enable=true
  • traefik.http.routers.evolution.rule=Host(EVOLUTION_DOMAIN_PLACEHOLDER)
  • traefik.http.routers.evolution.entrypoints=websecure
  • traefik.http.routers.evolution.priority=1
  • traefik.http.routers.evolution.tls.certresolver=letsencryptresolver
  • traefik.http.routers.evolution.service=evolution
  • traefik.http.services.evolution.loadbalancer.server.port=8080
  • traefik.http.services.evolution.loadbalancer.passHostHeader=true
evolution_redis: image: redis:latest command: ["redis-server", "--appendonly", "yes", "--port", "6379"] volumes:
  • evolution_redis:/data
networks:
  • network_overlay
deploy: placement: constraints:
  • node.role == manager
resources: limits: cpus: "1" memory: 1024M volumes: evolution_instances: external: true name: evolution_instances evolution_redis: external: true name: evolution_redis networks: network_overlay: external: true name: NETWORK_PLACEHOLDER EVOLUTIONEOF

Substituir placeholders

sed -i "s/EVOLUTION_DOMAIN_PLACEHOLDER/$VPS_EVOLUTION_DOMAIN/g" /root/evolution.yaml sed -i "s/EVOLUTION_APIKEY_PLACEHOLDER/$EVOLUTION_API_KEY/g" /root/evolution.yaml sed -i "s/POSTGRES_PASS_PLACEHOLDER/$POSTGRES_PASS/g" /root/evolution.yaml sed -i "s/NETWORK_PLACEHOLDER/$VPS_NETWORK/g" /root/evolution.yaml

Deploy

docker stack deploy --prune --resolve-image always -c /root/evolution.yaml evolution
` Aguardar Evolution API ficar online: `bash

Aguardar Redis + Evolution API

while ! docker service ls --filter name='evolution_evolution_redis' --format '{{.Replicas}}' | grep -q '1/1'; do echo "Aguardando Redis..." sleep 10 done echo "Redis online!" while ! docker service ls --filter name='evolution_evolution_api' --format '{{.Replicas}}' | grep -q '1/1'; do echo "Aguardando Evolution API..." sleep 10 done echo "Evolution API online!"

Aguardar inicialização completa

sleep 30
` Verificação: `bash docker service ls --filter name=evolution

Esperado: evolution_evolution_api 1/1, evolution_evolution_redis 1/1

Testar API

curl -sk "https://$VPS_EVOLUTION_DOMAIN" | head -c 200

Esperado: resposta JSON da API

echo "" echo "=== DADOS DA EVOLUTION API ===" echo "Manager: https://$VPS_EVOLUTION_DOMAIN/manager" echo "BaseUrl: https://$VPS_EVOLUTION_DOMAIN" echo "Global API Key: $EVOLUTION_API_KEY"
`

Operações de Manutenção

Reiniciar Traefik

`bash docker service update --force $(docker service ls --filter name='traefik_traefik' -q) `

Reiniciar Portainer

`bash docker service update --force $(docker service ls --filter name='portainer_agent' -q) docker service update --force $(docker service ls --filter name='portainer_portainer' -q) `

Atualizar Portainer

`bash docker stack deploy --prune --resolve-image always -c /root/portainer.yaml portainer `

Reset Senha Portainer

`bash

Parar Portainer

docker service scale portainer_portainer=0

Reset

docker pull portainer/helper-reset-password docker run --rm -v /var/lib/docker/volumes/portainer_data/_data:/data portainer/helper-reset-password

Subir novamente

docker stack deploy --prune --resolve-image always -c /root/portainer.yaml portainer
`

Atualizar Traefik

`bash docker stack deploy --prune --resolve-image always -c /root/traefik.yaml traefik `

Ver Logs do Traefik

`bash docker service logs traefik_traefik --tail 100 -f `

Ver Logs do Portainer

`bash docker service logs portainer_portainer --tail 100 -f `

Reiniciar PostgreSQL

`bash docker service update --force $(docker service ls --filter name='postgres_postgres' -q) `

Reiniciar Evolution API

`bash docker service update --force $(docker service ls --filter name='evolution_evolution_api' -q) docker service update --force $(docker service ls --filter name='evolution_evolution_redis' -q) `

Atualizar Evolution API

`bash docker stack deploy --prune --resolve-image always -c /root/evolution.yaml evolution `

Ver Logs da Evolution API

`bash docker service logs evolution_evolution_api --tail 100 -f `

Ver Logs do Redis (Evolution)

`bash docker service logs evolution_evolution_redis --tail 50 -f `

Criar Banco Adicional no PostgreSQL

`bash CONTAINER_ID=$(docker ps -q --filter "name=^postgres_postgres") docker exec "$CONTAINER_ID" psql -U postgres -c "CREATE DATABASE nome_do_banco;" `

Listar Bancos no PostgreSQL

`bash CONTAINER_ID=$(docker ps -q --filter "name=^postgres_postgres") docker exec "$CONTAINER_ID" psql -U postgres -lqt `

Deploy de Novos Serviços via Portainer API

Use a API do Portainer para deploy automatizado:
`bash

1. Obter token

TOKEN=$(curl -k -s -X POST "https://$VPS_PORTAINER_DOMAIN/api/auth" \ -H "Content-Type: application/json" \ -d "{\"username\":\"$VPS_PORTAINER_USER\",\"password\":\"$VPS_PORTAINER_PASS\"}" | jq -r .jwt)

2. Listar endpoints (stacks)

curl -k -s "https://$VPS_PORTAINER_DOMAIN/api/endpoints" \ -H "Authorization: Bearer $TOKEN" | jq '.[].Id'

3. Deploy stack via API (exemplo)

curl -k -s -X POST "https://$VPS_PORTAINER_DOMAIN/api/stacks/create/swarm/string?endpointId=1" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"meu-servico\", \"stackFileContent\": \"$(cat /root/meu-servico.yaml | jq -sR .)\" }"
`

Habilitar Dashboard do Traefik (Opcional)

Para acessar o painel do Traefik com autenticação:
`bash

Gerar credenciais BasicAuth

TRAEFIK_USER="admin" TRAEFIK_PASS="SuaSenhaForte123" TRAEFIK_DOMAIN="traefik.seudominio.com" BASICAUTH=$(htpasswd -nbB "$TRAEFIK_USER" "$TRAEFIK_PASS" | sed 's/\$/\$\$/g')

Recriar traefik.yaml adicionando '--api.insecure=true' no command

E estas labels extras no deploy:

- "traefik.http.routers.traefik.rule=Host($TRAEFIK_DOMAIN)"

- "traefik.http.services.traefik.loadbalancer.server.port=8080"

- "traefik.http.routers.traefik.tls.certresolver=letsencryptresolver"

- "traefik.http.routers.traefik.service=traefik"

- "traefik.http.routers.traefik.entrypoints=websecure"

- "traefik.http.routers.traefik.priority=1"

- "traefik.http.routers.traefik.middlewares=authtraefik"

- "traefik.http.middlewares.authtraefik.basicauth.users=$BASICAUTH"

Redeploy

docker stack deploy --prune --resolve-image always -c /root/traefik.yaml traefik
`

Checklist Final

Após completar todas as etapas, verifique:
`bash echo "=== Status dos Serviços ===" docker service ls echo "" echo "=== Rede Overlay ===" docker network ls | grep overlay echo "" echo "=== Volumes ===" docker volume ls echo "" echo "=== Nodes do Swarm ===" docker node ls echo "" echo "=== Portas em uso ===" ss -tlnp | grep -E ':80|:443|:9000|:8080|:5432|:6379' ` Resultado esperado: | Serviço | Status | URL | |---------|--------|-----| | Traefik | 1/1 | (interno, gerencia SSL) | | Portainer Agent | 1/1 (global) | (interno) | | Portainer CE | 1/1 | https://$VPS_PORTAINER_DOMAIN | | PostgreSQL 14 | 1/1 | postgres:5432 (interno) | | Evolution API | 1/1 | https://$VPS_EVOLUTION_DOMAIN | | Evolution Redis | 1/1 | redis:6379 (interno) | | Rede overlay | ativa | $VPS_NETWORK |

Troubleshooting

Docker Swarm não inicia

`bash

Verificar IP usado

hostname -I

Forçar com IP específico

docker swarm init --advertise-addr SEU_IP_AQUI
`

Certificado SSL não gerado

`bash

Verificar logs do Traefik

docker service logs traefik_traefik 2>&1 | grep -i "acme\|certificate\|error"

Verificar se porta 80 está acessível externamente

curl -sI http://SEU_DOMINIO
`

Portainer API não responde

`bash

Verificar se o container está rodando

docker service ps portainer_portainer

Testar conectividade

curl -k -s https://$VPS_PORTAINER_DOMAIN/api/status
`

Container não conecta à rede

`bash

Listar redes do container

docker inspect CONTAINER_ID | jq '.[].NetworkSettings.Networks'

Reconectar

docker network connect $VPS_NETWORK CONTAINER_ID
`

PostgreSQL não inicia

`bash

Verificar logs

docker service logs postgres_postgres --tail 50

Verificar volume

docker volume inspect postgres_data

Se o volume está corrompido, recriar (PERDA DE DADOS!)

docker volume rm postgres_data && docker volume create postgres_data

docker stack deploy --prune --resolve-image always -c /root/postgres.yaml postgres

`

Evolution API não conecta ao banco

`bash

Verificar se o banco existe

CONTAINER_ID=$(docker ps -q --filter "name=^postgres_postgres") docker exec "$CONTAINER_ID" psql -U postgres -lqt | grep evolution

Se não existe, criar:

docker exec "$CONTAINER_ID" psql -U postgres -c "CREATE DATABASE evolution;"

Verificar logs da Evolution

docker service logs evolution_evolution_api --tail 50 2>&1 | grep -i "database\|error\|postgres"
`

Evolution API retorna 401/403

`bash

Verificar API Key configurada no YAML

grep "AUTHENTICATION_API_KEY" /root/evolution.yaml

Testar com a API Key correta

curl -sk -H "apikey: SUA_API_KEY" "https://$VPS_EVOLUTION_DOMAIN/instance/fetchInstances"
`

Redis da Evolution não inicia

`bash docker service logs evolution_evolution_redis --tail 30

Verificar volume

docker volume inspect evolution_redis
`

Dicas

  • Sempre use docker stack deploy em vez de docker compose up — Swarm gerencia réplicas, restart e rolling updates
  • Todo serviço precisa estar na rede overlay $VPS_NETWORK para o Traefik fazer proxy
  • Labels Traefik obrigatórias para cada serviço: traefik.enable=true, Host(), server.port, certresolver, entrypoints=websecure
  • Nunca exponha portas diretamente — use Traefik como proxy reverso
  • Salve os YAMLs em /root/` para facilitar redeploys futuros
  • Portainer API permite deploy automatizado sem acessar o painel web

Installation

Terminal bash

openclaw install setuporion-byimpa
    
Copied!

Tags

#devops_and-cloud #docker

Quick Info

Category Development
Model Claude 3.5
Complexity One-Click
Author impa365
Last Updated 3/10/2026
🚀
Optimized for
Claude 3.5
🧠

Ready to Install?

Get started with this skill in seconds

openclaw install setuporion-byimpa