Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1177b3d
feat(synology): add Synology DSM 7 SPK packaging and deployment workflow
erseco Aug 23, 2026
69eec20
ci(synology): trigger SPK build workflow strictly on release events
erseco Aug 23, 2026
df12334
fix(synology): support cross-platform tar flags and fallback to lates…
erseco Aug 23, 2026
9e6b719
Merge branch 'main' into feature/add-synology-package
erseco Aug 23, 2026
b167405
Merge branch 'main' into feature/add-synology-package
erseco Aug 25, 2026
2c75032
Merge branch 'main' into feature/add-synology-package
erseco Aug 26, 2026
499de4b
Merge branch 'main' into feature/add-synology-package
erseco Aug 28, 2026
90ef263
Merge branch 'main' into feature/add-synology-package
erseco Aug 30, 2026
26a5957
Merge branch 'main' into feature/add-synology-package
erseco Aug 31, 2026
784e8c4
Merge branch 'main' into feature/add-synology-package
erseco Aug 31, 2026
c6b2a52
Merge branch 'main' into feature/add-synology-package
erseco Sep 1, 2026
d11a938
Merge branch 'main' into feature/add-synology-package
erseco Sep 2, 2026
9612ffa
Merge branch 'main' into feature/add-synology-package
erseco Sep 3, 2026
9f67df4
Merge branch 'main' into feature/add-synology-package
erseco Sep 3, 2026
020f17a
Merge branch 'main' into feature/add-synology-package
erseco Sep 3, 2026
ef2ffc9
Merge branch 'main' into feature/add-synology-package
erseco Sep 5, 2026
ed5cd98
Merge branch 'main' into feature/add-synology-package
erseco Sep 6, 2026
0449996
Merge branch 'main' into feature/add-synology-package
erseco Sep 7, 2026
fbf1bfd
Merge branch 'main' into feature/add-synology-package
erseco Sep 8, 2026
bbd1de6
Merge branch 'main' into feature/add-synology-package
erseco Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/workflows/synology-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Build Synology SPK Release

on:
release:
types: [prereleased, released]
workflow_dispatch:
inputs:
version:
description: 'Version (e.g., 4.0.4 or latest)'
required: false
default: 'latest'

jobs:
build-spk:
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- name: Checkout code
uses: actions/checkout@v7

- name: Set up Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Get version
id: version
shell: bash
run: |
if [ "${{ github.event_name }}" = "release" ]; then
TAG="${GITHUB_REF#refs/tags/}"
echo "version=${TAG#v}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
else
INPUT_VER="${{ github.event.inputs.version || 'latest' }}"
if [ "$INPUT_VER" = "latest" ]; then
echo "version=latest" >> $GITHUB_OUTPUT
echo "tag=latest" >> $GITHUB_OUTPUT
else
echo "version=${INPUT_VER#v}" >> $GITHUB_OUTPUT
echo "tag=v${INPUT_VER#v}" >> $GITHUB_OUTPUT
fi
fi

- name: Build Synology SPK
run: |
make package-synology VERSION=${{ steps.version.outputs.version }}

- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: exelearning-${{ steps.version.outputs.version }}-spk
path: release/exelearning-*.spk

- name: Upload to GitHub Release
if: github.event_name == 'release'
run: |
gh release upload ${{ steps.version.outputs.tag }} \
release/exelearning-${{ steps.version.outputs.version }}.spk \
--clobber
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,14 @@ package-windows-local-sign: fail-on-windows check-release-env eb-inject-config

## --------- END WINDOWS LOCAL SIGN ---------

# Build Synology SPK package
# Usage: make package-synology VERSION=4.0.4
.PHONY: package-synology
package-synology:
@$(if $(VERSION),,$(error VERSION is required. Usage: make package-synology VERSION=x.y.z [DOCKER_TAG=latest]))
@DOCKER_TAG="$(DOCKER_TAG)" bash packaging/synology/build-spk.sh $(VERSION)



# =============================================================================
# UTILITIES
Expand Down Expand Up @@ -972,5 +980,6 @@ help:
@echo "Packaging:"
@echo " make package VERSION=1.0.0 Build release"
@echo " make package VERSION=1.0.0 PUBLISH=always Build & publish to GitHub"
@echo " make package-synology VERSION=1.0.0 Build Synology SPK package"
@echo " make package-windows-local-sign VERSION=1.0.0 CERT_THUMBPRINT=xxx"
@echo " Build signed Windows release"
134 changes: 134 additions & 0 deletions doc/deploy/synology.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Despliegue en Synology NAS (SPK / Container Manager)

eXeLearning se puede instalar y ejecutar en servidores NAS de Synology mediante un paquete oficial **SPK (Synology Package)** ligero que aprovecha el recurso nativo `docker-project` de **Container Manager** (DSM 7.2.1+).

---

## 1. Arquitectura del Paquete

El SPK actúa como un envoltorio nativo que se integra con DSM:

