diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..9e61c2f --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,92 @@ +# Guía de Despliegue - Analítica Núcleo + +Este proyecto se despliega automáticamente usando Gitea Actions en cada push a la rama `master`. + +## Configuración en Gitea + +### Secretos (Settings → Secrets) + +Los siguientes secretos deben configurarse en el repositorio de Gitea: + +| Secret | Descripción | Ejemplo | +|--------|-------------|---------| +| `SUPABASE_URL` | URL de tu instancia Supabase | `https://xxx.supabase.co` | +| `SUPABASE_ANON_KEY` | Clave anónima de Supabase | `eyJhbGc...` | + +### Cómo agregar secretos en Gitea: + +1. Ve a tu repositorio en Gitea +2. Navega a **Settings → Secrets** +3. Haz clic en **Add Secret** +4. Agrega cada uno de los secretos listados arriba + +## Infraestructura + +### Stack Docker + +El proyecto se despliega como un stack de Docker Compose llamado `analiticanucleo` que contiene: + +- **nuxt-app**: Aplicación Nuxt.js con SSR deshabilitado + +### Traefik + +La aplicación está configurada para usar Traefik como reverse proxy: + +- **Dominio**: `analitica.nucleoriofrio.com` +- **Puerto interno**: `3000` (no expuesto públicamente) +- **TLS**: Habilitado con Let's Encrypt +- **Red**: `principal` (red externa compartida) + +### Workflow de Despliegue + +El workflow `.gitea/workflows/deploy.yml` se ejecuta automáticamente en cada push a `master` y: + +1. Crea el archivo `.env` con los secretos +2. Verifica/crea la red Docker `principal` +3. Detiene el stack existente (si existe) +4. Construye la nueva imagen Docker +5. Inicia el stack actualizado +6. Muestra logs y estado de los servicios + +## Archivos del Proyecto + +``` +. +├── Dockerfile # Imagen Docker multi-stage con Node 22 +├── docker-compose.yml # Configuración del stack con labels de Traefik +├── .gitea/workflows/deploy.yml # Workflow de CI/CD +└── nuxt4-app/ # Código de la aplicación Nuxt + ├── nuxt.config.ts # Configuración de Nuxt (ssr: false) + └── nuxt.config.workaround.ts # Workaround para @nuxt/ui v4 con ssr: false +``` + +## Notas Técnicas + +### Workaround para @nuxt/ui v4 + +Debido a un issue conocido con `@nuxt/ui` v4 y `ssr: false`, se implementó un plugin de Vite (`nuxt.config.workaround.ts`) que marca como externos los módulos de servidor (`@nuxt/kit`, `@tailwindcss/*`, etc.) para evitar que se incluyan en el bundle del cliente. + +### Build + +El build utiliza: +- Node.js 22 Alpine +- Vite 7 +- Nuxt 4 +- Sharp para procesamiento de imágenes + +## Troubleshooting + +### El build falla con errores de importación + +Asegúrate de que el archivo `nuxt.config.workaround.ts` está presente y correctamente importado en `nuxt.config.ts`. + +### La aplicación no es accesible + +1. Verifica que Traefik esté corriendo +2. Verifica que la red `principal` existe: `docker network ls` +3. Verifica los logs del contenedor: `docker logs analiticanucleo-nuxt-app` +4. Verifica las labels de Traefik: `docker inspect analiticanucleo-nuxt-app` + +### Variables de entorno no se aplican + +Verifica que los secretos estén configurados correctamente en Gitea y que el workflow los esté pasando al archivo `.env`. diff --git a/Dockerfile b/Dockerfile index 2ff31e5..1eff199 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,9 @@ FROM node:22-alpine AS builder WORKDIR /app +# Install build dependencies for sharp +RUN apk add --no-cache python3 make g++ vips-dev + # Copy package files COPY nuxt4-app/package*.json ./ @@ -20,6 +23,9 @@ FROM node:22-alpine WORKDIR /app +# Install runtime dependencies for sharp +RUN apk add --no-cache vips + # Copy built application from builder COPY --from=builder /app/.output /app/.output diff --git a/nuxt4-app/nuxt.config.ts b/nuxt4-app/nuxt.config.ts index 04802f9..abc8dc0 100644 --- a/nuxt4-app/nuxt.config.ts +++ b/nuxt4-app/nuxt.config.ts @@ -1,4 +1,6 @@ // https://nuxt.com/docs/api/configuration/nuxt-config +import { disableImportProtection } from './nuxt.config.workaround' + export default defineNuxtConfig({ ssr: false, compatibilityDate: '2025-07-15', @@ -14,6 +16,7 @@ export default defineNuxtConfig({ // Optimize build vite: { + plugins: [disableImportProtection()], build: { cssCodeSplit: true, rollupOptions: { diff --git a/nuxt4-app/nuxt.config.workaround.ts b/nuxt4-app/nuxt.config.workaround.ts new file mode 100644 index 0000000..830e6ac --- /dev/null +++ b/nuxt4-app/nuxt.config.workaround.ts @@ -0,0 +1,31 @@ +// Workaround for @nuxt/ui v4 import protection issue +// This is a temporary fix until @nuxt/ui properly handles ssr: false + +import type { Plugin } from 'vite' + +export function disableImportProtection(): Plugin { + return { + name: 'disable-import-protection-for-nuxt-ui', + enforce: 'pre', + resolveId(id, importer) { + // External node binary files + if (id.endsWith('.node')) { + return { id, external: true } + } + + // External Node.js built-in modules + const nodeModules = ['fs', 'path', 'url', 'fs/promises', 'node:url', 'node:module', 'node:fs', 'node:path'] + if (nodeModules.includes(id) || id.startsWith('node:')) { + return { id, external: true } + } + + // External server-only packages from @nuxt/ui imports + const serverPackages = ['@nuxt/kit', '@tailwindcss/node', '@tailwindcss/oxide', 'jiti'] + for (const pkg of serverPackages) { + if (id === pkg || id.startsWith(pkg + '/')) { + return { id, external: true } + } + } + } + } +}