> For the complete documentation index, see [llms.txt](https://doc.velneo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://doc.velneo.com/38/aplicacion-vlanzadera-y-login-social/configuracion-de-vlanzadera-en-servidores-propietarios-linux.md).

# Configuración de vLanzadera en servidores propietarios Linux

A continuación indicamos los pasos para publicar la vLanzadera en un servidor propietario con Linux, sirviéndola **desde el propio** [**Velneo vServer**](/38/velneo-vserver/que-es-velneo-vserver.md). Toda la configuración se hace desde Velneo vAdmin y el fichero de configuración del servidor.

Basado en **Ubuntu 22**; con otra distribución hay que adaptar rutas y comandos. Se asume que Velneo vServer se ejecuta como servicio con el usuario `velneo`. A lo largo de la guía, **mi-dominio** es tu dominio y **PUERTO** el del virtual host que configurarás en el paso 4.1.

Hace falta tener activada la **licencia de servicio HTTP**: sin ella el servidor responde con un error de acceso denegado al pedir la lanzadera.

{% hint style="info" %}
La lanzadera también puede servirse con Velneo vModApache, que es como se montaba antes de la versión 38. Funciona y tiene soporte, pero necesita Apache instalado y configurado a mano: si aun así es lo que prefieres, está en el [anexo](#anexo-publicarla-con-velneo-vmodapache).
{% endhint %}

## Resumen, si ya lo has hecho antes

Los datos que hay que acertar, para no releer la guía entera. Si es tu primera vez, sáltate esta sección y empieza por el paso 1.

Cada bloque acaba en lo que tiene que funcionar antes de pasar al siguiente. Si eso no funciona, el problema está en ese bloque.

### El certificado — paso 2

* `/home/velneo/.config/Velneo/ssl/`: tu certificado y tu clave. El `.crt` con la cadena completa y en base64.
* `chown velneo:velneo` en el directorio y `chmod 600` en el `.key`.
* `/home/velneo/.config/Velneo/vServer.conf`: `CertificateKey=` y `PrivateKey=` con la ruta de cada uno.

**Comprobar:** en Velneo vAdmin aparece `Cifrado de VATPS activado, certificado ssl: [...]`.

### La lanzadera — paso 3

* `vServer.conf`: `jwtKey=`, 32 caracteres como mínimo.

### El virtual host y la ruta — paso 4

* vAdmin › **Web**, virtual host **Principal**: activo, tu dominio, **SSL marcado** y un puerto libre **por encima del 1024**.
* Pestaña **Rutas**: ruta `/auth`, tipo **App**, la instancia de la lanzadera y el usuario con el que se ejecuta.
* Reiniciar el servidor HTTP.

**Comprobar:** **[https://mi-dominio:PUERTO/auth](https://doc.velneo.com/38/aplicacion-vlanzadera-y-login-social/https:/mi-dominio:PUERTO/auth)** carga la lanzadera, y desde ella arranca una aplicación.

### El cortafuegos — paso 5

* Abrir el puerto del virtual host, el de vatp y el de websockets.

Si alguna comprobación falla, la tabla de síntomas del final dice dónde mirar.

## Paso 1 - Instalar Velneo vServer

Sigue la documentación para instalar Velneo vServer en Linux. Recomendamos ejecutarlo como servicio con un usuario llamado `velneo` y en un puerto superior al 1024.

En los mensajes de arranque de Velneo vAdmin, apunta los dos puertos que hacen falta en el paso 5:

* El **puerto vatp**, del mensaje `Servidor vatp de 64 bits iniciado con licencia [...] Puerto: 690 [...]`.
* El **puerto de websockets**, del mensaje `Servidor websockets iniciado en puerto xxx`.

## Paso 2 - Copiar el certificado para Velneo vServer

Con este certificado Velneo vServer cifra las dos cosas: las conexiones VATPS de las aplicaciones y la propia lanzadera.

1. Copia los ficheros y déjaselos en propiedad:

```bash
sudo mkdir -p /home/velneo/.config/Velneo/ssl
sudo cp mi-dominio.crt /home/velneo/.config/Velneo/ssl/server.crt
sudo cp mi-dominio.key /home/velneo/.config/Velneo/ssl/server.key
sudo chown -R velneo:velneo /home/velneo/.config/Velneo/ssl
sudo chmod 600 /home/velneo/.config/Velneo/ssl/server.key
```

2. Añade las dos rutas a `/home/velneo/.config/Velneo/vServer.conf`:

```
CertificateKey=/home/velneo/.config/Velneo/ssl/server.crt
PrivateKey=/home/velneo/.config/Velneo/ssl/server.key
```

3. Reinicia Velneo vServer.

**Comprobar:** en Velneo vAdmin aparece `Cifrado de VATPS activado, certificado ssl: [...]`. Si aparece `Se usará el certificado por defecto`, no ha podido cargarlo.

* El `.crt` tiene que estar en base64 y llevar la **cadena completa**: tu certificado, los intermedios y la raíz. Con Let's Encrypt es `fullchain.pem`, no `cert.pem`.
* Los ficheros tienen que ser **legibles por `velneo`**. Si los dejas donde suele estar la clave de un certificado del sistema, `/etc/ssl/private/`, solo puede leerlos `root` y el servidor no cargará nada.
* **Al renovar el certificado** hay que volver a copiarlo aquí y reiniciar el servidor. Con Let's Encrypt toca cada pocas semanas, y si esta copia caduca las aplicaciones dejan de funcionar aunque el navegador siga viendo bien el sitio.

## Paso 3 - Instalar la vLanzadera y su clave JWT

1. Sigue la sección de instalación de vLanzadera.
2. Añade la clave JWT a `vServer.conf`:

```
jwtKey=TU_CLAVE_JWT_DE_32
```

3. Reinicia Velneo vServer.

La clave debe tener **32 caracteres como mínimo**. Opcionalmente puedes limitar la validez del token:

```
jwtExpiredSeconds=NUMERICO_SEGUNDOS
```

El servidor acepta el token durante ese tiempo más 60 segundos de cortesía, por si hay desviación de hora entre cliente y servidor. Por defecto, 60 segundos.

{% hint style="danger" %}
La clave JWT solo debe conocerla el administrador.
{% endhint %}

## Paso 4 - Publicar la lanzadera

En Velneo vAdmin, sección **Web** del menú lateral.

### 4.1 Configurar el virtual host

Haz doble clic sobre el virtual host marcado como **Principal** —o créalo con el botón de añadir— y configúralo así:

* **Activo**: marcado
* **Puerto de escucha**: un puerto libre por encima del 1024, por ejemplo `8443`
* **Dominio de escucha**: tu dominio
* **SSL**: **marcado**
* **Máximas conexiones concurrentes**: el valor por defecto

{% hint style="danger" %}
**SSL va marcado.** Es el propio servidor el que cifra, con el certificado del paso 2, y sin cifrado las aplicaciones WebAssembly no funcionan: los navegadores solo habilitan lo que necesitan en un contexto seguro.
{% endhint %}

* **Por encima del 1024**: los puertos por debajo solo los abre un proceso que corra como `root`, y el paso 1 recomienda ejecutar el servidor con el usuario `velneo`. Para publicar en el 443, pon un proxy delante.
* Elige un **puerto libre**: si hay un Apache u otro servidor web escuchando en el mismo, uno de los dos no podrá abrirlo y el fallo no siempre queda claro en los mensajes del servidor.
* Si pones un proxy delante y **termina el TLS**, esta conexión puede ir en claro y SSL va sin marcar; las condiciones están en esa misma sección.

### 4.2 Publicar la lanzadera en una ruta

En el mismo diálogo, pestaña **Rutas**, añade una:

| Campo         | Valor                            | Ejemplo          |
| ------------- | -------------------------------- | ---------------- |
| **Ruta**      | `/auth`                          | `/auth`          |
| **Instancia** | La instancia de la vLanzadera    | `VLANZADERA_APP` |
| **Usuario**   | El usuario con el que se ejecuta | `velneo`         |
| **Tipo**      | App                              | App              |

Acepta y **reinicia el servidor HTTP** desde la barra de herramientas de la sección **Web**.

**Comprobar:** **[https://mi-dominio:PUERTO/auth](https://doc.velneo.com/38/aplicacion-vlanzadera-y-login-social/https:/mi-dominio:PUERTO/auth)** carga la lanzadera. Esa es la dirección que hay que repartir a los usuarios.

{% hint style="danger" %}
**La ruta tiene que ser `/auth`.** La página de la lanzadera pide el token de acceso a `/auth/get_tok`, con la ruta escrita tal cual, así que en cualquier otra la lanzadera carga y se ve bien, pero al pulsar una aplicación falla con un error de comunicación. Los favoritos, igual.
{% endhint %}

* En el mismo virtual host puedes publicar otras aplicaciones añadiendo más rutas, esas sí con el nombre que quieras.
* **La raíz del dominio no sirve la lanzadera**: se entra por `/auth`. Si la necesitas en la raíz, hace falta algo delante que reescriba la petición, como el Apache del anexo.
* Los cambios no se aplican hasta reiniciar el servidor HTTP.

## Paso 5 - Abrir los puertos

Con un cortafuegos activo, abre en la máquina del servidor:

* El **puerto del virtual host** del paso 4.1.
* El **puerto vatp** y el **de websockets** que apuntaste en el paso 1.

## Comprobación final

1. **[https://mi-dominio:PUERTO/auth](https://doc.velneo.com/38/aplicacion-vlanzadera-y-login-social/https:/mi-dominio:PUERTO/auth)** carga la lanzadera.
2. Entras con un usuario y una aplicación arranca en el navegador.

No hay que configurar nada para las aplicaciones de escritorio web: vienen con la instalación de Velneo vServer y las sirve él mismo. Si importas un paquete desde los parámetros de la lanzadera, se sirve por la misma vía.

**Si algo falla:**

| Síntoma                                                                                             | Dónde mirar                                                                                                                         |
| --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Error de acceso denegado al pedir la lanzadera                                                      | La licencia de servicio HTTP                                                                                                        |
| **404** al pedir `/auth`                                                                            | La ruta del paso 4.2, o el servidor HTTP sin reiniciar después de crearla                                                           |
| **404** en la raíz del dominio                                                                      | Es lo normal en este modo: se entra por `/auth`                                                                                     |
| Carga, pero las aplicaciones no arrancan                                                            | Que entras por `https`: sin contexto seguro no arrancan, y eso exige **SSL marcado** en el virtual host (paso 4.1)                  |
| Entras, pero la aplicación se queda sin abrir y la consola del navegador da un error de `WebSocket` | El puerto de websockets (paso 5): cerrado en el cortafuegos, o con un proxy delante que no lo reenvía ni lo declara en «Puerto WSS» |
| Ninguna aplicación abre, y en el arranque no aparece `Servidor websockets iniciado en puerto`       | La licencia de ejecución web: sin ella Velneo vServer no levanta ese servicio, así que no hay ningún puerto al que conectarse       |
| La lanzadera carga pero no deja entrar                                                              | La clave JWT, en `vServer.conf` (paso 3)                                                                                            |
| El servidor HTTP no levanta el puerto                                                               | Un puerto por debajo del 1024, u otro servidor web escuchando en el mismo. Compruébalo con `ss -lntp`                               |
| `Se usará el certificado por defecto` en el arranque                                                | Permisos del certificado: tiene que poder leerlo `velneo` (paso 2)                                                                  |
| Las aplicaciones dejan de funcionar de golpe, semanas después                                       | El certificado, caducado tras una renovación (paso 2)                                                                               |

## Antes de exponerlo a internet

Con lo anterior la lanzadera funciona y se puede probar. Para publicarla hacia fuera **recomendamos poner un proxy delante** del servidor HTTP: le faltan funcionalidades de seguridad que un proxy sí aporta. Vale cualquiera —Apache, nginx u otro—, y su configuración es parte del despliegue de cada uno. Es además lo que permite publicar en el 443.

Lo que el proxy tiene que hacer:

* **Reenviar el virtual host completo** al puerto del servidor HTTP, no rutas concretas: por esa misma vía van la lanzadera, las aplicaciones de escritorio web y cualquier otra ruta que publiques.
* **Dejar pasar el tráfico tal cual**, sin añadir ni reescribir cabeceras. Las emiten ya la propia lanzadera en su página —incluidas `Cross-Origin-Embedder-Policy` y `Cross-Origin-Opener-Policy`— y el servidor HTTP en las aplicaciones. Duplicadas, el navegador las descarta y las aplicaciones no arrancan.

Con el proxy delante, el **puerto del servidor HTTP deja de publicarse**: en el cortafuegos se abre el del proxy, y el otro queda accesible solo desde él.

El **puerto de websockets no es ninguno de esos dos**. Por él entra el navegador para ejecutar las aplicaciones, y va directo a Velneo vServer: el proxy no lo toca salvo que lo configures para ello, así que si lo cierras al abrir el del proxy, la lanzadera seguirá cargando y las aplicaciones dejarán de arrancar. Hay dos salidas, y las dos valen:

* **Dejarlo abierto**, como en el paso 5. No hay nada que configurar: la lanzadera anuncia el puerto en el que escucha el servidor y el navegador llega hasta él.
* **Reenviarlo también por el proxy**, si prefieres que hacia fuera solo haya un puerto abierto. Puedes llevarlo al puerto de websockets del servidor, o dejar que entre por la misma vía que todo lo demás: el servidor HTTP atiende el websocket en la ruta `/ws` del virtual host que ya estás reenviando. Por ese segundo camino el servidor **comprueba que el `Origin` de la petición coincide con el `Host`**, así que el proxy tiene que reenviar el `Host` original; si lo reescribe, el navegador recibe un 403 y no dice por qué.

Reenviándolo, el navegador ya no llega al puerto del servidor sino al del proxy, y entonces hay que **declararlo en el parámetro «Puerto WSS»** de la lanzadera: Velneo vServer no tiene forma de saber que hay un proxy delante, así que seguiría anunciando el suyo.

Si el proxy **termina el TLS**, el cifrado de cara al navegador lo pone él y la conexión con el servidor HTTP puede ir en claro, con SSL sin marcar en el paso 4.1. Lo que sí hace falta es que **ese tramo no sea observable por terceros**: lo habitual es que el proxy y el servidor estén en la misma máquina, y entonces el reenvío va a `localhost` y no sale de ella. Si el tráfico atraviesa una red que no controlas por completo, tiene que ir cifrado — por ahí pasan las credenciales del formulario de login y el token JWT.

Cómo se configura cada proxy queda fuera de esta documentación: depende del que elijas.

***

## Anexo: publicarla con Velneo vModApache

Así se montaba la lanzadera antes de la versión 38: la página la sirve Apache con el módulo de Velneo, y las aplicaciones de escritorio web se reenvían al servidor HTTP. Sigue funcionando y tiene soporte, pero es bastante más trabajo que el modo del cuerpo de esta guía, así que se mantiene para quien ya lo tenga montado o prefiera seguir con él.

Los **pasos 1 a 3** son los mismos: Velneo vServer, su certificado y la lanzadera con su clave JWT. Cambia todo lo que viene después, y el virtual host se configura al revés que en el paso 4.1: en un puerto interno, sin dominio y **sin SSL**, porque aquí quien cifra de cara al navegador es Apache.

En este anexo, **PUERTO\_HTTP** es el puerto que configurarás en el paso A.3.

{% hint style="warning" %}
Apache y Velneo vServer tienen que estar **en la misma máquina**. En máquinas separadas hay que resolver el acceso entre ellas y su cifrado, y eso queda fuera de esta documentación.
{% endhint %}

### A.1 Instalar Apache

1. Actualiza el repositorio e instala Apache:

```bash
sudo apt update
sudo apt install apache2
```

2. Cambia el módulo de multiproceso:

```bash
sudo a2dismod mpm_event
sudo a2enmod mpm_worker
sudo systemctl restart apache2
```

3. Activa SSL y el sitio con SSL:

```bash
sudo a2dissite 000-default.conf
sudo a2ensite default-ssl.conf
sudo a2enmod ssl
sudo service apache2 restart
```

4. Activa los tres módulos que necesita la configuración del paso A.5:

```bash
sudo a2enmod rewrite
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo service apache2 restart
```

**`mpm_event` hay que quitarlo**: Velneo vModApache no es compatible con él.

### A.2 Configurar el certificado en Apache

Apache necesita su propia copia del certificado: la del paso 2 la lee el servicio `velneo`, y Apache se ejecuta con otra cuenta.

1. Coloca el certificado y la clave donde solo pueda leerlos `root`, por ejemplo el certificado en `/etc/ssl/certs/` y la clave en `/etc/ssl/private/`.
2. En `/etc/apache2/sites-available/default-ssl.conf`, dentro de `<VirtualHost _default_:443>`:
   * `SSLCertificateFile` y `SSLCertificateKeyFile`: las rutas de tu certificado y tu clave, en lugar de los `ssl-cert-snakeoil` que trae Ubuntu.
   * `ServerName mi-dominio:443`, descomentando la línea de ejemplo.
3. Reinicia Apache:

```bash
sudo apache2ctl configtest
sudo service apache2 restart
```

**Comprobar:** **<https://mi-dominio>** carga la página de bienvenida de Apache, con el candado del navegador y sin avisos de certificado.

* Si Apache no arranca, `apache2ctl configtest` dice en qué línea está el problema.
* No sigas sin esto: los pasos siguientes tampoco funcionarán.

### A.3 Configurar el virtual host del servidor HTTP

En Velneo vAdmin, sección **Web** del menú lateral:

1. **Desactiva el virtual host del 443** que Velneo vServer ha creado al arrancar: doble clic, **desmarca Activo**, acepta. Si vienes del modo del cuerpo de esta guía, desactiva también el que configuraste en el paso 4.1.
2. Añade el virtual host de trabajo con estos valores:
   * **Activo**: marcado
   * **Puerto de escucha**: uno libre, por ejemplo `8080`
   * **Dominio de escucha**: **vacío**
   * **SSL**: **sin marcar**
3. Reinicia el servidor HTTP desde la barra de herramientas de esa pantalla.
4. Apunta el puerto: es **PUERTO\_HTTP** del paso A.5.

**Comprobar:** desde la propia máquina, `curl -I -H "Accept-Encoding: br" http://localhost:8080/login/38.0.0/wasm-bridge.js` responde `200 OK`. Cambia `38.0.0` por la versión de tu Velneo vServer, la del mensaje de arranque.

{% hint style="danger" %}
**Desactiva el virtual host del 443, no lo borres**: si lo borras, el servidor lo vuelve a crear en el siguiente arranque.

Y hazlo antes de seguir, porque si un virtual host no consigue abrir su puerto **el servidor HTTP no arranca ninguno**. El síntoma engaña: Apache responde **503** a todas las aplicaciones con la configuración correcta, y en vAdmin sale `Error al iniciar servidor HTTP`.
{% endhint %}

{% hint style="danger" %}
**Aquí SSL va sin marcar**, al contrario que en el paso 4.1. El cifrado de cara al navegador lo pone Apache; esta conexión es interna y va sin cifrar. Si marcas SSL, el servidor responde cifrado, Apache reenvía en claro y todas las aplicaciones dan **502**.
{% endhint %}

* La cabecera `Accept-Encoding: br` del `curl` hace falta: los ficheros se sirven precomprimidos en brotli y sin pedirla no se encuentran. Y la versión en la ruta también, o la respuesta es un 404.
* **Dominio de escucha vacío** hace que atienda cualquier dominio, que es lo que quieres para una conexión interna. Si le pones uno, el reenvío del paso A.5 tendrá que usarlo en lugar de `localhost`.
* El puerto del servidor HTTP **no hay que abrirlo** en el cortafuegos: solo lo usa Apache dentro de la misma máquina. Los que sí se abren son el 443, el de vatp y el de websockets — este último solo si no lo reenvías por Apache (paso A.6).
* Si no responde, comprueba que está escuchando con `ss -lntp | grep 8080`.

### A.4 Instalar Velneo vModApache

Sigue los pasos de la documentación de vModApache.

### A.5 Configurar Apache para la vLanzadera

1. Abre `/etc/apache2/sites-enabled/default-ssl.conf`.
2. Pega este bloque **dentro** de `<VirtualHost>`, justo antes de `</VirtualHost>`:

```apacheconf
# --- vLanzadera ------------------------------------------------------------

# La raíz responde con la lanzadera. El flag PT es imprescindible: sin él
# Apache busca un fichero llamado "auth" y la raíz responde 404.
RewriteEngine On
RewriteRule ^/?$ /auth?%{QUERY_STRING} [NC,PT,L]

# La página de la lanzadera, servida por Velneo vModApache
<Location /auth>
	SetHandler velneo
	#VelneoMode SERVER
	Vrl vatps://usuario:contraseña@servidor[:num_puerto]/id_instancia
</Location>

# Las aplicaciones WebAssembly: /login las de la instalación de Velneo vServer,
# /velneoWASM las de un paquete importado. Las dos son necesarias.
<Location /login>
	ProxyPass        http://localhost:PUERTO_HTTP/login
	ProxyPassReverse http://localhost:PUERTO_HTTP/login
	SetEnv no-gzip 1
</Location>

<Location /velneoWASM>
	ProxyPass        http://localhost:PUERTO_HTTP/velneoWASM
	ProxyPassReverse http://localhost:PUERTO_HTTP/velneoWASM
	SetEnv no-gzip 1
</Location>
```

3. Sustituye la `Vrl` por los datos de tu instancia de la vLanzadera y **PUERTO\_HTTP** por el puerto del paso A.3.
4. Reinicia Apache:

```bash
sudo service apache2 restart
```

{% hint style="danger" %}
**No añadas ninguna cabecera para la vLanzadera.** Las emiten ya la propia lanzadera en su página —incluidas `Cross-Origin-Embedder-Policy` y `Cross-Origin-Opener-Policy`— y el servidor HTTP de Velneo vServer en las aplicaciones. Duplicadas, el navegador las descarta y las aplicaciones no arrancan.

Si vienes de una configuración anterior de la vLanzadera, quita antes:

* los `Include` de `vLanzadera.conf`, `vLanzadera-headers.conf`, `vLanzadera-assets.conf` y `vLanzadera-rewrites.conf`, y los propios ficheros,
* cualquier `Header` con `Cross-Origin-Embedder-Policy`, `Cross-Origin-Opener-Policy` o `Cache-Control` en el camino de la vLanzadera,
* el `RewriteRule` de la raíz hacia `/auth` que tuvieras dentro de un `<Directory>`,
* y el `<LocationMatch>` de los assets de la vLanzadera.

Tampoco hace falta ya cambiar el `DocumentRoot` ni crear directorios para los assets: Apache no sirve ninguno.
{% endhint %}

### A.6 El websocket, si no quieres abrir su puerto

Por defecto el navegador abre el websocket **directamente contra Velneo vServer**, en el puerto de websockets del paso 1, así que ese puerto tiene que estar abierto. Si prefieres que hacia fuera solo esté abierto el 443, Apache también puede reenviarlo, y entonces no hay que abrirlo.

Hace falta el módulo de túnel de websockets, que no está entre los del paso A.1:

```bash
sudo a2enmod proxy_wstunnel
sudo service apache2 restart
```

Elige **una** de las dos formas y añade su bloque dentro del mismo `<VirtualHost>` del paso A.5. La ruta es `/ws` en los dos casos: es la que pide el navegador, y no se configura en ninguna parte.

**Al puerto de websockets de Velneo vServer**, que es el mismo destino al que iba el navegador:

```apacheconf
SSLProxyEngine On

<Location /ws>
	ProxyPass        wss://mi-dominio:PUERTO_WS/
	ProxyPassReverse wss://mi-dominio:PUERTO_WS/
</Location>
```

Sustituye **PUERTO\_WS** por el puerto de websockets del paso 1, y **mi-dominio** por el tuyo. Ese puerto va cifrado, con el mismo certificado del paso 2, y por eso hace falta `SSLProxyEngine On`: sin él Apache reenvía en claro y responde **500** sin reclamar la directiva que falta.

Y va el **dominio**, no `localhost`: Apache comprueba que el nombre del certificado del otro extremo coincida con el del destino, así que por `localhost` responde también **500** y deja en el log `SSL Proxy: Peer certificate does not match for hostname localhost`. Eso sí, el dominio tiene que resolver desde la propia máquina; si tu DNS interno no lo hace, basta una línea en el fichero de `hosts` apuntándolo a `127.0.0.1`.

**Al servidor HTTP, por la misma vía que todo lo demás.** El servidor HTTP atiende el websocket en el `/ws` del virtual host que ya estás reenviando, así que va sin cifrar al mismo **PUERTO\_HTTP** del paso A.3:

```apacheconf
ProxyPreserveHost On

<Location /ws>
	ProxyPass        ws://localhost:PUERTO_HTTP/ws
	ProxyPassReverse ws://localhost:PUERTO_HTTP/ws
</Location>
```

`ProxyPreserveHost On` **no es opcional aquí**: por este camino el servidor comprueba que el `Origin` de la petición coincide con el `Host`, y si Apache reescribe el `Host` a `localhost` el navegador recibe un **403** sin más explicación.

Sea cual sea la que elijas, el navegador deja de llegar al puerto del servidor y llega al de Apache, así que hay que **declarar el 443 en el parámetro «Puerto WSS»** de la lanzadera. Velneo vServer no tiene forma de saber que hay un Apache delante: si no se lo dices, sigue anunciando su propio puerto y el navegador vuelve a intentar el que acabas de cerrar.

Reinicia Apache al terminar:

```bash
sudo service apache2 restart
```

### Comprobación del anexo

1. **<https://mi-dominio/auth>** carga la lanzadera.
2. **<https://mi-dominio>** devuelve lo mismo: aquí la raíz sí sirve la lanzadera, por el `RewriteRule` del bloque.
3. Entras con un usuario y una aplicación arranca en el navegador.

#### **Si algo falla:**

| Síntoma                                                                                | Dónde mirar                                                                                                                                                                                               |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **503** en todas las aplicaciones                                                      | El virtual host del 443 sin desactivar (paso A.3)                                                                                                                                                         |
| **502** al cargar la aplicación                                                        | SSL marcado en el virtual host, o `PUERTO_HTTP` distinto del configurado en vAdmin                                                                                                                        |
| **500** al abrir el websocket, con `Peer certificate does not match` en el `error_log` | El destino del reenvío puesto como `localhost`: tiene que ser el dominio del certificado (paso A.6)                                                                                                       |
| **403** `Origin no permitido` al abrir el websocket                                    | Falta `ProxyPreserveHost On` en el reenvío al `/ws` del servidor HTTP (paso A.6)                                                                                                                          |
| **404** en la raíz, pero `/auth` funciona                                              | Falta el flag `PT` en el `RewriteRule`                                                                                                                                                                    |
| Error de `SharedArrayBuffer` o `crossOriginIsolated`                                   | Cabeceras duplicadas. Escribe `self.crossOriginIsolated` en la consola; si da `false`, mira en la pestaña **Network** si `cross-origin-embedder-policy` o `cross-origin-opener-policy` aparecen dos veces |
| Entras, pero la aplicación se queda sin abrir y la consola da un error de `WebSocket`  | El websocket: si no lo reenvías por Apache, su puerto tiene que estar abierto en el cortafuegos; si lo reenvías (paso A.6), falta declarar el 443 en «Puerto WSS»                                         |
