#!/usr/bin/env bash # Instalação do B2BCall em um Debian 13 (trixie) limpo (agente.md seção 86). # Idempotente na medida do possível: pula passos já satisfeitos. set -euo pipefail cd "$(dirname "$0")/.." REPO_ROOT="$(pwd)" echo "############################################################" echo "# B2BCall - instalação" echo "############################################################" # 1. Permissões ------------------------------------------------------------- if [ "$(id -u)" -ne 0 ]; then echo "Erro: rode este script como root (sudo)." >&2 exit 1 fi # 2. Dependências de sistema ------------------------------------------------- echo "==> Instalando dependências de sistema..." apt-get update -qq apt-get install -y -qq git curl ca-certificates gnupg lsb-release apt-transport-https openssl if ! command -v node >/dev/null 2>&1; then echo "==> Instalando Node.js 24 LTS..." curl -fsSL https://deb.nodesource.com/setup_24.x -o /tmp/nodesource_setup.sh bash /tmp/nodesource_setup.sh apt-get install -y -qq nodejs fi echo "==> Habilitando pnpm via corepack..." corepack enable corepack prepare pnpm@11.24.0 --activate # 3. Docker ------------------------------------------------------------- if ! command -v docker >/dev/null 2>&1; then echo "==> Instalando Docker Engine + Compose plugin..." install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc CODENAME=$(. /etc/os-release && echo "$VERSION_CODENAME") echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $CODENAME stable" \ > /etc/apt/sources.list.d/docker.list apt-get update -qq apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable --now docker fi # 4. Diretórios ------------------------------------------------------------- mkdir -p backups # 5/6. Secrets e .env --------------------------------------------------- if [ ! -f .env ]; then echo "==> Gerando .env a partir de .env.example..." cp .env.example .env chmod 600 .env eval "$(bash scripts/generate-secrets.sh | sed 's/^/GEN_/')" sed -i \ -e "s#^POSTGRES_PASSWORD=.*#POSTGRES_PASSWORD=${GEN_POSTGRES_PASSWORD}#" \ -e "s#^DATABASE_URL=.*#DATABASE_URL=postgresql://b2bcall:${GEN_POSTGRES_PASSWORD}@postgres:5432/b2bcall?schema=public#" \ -e "s#^REDIS_PASSWORD=.*#REDIS_PASSWORD=${GEN_REDIS_PASSWORD}#" \ -e "s#^REDIS_URL=.*#REDIS_URL=redis://:${GEN_REDIS_PASSWORD}@redis:6379#" \ -e "s#^JWT_ACCESS_SECRET=.*#JWT_ACCESS_SECRET=${GEN_JWT_ACCESS_SECRET}#" \ -e "s#^JWT_REFRESH_SECRET=.*#JWT_REFRESH_SECRET=${GEN_JWT_REFRESH_SECRET}#" \ -e "s#^SECRETS_MASTER_KEY=.*#SECRETS_MASTER_KEY=${GEN_SECRETS_MASTER_KEY}#" \ -e "s#^AMI_SECRET=.*#AMI_SECRET=${GEN_AMI_SECRET}#" \ -e "s#^ARI_SECRET=.*#ARI_SECRET=${GEN_ARI_SECRET}#" \ .env echo " .env gerado com segredos aleatórios fortes." else echo "==> .env já existe, mantendo." fi set -a; source .env; set +a # nftables (proteção AMI/ARI/SIP contra a LAN, nunca bloqueia SSH) ------- if command -v nft >/dev/null 2>&1; then echo "==> Instalando regras de firewall (nftables)..." ln -sf "$REPO_ROOT/infrastructure/nftables/b2bcall-nftables.service" /etc/systemd/system/b2bcall-nftables.service systemctl daemon-reload systemctl enable b2bcall-nftables.service systemctl restart b2bcall-nftables.service fi if ! grep -q "^vm.overcommit_memory" /etc/sysctl.d/99-b2bcall-redis.conf 2>/dev/null; then echo "vm.overcommit_memory = 1" > /etc/sysctl.d/99-b2bcall-redis.conf sysctl -w vm.overcommit_memory=1 >/dev/null fi # 7. Dependências do monorepo + build ---------------------------------- echo "==> Instalando dependências do monorepo (pnpm install)..." pnpm install --frozen-lockfile echo "==> Buildando imagens Docker (pode levar vários minutos na primeira vez)..." docker compose build # 8. Postgres/Redis ----------------------------------------------------- echo "==> Subindo Postgres e Redis..." docker compose up -d postgres redis echo " Aguardando ficarem saudáveis..." until [ "$(docker inspect -f '{{.State.Health.Status}}' b2bcall-postgres 2>/dev/null)" = "healthy" ] && \ [ "$(docker inspect -f '{{.State.Health.Status}}' b2bcall-redis 2>/dev/null)" = "healthy" ]; do sleep 2 done # 9. Migrations + seed ---------------------------------------------------- echo "==> Aplicando migrations e seed inicial (permissões, perfis, super_admin)..." ( cd packages/database export DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@127.0.0.1:${POSTGRES_PORT:-5432}/${POSTGRES_DB}?schema=public" pnpm exec prisma migrate deploy pnpm run seed ) # 10/11. Asterisk + demais serviços -------------------------------------- echo "==> Subindo Asterisk e demais serviços..." docker compose up -d # 12. Health checks ------------------------------------------------------- echo "==> Aguardando serviços ficarem saudáveis..." sleep 15 bash scripts/healthcheck.sh || true # 13. Resultado ----------------------------------------------------------- echo "" echo "############################################################" echo "# Instalação concluída" echo "############################################################" echo "URL: http://$(hostname -I | awk '{print $1}')/" echo "API: http://$(hostname -I | awk '{print $1}')/api/health" if [ -f FIRST_LOGIN.txt ]; then echo "" echo "Credenciais do primeiro acesso em: $REPO_ROOT/FIRST_LOGIN.txt" echo "(remova este arquivo do servidor após o primeiro login)" fi