```mermaid
flowchart TD
DSM["Synology DSM (Package Center)"] --> SPK["eXeLearning SPK"]
SPK --> CM["Container Manager (docker-project)"]
CM --> IMG["Docker Image: ghcr.io/exelearning/exelearning:tag"]
IMG --> VOL["Volumen NAS: /volume1/docker/exelearning"]
IMG --> SSO["Synology SSO Server (OIDC)"]
```

- **Tamaño ligero:** El SPK pesa ~100 KB (solo metadatos, asistentes de interfaz y scripts de ciclo de vida).
- **Imagen oficial multiarquitectura:** Descarga automáticamente la imagen oficial optimizada para `linux/amd64` (Intel/AMD) o `linux/arm64` (ARMv8).
- **Persistencia garantizada:** Los datos, base de datos SQLite y assets se almacenan en una carpeta compartida del NAS (`/volume1/docker/exelearning` por defecto).

---

## 2. Requisitos Previos

- **Sistema operativo:** Synology DSM **7.2.1-69057** o superior.
- **Paquetes requeridos:** **Container Manager** (versión 1432 o superior), disponible de forma gratuita en el Package Center.
- **Arquitectura de CPU:** Modelos Synology con procesador **x86_64** (Intel/AMD) o **ARM64** (Realtek RTD1619b, etc. compatibles con Docker).

---

## 3. Instalación

### Opción A: Instalación manual del archivo `.spk`

