Instalando VPS para NOCODE

Saudações. Nesse tutorial vou te ensinar como instalar os principais softwares para aprender tecnologias NOCODE/LOWCODE para fazer automações e integrações com Inteligencia Artificial.

Vou considerar com base o Linux Debian, você pode usar o Ubuntu ou Alpine se dominar as poucas diferenças entre eles.

Requisitos

  • Instalar o Debian Linux;
  • IP público – VPS na nuvem ou em infra dedicada;

Softwares utilizados nesse artigo

  • Linux Debian 12 ou versão mais nova;
  • Docker;

Onde contratar uma VPS (virtual private server)

O curso de uma VPS com IP público pode variar entre R$ 15,00 e R$ 150,00 por mês, o custo está relacionado a quantidade de recursos (núcleos de CPU, RAM, espaço de armazenamento e tráfego de rede). Alguns datacenters confiáveis:

Softwares para instalar no seu notebook/PC

Para iniciar as instalações você precisará entrar no Linux por linha de comando para fazer as primeiras instalações e depois poderá operar 99% via interface web bonitinha. Escolha um dos softwares de cliente SSH abaixo para fazer o primeiro acesso:

Para Windows o Putty é a opção gratuita mais pontual.
Para macOS você pode usar o Terminal nativo no menu Aplicações -> Utilitários -> Terminal.

O Termius é a melhor opção para usuários não técnicos, bonito, simples e com opção de backup automático das contas no site deles, cadastre-se em https://termius.com/index.html e faça o download do instalador.

1 – DNS e nome do seu servidor

Todas as aplicações web vão exigir URL e acesso pelo navegador em algum ponto.

Softwares de automação são baseadas em WebHooks (URLs que você fornece a eles para ser avisado de eventos).

Tudo isso depende de HTTPS – HTTP criptografado por TLS.

Para obter um certificado digital para uso do HTTPS você precisará de um domínio de DNS que aponte nomes para o IP da sua VPS (fornecido pelo datacenter na contratação).

Supondo que seu servidor/VPS terá o endereço IPv4 45.255.128.2 (IP de exemplo) e seu domínio seja exemplo.com.br (domínio de exemplo), recomendo que os seguintes nomes sejam registrados, exemplo:

  • Nome: www (www.exemplo.com.br) apontando para (registro tipo A) para 45.255.128.2

Outros nomes comuns:

  • n8n, portainer, mariadb, postgres, redis, mail, webmail

Aponte-os para o IP da sua VPS.

Alguns sistemas de DNS permitem que você crie um registro WILDCARD DNS para que qualquer nome que você digite antes do seu domínio seja direcionado para sua VPS, exemplo:

  • *.exemplo.com.br. IN A 45.255.128.2

Assim se você acessar qualquer-coisa-mesmo.exemplo.com.br seu navegador será conduzido até o IP da VPS (45.255.128.2 no exemplo acima).

Você tambêm pode criar um subdomínio só para uma VPS especifica, exemplo:

  • *.automacao.exemplo.com.br. IN A 45.255.128.2

É muito importante que sua VPS tenha um nome de DNS próprio, exemplo: automacao.exemplo.com.br

Após configurar o nome da VPS no DNS, defina-o no Linux com esse comando (troque o nome de exemplo pelo nome real, não cole o comando abaixo às cegas):

Bash
# Definindo nome do servidor:
hostnamectl  set-hostname  automacao.exemplo.com.br

2 – Instalando Docker

O Docker é um software para rodar aplicativos em containers: uma forma de cada software rodar isolado dos demais, como uma “AppStore” de softwares para servidores.

Instalar pacotes básicos no sistema:

Bash
# Atualizar base do sistema:
apt-get -y update;
apt-get -y upgrade;
apt-get -y dist-upgrade;

# Instalar pacotes básicos:
apt-get -y install sudo;
apt-get -y install curl;
apt-get -y install wget;
apt-get -y install apache2-utils;

Copie e cole os comandos abaixo no terminal da sua VPS (como root):

Bash
# Baixar script instalador oficial:
wget https://get.docker.com -O /tmp/get-docker.sh;

# Executar script instalador:
sh /tmp/get-docker.sh;

Crie uma rede para rodar os containers:

Bash
# Criar rede de containers
# Rede de containers somente ipv4
docker network create -d bridge \
    -o "com.docker.network.bridge.name"="br-net-public" \
    --subnet 10.249.0.0/16 --gateway 10.249.255.254 \
    network_public

3 – Instalando Traefik

O Traefik é um software de proxy-reverso simples e objetivo: ele monitora os containers que você irá criar e se eles possuirem labels (marcações) com o prefixo “traefik”. Essas marcações servem para instruir o Traefik a redirecionar acesso para o container e obter um certificado SSL/TLS válido para ele automaticamente.

Bash
# Variaveis
    NAME=traefik-app;
    LOCAL=$NAME.intranet.br;
    DATADIR=/storage/$NAME;
    EMAIL=seu-email-aqui@dominio-aqui.com.br;

# Diretorio de dados persistentes
    mkdir -p $DATADIR/letsencrypt;
    mkdir -p $DATADIR/logs;
    mkdir -p $DATADIR/config;

# Remover atual para garantir a renovacao:
    docker rm -f $NAME 2>/dev/null;

# - Rodar (A porta 8080 e' opcional parar acesso a Dashboard)
    docker pull traefik:latest;
    docker run -d --restart=unless-stopped \
      --name $NAME -h $LOCAL \
      --network network_public \
      --ip=10.249.255.253 \
      -p 80:80 \
      -p 443:443 \
      -p 8080:8080 \
      --memory=1g --memory-swap=1g \
      \
      -v /var/run/docker.sock:/var/run/docker.sock:ro \
      -v $DATADIR/letsencrypt:/etc/letsencrypt \
      -v $DATADIR/config:/etc/traefik \
      -v $DATADIR/logs:/logs \
      \
      traefik:latest \
      --global.checkNewVersion=false \
      --global.sendAnonymousUsage=false \
      --api.insecure=true \
      --log.level=INFO \
      --log.filePath=/logs/error.log \
      --accessLog.filePath=/logs/access.log \
      --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 \
      --providers.docker=true \
      --providers.file.directory=/etc/traefik \
      --certificatesresolvers.letsencrypt.acme.email=$EMAIL \
      --certificatesresolvers.letsencrypt.acme.storage=/etc/letsencrypt/acme.json \
      --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web

4 – Instalando Portainer

O Portainer é um software que te permitirá administrar os aplicativos usando o navegador, assim você poderá evitar a linha de comando.

Bash
# Variaveis
    NAME=portainer;
    DOMAIN="$(hostname -f)";
    FQDN="$NAME.$DOMAIN";
    LOCAL=$NAME.intranet.br;
    DATADIR=/storage/portainer;
    IMAGE=portainer/portainer-ce:latest;

# Diretorio de dados persistentes:
    mkdir -p $DATADIR;

# Remover atual para garantir a renovacao:
    docker rm -f $NAME 2>/dev/null;
    docker pull $IMAGE;

# Criar e rodar:
    docker run -d --restart=always \
      --name $NAME -h $LOCAL \
      --network network_public \
      --ip=10.249.255.251 \
      -e "TZ=America/Sao_Paulo" \
      -p 8000:8000 \
      -p 9443:9443 \
      --memory=1g --memory-swap=1g \
      \
      -v /var/run/docker.sock:/var/run/docker.sock \
      --mount type=bind,source=$DATADIR,destination=/data,readonly=false \
      \
      --label "traefik.enable=true" \
      --label "traefik.http.routers.portainer.rule=Host(\`$FQDN\`)" \
      --label "traefik.http.routers.portainer.entrypoints=websecure" \
      --label "traefik.http.routers.portainer.tls=true" \
      --label "traefik.http.routers.portainer.tls.certresolver=letsencrypt" \
      --label "traefik.http.services.portainer.loadbalancer.server.port=9000" \
      \
        $IMAGE;

# Acesso:
    echo;
    echo "Acesso:";
    echo "Web......: https://$FQDN";
    echo;

Ao instalar o Portainer ele criará um painel na porta 9443, acesse:

  • https://45.255.128.2:9443/ e define o usuário e senha inicial.

Lembrando mais uma vez que o IP 45.255.128.2 é para fins educativos, troque esse IP pelo endereço da sua VPS.

Se você configurou o nome portainer.automacao.exemplo.com.br no DNS você poderá acessar esse nome no navegador sem especificar a porta que o Traefik entregará o acesso ao Portainer internamente com certificado de segurança!

Primeiro acesso ao Portainer

Assim que instalar o Portainer você tem 1 minuto pra acessar a definir a senha, se você perder esse tempo o Portainer ficará travador para definição do primeiro acesso por motivos de segurança.

Você deve reiniciar o Portainer para que ele volte a permitir a definição da primeira senha caso você tenha perdido esse tempo:

Bash
docker  restart   portainer;

5 – Instalando WeaveScope

O WeaveScope é uma ferramenta de visualização de containers em tempo real. Ele é muito bom para visualizar limites e uso de recursos dos containers em tempo real com visual muito bonito e simples.

Instalar script de setup no HOST:

Bash
# Nota: se ele bugar, apenas destrua-o e execute novamente!

# Baixar script de provisionamento:
curl -L git.io/scope -o /usr/sbin/scope;

# Tornar executavel:
chmod a+x /usr/sbin/scope;

Executar container do WeaveScope (usando script de setup):

Bash
# Usuário e senha
    WEAVESCOPE_USER="admin";
    WEAVESCOPE_PASS="nuva_okia_2025";  # < mude a senha

# Variaveis para ativar instalação:
    arg1="ENABLE_BASIC_AUTH=true";
    arg2="BASIC_AUTH_USERNAME=$WEAVESCOPE_USER";
    arg3="BASIC_AUTH_PASSWORD=$WEAVESCOPE_PASS";
    export WEAVESCOPE_DOCKER_ARGS="-e $arg1 -e $arg2 -e $arg3";

# Destruir container atual (renovar):
    docker rm -f weavescope 2>/dev/null;

# Subir container do WeaveScope com usuário e senha (senão ele fica aberto):
    scope launch;

# Acesso:
    HOSTNAME="$(hostname -f)";
    echo;
    echo "Acesso:";
    echo "Web......: http://$HOSTNAME:4040/";
    echo;

6 – Instalando o REDIS

O REDIS é um banco de dados de chave-valor e listas simples de altíssima velocidade. Ele é muito útil em várias automações e integrações com IA.

Vou instalar dois servidores REDIS e explicar as características de cada um.

REDIS CACHE – Um REDIS 100% operado em memória RAM, sem uso de disco/storage

Esse REDIS deve ser usado para operações de manipulação de dados temporários que não precisam ser armazenados definitivamente (paginas web, listas para conversão, etc…).

Bash
# Parar instancia atual, caso exista:
    docker rm -f redis-cache 2>/dev/null;

# Criar e rodar:
    docker pull redis:8-alpine;
    docker run -d --restart=always \
      --name redis-cache -h redis-cache.intranet.br \
      --network network_public \
      --ip=10.249.255.151 \
      --memory=1g --memory-swap=1g \
      redis:8-alpine

REDIS DB – Um REDIS operando em RAM que salva dados no disco/storage

Esse REDIS deve ser usado para dados persistentes, que devem ser mantidos a salvo mesmo que seu servidor seja reiniciado. Ele é recomendado para tarefas mais importantes como histórico de conversas recentes em um chat de IA:

Bash
# Diretorio para armazenar os dados:
    DATADIR=/storage/redis-db;
    mkdir -p $DATADIR;

# Parar instancia atual, caso exista:
    docker rm -f redis-db 2>/dev/null;

# Criar e rodar:
    docker pull redis:8-alpine;
    docker run -d --restart=always \
      --name redis-db -h redis-db.intranet.br \
      --network network_public \
      --ip=10.249.255.152 \
      --memory=1g --memory-swap=1g \
      \
      -v $DATADIR:/data \
      \
      redis:8-alpine \
        redis-server \
            --bind '0.0.0.0 ::' \
            --port 6379 \
            --set-proc-title no \
            --tcp-backlog 8192 \
            --tcp-keepalive 30 \
            --timeout 0 \
            --save 900 1 \
            --save 300 10 \
            --save 60 10000 \
            --dir /data \
            --rdbcompression no \
            --rdbchecksum yes \
            --dbfilename data.rdb \
            --appendonly yes \
            --appendfsync everysec \
            --appendfilename data.aof

REDIS Commander – Software para navegar pelo REDIS visualmente pelo navegador

O redis-commander é um gestor simples de servidores REDIS, muito bom para navegar nas chaves e fazer operações usando o navegador:

Bash
# Instalar comando htpasswd do pacote apache2-utils
    apt-get -y install apache2-utils;

# Variaveis:
    NAME="redis-commander";
    DOMAIN="$(hostname -f)";
    FQDN="$NAME.$DOMAIN";

    # Usuario e senha para login
    RADM_USER=admin;
    RADM_PASS=ok_ia_redis;  # < trocar essa senha por uma senha sua segura
    RADM_HWPWD=$(htpasswd -nb "$RADM_USER" "$RADM_PASS" | sed -e 's/\\$/\\$\\$/g');

    # Cadastro de servidores REDIS para visualizar no software
    REDIS_HOSTS="REDIS-CACHE:10.249.255.151:6379";
    REDIS_HOSTS="$REDIS_HOSTS,REDIS-DB:10.249.255.152:6379";

# Parar instancia atual, caso exista:
    docker rm -f redis-commander 2>/dev/null;

# Criar e rodar:
    docker run -d --restart=always \
        --name redis-commander \
        -h redis-commander.intranet.br \
        --network network_public \
        --ip=10.249.255.159 \
        --memory=1g --memory-swap=1g \
        \
        --env REDIS_HOSTS=$REDIS_HOSTS \
        \
        --label "traefik.enable=true" \
        --label "traefik.http.middlewares.radmauth.basicauth.users=$RADM_HWPWD" \
        --label "traefik.http.routers.rediscmd.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.rediscmd.entrypoints=websecure" \
        --label "traefik.http.routers.rediscmd.tls=true" \
        --label "traefik.http.routers.rediscmd.tls.certresolver=letsencrypt" \
        --label "traefik.http.routers.rediscmd.middlewares=radmauth" \
        --label "traefik.http.services.rediscmd.loadbalancer.server.port=8081" \
    \
    rediscommander/redis-commander:latest;

# Acesso:
    echo;
    echo "Acesso:";
    echo "Web......: https://$FQDN";
    echo;

7 – Instalando MariaDB

O MariaDB é um servidor SQL tipo MySQL gratuito e open-source muito utilizado por diversos aplicativos, vamos instala-lo para servir de base para todos os softwares que precisem de um servidor SQL compatível com MySQL.

O nome do servidor MariaDB será mariadb-main para referência nos demais containers.

