mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 02:51:46 +00:00
docs: atualizar CLAUDE.md e README; adicionar script de instalação Ubuntu
- CLAUDE.md: rota attachments/ adicionada ao mapa de diretórios (app e features); seção Response Style substituída por Security Rules - README.md: instruções para servidor Ubuntu 24.04, preview do Companion, seção de Backup; menção ao Companion atualizada - scripts/install-deps.sh: prepara VPS Ubuntu limpa instalando Docker, Node.js 22 e pnpm Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
37
CLAUDE.md
37
CLAUDE.md
@@ -16,7 +16,7 @@
|
||||
3. **Periods** usam formato `YYYY-MM` (ex: `"2025-11"`). Utils em `src/shared/utils/period/`.
|
||||
4. **Moeda**: R$ com 2 decimais. DB: `numeric(12, 2)`. Utils em `src/shared/utils/currency.ts`.
|
||||
5. **Revalidation**: usar `revalidateForEntity("entity")` de `src/shared/lib/actions/helpers.ts` apos mutations.
|
||||
6. **Versionamento**: registrar mudancas no `CHANGELOG.md` seguindo Keep a Changelog, também altere o `package.json` e `readme.md`.
|
||||
6. **Versionamento**: registrar mudancas no `CHANGELOG.md` seguindo Keep a Changelog, também altere o `package.json` e `readme.md` (Badges do README.md).
|
||||
7. **Comunicacao**: responder em portugues clara e direta com o time.
|
||||
8. **Commit messages**: agrupar por natureza. em pt-br. seguindo o padrao do sistema.
|
||||
9. **README.md**: sempre que fizer alteracoes significativas, atualize o README.md.
|
||||
@@ -85,6 +85,7 @@ src/
|
||||
│ │ ├── insights/
|
||||
│ │ ├── calendar/
|
||||
│ │ ├── inbox/
|
||||
│ │ ├── attachments/
|
||||
│ │ ├── changelog/
|
||||
│ │ ├── reports/
|
||||
│ │ │ ├── category-trends/
|
||||
@@ -111,6 +112,7 @@ src/
|
||||
│ ├── insights/
|
||||
│ ├── calendar/
|
||||
│ ├── inbox/
|
||||
│ ├── attachments/
|
||||
│ ├── reports/
|
||||
│ └── settings/
|
||||
├── shared/
|
||||
@@ -307,18 +309,29 @@ export async function fetchData(userId: string, period: string) {
|
||||
|
||||
---
|
||||
|
||||
## Response Style
|
||||
## Security Rules
|
||||
|
||||
Quando o time pedir avaliacao de plano ou feature:
|
||||
Regras aplicadas automaticamente ao gerar codigo.
|
||||
|
||||
1. Responder em portugues simples.
|
||||
2. Listar 3-5 problemas principais.
|
||||
3. Fechar com decisao pratica:
|
||||
- aprova agora
|
||||
- nao aprova agora
|
||||
- o que ajustar antes de comecar codigo
|
||||
### Secrets
|
||||
Nunca colocar API keys, credenciais de banco ou tokens em codigo frontend. Evitar variaveis prefixadas com `NEXT_PUBLIC_` para dados sensiveis — estas sao bundladas no cliente. Usar variaveis server-side apenas. `.env` deve estar no `.gitignore` antes do primeiro commit. `.env.example` deve ter apenas placeholders.
|
||||
|
||||
Exemplo:
|
||||
### Autenticacao & Autorizacao
|
||||
Toda rota protegida em `src/app/api/` requer `getUser()` ou `getOptionalUserSession()` antes de qualquer logica, retornando 401 para nao autenticados. Rotas com IDs de recursos devem verificar ownership: `eq(table.userId, userId)`. Rotas admin devem checar role e retornar 403 para nao-admins. Session cookies em Better Auth ja tem `httpOnly`, `secure` e `sameSite` configurados — nao alterar.
|
||||
|
||||
- "Nao aprovaria para comecar codigo imediatamente."
|
||||
- "Primeiro ajustaria o doc com estes 5 pontos."
|
||||
### Input & Output
|
||||
Usar Drizzle ORM (parametrizado por padrao) — nunca concatenar input de usuario em SQL. Validar todo input com Zod antes de usar. Upload de arquivos: usar whitelist de MIME types (`ALLOWED_MIME_TYPES`), presigned URLs para S3, token de upload assinado com verificacao pos-upload. Nunca usar `dangerouslySetInnerHTML` com conteudo de usuario.
|
||||
|
||||
### Headers & CSP
|
||||
CSP definida em `src/proxy.ts` via middleware — alterar la, nao em `next.config.ts`. Headers de seguranca (HSTS, X-Frame-Options, etc.) definidos em `next.config.ts`. Nao remover nem enfraquecer essas configuracoes.
|
||||
|
||||
### Rate Limiting
|
||||
Login: 5 tentativas/min. Signup: 3 tentativas/min. API tokens: 100 req/min (inbox), 20 req/min (batch). Configurado em `src/shared/lib/auth/config.ts` e nas rotas de inbox. Nao remover.
|
||||
|
||||
### Tratamento de Erros
|
||||
Erros nao devem expor stack traces, paths ou nomes de bibliotecas ao cliente. Usar mensagens genericas: `"Algo deu errado"`. Logar detalhes apenas no servidor com `console.error()`.
|
||||
|
||||
### Dependencias
|
||||
Verificar pacotes novos sugeridos pela IA em npmjs.com antes de instalar. Red flags: menos de 1.000 downloads/semana, publicado nos ultimos 30 dias, nome muito parecido com pacote popular. Rodar `pnpm audit` periodicamente.
|
||||
|
||||
---
|
||||
|
||||
169
README.md
169
README.md
@@ -8,7 +8,7 @@
|
||||
|
||||
> **⚠️ Não há versão online hospedada.** Você precisa clonar o repositório e rodar localmente ou no seu próprio servidor.
|
||||
|
||||
[](CHANGELOG.md)
|
||||
[](CHANGELOG.md)
|
||||
[](https://nextjs.org/)
|
||||
[](https://www.typescriptlang.org/)
|
||||
[](https://www.postgresql.org/)
|
||||
@@ -23,15 +23,21 @@
|
||||
<img src="./public/images/dashboard-preview-light.webp" alt="Dashboard Preview" width="800" />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="./public/images/preview-lancamentos-light.webp" alt="Lançamentos" width="800" />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## 📖 Índice
|
||||
|
||||
- [Sobre o Projeto](#-sobre-o-projeto)
|
||||
- [Instalação via Script](#-instalação-via-script)
|
||||
- [Preparar o servidor (Ubuntu 24.04)](#-preparar-o-servidor-ubuntu-2404)
|
||||
- [Início Rápido (manual)](#-início-rápido)
|
||||
- [Scripts Disponíveis](#-scripts-disponíveis)
|
||||
- [Docker](#-docker)
|
||||
- [Backup](#-backup)
|
||||
- [Storage S3 Compatível](#-storage-s3-compatível)
|
||||
- [Variáveis de Ambiente](#-variáveis-de-ambiente)
|
||||
- [Arquitetura](#-arquitetura)
|
||||
@@ -53,7 +59,7 @@ A ideia é simples: ter um lugar onde consigo ver todas as minhas contas, cartõ
|
||||
|
||||
**1. Não há versão hospedada online** — Este projeto é self-hosted. Você precisa rodar no seu próprio computador ou servidor.
|
||||
|
||||
**2. Não há Open Finance** — Não há conexão automática com bancos. Você pode registrar transações manualmente ou importar extratos nos formatos OFX e XLS/XLSX.
|
||||
**2. Não há Open Finance** — Não há conexão automática com bancos. Você pode registrar transações manualmente, usar o app companion para capturar notificações bancárias ou importar extratos nos formatos OFX e XLS/XLSX.
|
||||
|
||||
**3. Requer disciplina** — O OpenMonetis funciona melhor para quem tem disciplina de registrar os gastos regularmente, quer controle total sobre seus dados e gosta de entender exatamente onde o dinheiro está indo.
|
||||
|
||||
@@ -77,7 +83,11 @@ A ideia é simples: ter um lugar onde consigo ver todas as minhas contas, cartõ
|
||||
|
||||
📅 **Calendário financeiro** — Visualize todos os lançamentos em um calendário mensal.
|
||||
|
||||
📲 **OpenMonetis Companion** — App Android que captura notificações bancárias (Nubank, Itaú, Bradesco, Inter, C6 e outros) e envia como pré-lançamentos para revisão. [Repositório](https://github.com/felipegcoutinho/openmonetis-companion).
|
||||
📲 **OpenMonetis Companion** — App Android que captura notificações bancárias (Nubank, Itaú, Bradesco, Inter, C6 e outros) e envia automaticamente como pré-lançamentos para revisão — sem digitar nada. [Repositório](https://github.com/felipegcoutinho/openmonetis-companion).
|
||||
|
||||
<p align="center">
|
||||
<img src="./public/images/companion-preview-light.webp" alt="OpenMonetis Companion" width="300" height="600" />
|
||||
</p>
|
||||
|
||||
⚙️ **Personalização** — Tema dark/light e modo privacidade.
|
||||
|
||||
@@ -97,6 +107,31 @@ A ideia é simples: ter um lugar onde consigo ver todas as minhas contas, cartõ
|
||||
|
||||
A forma mais rápida de instalar. O script verifica dependências, configura o `.env` interativamente e sobe o banco automaticamente.
|
||||
|
||||
### 🖥️ Preparar o servidor (Ubuntu 24.04)
|
||||
|
||||
Se você está num **servidor Ubuntu limpo** (VPS, Oracle Cloud, DigitalOcean...) sem Node.js, Docker ou pnpm instalados, use o script de preparação antes de continuar.
|
||||
|
||||
> ⚠️ **Testado apenas em Ubuntu Server 24.04 LTS.** Em outras distribuições ou versões é necessário testar ou ajustar o script.
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/felipegcoutinho/openmonetis/main/scripts/install-deps.sh -o install-deps.sh
|
||||
sudo sh install-deps.sh
|
||||
```
|
||||
|
||||
O script instala (e pula o que já estiver presente):
|
||||
|
||||
| Ferramenta | Como instala |
|
||||
|---|---|
|
||||
| `git`, `curl`, `ca-certificates` | apt |
|
||||
| Docker Engine + Docker Compose | Repositório oficial do Docker |
|
||||
| Homebrew | Script oficial (como usuário não-root) |
|
||||
| Node.js 22 | Via Homebrew |
|
||||
| pnpm | Via corepack |
|
||||
|
||||
Após a conclusão, adiciona o usuário atual ao grupo `docker` — faça logout/login para ativar. Em seguida, prossiga com o `setup.mjs` abaixo.
|
||||
|
||||
---
|
||||
|
||||
**Pré-requisito:** Node.js 22+
|
||||
|
||||
```bash
|
||||
@@ -168,7 +203,7 @@ O script irá:
|
||||
|
||||
5. Acesse `http://localhost:3000`
|
||||
|
||||
> **Docker completo** (app + banco em containers): use `pnpm docker:up` ao invés dos passos 3-4.
|
||||
> **Docker completo** (app + banco em containers): use `pnpm docker:up:local` ao invés dos passos 3-4.
|
||||
|
||||
---
|
||||
|
||||
@@ -190,26 +225,30 @@ pnpm lint:fix # Biome auto-fix
|
||||
pnpm db:generate # Gerar migrations
|
||||
pnpm db:migrate # Executar migrations
|
||||
pnpm db:push # Push schema direto (dev)
|
||||
pnpm db:extensions # Habilitar extensões PostgreSQL (rodar uma vez)
|
||||
pnpm db:studio # Drizzle Studio (UI visual)
|
||||
```
|
||||
|
||||
### Utilitários
|
||||
|
||||
```bash
|
||||
pnpm backup # Backup do banco (requer scripts/backup.sh configurado)
|
||||
pnpm backup # Backup completo do banco (ver seção Backup)
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
pnpm docker:up # Subir app + banco
|
||||
pnpm docker:up:d # Subir em background
|
||||
pnpm docker:up:db # Subir apenas o banco
|
||||
pnpm docker:down # Parar containers
|
||||
pnpm docker:down:volumes # Parar e remover volumes (⚠️ apaga dados!)
|
||||
pnpm docker:logs # Logs em tempo real
|
||||
pnpm docker:restart # Reiniciar
|
||||
pnpm docker:rebuild # Rebuild completo
|
||||
pnpm docker:up:local # Sobe app + banco PostgreSQL juntos (imagem do Hub)
|
||||
pnpm docker:up # Sobe apenas o app com build local
|
||||
pnpm docker:up:d # Sobe apenas o app com build local em background
|
||||
pnpm docker:up:db # Sobe apenas o banco em background
|
||||
pnpm docker:down # Para e remove os containers
|
||||
pnpm docker:down:volumes # Para containers e remove volumes (⚠️ apaga dados!)
|
||||
pnpm docker:logs # Logs em tempo real (todos os containers)
|
||||
pnpm docker:logs:app # Logs do container da aplicação
|
||||
pnpm docker:logs:db # Logs do container do banco
|
||||
pnpm docker:restart # Reinicia todos os containers
|
||||
pnpm docker:rebuild # Rebuild completo forçando recriação
|
||||
```
|
||||
|
||||
---
|
||||
@@ -220,6 +259,46 @@ O `Dockerfile` usa multi-stage build (deps → builder → runner) com imagem fi
|
||||
|
||||
Health checks configurados para ambos os serviços (PostgreSQL via `pg_isready`, app via `GET /api/health`).
|
||||
|
||||
### Modos de uso
|
||||
|
||||
**Modo 1 — App + banco local (recomendado para self-hosting)**
|
||||
|
||||
Puxa a imagem pronta do Docker Hub e sobe app + banco juntos. Não precisa de Node.js instalado.
|
||||
|
||||
```bash
|
||||
# 1. Baixar o docker-compose.yml
|
||||
curl -fsSL https://raw.githubusercontent.com/felipegcoutinho/openmonetis/main/docker-compose.yml -o docker-compose.yml
|
||||
|
||||
# 2. Criar o .env (copie o .env.example como referência)
|
||||
# DATABASE_URL=postgresql://openmonetis:SUA_SENHA@db:5432/openmonetis_db
|
||||
# POSTGRES_PASSWORD=SUA_SENHA
|
||||
# BETTER_AUTH_SECRET=string-longa-aleatoria
|
||||
# BETTER_AUTH_URL=http://localhost:3000
|
||||
|
||||
# 3. Subir
|
||||
docker compose --profile local up
|
||||
# ou, se tiver o projeto clonado:
|
||||
pnpm docker:up:local
|
||||
```
|
||||
|
||||
**Modo 2 — App com banco remoto**
|
||||
|
||||
Use quando o banco está em um provider externo (Supabase, Neon, Railway...).
|
||||
|
||||
```bash
|
||||
# DATABASE_URL deve apontar para o banco remoto no .env
|
||||
docker compose up
|
||||
```
|
||||
|
||||
**Modo 3 — Build local (desenvolvimento)**
|
||||
|
||||
Builda a imagem localmente a partir do código-fonte.
|
||||
|
||||
```bash
|
||||
pnpm docker:up # app apenas (banco separado)
|
||||
pnpm docker:up:db # sobe o banco em background
|
||||
```
|
||||
|
||||
### Comandos úteis
|
||||
|
||||
```bash
|
||||
@@ -239,6 +318,68 @@ DB_PORT=5433 # Padrão: 5432
|
||||
|
||||
---
|
||||
|
||||
## 💾 Backup
|
||||
|
||||
O backup é uma rotina de infraestrutura — não é uma tela no app. Ele opera diretamente sobre o banco PostgreSQL e é executado via linha de comando.
|
||||
|
||||
```bash
|
||||
pnpm backup
|
||||
```
|
||||
|
||||
### O que é salvo
|
||||
|
||||
Cada execução gera **3 arquivos** em `backup/`:
|
||||
|
||||
| Arquivo | Conteúdo | Uso |
|
||||
|---|---|---|
|
||||
| `openmonetis_YYYY-MM-DD_HH-MM.dump` | Dump custom do PostgreSQL (binário) | Restore completo via `pg_restore` |
|
||||
| `openmonetis_YYYY-MM-DD_HH-MM.sql.gz` | Dump SQL completo compactado | Inspeção manual, portabilidade |
|
||||
| `openmonetis_YYYY-MM-DD_HH-MM.data.sql.gz` | Apenas os dados da schema `public` | Migração parcial, seed de outro ambiente |
|
||||
|
||||
### Modos de conexão
|
||||
|
||||
Configure `DB_MODE` no topo de `scripts/backup.sh`:
|
||||
|
||||
| Modo | Quando usar | Fonte de dados |
|
||||
|---|---|---|
|
||||
| `remote` (padrão) | Banco em Supabase, Neon, Railway, etc. | `DATABASE_URL` do `.env` |
|
||||
| `docker` | Banco no container local | Container `openmonetis_postgres` |
|
||||
|
||||
### Upload para Google Drive (opcional)
|
||||
|
||||
Se o [rclone](https://rclone.org/) estiver instalado e configurado com um remote chamado `gdrive`, os arquivos são enviados automaticamente para `gdrive:BACKUP OPENMONETIS`. Sem o rclone, o backup funciona normalmente e fica apenas local.
|
||||
|
||||
**Retenção:**
|
||||
- Local: 7 dias
|
||||
- Google Drive: 30 dias
|
||||
|
||||
### Automatizar com cron
|
||||
|
||||
Para rodar o backup automaticamente todo dia às 3h:
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
```cron
|
||||
0 3 * * * cd /caminho/para/openmonetis && pnpm backup >> /var/log/openmonetis-backup.log 2>&1
|
||||
```
|
||||
|
||||
### Restore
|
||||
|
||||
```bash
|
||||
# A partir do .dump (recomendado — mais rápido)
|
||||
pg_restore --clean --no-owner --no-privileges \
|
||||
-d "postgresql://user:senha@host:5432/openmonetis_db" \
|
||||
backup/openmonetis_YYYY-MM-DD_HH-MM.dump
|
||||
|
||||
# A partir do .sql.gz (banco local via Docker)
|
||||
gunzip -c backup/openmonetis_YYYY-MM-DD_HH-MM.sql.gz | \
|
||||
docker compose exec -T db psql -U openmonetis -d openmonetis_db
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ☁️ Storage S3 Compatível
|
||||
|
||||
O suporte a anexos de lançamentos usa upload direto com URL pré-assinada. Essa configuração é opcional, mas passa a ser necessária se você quiser habilitar anexos no app.
|
||||
@@ -256,7 +397,7 @@ S3_BUCKET=
|
||||
### Compatibilidade
|
||||
|
||||
- O código atual espera um provider com API compatível com S3 e suporte a `PutObject`, `GetObject`, `HeadObject`, `DeleteObject` e URLs pré-assinadas.
|
||||
- A implementação usa `endpoint` customizado e `forcePathStyle: true` em [`src/shared/lib/storage/s3-client.ts`](/home/ubuntu/github/openmonetis/src/shared/lib/storage/s3-client.ts).
|
||||
- A implementação usa `endpoint` customizado e `forcePathStyle: true` em [`src/shared/lib/storage/s3-client.ts`](./src/shared/lib/storage/s3-client.ts).
|
||||
- Em geral isso cobre MinIO, Cloudflare R2, Backblaze B2 S3-Compatible, DigitalOcean Spaces e AWS S3. Mas foi testado apenas no Supabase Storage.
|
||||
- Se o seu provider exigir `virtual-hosted-style` em vez de `path-style`, você vai precisar ajustar essa configuração antes de usar anexos.
|
||||
- Se as variáveis de S3 não forem configuradas, mantenha os anexos desabilitados no seu fluxo de uso.
|
||||
|
||||
241
scripts/install-deps.sh
Executable file
241
scripts/install-deps.sh
Executable file
@@ -0,0 +1,241 @@
|
||||
#!/bin/sh
|
||||
# install-deps.sh — Instala pré-requisitos do OpenMonetis
|
||||
# Testado apenas em Ubuntu Server 24.04 LTS
|
||||
# Uso: curl -fsSL https://raw.githubusercontent.com/felipegcoutinho/openmonetis/main/scripts/install-deps.sh -o install-deps.sh
|
||||
# sudo sh install-deps.sh
|
||||
|
||||
set -e
|
||||
|
||||
LOG_FILE="/tmp/openmonetis-install.log"
|
||||
> "$LOG_FILE"
|
||||
|
||||
# ── Cores ──────────────────────────────────────────────────────────────────────
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
RESET='\033[0m'
|
||||
|
||||
ok() { printf "${GREEN}✔${RESET} %s\n" "$1"; }
|
||||
warn() { printf "${YELLOW}!${RESET} %s\n" "$1"; }
|
||||
info() { printf "${CYAN}→${RESET} %s\n" "$1"; }
|
||||
fail() { printf "${RED}✗${RESET} %s\n" "$1"; exit 1; }
|
||||
|
||||
# ── Contador de etapas ─────────────────────────────────────────────────────────
|
||||
_STEP=0
|
||||
_TOTAL=5
|
||||
|
||||
section() {
|
||||
_STEP=$((_STEP + 1))
|
||||
printf "\n${BOLD}[%d/%d] %s${RESET}\n" "$_STEP" "$_TOTAL" "$1"
|
||||
}
|
||||
|
||||
# ── Spinner ────────────────────────────────────────────────────────────────────
|
||||
_spin_pid=""
|
||||
|
||||
spinner_start() {
|
||||
_spin_label="$1"
|
||||
( i=0
|
||||
while true; do
|
||||
case $((i % 4)) in
|
||||
0) d=" " ;; 1) d=". " ;; 2) d=".. " ;; *) d="..." ;;
|
||||
esac
|
||||
printf "\r${CYAN}→${RESET} %s%s" "$_spin_label" "$d"
|
||||
i=$((i + 1))
|
||||
sleep 0.4
|
||||
done
|
||||
) &
|
||||
_spin_pid=$!
|
||||
}
|
||||
|
||||
spinner_stop() {
|
||||
if [ -n "$_spin_pid" ]; then
|
||||
kill "$_spin_pid" 2>/dev/null
|
||||
wait "$_spin_pid" 2>/dev/null
|
||||
_spin_pid=""
|
||||
printf "\r\033[2K"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Executores silenciosos com spinner ─────────────────────────────────────────
|
||||
|
||||
# run_quiet "label" cmd [args...] — roda comando com spinner, falha mostra log
|
||||
run_quiet() {
|
||||
_rq_label="$1"; shift
|
||||
spinner_start "$_rq_label"
|
||||
if ! "$@" >> "$LOG_FILE" 2>&1; then
|
||||
spinner_stop
|
||||
printf "${RED}✗ Falha em: %s${RESET}\n" "$_rq_label"
|
||||
printf " Log completo: %s\n\n" "$LOG_FILE"
|
||||
tail -20 "$LOG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
spinner_stop
|
||||
}
|
||||
|
||||
# run_as_user "label" "comando_shell" — roda comando como $CURRENT_USER com spinner
|
||||
run_as_user() {
|
||||
_ru_label="$1"; shift
|
||||
spinner_start "$_ru_label"
|
||||
if ! su - "$CURRENT_USER" -c "$*" >> "$LOG_FILE" 2>&1; then
|
||||
spinner_stop
|
||||
printf "${RED}✗ Falha em: %s${RESET}\n" "$_ru_label"
|
||||
printf " Log completo: %s\n\n" "$LOG_FILE"
|
||||
tail -20 "$LOG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
spinner_stop
|
||||
}
|
||||
|
||||
# ── Cleanup no Ctrl+C ──────────────────────────────────────────────────────────
|
||||
cleanup() {
|
||||
spinner_stop
|
||||
printf "\n${YELLOW}Instalação interrompida.${RESET} Log em: %s\n" "$LOG_FILE"
|
||||
exit 1
|
||||
}
|
||||
trap cleanup INT TERM
|
||||
|
||||
# ── Tempo total ────────────────────────────────────────────────────────────────
|
||||
_START=$(date +%s)
|
||||
elapsed() {
|
||||
_secs=$(( $(date +%s) - _START ))
|
||||
printf "%dm%ds" $((_secs / 60)) $((_secs % 60))
|
||||
}
|
||||
|
||||
# ── Root check ─────────────────────────────────────────────────────────────────
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
fail "Execute como root ou com sudo: sudo sh install-deps.sh"
|
||||
fi
|
||||
|
||||
CURRENT_USER="${SUDO_USER:-$(whoami)}"
|
||||
|
||||
printf "\n${BOLD}OpenMonetis — Instalação de Dependências${RESET}\n"
|
||||
printf "Usuário: ${CYAN}%s${RESET} | Log: %s\n" "$CURRENT_USER" "$LOG_FILE"
|
||||
|
||||
# ── [1/5] Dependências base ────────────────────────────────────────────────────
|
||||
section "Dependências base"
|
||||
run_quiet "Atualizando lista de pacotes" apt-get update -qq
|
||||
run_quiet "Instalando git, curl, ca-certificates" apt-get install -y -qq ca-certificates curl git
|
||||
ok "git $(git --version | cut -d' ' -f3) · curl · ca-certificates"
|
||||
|
||||
# ── [2/5] Docker ───────────────────────────────────────────────────────────────
|
||||
section "Docker"
|
||||
|
||||
if command -v docker > /dev/null 2>&1; then
|
||||
ok "Docker já instalado: $(docker --version | cut -d',' -f1)"
|
||||
else
|
||||
info "Adicionando repositório oficial do Docker..."
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
run_quiet "Baixando chave GPG do Docker" \
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||
chmod a+r /etc/apt/keyrings/docker.asc
|
||||
|
||||
. /etc/os-release
|
||||
mkdir -p /etc/apt/sources.list.d
|
||||
printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu %s stable\n' \
|
||||
"$(dpkg --print-architecture)" "$VERSION_CODENAME" \
|
||||
> /etc/apt/sources.list.d/docker.list
|
||||
|
||||
run_quiet "Atualizando lista de pacotes" apt-get update -qq
|
||||
run_quiet "Instalando Docker Engine (pode levar alguns minutos)" \
|
||||
apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
systemctl enable docker > /dev/null 2>&1 || true
|
||||
systemctl start docker > /dev/null 2>&1 || true
|
||||
ok "Docker $(docker --version | cut -d',' -f1 | cut -d' ' -f3) instalado"
|
||||
fi
|
||||
|
||||
if docker compose version > /dev/null 2>&1; then
|
||||
ok "Docker Compose $(docker compose version | cut -d' ' -f4)"
|
||||
else
|
||||
run_quiet "Instalando Docker Compose plugin" \
|
||||
sh -c 'mkdir -p /usr/local/lib/docker/cli-plugins && curl -fsSL "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/lib/docker/cli-plugins/docker-compose && chmod +x /usr/local/lib/docker/cli-plugins/docker-compose'
|
||||
ok "Docker Compose $(docker compose version | cut -d' ' -f4) instalado"
|
||||
fi
|
||||
|
||||
if [ -n "$CURRENT_USER" ] && [ "$CURRENT_USER" != "root" ]; then
|
||||
if ! groups "$CURRENT_USER" | grep -q docker; then
|
||||
usermod -aG docker "$CURRENT_USER"
|
||||
warn "Usuário '$CURRENT_USER' adicionado ao grupo docker — faça logout/login para aplicar"
|
||||
else
|
||||
ok "Usuário '$CURRENT_USER' já está no grupo docker"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── [3/5] Homebrew ─────────────────────────────────────────────────────────────
|
||||
section "Homebrew"
|
||||
|
||||
if command -v brew > /dev/null 2>&1; then
|
||||
ok "Homebrew já instalado: $(brew --version | head -1)"
|
||||
else
|
||||
warn "Esta etapa pode levar de 5 a 10 minutos."
|
||||
run_quiet "Instalando dependências de compilação" \
|
||||
apt-get install -y -qq build-essential procps file
|
||||
|
||||
if [ -n "$CURRENT_USER" ] && [ "$CURRENT_USER" != "root" ]; then
|
||||
run_as_user "Instalando Homebrew" \
|
||||
'NONINTERACTIVE=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'
|
||||
|
||||
BREW_PROFILE="/home/$CURRENT_USER/.bashrc"
|
||||
BREW_EVAL='eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'
|
||||
grep -qxF "$BREW_EVAL" "$BREW_PROFILE" 2>/dev/null || echo "$BREW_EVAL" >> "$BREW_PROFILE"
|
||||
export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
|
||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 2>/dev/null || true
|
||||
else
|
||||
fail "Homebrew não pode ser instalado como root. Use sudo com um usuário normal."
|
||||
fi
|
||||
|
||||
ok "Homebrew instalado"
|
||||
fi
|
||||
|
||||
# ── [4/5] Node.js 22 ───────────────────────────────────────────────────────────
|
||||
section "Node.js 22"
|
||||
|
||||
NODE_MAJOR=0
|
||||
if command -v node > /dev/null 2>&1; then
|
||||
NODE_MAJOR=$(node -e "process.stdout.write(String(parseInt(process.versions.node)))")
|
||||
fi
|
||||
|
||||
if [ "$NODE_MAJOR" -ge 22 ] 2>/dev/null; then
|
||||
ok "Node.js já instalado: $(node --version)"
|
||||
else
|
||||
warn "Node.js via Homebrew pode levar alguns minutos."
|
||||
if [ -n "$CURRENT_USER" ] && [ "$CURRENT_USER" != "root" ]; then
|
||||
run_as_user "Instalando Node.js 22" \
|
||||
'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" && brew install node@22 && brew link node@22 --force --overwrite'
|
||||
export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
|
||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 2>/dev/null || true
|
||||
else
|
||||
fail "Node.js via Homebrew não pode ser instalado como root."
|
||||
fi
|
||||
ok "Node.js $(node --version) instalado"
|
||||
fi
|
||||
|
||||
# ── [5/5] pnpm ─────────────────────────────────────────────────────────────────
|
||||
section "pnpm"
|
||||
|
||||
if command -v pnpm > /dev/null 2>&1; then
|
||||
ok "pnpm já instalado: $(pnpm --version)"
|
||||
else
|
||||
if [ -n "$CURRENT_USER" ] && [ "$CURRENT_USER" != "root" ]; then
|
||||
run_as_user "Instalando pnpm via corepack" \
|
||||
'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" && corepack enable && corepack prepare pnpm@latest --activate'
|
||||
else
|
||||
run_quiet "Instalando pnpm via corepack" \
|
||||
sh -c 'corepack enable && corepack prepare pnpm@latest --activate'
|
||||
fi
|
||||
ok "pnpm instalado"
|
||||
fi
|
||||
|
||||
# ── Resumo ─────────────────────────────────────────────────────────────────────
|
||||
printf "\n${BOLD}Concluído em $(elapsed)${RESET}\n"
|
||||
|
||||
ok "git: $(git --version | cut -d' ' -f3)"
|
||||
ok "docker: $(docker --version | cut -d',' -f1 | cut -d' ' -f3)"
|
||||
ok "docker compose: $(docker compose version | cut -d' ' -f4)"
|
||||
ok "node: $(node --version)"
|
||||
ok "pnpm: $(pnpm --version)"
|
||||
|
||||
printf "\n${CYAN}Próximo passo:${RESET}\n"
|
||||
printf " node setup.mjs\n\n"
|
||||
Reference in New Issue
Block a user