{
  "id": "deploy",
  "title": "Deploy em produção",
  "description": "Requisitos e procedimentos documentados para executar o James em um servidor Linux.",
  "type": "guide",
  "status": "observed",
  "visibility": "public",
  "tags": [
    "deploy",
    "produção",
    "supervisor",
    "nginx"
  ],
  "related": [
    "primeiros-passos",
    "arquitetura",
    "automacoes"
  ],
  "sourceRefs": [
    "https://github.com/james-suite/james/blob/master/compose.yaml",
    "https://github.com/james-suite/james/blob/master/config/filesystems.php",
    "https://github.com/james-suite/james/blob/master/routes/console.php"
  ],
  "authors": [],
  "updated": null,
  "diagram": null,
  "body": "Este documento descreve os passos e requisitos essenciais para colocar o projeto James em produção em um servidor VPS (Linux/Ubuntu).\n\n## 1. Requisitos do Servidor\n\nO James foi construído utilizando tecnologias modernas. O servidor de produção **deve** ter:\n\n- **PHP 8.5+** (extensões recomendadas: `pdo_pgsql`, `pgsql`, `intl`, `mbstring`, `xml`, `bcmath`, `curl`, `zip`, `gd`/`imagick`)\n- **Node.js 20+** e **NPM** (Para compilar os assets do Vite)\n- **PostgreSQL 15+ (Obrigatório)**: O sistema exige PostgreSQL devido ao uso intensivo de busca textual agnóstica a acentos (através das extensões `unaccent` e `pg_trgm`). Não utilize MySQL ou SQLite em produção.\n- **Nginx**\n- **Composer**\n- **Supervisor** (Para manter o Scheduler e o worker da fila em background)\n\n## 2. Passo a Passo Inicial\n\n1. Clone o repositório no servidor (geralmente em `/var/www/james`):\n   ```bash\n   git clone https://github.com/james-suite/james.git /var/www/james\n   cd /var/www/james\n   ```\n2. Instale as dependências do PHP sem pacotes de desenvolvimento:\n   ```bash\n   composer install --optimize-autoloader --no-dev\n   ```\n3. Configure as permissões dos diretórios:\n   ```bash\n   chown -R www-data:www-data /var/www/james\n   chmod -R 775 /var/www/james/storage /var/www/james/bootstrap/cache\n   ```\n\n## 3. Configuração de Ambiente (.env)\n\nCopie o `.env.example` para `.env` e ajuste as seguintes chaves de forma estrita para produção:\n\n```ini\nAPP_NAME=James\nAPP_ENV=production\nAPP_DEBUG=false\nAPP_URL=https://james.seu-dominio.com\nAPP_TIMEZONE=America/Sao_Paulo\nAPP_LOCALE=pt_BR\nAPP_CURRENCY=BRL\n\n# Banco de Dados (PostgreSQL Obrigatório)\nDB_CONNECTION=pgsql\nDB_HOST=127.0.0.1\nDB_PORT=5432\nDB_DATABASE=james\nDB_USERNAME=seu_usuario\nDB_PASSWORD=sua_senha_segura\n\n# Spatie Media Library (Privacidade Absoluta)\nMEDIA_DISK=private\nFORCE_MEDIA_LIBRARY_LAZY_LOADING=false\n\n# Sistema de Notificações - Telegram Bot\nTELEGRAM_BOT_TOKEN=\"123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ\"\nTELEGRAM_CHAT_ID=\"123456789\"\n\n# Sistema de Notificações - E-mail\nNOTIFICATIONS_MAIL_ENABLED=false\nMAIL_MAILER=smtp\nMAIL_HOST=smtp.mailgun.org\nMAIL_PORT=587\nMAIL_USERNAME=seu_usuario\nMAIL_PASSWORD=sua_senha\nMAIL_ENCRYPTION=tls\nMAIL_FROM_ADDRESS=\"notificacoes@seu-dominio.com\"\nMAIL_FROM_NAME=\"${APP_NAME}\"\n\n# Fila de importações e notificações\nQUEUE_CONNECTION=database\nDB_QUEUE=default\nDB_QUEUE_RETRY_AFTER=90\n```\n\nGere a chave da aplicação:\n```bash\nphp artisan key:generate\n```\n\n---\n\n## 4. Configuração do Bot do Telegram\n\nO James conta com um canal de entrega de notificações espelhado diretamente no **Telegram**. Para receber alertas no seu celular (ex: fechamento de faturas, avisos de acertos, rotinas financeiras):\n\n1. Abra o Telegram e procure pelo bot oficial [@BotFather](https://t.me/BotFather).\n2. Envie o comando `/newbot` e siga as instruções para definir o nome e o username do seu bot (ex: `MeuJamesBot`).\n3. Ao finalizar, o BotFather fornecerá um **Token de Acesso HTTP** (ex: `7123456789:AAF...`). Preencha este valor na variável `TELEGRAM_BOT_TOKEN`.\n4. Obtenha seu **Chat ID** pessoal:\n   - Inicie uma conversa com seu novo bot enviando `/start`.\n   - Em seguida, envie uma mensagem para o bot [@userinfobot](https://t.me/userinfobot) ou acesse no navegador a URL: `https://api.telegram.org/bot<SEU_TOKEN>/getUpdates` para descobrir o seu `id` numérico.\n   - Preencha este número na variável `TELEGRAM_CHAT_ID`.\n5. Se ambas as variáveis estiverem preenchidas no `.env`, o canal do Telegram é ativado automaticamente pelo sistema de notificações.\n\n---\n\n## 5. Otimizações de Produção e Deploy Automatizado\n\nPara facilitar o processo de deploy contínuo, o James possui um comando Artisan inteligente que orquestra todo o fluxo de atualização:\n\n```bash\nphp artisan app:update\n```\n\nO comando executa atomicamente os seguintes passos:\n1. Ativa o modo de manutenção (`down`).\n2. Executa `git pull` para buscar as atualizações remotas.\n3. Executa `composer install --optimize-autoloader --no-dev`.\n4. Instala dependências do front-end com `npm ci`.\n5. Compila os assets otimizados de produção via `npm run build` (TailwindCSS v4 / Vite).\n6. Roda migrações pendentes do banco de dados com `migrate --force`.\n7. Garante o link simbólico do storage (`storage:link`).\n8. Pergunta se deseja executar os Seeders iniciais (Admin e Tags padrão, recomendado no 1º deploy).\n9. Limpa e recria os caches de configuração, rotas e views (`optimize`).\n10. Reinicia os processos gerenciados pelo **Supervisor** (`sudo supervisorctl restart all`).\n11. Desativa o modo de manutenção (`up`).\n\nSempre que atualizar o projeto no futuro, basta acessar a pasta e rodar `php artisan app:update`.\n\n---\n\n## 6. Configuração do Nginx\n\nAponte o Document Root do Nginx para a pasta `/var/www/james/public`. Exemplo de bloco seguro para o Nginx:\n\n```nginx\nserver {\n    listen 80;\n    listen [::]:80;\n    server_name james.seu-dominio.com;\n    return 301 https://$host$request_uri;\n}\n\nserver {\n    listen 443 ssl http2;\n    listen [::]:443 ssl http2;\n    server_name james.seu-dominio.com;\n    root /var/www/james/public;\n\n    # Certificados SSL (ex: Certbot / Let's Encrypt)\n    ssl_certificate /etc/letsencrypt/live/james.seu-dominio.com/fullchain.pem;\n    ssl_certificate_key /etc/letsencrypt/live/james.seu-dominio.com/privkey.pem;\n\n    add_header X-Frame-Options \"SAMEORIGIN\";\n    add_header X-Content-Type-Options \"nosniff\";\n\n    index index.php;\n    charset utf-8;\n\n    location / {\n        try_files $uri $uri/ /index.php?$query_string;\n    }\n\n    location = /favicon.ico { access_log off; log_not_found off; }\n    location = /robots.txt  { access_log off; log_not_found off; }\n\n    error_page 404 /index.php;\n\n    location ~ \\.php$ {\n        fastcgi_pass unix:/var/run/php/php8.5-fpm.sock;\n        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;\n        include fastcgi_params;\n        fastcgi_hide_header X-Powered-By;\n    }\n\n    location ~ /\\.(?!well-known).* {\n        deny all;\n    }\n}\n```\n\n---\n\n## 7. Schedulers e Processos em Background (Supervisor)\n\nO James depende de dois processos contínuos gerenciados pelo **Supervisor**:\n\n- O **Scheduler**, responsável por disparar as rotinas agendadas.\n- O **worker da fila**, responsável por processar importações de NFC-e e notificações assíncronas.\n\nAs tarefas agendadas mantêm a integridade temporal do módulo financeiro:\n- `finance:rollover-invoices`: Abre e rola faturas de cartão de crédito.\n- `finance:rollover-transactions`: Rola despesas pendentes do passado para a data presente.\n- `finance:process-recurrences`: Materializa recorrências financeiras em transações reais.\n\nCrie o arquivo `/etc/supervisor/conf.d/james.conf` com os dois programas:\n\n```ini\n[program:james-scheduler]\nprocess_name=%(program_name)s_%(process_num)02d\ncommand=/usr/bin/php8.5 /var/www/james/artisan schedule:work\nautostart=true\nautorestart=true\nstopasgroup=true\nkillasgroup=true\nuser=www-data\nnumprocs=1\nredirect_stderr=true\nstdout_logfile=/var/www/james/storage/logs/scheduler.log\nstopwaitsecs=3600\n\n[program:james-worker]\nprocess_name=%(program_name)s_%(process_num)02d\ncommand=/usr/bin/php8.5 /var/www/james/artisan queue:work database --sleep=3 --tries=3 --timeout=60 --max-time=3600\nautostart=true\nautorestart=true\nstopasgroup=true\nkillasgroup=true\nuser=www-data\nnumprocs=1\nredirect_stderr=true\nstdout_logfile=/var/www/james/storage/logs/worker.log\nstopwaitsecs=3600\n```\n\nCarregue e inicie o serviço:\n```bash\nsudo supervisorctl reread\nsudo supervisorctl update\nsudo supervisorctl start james-scheduler:*\nsudo supervisorctl start james-worker:*\n```\n\nVerifique o estado dos dois processos e acompanhe os logs quando necessário:\n\n```bash\nsudo supervisorctl status james-scheduler:*\nsudo supervisorctl status james-worker:*\ntail -f /var/www/james/storage/logs/worker.log\n```\n\nO worker usa `--timeout=60`, alinhado ao timeout do job de importação de NFC-e, enquanto `DB_QUEUE_RETRY_AFTER=90` garante que uma execução ainda não seja liberada para outro worker antes de terminar. Os atrasos transitórios da importação são definidos no próprio job (`5`, `15` e `30` segundos).\n\n### Configuração do Sudoers (Restart Automático)\n\nPara permitir que o comando `php artisan app:update` reinicie o Supervisor automaticamente sem pedir senha durante os deploys, adicione a seguinte regra ao `sudoers`:\n\n1. Execute `sudo visudo`.\n2. Adicione ao final do arquivo (substituindo `seu_usuario` pelo usuário SSH do servidor, ex: `avw`):\n   ```text\n   seu_usuario ALL=(ALL) NOPASSWD: /usr/bin/supervisorctl restart all\n   ```\n3. Salve o arquivo. Agora as atualizações serão 100% automatizadas e sem atrito!",
  "sections": [
    {
      "id": "1-requisitos-do-servidor",
      "level": 2,
      "title": "1. Requisitos do Servidor",
      "text": "O James foi construído utilizando tecnologias modernas. O servidor de produção **deve** ter:  - **PHP 8.5+** (extensões recomendadas: `pdo_pgsql`, `pgsql`, `intl`, `mbstring`, `xml`, `bcmath`, `curl`, `zip`, `gd`/`imagick`) - **Node.js 20+** e **NPM** (Para compilar os assets do Vite) - **PostgreSQL 15+ (Obrigatório)**: O sistema exige PostgreSQL devido ao uso intensivo de busca textual agnóstica a acentos (através das extensões `unaccent` e `pg_trgm`). Não utilize MySQL ou SQLite em produção. - **Nginx** - **Composer** - **Supervisor** (Para manter o Scheduler e o worker da fila em background)",
      "line": 3
    },
    {
      "id": "2-passo-a-passo-inicial",
      "level": 2,
      "title": "2. Passo a Passo Inicial",
      "text": "1. Clone o repositório no servidor (geralmente em `/var/www/james`): 2. Instale as dependências do PHP sem pacotes de desenvolvimento: 3. Configure as permissões dos diretórios:",
      "line": 14
    },
    {
      "id": "3-configuracao-de-ambiente-env",
      "level": 2,
      "title": "3. Configuração de Ambiente (.env)",
      "text": "Copie o `.env.example` para `.env` e ajuste as seguintes chaves de forma estrita para produção:   Gere a chave da aplicação:  ---",
      "line": 31
    },
    {
      "id": "4-configuracao-do-bot-do-telegram",
      "level": 2,
      "title": "4. Configuração do Bot do Telegram",
      "text": "O James conta com um canal de entrega de notificações espelhado diretamente no **Telegram**. Para receber alertas no seu celular (ex: fechamento de faturas, avisos de acertos, rotinas financeiras):  1. Abra o Telegram e procure pelo bot oficial [@BotFather](https://t.me/BotFather). 2. Envie o comando `/newbot` e siga as instruções para definir o nome e o username do seu bot (ex: `MeuJamesBot`). 3. Ao finalizar, o BotFather fornecerá um **Token de Acesso HTTP** (ex: `7123456789:AAF...`). Preencha este valor na variável `TELEGRAM_BOT_TOKEN`. 4. Obtenha seu **Chat ID** pessoal: - Inicie uma conversa com seu novo bot enviando `/start`. - Em seguida, envie uma mensagem para o bot [@userinfobot](https://t.me/userinfobot) ou acesse no navegador a URL: `https://api.telegram.org/bot<SEU_TOKEN>/getUpdates` para descobrir o seu `id` numérico. - Preencha este número na variável `TELEGRAM_CHAT_ID`. 5. Se ambas as variáveis estiverem preenchidas no `.env`, o canal do Telegram é ativado automaticamente pelo sistema de notificações.  ---",
      "line": 84
    },
    {
      "id": "5-otimizacoes-de-producao-e-deploy-automatizado",
      "level": 2,
      "title": "5. Otimizações de Produção e Deploy Automatizado",
      "text": "Para facilitar o processo de deploy contínuo, o James possui um comando Artisan inteligente que orquestra todo o fluxo de atualização:   O comando executa atomicamente os seguintes passos: 1. Ativa o modo de manutenção (`down`). 2. Executa `git pull` para buscar as atualizações remotas. 3. Executa `composer install --optimize-autoloader --no-dev`. 4. Instala dependências do front-end com `npm ci`. 5. Compila os assets otimizados de produção via `npm run build` (TailwindCSS v4 / Vite). 6. Roda migrações pendentes do banco de dados com `migrate --force`. 7. Garante o link simbólico do storage (`storage:link`). 8. Pergunta se deseja executar os Seeders iniciais (Admin e Tags padrão, recomendado no 1º deploy). 9. Limpa e recria os caches de configuração, rotas e views (`optimize`). 10. Reinicia os processos gerenciados pelo **Supervisor** (`sudo supervisorctl restart all`). 11. Desativa o modo de manutenção (`up`).  Sempre que atualizar o projeto no futuro, basta acessar a pasta e rodar `php artisan app:update`.  ---",
      "line": 99
    },
    {
      "id": "6-configuracao-do-nginx",
      "level": 2,
      "title": "6. Configuração do Nginx",
      "text": "Aponte o Document Root do Nginx para a pasta `/var/www/james/public`. Exemplo de bloco seguro para o Nginx:   ---",
      "line": 124
    },
    {
      "id": "7-schedulers-e-processos-em-background-supervisor",
      "level": 2,
      "title": "7. Schedulers e Processos em Background (Supervisor)",
      "text": "O James depende de dois processos contínuos gerenciados pelo **Supervisor**:  - O **Scheduler**, responsável por disparar as rotinas agendadas. - O **worker da fila**, responsável por processar importações de NFC-e e notificações assíncronas.  As tarefas agendadas mantêm a integridade temporal do módulo financeiro: - `finance:rollover-invoices`: Abre e rola faturas de cartão de crédito. - `finance:rollover-transactions`: Rola despesas pendentes do passado para a data presente. - `finance:process-recurrences`: Materializa recorrências financeiras em transações reais.  Crie o arquivo `/etc/supervisor/conf.d/james.conf` com os dois programas:   Carregue e inicie o serviço:  Verifique o estado dos dois processos e acompanhe os logs quando necessário:   O worker usa `--timeout=60`, alinhado ao timeout do job de importação de NFC-e, enquanto `DB_QUEUE_RETRY_AFTER=90` garante que uma execução ainda não seja liberada para outro worker antes de terminar. Os atrasos transitórios da importação são definidos no próprio job (`5`, `15` e `30` segundos).",
      "line": 176
    },
    {
      "id": "configuracao-do-sudoers-restart-automatico",
      "level": 3,
      "title": "Configuração do Sudoers (Restart Automático)",
      "text": "Para permitir que o comando `php artisan app:update` reinicie o Supervisor automaticamente sem pedir senha durante os deploys, adicione a seguinte regra ao `sudoers`:  1. Execute `sudo visudo`. 2. Adicione ao final do arquivo (substituindo `seu_usuario` pelo usuário SSH do servidor, ex: `avw`): 3. Salve o arquivo. Agora as atualizações serão 100% automatizadas e sem atrito!",
      "line": 236
    }
  ],
  "sourcePath": "content/deploy.md",
  "visuals": [],
  "apiVersion": 1
}