Bash
# Variaveis
    # Banco de dados vazio inicial
    START_DATABASE=admin;

    # Senha padrao
    ROOT_PASSWORD="tulipasql";
    USER_NAME="suporte";
    USER_PASSWORD="tulipasql";
    IMAGE=mariadb:latest;

# Pasta de persistencia
    DATADIR=/storage/mariadb-main;
    mkdir -p $DATADIR;

# Banco de dados principal
    docker run -d --restart=always \
      --name mariadb-main -h mariadb-main.intranet.br \
      --network network_public \
      --ip=10.249.255.100 \
      --memory=2g --memory-swap=2g \
      \
      -e "TZ=America/Sao_Paulo" \
      -e "MYSQL_ROOT_PASSWORD=$ROOT_PASSWORD" \
      -e "MYSQL_DATABASE=$START_DATABASE" \
      -e "MYSQL_USER=$USER_NAME" \
      -e "MYSQL_PASSWORD=$USER_PASSWORD" \
      \
      -v /storage/mariadb-main:/var/lib/mysql \
      \
      mariadb:latest;

Caso não esteja familiarizado com o MySQL/MariaDB, deixo alguns comandos que podem ser úteis para operações comuns:

Comandos opcionais, use “exit” para sair dos terminais do MariaDB:

Bash
# Acesso apartir do servidor VPS
    # Acesso: root / tulipasql
    apt-get -y install mariadb-client;
    mariadb -h 10.249.255.100 -u root    -ptulipasql;
    mariadb -h 10.249.255.100 -u suporte -ptulipasql;

# Backup:
    # Gerar data-hora para arquivo
    DTU=$(date -u '+utc-%Y-%m-%d-%H%M');

    # Criar pasta de backup:
    mkdir -p /storage/backup;

    # Extrair banco de dados 'admin'
    mariadb-dump \
        -h 10.249.255.100 \
        -u root \
        -ptulipasql \
        admin > "/storage/backup/admin-$DTU.sql";
        
    # Extrair dados de todos os bancos de dados:
    mariadb-dump \
        -h 10.249.255.100 \
        -u root \
        -ptulipasql \
        --all-databases > "/storage/backup/alldb-$DTU.sql";

# Listar variaveis:
    docker exec -it mariadb-main my_print_defaults --mysqld;

# Criar acessos extras:
# - analista21
    # Criando acesso:
    docker exec -it mariadb-main bash;
    mariadb -uroot -ptulipasql;
    
    # Comandos dentro do mariadb:
        GRANT ALL ON admin.* to analista21@'%' IDENTIFIED BY 'tulipasql' WITH GRANT OPTION;
        FLUSH PRIVILEGES;

    # Testando:
    mariadb -h 10.249.255.100 -u analista21 -ptulipasql  admin


# Comandos dentro do banco de dados:
    # Alterar senha:
    # root
    ALTER USER root@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD("tulipasql");
    FLUSH PRIVILEGES;

    # suporte
    ALTER USER suporte@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD("tulipasql");
    FLUSH PRIVILEGES;

8 – Instalando Postgres

O Postgres é um banco de dados SQL emergente que hoje ocupa a liderança do mercado de servidores SQL open-source e gratuitos. Se destaca pela performance superior e versatilidade. A tendencia é que o PGSQL (ou PG) domine o mercado totalmente.

O nome do servidor PGSQL será postgres-main para referência nos demais containers.

Bash
# Variaveis
    # Senha padrao (root), usuario padrao: postgres
    ROOT_PASSWORD="tulipa_pgsql";

# Pasta de persistencia
    DATADIR=/storage/postgres-main;
    mkdir -p $DATADIR;

# Banco de dados principal
    docker run -d --restart=always \
      --name postgres-main -h postgres-main.intranet.br \
      --network network_public \
      --ip=10.249.255.121 \
      --memory=2g --memory-swap=2g \
      -e "TZ=America/Sao_Paulo" \
      -e "POSTGRES_PASSWORD=$ROOT_PASSWORD" \
      -e POSTGRES_INITDB_ARGS="--auth-host=scram-sha-256" \
      -v $DATADIR:/var/lib/postgresql/data \
      postgres:latest \
          postgres --max_connections=8192

9 – Instalando PGVECTOR

O pgvector é uma extensão do PostgreSQL que adiciona suporte nativo para vetores e busca por similaridade vetorial (eita!). Não é um software separado do PostgreSQL, mas sim uma extensão que expande as capacidades do banco de dados.

Ele serve para:

  • Armazenamento de embeddings: Permite armazenar vetores de alta dimensionalidade (representações numéricas de texto, imagens, áudio, etc.);
  • Busca por similaridade: Oferece operadores para encontrar vetores similares usando métricas como distância euclidiana, produto escalar e similaridade de cosseno;
  • Aplicações de IA: Fundamental para sistemas de recomendação, busca semântica, RAG (Retrieval-Augmented Generation), e outras aplicações de machine learning;
  • Indexação eficiente: Suporta índices especializados (como IVFFlat e HNSW) para consultas rápidas em grandes volumes de dados vetoriais.

Resumindo: é um PGSQL para IA!

O nome do servidor PGSQL será pgvector-main para referência nos demais containers.

Bash
# Variaveis
    # Senha padrao (root), usuario padrao: postgres
    ROOT_PASSWORD="tulipa_pgsql";

# Pasta de persistencia
    DATADIR=/storage/pgvector-main;
    mkdir -p $DATADIR;

# Executar:
    # -p 5432:5432
    docker run -d --restart=always \
        --name pgvector-main -h pgvector-main.intranet.br \
        --network network_public \
        --ip=10.249.255.122 \
        --memory=2g --memory-swap=2g \
        \
        -e "TZ=America/Sao_Paulo" \
        -e "POSTGRES_PASSWORD=$ROOT_PASSWORD" \
        -e POSTGRES_INITDB_ARGS="--auth-host=scram-sha-256" \
        \
        -v $DATADIR:/var/lib/postgresql/data \
        --entrypoint "docker-entrypoint.sh" \
        \
        pgvector/pgvector:pg16 \
        postgres \
            --max_connections=8192 \
            --wal_level=minimal \
            --max_wal_senders=0 \
            --port=5432

10 – Instalando pgAdmin

O pgAdmin é um software de interface web para administração de servidores PostgreSQL.

Vamos usá-lo para administrar principalmente o postgres-main e pgvector-main.

Bash
# Variaveis
    NAME="pgadmin";
    DOMAIN=$(hostname -f);
    FQDN="$NAME.$DOMAIN";
    LOCAL="$NAME.intranet.br";
    IMAGE=dpage/pgadmin4;

    # Troque o email e a senha para garantir a segurança
    PGADMIN_DEFAULT_EMAIL="root@intranet.br";
    PGADMIN_DEFAULT_PASSWORD="pgadmin@2025";

    DATADIR=/storage/pgadmin;
    mkdir -p $DATADIR;
    chown 5050 $DATADIR;

# Obter imagem sempre atualizada:
    docker pull $IMAGE;

# Parar container atual:
    docker rm -f $NAME 2>/dev/null;

# Criar e rodar:
    docker run -d --restart=always \
        --name $NAME -h $NAME.intranet.br \
        --network network_public \
        --ip=10.249.255.138 \
        --memory=2g --memory-swap=2g \
        \
        -p 15080:80 \
        \
        -e PGADMIN_DEFAULT_EMAIL=$PGADMIN_DEFAULT_EMAIL \
        -e PGADMIN_DEFAULT_PASSWORD=$PGADMIN_DEFAULT_PASSWORD \
        \
        -v $DATADIR:/var/lib/pgadmin \
        \
        --label "traefik.enable=true" \
        --label "traefik.http.routers.$NAME.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.$NAME.entrypoints=web,websecure" \
        --label "traefik.http.routers.$NAME.tls=true" \
        --label "traefik.http.routers.$NAME.tls.certresolver=letsencrypt" \
        --label "traefik.http.services.$NAME.loadbalancer.passHostHeader=true" \
        --label "traefik.http.services.$NAME.loadbalancer.server.port=80" \
        \
        $IMAGE;

