infra: stack Traefik (Swarm), exemplos de env, CI GitHub Actions e ajuste workspace pnpm

This commit is contained in:
Esdras Renan 2025-10-08 10:20:04 -03:00
parent e4db48d8b4
commit ec1539b446
7 changed files with 255 additions and 1 deletions

59
.env.example Normal file
View file

@ -0,0 +1,59 @@
# Ambiente local — Sistema de Chamados
# Copie este arquivo para `.env` e preencha os valores sensíveis.
# Nunca faça commit de `.env` com segredos reais.
# Convex
CONVEX_DEPLOYMENT=anonymous:anonymous-sistema-de-chamados
NEXT_PUBLIC_CONVEX_URL=http://127.0.0.1:3210
CONVEX_SYNC_SECRET=dev-sync-secret
# Next.js / App URL
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Better Auth
# Gere um segredo forte (ex.: `openssl rand -hex 32`)
BETTER_AUTH_SECRET=change-me
BETTER_AUTH_URL=http://localhost:3000
# Banco de dados (Prisma)
DATABASE_URL=file:./prisma/db.sqlite
# Provisionamento e inventário de máquinas
# Segredo obrigatório para registrar/atualizar máquinas (Convex)
MACHINE_PROVISIONING_SECRET=change-me-provisioning
# Tempo de vida do token de máquina (ms) — padrão 30 dias
MACHINE_TOKEN_TTL_MS=2592000000
# Opcional: segredo dedicado para webhook do FleetDM (senão usa o de provisionamento)
FLEET_SYNC_SECRET=
# SMTP (envio de e-mails)
SMTP_ADDRESS=
SMTP_PORT=465
SMTP_DOMAIN=
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_AUTHENTICATION=login
SMTP_ENABLE_STARTTLS_AUTO=false
SMTP_TLS=true
MAILER_SENDER_EMAIL="Suporte <no-reply@seu-dominio.com>"
# Alertas (actions do Convex)
# Hora local (America/Sao_Paulo) para rodar alertas automáticos
ALERTS_LOCAL_HOUR=8
# Seeds e sincronizações auxiliares
SYNC_TENANT_ID=tenant-atlas
SYNC_DEFAULT_ASSIGNEE=agent@example.com
SEED_TENANT_ID=tenant-atlas
SEED_ADMIN_PASSWORD=admin123
SEED_AGENT_PASSWORD=agent123
SEED_USER_TENANT=tenant-atlas
SEED_USER_EMAIL=
SEED_USER_PASSWORD=
SEED_USER_NAME=
SEED_USER_ROLE=admin
# Desenvolvimento Desktop (Tauri/Vite)
# Em redes locais, defina o IP do host para HMR.
TAURI_DEV_HOST=

97
.github/workflows/ci-cd-web-desktop.yml vendored Normal file
View file