1. Descarga el archivo `exelearning-<version>.spk` desde los [Releases oficiales de GitHub](https://github.com/exelearning/exelearning/releases).
2. Entra en el panel de control de tu Synology DSM y abre **Package Center** (Centro de paquetes).
3. Haz clic en el botón superior **Instalación manual** (Manual Install) y selecciona el archivo `.spk`.
4. El asistente de instalación solicitará:
- **Puerto web:** Puerto local del NAS para eXeLearning (por defecto `8080`).
- **Ruta de datos:** Carpeta en el NAS donde se guardarán proyectos y configuraciones (por defecto `/volume1/docker/exelearning`).
- **Método de autenticación:** Modo inicial (`password,guest`, `password`, `openid,password`, o `none`).
5. Confirma la instalación. Container Manager descargará la imagen y levantará el servicio automáticamente.

---

### Opción B: Repositorio de paquetes (Package Center)

1. En **Package Center**, pulsa en **Configuración** -> pestaña **Orígenes de paquetes** (Package Sources).
2. Añade un nuevo origen:
- **Nombre:** `eXeLearning`
- **Ubicación:** `https://synology.exelearning.net/` (o la URL de GitHub Pages configurada)
3. Ve a la sección **Comunidad** en el Package Center y haz clic en **Instalar** en eXeLearning.

---

## 4. Federación de Login con Synology SSO (OpenID Connect)

Es posible permitir que los usuarios de tu Synology NAS inicien sesión en eXeLearning utilizando sus credenciales de DSM (locales o de Directorio LDAP/Active Directory).

```mermaid
sequenceDiagram
autonumber
actor Usuario
participant eXe as eXeLearning (Web)
participant SSO as Synology SSO Server

Usuario->>eXe: Clic en "Iniciar sesión con Synology"
eXe->>SSO: Redirige a https://nas:5001/sso/
SSO-->>Usuario: Solicita credenciales de DSM
Usuario->>SSO: Autenticación exitosa
SSO-->>eXe: Retorna Authorization Code
eXe->>SSO: Intercambia token y obtiene perfil (UserInfo)
eXe->>eXe: Crea/enlaza el usuario
eXe-->>Usuario: Sesión iniciada
```

### Paso 1: Instalar Synology SSO Server
1. En el **Package Center** de DSM, busca e instala **SSO Server**.
2. Abre **SSO Server** y en **Servicio** activa la casilla **Habilitar el servicio OIDC**.

### Paso 2: Registrar la aplicación eXeLearning
1. Dentro de **SSO Server**, dirígete a **Lista de aplicaciones** -> **Añadir**.
2. Completa los datos:
- **Nombre de la aplicación:** `eXeLearning`
- **URI de redirección:** `https://<ip-o-dominio-del-nas>:<puerto>/login/openid/callback`
*(ejemplo: `https://nas.local:8080/login/openid/callback` o la URL configurada en el proxy inverso)*
3. Guarda y copia el **ID de cliente** (App ID) y el **Secreto de cliente** (App Secret).

### Paso 3: Configurar eXeLearning
Edita el archivo `.env` ubicado en la carpeta de instalación del paquete (`/var/packages/exelearning/target/.env` o en el proyecto de Container Manager):

```env
APP_AUTH_METHODS=openid,password
AUTH_CREATE_USERS=true

# Configuración SSO de Synology
OIDC_ISSUER=https://<ip-o-dominio-del-nas>:5001/sso
OIDC_CLIENT_ID=<tu-app-id>
OIDC_CLIENT_SECRET=<tu-app-secret>
OIDC_SCOPE="openid email profile"
```

Reinicia el contenedor desde Container Manager. Ahora aparecerá el botón de inicio de sesión OpenID / Synology en la pantalla de bienvenida.

---

## 5. Configurar HTTPS y Dominio con el Proxy Inverso de DSM

Para acceder de forma segura a través de `https://exelearning.tu-dominio.com`:

1. Ve a **Panel de control** -> **Portal de inicio de sesión** -> pestaña **Avanzado**.
2. Haz clic en **Proxy inverso** -> **Crear**:
- **Nombre descriptivo:** `eXeLearning`
- **Origen:**
- Protocolo: `HTTPS`
- Nombre de host: `exelearning.tu-dominio.com`
- Puerto: `443`
- Activar HSTS y HTTP/2
- **Destino:**
- Protocolo: `HTTP`
- Nombre de host: `localhost`
- Puerto: `8080` (o el puerto configurado en el SPK)
3. En la pestaña **Encabezado personalizado**, pulsa en **Crear** -> **WebSocket** (para asegurar soporte de colaboración en tiempo real).
4. Ve a **Panel de control** -> **Seguridad** -> **Certificado** y asigna tu certificado SSL (Let's Encrypt) a la regla de proxy inverso creada.

---

## 6. Copias de Seguridad y Mantenimiento

- **Base de datos y archivos:** Todo el estado se almacena en la ruta de datos configurada (`/volume1/docker/exelearning`). Puedes incluir este directorio en las tareas de **Hyper Backup** de Synology.
- **Actualizaciones:** Al actualizar el paquete desde el Package Center o reinstalar un `.spk` más reciente, la configuración y los datos del volumen persistente se preservan intactos.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ nav:
- Deployment: deployment.md
- High Availability: high-availability.md
- "Deploy: Sample Configs": deploy/README.md
- "Deploy: Synology NAS": deploy/synology.md
- Architecture:
- Overview: architecture.md
- Conventions: conventions.md
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
"export-scorm2004": "bun run dist/cli.js elp:export --format=scorm2004",
"export-ims": "bun run dist/cli.js elp:export --format=ims",
"export-epub3": "bun run dist/cli.js elp:export --format=epub3",
"test:unit": "bun test ./src ./test/helpers ./scripts ./app --coverage",
"test:unit:ci": "bun test ./src ./test/helpers ./scripts ./app --coverage --coverage-reporter=lcov --coverage-dir=coverage/bun --reporter=junit --reporter-outfile=coverage/bun/junit.xml",
"test:unit": "bun test ./src ./test/helpers ./scripts ./app ./packaging --coverage",
"test:unit:ci": "bun test ./src ./test/helpers ./scripts ./app ./packaging --coverage --coverage-reporter=lcov --coverage-dir=coverage/bun --reporter=junit --reporter-outfile=coverage/bun/junit.xml",
"test:integration": "bun test ./test/integration",
"test:frontend": "vitest run --config vitest.config.mts --coverage --reporter=default --reporter=junit --outputFile=coverage/vitest/junit.xml",
"test:frontend:ui": "vitest --ui --config vitest.config.mts",
Expand Down
19 changes: 19 additions & 0 deletions packaging/synology/INFO.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package="exelearning"
name="exelearning"
version="{{VERSION}}"
displayname="eXeLearning"
maintainer="INTEF"
maintainer_url="https://exelearning.net"
distributor="INTEF"
distributor_url="https://exelearning.net"
support_url="https://exelearning.net"
description="eXeLearning authoring tool to create interactive educational contents and export to SCORM, IMS and HTML5."
os_min_ver="7.0-40000"
install_type="system"
arch="apollolake x86_64 noarch armv8 aarch64 geminilake broadwell v1000 rtd1296 rtd1619b"
startable="yes"
dsmuidir="ui"
dsmappname="SYNO.SDS.eXeLearning"
adminport="8085"
adminurl="/"
helpurl="https://exelearning.net"
Binary file added packaging/synology/PACKAGE_ICON.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packaging/synology/PACKAGE_ICON_256.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions packaging/synology/WIZARD_UIFILES/install_uifile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[
{
"step_title": "Network and Storage Settings",
"items": [
{
"type": "textfield",
"desc": "Web port to access eXeLearning:",
"subitems": [
{
"key": "wizard_port",
"desc": "Port",
"defaultValue": "8080",
"validator": {
"regex": {
"expr": "^[0-9]+$",
"errorText": "Port must be an integer between 1024 and 65535"
}
}
}
]
},
{
"type": "textfield",
"desc": "Storage folder on NAS for projects and data:",
"subitems": [
{
"key": "wizard_data_path",
"desc": "Data path",
"defaultValue": "/volume1/docker/exelearning"
}
]
}
]
},
{
"step_title": "Authentication Mode",
"items": [
{
"type": "combobox",
"desc": "Select default authentication mode:",
"subitems": [
{
"key": "wizard_auth_methods",
"defaultValue": "password,guest",
"displayField": "display",
"valueField": "value",
"mode": "local",
"editable": false,
"store": [
["password,guest", "Local password and Guest access"],
["password", "Local password only"],
["openid,password", "OpenID Connect (SSO) and Local password"],
["none", "Open / Offline mode (No login)"]
]
}
]
}
]
}
]
1 change: 1 addition & 0 deletions packaging/synology/WIZARD_UIFILES/upgrade_uifile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Loading
Loading