echo;
echo "Acesso:";
echo "Web......: https://$FQDN";
echo;

Você pode acessar o pgAdmin pelo endereço WEB ou pela porta 15080 no IP ou nome do servidor.

11 – Instalando RabbitMQ

O RabbitMQ é um software de mensageria (uma especie de “emails entre softwares”) muito bom para acumular tarefas sem risco de perder mensagens.

Bash
# Variaveis
    NAME="rabbitmq";
    DOMAIN=$(hostname -f);
    FQDN="$NAME.$DOMAIN";
    LOCAL="$NAME.intranet.br";
    TZ="$(timedatectl show | egrep Timezone= | cut -f2 -d=)";

    # Troque por uma sequencia hexadecimal aleatoria
    RABBITMQ_COOKIE="b09c62afcd9908a431";

    # Mude a senha!
    RABBITMQ_USER="admin";
    RABBITMQ_PASS="nuva_okia_2025";

    DATADIR=/storage/rabbitmq;
    mkdir -p $DATADIR;

    IMAGE=rabbitmq:management;

# Parar container atual:
    docker rm -f $NAME 2>/dev/null;

# Criar e rodar:
    docker run -d --restart=always \
        --name $NAME -h $NAME.intranet.br \
        --network network_public \
        --ip=10.249.255.161 \
        --memory=2g --memory-swap=2g \
        \
        -p 5672:5672 \
        -p 15672:15672 \
        -p 25676:25676 \
        \
        -e TZ=$TZ \
        -e RABBITMQ_ERLANG_COOKIE=$RABBITMQ_COOKIE \
        -e RABBITMQ_DEFAULT_VHOST=default \
        -e RABBITMQ_DEFAULT_USER=$RABBITMQ_USER \
        -e RABBITMQ_DEFAULT_PASS=$RABBITMQ_PASS \
        \
        -v $DATADIR:/var/lib/rabbitmq \
        \
        --label "traefik.enable=true" \
        --label "traefik.http.routers.$NAME.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.$NAME.entrypoints=web,websecure" \
        --label "traefik.http.routers.$NAME.tls=true" \
        --label "traefik.http.routers.$NAME.tls.certresolver=letsencrypt" \
        --label "traefik.http.services.$NAME.loadbalancer.passHostHeader=true" \
        --label "traefik.http.services.$NAME.loadbalancer.server.port=15672" \
        \
        --entrypoint "docker-entrypoint.sh" \
        \
        rabbitmq:management rabbitmq-server;

echo;
echo "Acesso:";
echo "Web......: https://$FQDN";
echo;

12 – Instalando MinIO (S3)

O MinIO é um software de armazenamento de arquivos compativel com Amazon S3 (Armazenamento na nuvem), ótimo para armazenar todo tipo de arquivo (fotos, videos e filmes, logs, backups, discos virtuais, ISOs) em “baldes” (Buckets) nomeados. Podem ser integrados em clusters distribuídos para garantir arquivos eternos e imutáveis (alterar um arquivo cria uma nova versão e preserva a anterior, tornando o armazenamento imune a ransomware).

Bash
# Variaveis
    NAME=minio;
    IMAGE="quay.io/minio/minio:RELEASE.2025-04-22T22-12-26Z";
    TZ="$(timedatectl show | egrep Timezone= | cut -f2 -d=)";

    # nomes de dns: minio e minio-console
    DOMAIN=$(hostname -f);
    FQDN_WEB="$NAME.$DOMAIN";
    FQDN_CONSOLE="$NAME-console.$DOMAIN";

    # Mude a senha!
    MINIO_ROOT_USER="admin";
    MINIO_ROOT_PASSWORD="nuva_okia_2025";

    DATADIR=/storage/minio;
    mkdir -p $DATADIR;

# Parar container atual:
    docker rm -f $NAME 2>/dev/null;

# Atualizar/baixar imagem:
    docker pull $IMAGE;

# Rodar:
    docker run \
      -d --restart=always \
      --name $NAME -h $NAME.intranet.br \
      --network network_public \
      --ip=10.249.255.240 \
      --memory=2g --memory-swap=2g \
      \
      -e TZ=$TZ \
      \
      -e "MINIO_ROOT_USER=$MINIO_ROOT_USER" \
      -e "MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD" \
      -e "MINIO_BROWSER_REDIRECT_URL=https://$FQDN_CONSOLE" \
      -e "MINIO_SERVER_URL=https://$FQDN_WEB" \
      \
      -v $DATADIR:/data \
      \
      --label "traefik.enable=true" \
      \
      --label "traefik.http.routers.${NAME}_web.rule=Host(\`$FQDN_WEB\`)" \
      --label "traefik.http.routers.${NAME}_web.entrypoints=web,websecure" \
      --label "traefik.http.routers.${NAME}_web.tls=true" \
      --label "traefik.http.routers.${NAME}_web.tls.certresolver=letsencrypt" \
      --label "traefik.http.routers.${NAME}_web.service=${NAME}_web" \
      --label "traefik.http.services.${NAME}_web.loadbalancer.server.port=9000" \
      --label "traefik.http.services.${NAME}_web.loadbalancer.passHostHeader=true" \
      \
      --label "traefik.http.routers.${NAME}_con.rule=Host(\`$FQDN_CONSOLE\`)" \
      --label "traefik.http.routers.${NAME}_con.entrypoints=web,websecure" \
      --label "traefik.http.routers.${NAME}_con.tls=true" \
      --label "traefik.http.routers.${NAME}_con.tls.certresolver=letsencrypt" \
      --label "traefik.http.routers.${NAME}_con.service=${NAME}_con" \
      --label "traefik.http.services.${NAME}_con.loadbalancer.server.port=9001" \
      --label "traefik.http.services.${NAME}_con.loadbalancer.passHostHeader=true" \
      \
      $IMAGE \
          server /data --console-address ":9001";

# Acesso:
    echo;
    echo "Acesso:";
    echo "Web......: https://$FQDN_WEB";
    echo "Console..: https://$FQDN_CONSOLE";
    echo;

13 – Instalando N8N – modo simples

O N8N é um software para construir automações de maneira visual e com pouco (ou nenhum) conhecimento de programação.

Por conta disso ele é classificado como um software NOCODE (sem precisar escrever código) ou LOWCODE (desenvolvendo o mínimo e usando o máximo de itens prontos).

Existem muitas formas de rodar o N8N, vamos usar a mais simples possível e deixar as formas mais complexas para o futuro. Saiba que é possível instalar:

  • (A) N8N simples – uma única instância do software fica responsável pelo editor (parte visual), pelo WebHook (receber pedidos externos) e pelo Worker (parte que cuida da execução dos nodes – pequenos pedaços do workflow) e todos os dados de execução e trabalhos ficam num banco de dados de arquivo simples tipo SQLITE;
  • (B) N8N simples com PGSQL – semelhante ao modo acima, mas troca o SQLITE limitado pelo poderoso Postres (deve rodar em container separado);
  • (C) N8N modo fila – cada parte do sistema é executado em containers diferentes, possuindo um container para o editor (1), um container para receber as chamadas WebHook (2), um container ou mais para a execução Worker (3), um container para servidores MCP (4) e o container adicional para o Postgres;

