From c2c5067c6c26dd4e452503d1cae10e5e19cc7b2f Mon Sep 17 00:00:00 2001 From: Eduardo Lopes <155753879+eduardolopesx03@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:14:19 -0300 Subject: [PATCH 1/5] Add temporary production compose without Caddy --- .env.example | 17 +++++++++++++++ DEPLOYMENT.md | 25 ++++++++++++++++++++-- docker-compose.prod.yml | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 .env.example create mode 100644 docker-compose.prod.yml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..1999202 --- /dev/null +++ b/.env.example @@ -0,0 +1,17 @@ +ASPNETCORE_ENVIRONMENT=Production +APP_USE_HTTPS_REDIRECTION=false + +JWT_KEY=troque-por-uma-chave-bem-forte +JWT_ISSUER=LineGestao +JWT_AUDIENCE=LineGestao + +POSTGRES_DB=linegestao +POSTGRES_USER=linegestao_app +POSTGRES_PASSWORD=troque-por-uma-senha-forte + +SEED_ADMIN_EMAIL=admin@linegestao.local +SEED_ADMIN_PASSWORD=troque-por-uma-senha-forte +SEED_ADMIN_NAME=Administrador +SEED_DEFAULT_TENANT_NAME=Default + +FRONTEND_PUBLIC_URL=http://localhost:4200 diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 3d4fde5..b45abdb 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -74,6 +74,27 @@ FRONTEND_PUBLIC_URL=https://seu-dominio.com ## 4) Subir a stack com Docker Compose +### Alternativa A (provisória e mais rápida): sem Caddy, expondo API direto + +Se você ainda não tem acesso ao DNS/domínio no Wix, use o arquivo `docker-compose.prod.yml` deste repositório para publicar só a API (porta `8080`) e o banco. + +```bash +cd ~/apps/line-gestao-api + +docker compose -f docker-compose.prod.yml up -d --build +curl -i http://localhost:8080/health +``` + +Teste externo (do seu PC), trocando pelo IP público do servidor: + +```bash +curl -i http://76.13.231.13:8080/health +``` + +> Se o UFW estiver ativo, libere a porta temporariamente: `sudo ufw allow 8080/tcp`. + +### Stack completa (quando domínio/DNS estiver pronto) + ```bash cd ~/apps/line-gestao-api @@ -95,13 +116,13 @@ docker compose logs -f --tail=200 - API respondendo: ```bash -curl -I http://SEU_SERVIDOR:4000 +curl -I http://SEU_SERVIDOR:8080 ``` - Logs do backend: ```bash -docker compose logs backend --tail=200 +docker compose -f docker-compose.prod.yml logs api --tail=200 ``` - Login admin: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..4c21c3d --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,46 @@ +services: + api: + build: + context: . + dockerfile: Dockerfile + container_name: linegestao-api + restart: unless-stopped + env_file: + - .env + environment: + ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Production} + ASPNETCORE_URLS: http://+:8080 + App__UseHttpsRedirection: ${APP_USE_HTTPS_REDIRECTION:-false} + ConnectionStrings__Default: Host=db;Port=5432;Database=${POSTGRES_DB:-linegestao};Username=${POSTGRES_USER:-linegestao_app};Password=${POSTGRES_PASSWORD:-CHANGE_ME} + Jwt__Issuer: ${JWT_ISSUER:-LineGestao} + Jwt__Audience: ${JWT_AUDIENCE:-LineGestao} + Jwt__Key: ${JWT_KEY:?JWT_KEY is required} + Seed__AdminEmail: ${SEED_ADMIN_EMAIL:-admin@linegestao.local} + Seed__AdminPassword: ${SEED_ADMIN_PASSWORD:-CHANGE_ME} + Seed__AdminName: ${SEED_ADMIN_NAME:-Administrador} + Seed__DefaultTenantName: ${SEED_DEFAULT_TENANT_NAME:-Default} + Cors__AllowedOrigins__0: ${FRONTEND_PUBLIC_URL:-http://localhost:4200} + depends_on: + db: + condition: service_healthy + ports: + - "8080:8080" + + db: + image: postgres:16-alpine + container_name: linegestao-db + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB:-linegestao} + POSTGRES_USER: ${POSTGRES_USER:-linegestao_app} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-CHANGE_ME} + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-linegestao_app} -d ${POSTGRES_DB:-linegestao}"] + interval: 10s + timeout: 5s + retries: 10 + +volumes: + postgres_data: From f5dda61c7a3a5e596c08e4713391c4ce481ea80e Mon Sep 17 00:00:00 2001 From: Eduardo Lopes <155753879+eduardolopesx03@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:23:16 -0300 Subject: [PATCH 2/5] Document next steps after healthcheck and frontend testing --- DEPLOYMENT.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index b45abdb..c3c9093 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -128,6 +128,50 @@ docker compose -f docker-compose.prod.yml logs api --tail=200 - Login admin: - Use `SEED_ADMIN_EMAIL` e `SEED_ADMIN_PASSWORD` do `.env`. +### Próximo passo após `HTTP 200` no `/health` + +Se você já recebeu `HTTP/1.1 200 OK` em `http://localhost:8080/health` **e** no IP público (`http://SEU_IP:8080/health`), o back-end está pronto para testes funcionais. + +Checklist recomendado: + +1. Confirmar documentação da API: + +```bash +curl -I http://SEU_IP:8080/swagger +``` + +2. Testar autenticação (via Swagger/UI ou cliente HTTP) com o admin seed. +3. Criar um registro real do seu fluxo principal (ex.: cliente/chamado/ordem) e validar leitura/listagem. +4. Verificar logs enquanto testa: + +```bash +docker compose -f docker-compose.prod.yml logs -f api +``` + +--- + +## 5.1) Como testar o front-end agora (sem DNS) + +Sem Wix/DNS, você ainda consegue testar o front-end por IP público. O essencial é apontar o front para a API externa: + +- API base URL: `http://SEU_IP:8080` + +Se o front for Vite/React (exemplo comum), configure algo como: + +```env +VITE_API_URL=http://SEU_IP:8080 +``` + +Depois gere e publique o front da forma que o repositório dele definir (build estático + servidor web/container). + +Teste final esperado no navegador: + +1. Abrir o front por IP (porta do front). +2. Fazer login com o admin seed. +3. Executar o fluxo principal da aplicação sem erro de CORS ou 401 inesperado. + +> Se houver erro de CORS, ajuste `FRONTEND_PUBLIC_URL` no `.env` da API para a URL exata usada no navegador (incluindo porta), e recrie o container da API. + --- ## 6) HTTPS (domínio público) From ce16f2f5efaafbcb5f582ce6e48338e2a647b09c Mon Sep 17 00:00:00 2001 From: Eduardo Lopes <155753879+eduardolopesx03@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:23:22 -0300 Subject: [PATCH 3/5] Add copy-paste frontend server test steps by public IP --- DEPLOYMENT.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index c3c9093..4c6f5a5 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -172,6 +172,66 @@ Teste final esperado no navegador: > Se houver erro de CORS, ajuste `FRONTEND_PUBLIC_URL` no `.env` da API para a URL exata usada no navegador (incluindo porta), e recrie o container da API. +## 5.2) Passo a passo (copiar e colar) para subir o front no servidor + +> Objetivo: abrir o front no navegador usando IP público, consumindo a API em `http://SEU_IP:8080`. + +No servidor (SSH), como usuário `deploy`: + +```bash +cd ~/apps/line-gestao-frontend + +# 1) Atualiza código do front +git fetch --all --prune +git pull --ff-only origin + +# 2) Configura URL da API para build de produção (Vite) +cat > .env.production << 'EOF' +VITE_API_URL=http://SEU_IP:8080 +EOF + +# 3) Build do front +npm ci +npm run build + +# 4) Publica build estático do front em container Nginx (porta 4173) +docker rm -f linegestao-frontend 2>/dev/null || true +docker run -d \ + --name linegestao-frontend \ + --restart unless-stopped \ + -p 4173:80 \ + -v "$PWD/dist:/usr/share/nginx/html:ro" \ + nginx:alpine +``` + +Agora teste: + +```bash +# no servidor +curl -I http://localhost:4173 + +# no seu computador +# http://SEU_IP:4173 +``` + +Se a porta 4173 não abrir externamente, libere no firewall: + +```bash +sudo ufw allow 4173/tcp +``` + +### Checklist final no navegador + +1. Abrir `http://SEU_IP:4173`. +2. Fazer login com o usuário admin seed da API. +3. Navegar no fluxo principal (cadastro/listagem/edição) e confirmar persistência. +4. Se aparecer erro de CORS, setar `FRONTEND_PUBLIC_URL=http://SEU_IP:4173` no `.env` da API e recriar o backend: + +```bash +cd ~/apps/line-gestao-api +docker compose -f docker-compose.prod.yml up -d --build +``` + --- ## 6) HTTPS (domínio público) From e464c9544a7a2f4fbc716ddfb3318a90c849a776 Mon Sep 17 00:00:00 2001 From: Eduardo Lopes <155753879+eduardolopesx03@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:23:27 -0300 Subject: [PATCH 4/5] Add domain-based HTTPS deployment with Caddy --- .env.example | 4 ++- Caddyfile | 5 +++ DEPLOYMENT.md | 46 +++++++++++++++++++++++++++ docker-compose.domain.yml | 65 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 Caddyfile create mode 100644 docker-compose.domain.yml diff --git a/.env.example b/.env.example index 1999202..f1d6686 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,7 @@ ASPNETCORE_ENVIRONMENT=Production APP_USE_HTTPS_REDIRECTION=false +DOMAIN=linegestao.inglinesystems.com.br +ACME_EMAIL=seu-email@dominio.com JWT_KEY=troque-por-uma-chave-bem-forte JWT_ISSUER=LineGestao @@ -14,4 +16,4 @@ SEED_ADMIN_PASSWORD=troque-por-uma-senha-forte SEED_ADMIN_NAME=Administrador SEED_DEFAULT_TENANT_NAME=Default -FRONTEND_PUBLIC_URL=http://localhost:4200 +FRONTEND_PUBLIC_URL=https://linegestao.inglinesystems.com.br diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..28c6635 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,5 @@ +{$DOMAIN} { + encode zstd gzip + + reverse_proxy api:8080 +} diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 4c6f5a5..df6bf9b 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -74,6 +74,52 @@ FRONTEND_PUBLIC_URL=https://seu-dominio.com ## 4) Subir a stack com Docker Compose +### Alternativa principal (com domínio + HTTPS automático via Caddy) + +Agora que o domínio está apontando para o servidor, use `docker-compose.domain.yml` para publicar em **HTTPS** com certificado automático (Let's Encrypt). + +1. Ajuste o `.env` na pasta da API: + +```env +DOMAIN=linegestao.inglinesystems.com.br +ACME_EMAIL=seu-email@dominio.com +FRONTEND_PUBLIC_URL=https://linegestao.inglinesystems.com.br +APP_USE_HTTPS_REDIRECTION=false +``` + +2. Libere portas públicas no firewall (uma vez): + +```bash +sudo ufw allow 80/tcp +sudo ufw allow 443/tcp +``` + +3. Suba stack com Caddy: + +```bash +cd ~/apps/line-gestao-api +docker compose -f docker-compose.domain.yml up -d --build +``` + +4. Valide certificado e API em HTTPS: + +```bash +curl -Iv https://linegestao.inglinesystems.com.br/health +``` + +Resultado esperado: +- status `HTTP/2 200` +- certificado emitido para `linegestao.inglinesystems.com.br` + +> Importante: no primeiro boot o Caddy pode levar alguns segundos para obter o certificado. Se falhar, confira se DNS já propagou e se as portas 80/443 estão acessíveis. + +Comandos úteis de diagnóstico: + +```bash +docker compose -f docker-compose.domain.yml logs -f caddy +docker compose -f docker-compose.domain.yml logs -f api +``` + ### Alternativa A (provisória e mais rápida): sem Caddy, expondo API direto Se você ainda não tem acesso ao DNS/domínio no Wix, use o arquivo `docker-compose.prod.yml` deste repositório para publicar só a API (porta `8080`) e o banco. diff --git a/docker-compose.domain.yml b/docker-compose.domain.yml new file mode 100644 index 0000000..25583bd --- /dev/null +++ b/docker-compose.domain.yml @@ -0,0 +1,65 @@ +services: + api: + build: + context: . + dockerfile: Dockerfile + container_name: linegestao-api + restart: unless-stopped + env_file: + - .env + environment: + ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Production} + ASPNETCORE_URLS: http://+:8080 + App__UseHttpsRedirection: ${APP_USE_HTTPS_REDIRECTION:-false} + ConnectionStrings__Default: Host=db;Port=5432;Database=${POSTGRES_DB:-linegestao};Username=${POSTGRES_USER:-linegestao_app};Password=${POSTGRES_PASSWORD:-CHANGE_ME} + Jwt__Issuer: ${JWT_ISSUER:-LineGestao} + Jwt__Audience: ${JWT_AUDIENCE:-LineGestao} + Jwt__Key: ${JWT_KEY:?JWT_KEY is required} + Seed__AdminEmail: ${SEED_ADMIN_EMAIL:-admin@linegestao.local} + Seed__AdminPassword: ${SEED_ADMIN_PASSWORD:-CHANGE_ME} + Seed__AdminName: ${SEED_ADMIN_NAME:-Administrador} + Seed__DefaultTenantName: ${SEED_DEFAULT_TENANT_NAME:-Default} + Cors__AllowedOrigins__0: ${FRONTEND_PUBLIC_URL:-https://linegestao.inglinesystems.com.br} + depends_on: + db: + condition: service_healthy + + db: + image: postgres:16-alpine + container_name: linegestao-db + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB:-linegestao} + POSTGRES_USER: ${POSTGRES_USER:-linegestao_app} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-CHANGE_ME} + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-linegestao_app} -d ${POSTGRES_DB:-linegestao}"] + interval: 10s + timeout: 5s + retries: 10 + + caddy: + image: caddy:2-alpine + container_name: linegestao-caddy + restart: unless-stopped + depends_on: + api: + condition: service_started + environment: + DOMAIN: ${DOMAIN:?DOMAIN is required} + ACME_AGREE: "true" + EMAIL: ${ACME_EMAIL:-} + ports: + - "80:80" + - "443:443" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:ro + - caddy_data:/data + - caddy_config:/config + +volumes: + postgres_data: + caddy_data: + caddy_config: From 8fc2a134d960fcdefa5b47a0b098063c474c7ac9 Mon Sep 17 00:00:00 2001 From: Eduardo Lopes <155753879+eduardolopesx03@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:36:19 -0300 Subject: [PATCH 5/5] Handle missing DOMAIN gracefully and document same-server steps --- Caddyfile | 2 +- DEPLOYMENT.md | 57 +++++++++++++++++++++++++++++++++++++++ docker-compose.domain.yml | 2 +- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/Caddyfile b/Caddyfile index 28c6635..ee84c88 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,4 +1,4 @@ -{$DOMAIN} { +{$DOMAIN:linegestao.inglinesystems.com.br} { encode zstd gzip reverse_proxy api:8080 diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index df6bf9b..6130932 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -113,6 +113,30 @@ Resultado esperado: > Importante: no primeiro boot o Caddy pode levar alguns segundos para obter o certificado. Se falhar, confira se DNS já propagou e se as portas 80/443 estão acessíveis. + +### Erro comum: `DOMAIN is required` + +Se aparecer este erro ao subir `docker-compose.domain.yml`, o `.env` da API está sem a variável `DOMAIN`. + +Corrija assim no servidor: + +```bash +cd ~/apps/line-gestao-api +cp -n .env.example .env + +# confirme variáveis mínimas +grep -E '^(DOMAIN|ACME_EMAIL|FRONTEND_PUBLIC_URL|JWT_KEY|POSTGRES_PASSWORD)=' .env + +# se DOMAIN não aparecer, adicione +echo 'DOMAIN=linegestao.inglinesystems.com.br' >> .env +``` + +Depois suba novamente: + +```bash +docker compose -f docker-compose.domain.yml up -d --build --remove-orphans +``` + Comandos úteis de diagnóstico: ```bash @@ -352,3 +376,36 @@ docker exec -t pg_dump -U > backup.sql ```bash docker compose logs -f --tail=200 ``` + + +## 5.3) Front-end + Back-end no mesmo servidor (com domínio) + +Sim, é possível e esse é o fluxo recomendado quando os repositórios estão em pastas irmãs. + +1. Build do front: + +```bash +cd ~/apps/line-gestao-frontend + +git fetch --all --prune +git pull --ff-only origin + +cat > .env.production << 'EOF' +VITE_API_URL=https://linegestao.inglinesystems.com.br +EOF + +npm ci +npm run build +``` + +2. Subir API + Caddy com HTTPS: + +```bash +cd ~/apps/line-gestao-api +docker compose -f docker-compose.domain.yml up -d --build --remove-orphans +``` + +3. Testar no navegador: +- Front: `https://linegestao.inglinesystems.com.br` +- API health: `https://linegestao.inglinesystems.com.br/health` + diff --git a/docker-compose.domain.yml b/docker-compose.domain.yml index 25583bd..a1e55aa 100644 --- a/docker-compose.domain.yml +++ b/docker-compose.domain.yml @@ -48,7 +48,7 @@ services: api: condition: service_started environment: - DOMAIN: ${DOMAIN:?DOMAIN is required} + DOMAIN: ${DOMAIN:-linegestao.inglinesystems.com.br} ACME_AGREE: "true" EMAIL: ${ACME_EMAIL:-} ports: