Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .env.vps.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# ===========================================
# EVOLUTION API - VPS ENV (EXAMPLE)
# ===========================================

# ===========================================
# SERVER
# ===========================================
SERVER_NAME=evolution
SERVER_TYPE=http
SERVER_PORT=8080
SERVER_URL=http://YOUR_SERVER_IP:8080
SERVER_DISABLE_DOCS=false
SERVER_DISABLE_MANAGER=false

# ===========================================
# DATABASE (PostgreSQL)
# ===========================================
DATABASE_PROVIDER=postgresql
POSTGRES_DATABASE=evolution_api
POSTGRES_USERNAME=evolution
POSTGRES_PASSWORD=supersecret
DATABASE_CONNECTION_URI=postgresql://evolution:supersecret@postgres:5432/evolution_api

# ===========================================
# REDIS
# ===========================================
CACHE_REDIS_ENABLED=true
CACHE_REDIS_URI=redis://redis:6379
CACHE_REDIS_PREFIX_KEY=evolution-cache
CACHE_REDIS_TTL=604800

# ===========================================
# AUTH
# ===========================================
AUTHENTICATION_API_KEY=change-this-key
AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=false

# ===========================================
# CORS
# ===========================================
CORS_ORIGIN=*
CORS_METHODS=POST,GET,PUT,DELETE
CORS_CREDENTIALS=true

# ===========================================
# LANGUAGE
# ===========================================
LANGUAGE=pt-BR

# ===========================================
# WEBSOCKET
# ===========================================
WEBSOCKET_ENABLED=true
WEBSOCKET_GLOBAL_EVENTS=true

# ===========================================
# LOGS
# ===========================================
LOG_LEVEL=ERROR,WARN,INFO
LOG_COLOR=true

75 changes: 75 additions & 0 deletions DEPLOY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
### Deploy da Evolution API (Railway e VPS)

Este guia cobre dois cenários: deploy no Railway (PaaS) e em uma VPS usando Docker Compose.

## Requisitos
- Node/TS não necessários no servidor (usaremos Docker)
- Banco: PostgreSQL
- Cache: Redis

## 1) Railway

O repositório já possui `Dockerfile` e `railway.json` (raiz) para build via Docker. Passos:

1. Crie um projeto no Railway.
2. Adicione dois serviços gerenciados: PostgreSQL e Redis.
3. Adicione um serviço "Deploy from Repo" apontando para este repositório.
- Builder: Dockerfile (automaticamente detectado pelo `railway.json`).
4. Configure as variáveis de ambiente no serviço da API:
- `DATABASE_PROVIDER=postgresql`
- `DATABASE_CONNECTION_URI` = string de conexão do PostgreSQL fornecida pelo Railway
- `CACHE_REDIS_URI` = URL do Redis fornecida pelo Railway
- `AUTHENTICATION_API_KEY` = defina uma chave forte
- Opcional: `SERVER_PORT=8080` (padrão já é 8080), `LANGUAGE=pt-BR`, `CORS_ORIGIN=*`

O container roda `./Docker/scripts/deploy_database.sh` no entrypoint e aplica as migrations automaticamente. A porta exposta é 8080.

Observações:
- Armazenamento local do diretório `/evolution/instances` é efêmero no Railway. Se precisar persistência de sessões do WhatsApp, use volumes persistentes do Railway (se disponível) ou uma estratégia externa de storage.

## 2) VPS (Docker Compose)

Arquivos preparados:
- `docker-compose.vps.yaml` (API, Postgres, Redis)
- `.env.vps.example` (variáveis mínimas para subir)
- `scripts/install_vps.sh` (instala Docker e sobe a stack)

Passos:
1. Copie `.env.vps.example` para `.env` e ajuste se necessário:
- `AUTHENTICATION_API_KEY` (será gerada automaticamente pelo script se não setada)
- `SERVER_URL` com IP/host público
2. Execute o script (como root ou com sudo):

```bash
bash scripts/install_vps.sh
```

3. Verifique serviços:

```bash
docker compose -f docker-compose.vps.yaml ps
```

4. A API ficará disponível em `http://SEU_IP:8080`.

Atualizações:
```bash
docker compose -f docker-compose.vps.yaml pull
docker compose -f docker-compose.vps.yaml up -d --build
```

Logs:
```bash
docker compose -f docker-compose.vps.yaml logs -f api
```

## Variáveis essenciais
- `DATABASE_PROVIDER=postgresql`
- `DATABASE_CONNECTION_URI` (ex.: `postgresql://user:pass@postgres:5432/db`)
- `CACHE_REDIS_URI` (ex.: `redis://redis:6379`)
- `AUTHENTICATION_API_KEY` (chave da sua API)

## Segurança
- Use uma chave forte em `AUTHENTICATION_API_KEY`.
- Restrinja acesso à porta 8080 via firewall se necessário e exponha via proxy (Nginx) com HTTPS.

55 changes: 55 additions & 0 deletions docker-compose.vps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version: "3.8"

services:
api:
container_name: evolution_api
build:
context: .
dockerfile: Dockerfile
image: evolution-api:vps
restart: always
depends_on:
- postgres
- redis
ports:
- "8080:8080"
env_file:
- .env
volumes:
- evolution_instances:/evolution/instances
networks:
- evolution-net

postgres:
container_name: evolution_postgres
image: postgres:15
restart: always
environment:
- POSTGRES_DB=${POSTGRES_DATABASE}
- POSTGRES_USER=${POSTGRES_USERNAME}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- evolution-net

redis:
container_name: evolution_redis
image: redis:7
restart: always
command: redis-server --port 6379 --appendonly yes
volumes:
- redis_data:/data
networks:
- evolution-net

volumes:
evolution_instances:
postgres_data:
redis_data:

networks:
evolution-net:
name: evolution-net
driver: bridge

15 changes: 15 additions & 0 deletions railway.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://railway.com/railway.schema.json",
"build": {
"builder": "DOCKERFILE",
"dockerfilePath": "Dockerfile"
},
"deploy": {
"runtime": "V2",
"numReplicas": 1,
"sleepApplication": false,
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 10
}
}

104 changes: 104 additions & 0 deletions scripts/install_vps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env bash

set -euo pipefail

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

log() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
err() { echo -e "${RED}[ERROR]${NC} $*"; }

require_cmd() {
command -v "$1" >/dev/null 2>&1 || { err "Comando necessário não encontrado: $1"; exit 1; }
}

ensure_root() {
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
if command -v sudo >/dev/null 2>&1; then
export SUDO=sudo
else
err "Execute como root ou instale sudo"; exit 1
fi
else
export SUDO=
fi
}

install_docker() {
if command -v docker >/dev/null 2>&1; then
log "Docker já instalado: $(docker --version)"
else
log "Instalando Docker Engine..."
. /etc/os-release
case "$ID" in
ubuntu|debian)
$SUDO apt-get update -y
$SUDO apt-get install -y ca-certificates curl gnupg lsb-release
install -d -m 0755 /etc/apt/keyrings
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Potential permission issue when creating /etc/apt/keyrings without sudo.

Prefix the 'install' command with $SUDO to avoid permission errors when not running as root.

curl -fsSL https://download.docker.com/linux/$ID/gpg | $SUDO gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$ID $(. /etc/os-release && echo $VERSION_CODENAME) stable" | $SUDO tee /etc/apt/sources.list.d/docker.list >/dev/null
$SUDO apt-get update -y
$SUDO apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
;;
centos|rhel|rocky|almalinux)
$SUDO yum install -y yum-utils
$SUDO yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$SUDO yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
$SUDO systemctl enable --now docker
;;
*)
err "Distribuição não suportada automaticamente ($ID). Instale Docker manualmente."; exit 1;
;;
esac
$SUDO systemctl enable --now docker || true
fi

if docker compose version >/dev/null 2>&1; then
log "Docker Compose plugin detectado."
else
warn "Docker Compose plugin não encontrado. Tentando instalar via pipx (fallback)."
$SUDO apt-get install -y python3-pip python3-venv || true
$SUDO pip3 install docker-compose || true
require_cmd docker-compose || warn "Instale manualmente o compose se necessário."
fi
}

prepare_env() {
if [ ! -f .env ]; then
log "Gerando .env a partir de .env.vps.example"
cp .env.vps.example .env
# gerar chave aleatória
local key
key=$(openssl rand -hex 24)
sed -i "s/^AUTHENTICATION_API_KEY=.*/AUTHENTICATION_API_KEY=${key}/" .env
Comment on lines +71 to +77
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: No check for existence of .env.vps.example before copying.

Add a file existence check before copying to prevent script failure if .env.vps.example is missing.

Suggested change
if [ ! -f .env ]; then
log "Gerando .env a partir de .env.vps.example"
cp .env.vps.example .env
# gerar chave aleatória
local key
key=$(openssl rand -hex 24)
sed -i "s/^AUTHENTICATION_API_KEY=.*/AUTHENTICATION_API_KEY=${key}/" .env
if [ ! -f .env ]; then
if [ ! -f .env.vps.example ]; then
log "Erro: .env.vps.example não encontrado. Não é possível gerar .env."
exit 1
fi
log "Gerando .env a partir de .env.vps.example"
cp .env.vps.example .env
# gerar chave aleatória
local key
key=$(openssl rand -hex 24)
sed -i "s/^AUTHENTICATION_API_KEY=.*/AUTHENTICATION_API_KEY=${key}/" .env

Comment on lines +74 to +77
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): No check for openssl availability before using it.

Use 'require_cmd openssl' before this line to ensure the command doesn't fail if openssl is missing.

Suggested change
# gerar chave aleatória
local key
key=$(openssl rand -hex 24)
sed -i "s/^AUTHENTICATION_API_KEY=.*/AUTHENTICATION_API_KEY=${key}/" .env
# gerar chave aleatória
require_cmd openssl
local key
key=$(openssl rand -hex 24)
sed -i "s/^AUTHENTICATION_API_KEY=.*/AUTHENTICATION_API_KEY=${key}/" .env

else
log ".env já existe, mantendo configurações atuais."
fi

# Garantir que variáveis mínimas existam
grep -q '^DATABASE_PROVIDER=' .env || echo 'DATABASE_PROVIDER=postgresql' >> .env
grep -q '^SERVER_PORT=' .env || echo 'SERVER_PORT=8080' >> .env
}

bring_up() {
log "Subindo stack com docker compose (api, postgres, redis)..."
docker compose -f docker-compose.vps.yaml up -d --build
log "Aguardando containers iniciarem..."
sleep 5
docker compose -f docker-compose.vps.yaml ps
}

main() {
ensure_root
install_docker
prepare_env
bring_up
log "Pronto! API ouvindo em http://SEU_IP:8080"
}

main "$@"