As versões do N8N e lançamentos podem ser acompanhadas nessa página:

Como o foco desse tutorial é montar um ambiente de aprendizado e testes, vamos usar o modo simples (A):

Bash
# Preencha seu email corretamente
    EMAIL=seu-email-aqui@dominio-aqui.com.br

# Variaveis
    NAME=n8n
    DOMAIN="$(hostname -f)"
    FQDN="$NAME.$DOMAIN"
    DATADIR=/storage/n8n-data
    NODEDIR=/storage/n8n-nodes

    # Obter timezone do HOST para usar no container
    TZ="$(timedatectl show | egrep Timezone= | cut -f2 -d=)"
    # Versao N8N
    N8N_VERSION=latest # anterior 1.100.1
    IMAGE=n8nio/n8n:$N8N_VERSION

# Diretorio de dados persistentes - Criar e corrigir permissoes:
    mkdir -p $DATADIR; chown 1000:1000 $DATADIR -R;
    mkdir -p $NODEDIR; chown 1000:1000 $NODEDIR -R;

# Renovar/rodar:
    # Parar container atual:
    docker rm -f $NAME 2>/dev/null;
    # Forcar obtencao da imagem mais nova:
    docker pull $IMAGE;

    # Criar e rodar:
    docker run -d --restart=always \
        --name $NAME -h $NAME.intranet.br \
        --network network_public --ip=10.249.255.10 \
        --memory=2g --memory-swap=2g \
        \
        -e TZ=$TZ \
        -e GENERIC_TIMEZONE==$TZ \
        \
        -e N8N_HOST=$FQDN \
        -e N8N_PORT=5678 \
        -e N8N_PROTOCOL=https \
        -e NODE_ENV=production \
        -e WEBHOOK_URL=https://$FQDN/ \
        -e GENERIC_TIMEZONE=$TZ \
        -e SSL_EMAIL=$EMAIL \
        \
        -e EXECUTIONS_DATA_PRUNE=true \
        -e EXECUTIONS_DATA_MAX_AGE=24 \
        -e EXECUTIONS_DATA_PRUNE_MAX_COUNT=512 \
        -e EXECUTIONS_DATA_SAVE_ON_ERROR=all \
        -e EXECUTIONS_DATA_SAVE_ON_SUCCESS=all \
        -e EXECUTIONS_DATA_SAVE_ON_PROGRESS=true \
        -e EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true \
        \
        -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
        -e N8N_RUNNERS_ENABLED=true \
        -e N8N_RUNNERS_MODE=internal \
        -e N8N_NODE_PATH=/data/nodes \
        -e N8N_CUSTOM_EXTENSIONS=/data/nodes \
        -e N8N_COMMUNITY_PACKAGES_ENABLED=true \
        -e N8N_REINSTALL_MISSING_PACKAGES=true \
        -e N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true \
        -e OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=false \
        \
        -v $DATADIR:/home/node/.n8n \
        -v $NODEDIR:/data/nodes \
        \
        --label "traefik.enable=true" \
        --label "traefik.http.routers.$NAME.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.$NAME.entrypoints=web,websecure" \
        --label "traefik.http.routers.$NAME.tls=true" \
        --label "traefik.http.routers.$NAME.tls.certresolver=letsencrypt" \
        --label "traefik.http.services.$NAME.loadbalancer.server.port=5678" \
        $IMAGE;

# Acesso:
    echo;
    echo "Acesso:";
    echo "Web......: https://$FQDN";
    echo;

Agora acesse:

  • n8n.automacao.exemplo.com.br e informe seus dados para primeiro login!

14 – Instalando N8N – modo fila

O N8N no modo fila difere do modo simples pois implementa as seguintes técnicas de engenharia:

  • Utiliza o PostgreSQL (PG) em vez do SQLITE. O SQLITE não é bom para casos onde vários processos acessam o mesmo arquivo, já o PG foi feito exatamente para acessos paralelos e escaláveis;
  • Separa o processo principal (CORE e EDITOR) dos processos de trabalho (WORKERS e WEBHOOK).
  • Utiliza o REDIS para mensageria interna instantânea entre os processos acima.
  • Os WORKERS podem ser escalados verticalmente para que dezenas, centenas e até milhares de execuções possam acontecer paralelamente.

Temos duas escolhas para montar um N8N modo fila:

  • Usar containers de PG e REDIS dedicados ao N8N modo fila: essa opção é mais adequada para migrações de servidores e isolamento de acessos e dados, a desvantagem é o consumo adicional de RAM (caro em VPS);
  • Usar containers de PG e REDIS centrais compartilhados com outros softwares, a vantagem é a economia de recursos, a desvantagem é a falta de isolamento, o que requer do administrador mais conciência sobre os privilégios de acesso e questões de segurança;

Como nosso ambiente é de estudos e não expomos o PG e o REDIS na Internet, vou optar por usar o container postgres-main e redis-cache criados nos capítulos anteriores.

Preparativos

É necessário criar o banco de dados exclusivo para N8N no PG (postgres-main):

Bash
# Entrar no postgres-main:
docker exec -it --user=root postgres-main psql -U postgres;

Comandos SQL dentro do postgres-main:

SQL
-- 1. Criar o usuário 'n8n' com senha:
CREATE USER n8n WITH PASSWORD 'tulipasql';

-- 2. Criar o banco de dados 'n8n_queue', o banco pertence ao usuario 'n8n':
CREATE DATABASE n8n_queue OWNER n8n;

-- 3. Conceder privilégios ao usuário 'n8n' no banco 'n8n_queue':
GRANT ALL PRIVILEGES ON DATABASE n8n_queue TO n8n;

-- 4. Conectar ao banco 'n8n_queue' para configurar privilégios adicionais:
\c n8n_queue;

-- 5. Conceder privilégios no schema public
GRANT ALL ON SCHEMA public TO n8n;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO n8n;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO n8n;

-- 6. Garantir privilégios para tabelas e sequências futuras
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO n8n;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO n8n;

-- Sair do PSQL:
\q

Nenhuma configuração é necessária no redis-cache, vamos usar o banco de dados 8.

Preparando variáveis

Os endereços de DNS utilizados serão:

  • editor.SEU-DOMINIO-DNS: processo principal para edição de workflows e gestão do N8N;
  • ws.SEU-DOMINIO-DNS: processo responsável pelos triggers Webhook (servidor WEB do N8N, todos os fins e tipos semelhantes);

Vamos criar um arquivo /tmp/n8n-args.sh para armazenar todas as variáveis em forma de argumentos do comando “docker run”, esses argumentos serão compartilhadas entre os containers (cada processo interno do N8N terá seu container).

Bash
# Preencha seu email corretamente
    EMAIL=seu-email-aqui@dominio-aqui.com.br;


# Variaveis com nomes de DNS:
    SERVER_FQDN=$(hostname -f);
    FQDN_EDITOR="editor.$SERVER_FQDN";
    FQDN_WEBHOOK="ws.$SERVER_FQDN";


# Versao do N8N:
    N8N_VERSION=latest;  # anterior: 1.107.3
    IMAGE=n8nio/n8n:$N8N_VERSION;


# Variaveis gerais:
    # Diretorio de dados persistentes do modo fila:
    DATADIR=/storage/n8n-queue-data;
    NODEDIR=/storage/n8n-queue-nodes;

    # Obter timezone do HOST para usar no container
    TZ="$(timedatectl show | egrep Timezone= | cut -f2 -d=)";

    # Chave de criptografia dos dados no DB, nao mudar
    # apos definir e rodar pela primeira vez
    # Exemplo abaixo baseado em MD5(tulipa)
    N8N_ENCRYPTION_KEY=52169089a52705298a67f2f8d9895c76


