# Desplegar SmartCampus

Paquete del 28 de agosto de 2026. Lleva las dependencias ya instaladas (`vendor/`, sin las
de desarrollo), así que **no hace falta ejecutar composer en el servidor**. Requiere
**PHP 8.3** con `pdo_mysql` y `json`.

## 1. Subir y descomprimir

    unzip smartcampus-20260828.zip -d /var/www/
    cd /var/www/smartcampus

## 2. Configuración

**No viene ningún `.env` en el paquete**: lleva la contraseña de la base y no debe viajar
en un archivo que circula. Se crea a partir del ejemplo:

    cp .env.example .env
    nano .env

Lo que hay que cambiar sí o sí:

    APP_URL=https://tu-dominio.cl     ← sin barra al final
    APP_ENV=produccion
    APP_DEBUG=false                   ← en true, un error le muestra al visitante la traza
    DB_HOST, DB_DATABASE, DB_USERNAME, DB_PASSWORD
    SESSION_SECURE=true               ← déjalo en true si sirves por HTTPS
    OBJETOS_ORIGEN=https://…          ← el dominio APARTE desde el que se sirven las
                                        actividades interactivas

`OBJETOS_ORIGEN` tiene que ser **otro dominio**, no una carpeta del mismo sitio. Las
actividades interactivas corren en un marco aislado y ese aislamiento es lo que impide que
el HTML de un tercero alcance la sesión del campus.

### Las dos rutas de las actividades interactivas

`OBJETOS_ORIGEN` es la dirección pública; **`OBJETOS_RUTA` es la carpeta del disco donde
el campus escribe los objetos que se suben**, y tiene que ser la raíz que sirve ese otro
dominio. Por omisión apunta a `../lms-objetos/public`, que es la ruta de la máquina de
desarrollo y en el servidor casi nunca existe. Añádela al `.env`:

    OBJETOS_RUTA=/var/www/lms-objetos/public

Y dale escritura al servidor web sobre esa carpeta, igual que a `storage`. Si no está bien
puesta, subir un objeto falla al escribir; si apunta a una carpeta que ese otro dominio no
sirve, el objeto se guarda pero el alumno ve el marco vacío.

Opcionales, con valor por omisión razonable: `APP_LOCALE` (`es_CL`), `ALMACEN_RUTA`
(`storage/uploads`), `SESSION_IDLE` (2 h), `SESSION_MAX` (12 h), `CSP`.

## 3. Permisos

El servidor web solo necesita escribir en `storage`:

    chown -R www-data:www-data storage
    chmod -R 775 storage

Nada más es escribible. `public/` es lo único que debe quedar accesible desde fuera.

## 4. La raíz del sitio apunta a `public/`

En nginx:

    root /var/www/smartcampus/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

Si la raíz apunta a la carpeta del proyecto en vez de a `public/`, quedan expuestos el
`.env`, los PDF de las lecturas y el código entero.

## 5. Base de datos

    vendor/bin/phinx migrate -c database/phinx.php

Y para una instalación nueva, el primer usuario:

    php bin/crear-usuario

## 6. Contenido para probar

Dos cursos completos, listos para importar:

    php bin/curso importar database/cursos/excel-intermedio.json --ensayo   # dice qué haría
    php bin/curso importar database/cursos/excel-intermedio.json
    php bin/curso importar database/cursos/consola-de-linux.json

O desde la pantalla: **Gestión → Cursos → Desde un archivo**. Importar es idempotente por
slug: volver a pasar el mismo archivo corrige el curso en vez de duplicarlo.

Las actividades interactivas de ejemplo están en `database/laboratorios/`, ya comprimidas,
y se suben desde **Interactivas → Subir**. Necesitan `OBJETOS_ORIGEN` y `OBJETOS_RUTA`
configuradas.

## 7. Comprobar

- Abre la portada: debe cargarse con los estilos puestos.
- Entra a `/verificar`: es la pantalla que no necesita sesión.
- Entra al campus y abre un curso.

Si la página sale sin estilos, la raíz no está apuntando a `public/`.

---

## Qué NO viene en este paquete

- **`.env`** — se crea en el servidor, por lo dicho arriba.
- **`tests/`, `phpunit.xml.dist` y phpunit** — no hacen falta para servir y no conviene
  tenerlos accesibles.
- **`diseno/`** — las maquetas del handoff. Documentación, no código.
- **El contenido de `storage/`** — logs, caché y los PDF ya subidos. Las carpetas van
  vacías; si esto es una actualización y no una instalación nueva, **no sobrescribas
  `storage/uploads`**: ahí están los documentos de las lecturas.

## Actualizar sobre una instalación existente

    # respalda antes
    cp -r storage/uploads /ruta/segura/

    # sube el paquete nuevo, y luego devuelve lo tuyo
    cp .env.viejo .env
    cp -r /ruta/segura/uploads storage/

    vendor/bin/phinx migrate -c database/phinx.php
    rm -rf storage/cache/views/*      # las plantillas compiladas del build anterior