@ -0,0 +1,97 @@
name: CI/CD Web + Desktop
on:
push:
branches: [ main ]
tags:
- 'v*.*.*'
env:
APP_DIR: /srv/apps/sistema
VPS_UPDATES_DIR: /var/www/updates
jobs:
deploy:
name: Deploy (VPS Linux)
if: ${{ startsWith(github.ref, 'refs/heads/') }}
runs-on: [ self-hosted, linux, vps ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Sync workspace to APP_DIR
run: |
mkdir -p "$APP_DIR"
rsync -az --delete --exclude '.git' --exclude '.next' ./ "$APP_DIR"/
- name: Install and build (Next.js)
run: |
cd "$APP_DIR"
corepack enable || true
pnpm install --frozen-lockfile
pnpm prisma:generate
pnpm build
- name: Optional Swarm deploy (stack.yml)
if: ${{ hashFiles(format('{0}/stack.yml', env.APP_DIR)) != '' }}
run: |
cd "$APP_DIR"
docker stack deploy --with-registry-auth -c stack.yml sistema
desktop_release:
name: Desktop Release (Windows)
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
runs-on: [ self-hosted, windows, desktop ]
defaults:
run:
working-directory: apps/desktop
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install deps (desktop)
run: pnpm install --frozen-lockfile
- name: Build with Tauri
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
with:
projectPath: apps/desktop
- name: Upload latest.json + bundles to VPS
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
source: |
**/bundle/**/latest.json
**/bundle/**/*
target: ${{ env.VPS_UPDATES_DIR }}
overwrite: true

2
.gitignore vendored
View file

@ -33,6 +33,8 @@ yarn-error.log*
# env files (can opt-in for committing if needed)
.env*
!.env.example
!apps/desktop/.env.example
# vercel
.vercel

View file

@ -14,7 +14,7 @@ Aplicação Next.js 15 com Convex e Better Auth para gestão de tickets da Rever
```bash
pnpm install
```
2. Ajuste o arquivo `.env` (ou crie a partir do exemplo) e confirme os valores de:
2. Ajuste o arquivo `.env` (ou crie a partir de `.env.example`) e confirme os valores de:
- `NEXT_PUBLIC_CONVEX_URL` (gerado pelo Convex Dev)
- `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`, `DATABASE_URL`
3. Aplique as migrações e gere o client Prisma:
@ -42,6 +42,12 @@ Aplicação Next.js 15 com Convex e Better Auth para gestão de tickets da Rever
> Se o CLI perguntar sobre configuração do projeto Convex, escolha criar um novo deployment local (opção padrão) e confirme. As credenciais são armazenadas em `.convex/` automaticamente.
### Variáveis de ambiente
- Exemplo na raiz: `.env.example` — copie para `.env` e preencha segredos.
- App Desktop: `apps/desktop/.env.example` — copie para `apps/desktop/.env` e ajuste `VITE_APP_URL`.
- Nunca faça commit de arquivos `.env` com valores reais (já ignorados em `.gitignore`).
## Scripts úteis
- `pnpm lint` — ESLint com as regras do projeto.

10
apps/desktop/.env.example Normal file
View file

@ -0,0 +1,10 @@
# Ambiente local do App Desktop (Vite/Tauri)
# Copie para `apps/desktop/.env` e ajuste.
# URL da aplicação web (Next.js) que será carregada dentro do app desktop.
VITE_APP_URL=http://localhost:3000
# Opcional: IP do host para desenvolvimento com HMR fora do localhost
# Ex.: 192.168.0.10
TAURI_DEV_HOST=

View file

@ -1,3 +1,6 @@
packages:
- .
ignoredBuiltDependencies:
- '@prisma/client'
- '@prisma/engines'

77
stack.yml Normal file
View file

@ -0,0 +1,77 @@
version: "3.8"
services:
web:
image: node:20-bullseye
working_dir: /app
command: >
bash -lc "corepack enable \
&& corepack prepare pnpm@9 --activate \
&& pnpm install --frozen-lockfile \
&& pnpm prisma:generate \
&& npx prisma migrate deploy \
&& pnpm build \
&& pnpm start -p 3000"
volumes:
- ./:/app
- sistema_db:/app/data
environment:
NODE_ENV: "production"
# Mantém o SQLite fora do repositório
DATABASE_URL: "file:/app/data/db.sqlite"
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.docker.network=traefik_public
- traefik.http.routers.sistema_web.rule=Host(`tickets.esdrasrenan.com.br`)
- traefik.http.routers.sistema_web.entrypoints=websecure
- traefik.http.routers.sistema_web.tls=true
- traefik.http.routers.sistema_web.tls.certresolver=le
- traefik.http.services.sistema_web.loadbalancer.server.port=3000
networks:
- traefik_public
convex:
image: node:20-bullseye
working_dir: /app
command: >
bash -lc "corepack enable \
&& corepack prepare pnpm@9 --activate \
&& pnpm install --frozen-lockfile \
&& set -a && . ./.env && set +a \
&& pnpm convex:dev --port 3210 --hostname 0.0.0.0"
volumes:
- ./:/app
- convex_data:/root/.convex
environment:
NODE_ENV: "production"
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.docker.network=traefik_public
- traefik.http.routers.sistema_convex.rule=Host(`convex.esdrasrenan.com.br`)
- traefik.http.routers.sistema_convex.entrypoints=websecure
- traefik.http.routers.sistema_convex.tls=true
- traefik.http.routers.sistema_convex.tls.certresolver=le
- traefik.http.services.sistema_convex.loadbalancer.server.port=3210
networks:
- traefik_public
volumes:
sistema_db:
convex_data:
networks:
traefik_public:
external: true