# Variaveis de acesso ao REDIS:
    REDIS_SERVER="redis-cache";
    REDIS_PORT="6379";
    REDIS_DB="8";
    REDIS_PASSWORD=""; # mais rapido sem senha


# Variaveis de acesso ao PostgreSQL:
    POSTGRESDB_DATABASE="n8n_queue";
    POSTGRESDB_HOST="postgres-main";
    POSTGRESDB_PORT="5432";
    POSTGRESDB_USER="n8n";
    POSTGRESDB_PASSWORD="tulipasql";


# Variaveis de acesso SMTP (opcional):
    SMTP_HOST="mail.intranet.br";
    SMTP_PORT="587";
    SMTP_USER="username@intranet.br";
    SMTP_PASS="secret_smtp123";
    SMTP_SENDER="manager@intranet.br";
    SMTP_SSL="true";


# Gerar arquivo com todos os argumentos de variaveis de ambiente:
  (
      echo "  \\";
      echo "  -e TZ=$TZ \\";
      echo "  -e GENERIC_TIMEZONE=$TZ \\";
      echo "  -e SSL_EMAIL=$EMAIL \\";
      echo "  \\";
      echo "  -e NODE_ENV=production \\";
      echo "  -e EXECUTIONS_MODE=queue \\";
      echo "  -e EXECUTIONS_TIMEOUT=1800 \\";
      echo "  -e EXECUTIONS_TIMEOUT_MAX=1800 \\";
      echo "  \\";
      echo "  -e N8N_ENCRYPTION_KEY=$N8N_ENCRYPTION_KEY \\";
      echo "  -e N8N_HOST=$SERVER_FQDN \\";
      echo "  \\";
      echo "  -e N8N_EDITOR_BASE_URL=https://$FQDN_EDITOR \\";
      echo "  -e WEBHOOK_URL=https://$FQDN_WEBHOOK \\";
      echo "  \\";
      echo "  -e QUEUE_BULL_REDIS_HOST=$REDIS_SERVER \\";
      echo "  -e QUEUE_BULL_REDIS_PORT=$REDIS_PORT \\";
      echo "  -e QUEUE_BULL_REDIS_DB=$REDIS_DB \\";
      echo "  -e QUEUE_BULL_REDIS_PASSWORD=$REDIS_PASSWORD \\";
      echo "  \\";
      echo "  -e DB_TYPE=postgresdb \\";
      echo "  -e DB_POSTGRESDB_DATABASE=$POSTGRESDB_DATABASE \\";
      echo "  -e DB_POSTGRESDB_HOST=$POSTGRESDB_HOST \\";
      echo "  -e DB_POSTGRESDB_PORT=$POSTGRESDB_PORT \\";
      echo "  -e DB_POSTGRESDB_USER=$POSTGRESDB_USER \\";
      echo "  -e DB_POSTGRESDB_PASSWORD=$POSTGRESDB_PASSWORD \\";
      echo "  \\";
      echo "  -e N8N_EMAIL_MODE=smtp \\";
      echo "  -e N8N_SMTP_HOST=$SMTP_HOST \\";
      echo "  -e N8N_SMTP_PORT=$SMTP_PORT \\";
      echo "  -e N8N_SMTP_USER=$SMTP_USER \\";
      echo "  -e N8N_SMTP_PASS=$SMTP_PASS \\";
      echo "  -e N8N_SMTP_SENDER=$SMTP_SENDER \\";
      echo "  -e N8N_SMTP_SSL=true \\";
      echo "  \\";
      echo "  -e EXPRESS_TRUST_PROXY=true \\";
      echo "  -e N8N_PROXY_HOPS=1 \\";
      echo "  \\";
      echo "  -e N8N_CUSTOM_EXTENSIONS=/data/nodes \\";
      echo "  -e N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true \\";
      echo "  -e N8N_COMMUNITY_PACKAGES_ENABLED=true \\";
      echo "  -e N8N_DIAGNOSTICS_ENABLED=false \\";
      echo "  -e N8N_ENDPOINT_WEBHOOK=webhook \\";
      echo "  -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \\";
      echo "  -e 'NODE_FUNCTION_ALLOW_BUILTIN=*' \\";
      echo "  -e NODE_FUNCTION_ALLOW_EXTERNAL=moment,lodash,axios \\";
      echo "  -e N8N_HIDE_USAGE_PAGE=false \\";
      echo "  -e N8N_LOG_LEVEL=info \\";
      echo "  -e N8N_METRICS=true \\";
      echo "  -e N8N_NODE_PATH=/data/nodes \\";
      echo "  -e N8N_ONBOARDING_FLOW_DISABLED=true \\";
      echo "  -e N8N_PAYLOAD_SIZE_MAX=512 \\";
      echo "  -e N8N_PORT=5678 \\";
      echo "  -e N8N_PROTOCOL=https \\";
      echo "  -e N8N_PUBLIC_API_SWAGGERUI_DISABLED=false \\";
      echo "  -e N8N_REINSTALL_MISSING_PACKAGES=true \\";
      echo "  -e N8N_RUNNERS_ENABLED=true \\";
      echo "  -e N8N_RUNNERS_MODE=internal \\";
      echo "  -e N8N_TEMPLATES_ENABLED=true \\";
      echo "  -e N8N_TRUST_PROXY=true \\";
      echo "  -e N8N_VERSION_NOTIFICATIONS_ENABLED=true \\";
      echo "  -e N8N_WORKFLOW_TAGS_DISABLED=false \\";
      echo "  \\";
      echo "  -e EXECUTIONS_DATA_PRUNE=true \\";
      echo "  -e EXECUTIONS_DATA_MAX_AGE=336 \\";
      echo "  -e EXECUTIONS_DATA_PRUNE_MAX_COUNT=2048 \\";
      echo "  -e EXECUTIONS_DATA_PRUNE_HARD_DELETE_INTERVAL=15 \\";
      echo "  -e EXECUTIONS_DATA_PRUNE_SOFT_DELETE_INTERVAL=60 \\";
      echo "  -e EXECUTIONS_DATA_SAVE_ON_ERROR=all \\";
      echo "  -e EXECUTIONS_DATA_SAVE_ON_SUCCESS=all \\";
      echo "  -e EXECUTIONS_DATA_SAVE_ON_PROGRESS=true \\";
      echo "  -e EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=true \\";
      echo "  \\";
      echo "  -e OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true \\";
      echo "  \\";
      echo "  -v $DATADIR:/home/node/.n8n \\"
      echo "  -v $NODEDIR:/data/nodes \\"
      echo "  \\";
  ) > /tmp/n8n-args.sh;

Copie todo o bloco acima e cole no terminal.
Com o script /tmp/n8n-args.sh pronto, execute os containers:

Bash
# Preparativos
#----------------------------------------------------------------------

# 1 - remover containers atuais para renovar execucção:
  docker rm -f n8n-editor  2>/dev/null;
  docker rm -f n8n-worker  2>/dev/null;
  docker rm -f n8n-webhook 2>/dev/null;

# 2 - baixar imagem atualizada:
  docker pull $IMAGE;

# 3 - criar diretorio de dados com propriedade correta:
  mkdir -p $DATADIR; chown 1000:1000 $DATADIR -R;
  mkdir -p $NODEDIR; chown 1000:1000 $NODEDIR -R;


# EDITOR
#----------------------------------------------------------------------

# Nome do container do editor:
NAME=n8n-editor;

# Script do editor
(
  echo '#!/bin/sh';
  echo;
  echo "docker rm -f $NAME 2>/dev/null;";
  echo "docker run \\";
  echo " -d --restart=always \\";
  echo " --name $NAME -h $NAME.intranet.br \\";
  echo " --network network_public \\";
  echo " --ip=10.249.255.191 \\";
  cat /tmp/n8n-args.sh;
  echo " --label \"traefik.enable=true\" \\";
  echo " --label \"traefik.http.routers.$NAME.rule=Host(\\\`$FQDN_EDITOR\\\`)\" \\";
  echo " --label \"traefik.http.routers.$NAME.entrypoints=web,websecure\" \\";
  echo " --label \"traefik.http.routers.$NAME.tls=true\" \\";
  echo " --label \"traefik.http.routers.$NAME.tls.certresolver=letsencrypt\" \\";
  echo " --label \"traefik.http.services.$NAME.loadbalancer.server.port=5678\" \\";
  echo " $IMAGE start";
  echo;
) > /tmp/n8n-run-editor.sh;
sh /tmp/n8n-run-editor.sh;


# WEBHOOK
#----------------------------------------------------------------------

# Nome do container do webhook (servidor http de gatilhos):
NAME=n8n-webhook;

# Script do webhook
(
  echo '#!/bin/sh';
  echo;
  echo "docker rm -f $NAME 2>/dev/null;";
  echo;
  echo "docker run \\";
  echo " -d --restart=always \\";
  echo " --name $NAME -h $NAME.intranet.br \\";
  echo " --network network_public \\";
  echo " --ip=10.249.255.192 \\";
  cat /tmp/n8n-args.sh;
  echo " --label \"traefik.enable=true\" \\";
  echo " --label \"traefik.http.routers.$NAME.rule=Host(\\\`$FQDN_WEBHOOK\\\`)\" \\";
  echo " --label \"traefik.http.routers.$NAME.entrypoints=web,websecure\" \\";
  echo " --label \"traefik.http.routers.$NAME.service=$NAME\" \\";
  echo " --label \"traefik.http.routers.$NAME.tls=true\" \\";
  echo " --label \"traefik.http.routers.$NAME.tls.certresolver=letsencrypt\" \\";
  echo " --label \"traefik.http.services.$NAME.loadbalancer.server.port=5678\" \\";
  echo " $IMAGE webhook";
  echo;
) > /tmp/n8n-run-webhook.sh;
sh /tmp/n8n-run-webhook.sh;


# WORKERS
#----------------------------------------------------------------------

# Nome do container do worker (processos de execucao dos workflows)
NAME=n8n-worker;

# Contar quantidade de threads (processos paralelos) do worker:
WORKER_THREADS=16;

# Script do editor
(
  echo '#!/bin/sh';
  echo;
  echo "docker rm -f $NAME 2>/dev/null;";
  echo;
  echo "docker run \\";
  echo "  -d --restart=always \\";
  echo "  --name $NAME -h $NAME.intranet.br \\";
  echo "  --network network_public \\";
  echo "  --ip=10.249.255.193 \\";
  cat /tmp/n8n-args.sh;
  echo "  $IMAGE worker --concurrency=$WORKER_THREADS";
  echo;
) > /tmp/n8n-run-worker.sh;
sh /tmp/n8n-run-worker.sh;


# Fim
#----------------------------------------------------------------------

# Acesso:
    echo;
    echo "Acesso:";
    echo "Web (EDITOR)..: https://$FQDN_EDITOR";
    echo "Web (Webhook).: https://$FQDN_WEBHOOK";
    echo;

15 – Instalando ChatWoot

O ChatWoot (CW) é uma ferramenta de comunicação omni-channel – um canal central para utilizar várias tecnologias de mensagens, chat e gestão de atendimentos.

Ele atua como um “WhatsApp Web de todos os mensagens para equipes”.

Com ele você pode reunir Telegram, WhatsApp, Email e outros sistemas em uma única interface de chat. Ele suporta várias contas no mesmo sistema (várias caixas de entrada).

Preparativos: o ChatWoot requer um banco de dados em PostgreSQL com suporte a VectorStore, logo, vamos usar o container pgvector-main.

Bash
# Entrar no postgres-main:
docker exec -it --user=root pgvector-main psql -U postgres;

Comandos a executar dentro do PostgreSQL do container pgvector-main:

SQL
-- usuario:
CREATE USER chatwoot
    WITH PASSWORD 'cw_sql'
        CREATEDB
        LOGIN;

-- criar db e usuario do chatwoot
CREATE DATABASE chatwoot
    WITH 
    OWNER = chatwoot
        ENCODING = 'UTF8'
        TABLESPACE = pg_default
        IS_TEMPLATE = False
        CONNECTION LIMIT = -1;

-- Conectar no banco:
\c chatwoot;

-- Adicionar extensao:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

-- Conceder todos os privilégios no banco
GRANT ALL PRIVILEGES ON DATABASE chatwoot TO chatwoot;

-- Conceder privilégios no schema público
GRANT ALL ON SCHEMA public TO chatwoot;

-- Garantir privilégios em tabelas futuras
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO chatwoot;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO chatwoot;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO chatwoot;
ALTER USER chatwoot WITH SUPERUSER;

-- Verificar se o usuário foi criado
\du chatwoot;

-- Verificar se o banco foi criado
\l chatwoot;

-- Verificar privilégios no banco
\l+ chatwoot;

-- Sair
\q

Rodando container de administração do ChatWoot:

Bash
# Altere:
    EMAIL="seu-email-aqui@dominio.com.br";

# Variaveis
    NAME="chatwoot-admin";
    DOMAIN="$(hostname -f)";
    FQDN="chat.$DOMAIN";
    LOCAL="chat.intranet.br";
    TZ="$(timedatectl show | egrep Timezone= | cut -f2 -d=)";
    IMAGE=chatwoot/chatwoot:v4.4.0-ce

# Parametros do chatwoot
    # md5 de tulipa - md5(tulipa) = 52169089a52705298a67f2f8d9895c76
    CWA_SKEYB=52169089a52705298a67f2f8d9895c76;
    CWA_LANG=pt-BR;

# Acesso redis
    REDIS_HOST=redis-db;
    REDIS_PORT=6379;
    REDIS_DB=4;
    REDIS_URL="redis://$REDIS_HOST:$REDIS_PORT/$REDIS_DB";

# Acesso postgress
    POSTGRES_HOST=pgvector-main;
    POSTGRES_USERNAME=chatwoot;
    POSTGRES_PASSWORD=cw_sql;
    POSTGRES_DATABASE=chatwoot;

# Acesso SMTP
    SMTP_ADDRESS=smtp.seu-dominio.com.br;
    SMTP_AUTHENTICATION=plain;
    SMTP_DOMAIN=seu-dominio.com.br;
    SMTP_ENABLE_STARTTLS_AUTO=true;
    SMTP_PORT=465;
    SMTP_USERNAME=usuario@seu-dominio.com.br;
    SMTP_PASSWORD=senha_usuario_aqui;

# Minio
    STORAGE_BUCKET_NAME=chatwoot;
    STORAGE_ACCESS_KEY_ID=chatwoot_ak;
    STORAGE_SECRET_ACCESS_KEY=ZPutIJPVxTlNwjzhWsalLoWu1sgxoChjxl7Ided1;
    STORAGE_REGION=intranet1;
    STORAGE_ENDPOINT=https://minio.$DOMAIN;
    STORAGE_FORCE_PATH_STYLE=true;

# Diretorio de dados persistentes:
    DATADIR=/storage/chatwoot;
    mkdir -p $DATADIR;

# Renovar/rodar
    docker rm -f $NAME 2>/dev/null;
    docker pull $IMAGE;
    docker run \
        -d --restart=always \
        --name $NAME -h $LOCAL \
        --network network_public \
        --ip=10.249.241.250 \
        \
        -e TZ=$TZ \
        \
        -e INSTALLATION_NAME=chatwoot \
        -e NODE_ENV=production \
        -e RAILS_ENV=production \
        -e INSTALLATION_ENV=docker \
        -e WEB_CONCURRENCY=32 \
        -e RAILS_MAX_THREADS=64 \
        -e CW_API_ONLY_SERVER=false \
        \
        -e SECRET_KEY_BASE=$CWA_SKEYB \
        -e FRONTEND_URL=https://$FQDN \
        -e DEFAULT_LOCALE=$CWA_LANG \
        \
        -e REDIS_URL=$REDIS_URL \
        \
        -e POSTGRES_HOST=$POSTGRES_HOST \
        -e POSTGRES_USERNAME=$POSTGRES_USERNAME \
        -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \
        -e POSTGRES_DATABASE=$POSTGRES_DATABASE \
        \
        -e MAILER_SENDER_EMAIL=$EMAIL \
        \
        -e FORCE_SSL=true \
        -e ENABLE_ACCOUNT_SIGNUP=false \
        -e RAILS_LOG_TO_STDOUT=true \
        -e USE_INBOX_AVATAR_FOR_BOT=true \
        -e ENABLE_PUSH_RELAY_SERVER=true \
        \
        -e SMTP_ADDRESS=$SMTP_ADDRESS \
        -e SMTP_AUTHENTICATION=$SMTP_AUTHENTICATION \
        -e SMTP_DOMAIN=$SMTP_DOMAIN \
        -e SMTP_ENABLE_STARTTLS_AUTO=$SMTP_ENABLE_STARTTLS_AUTO \
        -e SMTP_PORT=$SMTP_PORT \
        -e SMTP_USERNAME=$SMTP_USERNAME \
        -e SMTP_PASSWORD=$SMTP_PASSWORD \
        \
        -e SIDEKIQ_CONCURRENCY=10 \
        -e ACTIVE_STORAGE_SERVICE=s3_compatible \
        -e STORAGE_BUCKET_NAME=$STORAGE_BUCKET_NAME \
        -e STORAGE_ACCESS_KEY_ID=$STORAGE_ACCESS_KEY_ID \
        -e STORAGE_SECRET_ACCESS_KEY=$STORAGE_SECRET_ACCESS_KEY \
        -e STORAGE_REGION=$STORAGE_REGION \
        -e STORAGE_ENDPOINT=$STORAGE_ENDPOINT \
        -e STORAGE_FORCE_PATH_STYLE=$STORAGE_FORCE_PATH_STYLE \
        \
        --mount \
            type=bind,source=$DATADIR,destination=/app/storage,readonly=false \
        \
        --label "traefik.enable=true" \
        \
        --label "traefik.http.routers.$NAME.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.$NAME.entrypoints=web,websecure" \
        --label "traefik.http.routers.$NAME.tls=true" \
        --label "traefik.http.routers.$NAME.tls.certresolver=letsencrypt" \
        --label "traefik.http.routers.$NAME.service=$NAME" \
        \
        --label "traefik.http.middlewares.${NAME}sslheader.headers.customrequestheaders.X-Forwarded-Proto=https" \
        --label "traefik.http.routers.$NAME.middlewares=${NAME}sslheader@docker" \
        \
        --label "traefik.http.services.$NAME.loadbalancer.server.port=3000" \
        --label "traefik.http.services.$NAME.loadbalancer.passHostHeader=true" \
        \
        --entrypoint "docker/entrypoints/rails.sh" \
        \
        $IMAGE \
            bundle exec rails s -p 3000 -b 0.0.0.0;

Rodando container da API ChatWoot:

Bash
# Variaveis
    NAME="chatwoot-api";
    DOMAIN="$(hostname -f)";
    FQDN="cwapi.$DOMAIN";
    LOCAL="$NAME.intranet.br";
    TZ="$(timedatectl show | egrep Timezone= | cut -f2 -d=)";
    IMAGE=chatwoot/chatwoot:v4.4.0-ce

# Diretorio de dados persistentes:
    DATADIR=/storage/chatwoot;
    mkdir -p $DATADIR;

# Renovar/rodar:
    docker rm -f $NAME 2>/dev/null;
    docker pull $IMAGE;
    docker run \
        -d --restart=always \
        --name $NAME -h $LOCAL \
        --network network_public \
        --ip=10.249.241.251 \
        \
        -e TZ=$TZ \
        -e CW_API_ONLY_SERVER=true \
        \
        --mount \
            type=bind,source=$DATADIR,destination=/app/storage,readonly=false \
        \
        --label "traefik.enable=true" \
        \
        --label "traefik.http.routers.$NAME.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.$NAME.entrypoints=web,websecure" \
        --label "traefik.http.routers.$NAME.tls=true" \
        --label "traefik.http.routers.$NAME.tls.certresolver=letsencrypt" \
        --label "traefik.http.routers.$NAME.service=$NAME" \
        \
        --label "traefik.http.middlewares.${NAME}sslheader.headers.customrequestheaders.X-Forwarded-Proto=https" \
        --label "traefik.http.routers.$NAME.middlewares=${NAME}sslheader@docker" \
        \
        --label "traefik.http.services.$NAME.loadbalancer.server.port=3000" \
        --label "traefik.http.services.$NAME.loadbalancer.passHostHeader=true" \
        \
        --entrypoint "docker/entrypoints/rails.sh" \
        \
        $IMAGE \
            bundle exec rails s -p 3000 -b 0.0.0.0;

Container do sidekiq (sistema interno do ChatWoot):

Bash
# Variaveis
    NAME="chatwoot-sidekiq";
    LOCAL="$NAME.intranet.br";
    TZ="$(timedatectl show | egrep Timezone= | cut -f2 -d=)";
    IMAGE=chatwoot/chatwoot:v4.4.0-ce

# Diretorio de dados persistentes:
    DATADIR=/storage/chatwoot;
    mkdir -p $DATADIR;

# Renovar/rodar:
    docker rm -f $NAME 2>/dev/null;
    docker pull $IMAGE;
    docker run \
        -d --restart=always \
        --name $NAME -h $LOCAL \
        --network network_public \
        --ip=10.249.241.252 \
        \
        -e TZ=$TZ \
        -e CW_API_ONLY_SERVER=true \
        \
        --mount \
            type=bind,source=$DATADIR,destination=/app/storage,readonly=false \
        \
        --entrypoint "docker/entrypoints/rails.sh" \
        \
        $IMAGE \
            bundle exec sidekiq -C config/sidekiq.yml;

Procedimentos de instalação (necessário para que os containers executem corretamente, se não executar eles ficarão reiniciando):

Bash
# Preparar banco de dados:
docker exec -it chatwoot-admin sh -c 'bundle exec rails db:chatwoot_prepare';

Conclusão

Agora dedique-se a estudar cada capítulo desse tutorial para dominar um ambiente de automações e transformar seu trabalho em mágica!

Um script plano desse tutorial pode ser encontrado em:

  • Script Docker-IA-LAB: https://tmsoft.com.br/temp/docker-ia-lab.sh
Bash
# Instalando via script
wget  http://arquivos.nuva.com.br/docker-ia-lab.sh  -O /tmp/docker-ia-lab.sh;
sh  /tmp/docker-ia-lab.sh;

Até mais,
Patrick Brandão, patrickbrandao@gmail.com