Instalación Panel

Paso 1: Copiar los archivos nuevos

La carpeta panel/new-files/ está armada para calzar carpeta por carpeta con la raíz de tu panel: app/ va sobre tu app/, database/ sobre tu database/, resources/ sobre tu resources/. No hay que renombrar ni reacomodar nada.

Opción A: arrastrando y soltando (recomendado si usás FileZilla, WinSCP o similar):

  1. Conectate por SFTP a tu servidor/panel.
  2. En el panel izquierdo (tu compu) abrí panel/new-files/.
  3. Arrastrá la carpeta app de la izquierda sobre la carpeta app de la derecha (la raíz de tu panel) y elegí fusionar/merge cuando el cliente te pregunte qué hacer con carpetas que ya existen (nunca "reemplazar todo"), solo tiene que agregar archivos nuevos dentro de subcarpetas que ya tenés.
  4. Repetí lo mismo con database y con resources.

Opción B: por SSH/terminal, si preferís línea de comandos:

bash
cp -r panel/new-files/app/*        /ruta/al/panel/app/
cp -r panel/new-files/database/*   /ruta/al/panel/database/
cp -r panel/new-files/resources/*  /ruta/al/panel/resources/

Archivos que se copian (28 en total, todos son archivos nuevos, ninguno pisa un archivo que ya exista en tu panel):

  • app/Services/Domains/WingsProxyClient.php
  • app/Services/Domains/DomainService.php
  • app/Jobs/Domains/ApplyDomainProxy.php
  • app/Jobs/Domains/RevokeDomainProxy.php
  • app/Models/Domain.php
  • app/Models/NodeProxySetting.php
  • app/Transformers/Api/Client/DomainTransformer.php
  • app/Http/Controllers/Api/Client/Servers/DomainController.php
  • app/Http/Controllers/Admin/Nodes/NodeProxyController.php
  • app/Http/Requests/Admin/Node/NodeProxyFormRequest.php
  • app/Http/Requests/Api/Client/Servers/Domains/StoreDomainRequest.php
  • app/Http/Requests/Api/Client/Servers/Domains/GetDomainsRequest.php
  • app/Http/Requests/Api/Client/Servers/Domains/DeleteDomainRequest.php
  • app/Http/Requests/Api/Client/Servers/Domains/VerifyDomainRequest.php
  • database/migrations/2025_05_04_000001_create_server_domains_table.php
  • database/migrations/2025_05_04_000002_create_node_proxy_settings_table.php
  • database/migrations/2026_05_29_000001_fix_server_domains_unique_index.php
  • database/migrations/2026_09_16_000001_add_custom_ssl_and_allocation_to_server_domains.php
  • database/migrations/2026_09_17_000001_add_verification_to_server_domains.php
  • database/migrations/2026_09_18_000001_add_show_conf_path_to_node_proxy_settings.php
  • resources/scripts/components/server/domains/DomainsContainer.tsx
  • resources/scripts/components/server/domains/AddDomainModal.tsx
  • resources/scripts/components/server/domains/DomainRow.tsx
  • resources/scripts/api/swr/getServerDomains.ts
  • resources/scripts/api/server/domains/createServerDomain.ts
  • resources/scripts/api/server/domains/deleteServerDomain.ts
  • resources/scripts/api/server/domains/verifyServerDomain.ts
  • resources/views/admin/nodes/view/proxy.blade.php

Paso 2: Aplicar los 6 fragmentos inyectados

Esta parte no se arrastra: son archivos que ya existen en tu panel y hay que abrirlos con un editor de texto (o el editor de archivos del propio panel/hPanel/lo que uses) para pegar un bloque de código en el lugar exacto. Cada archivo en panel/injected-code/ trae arriba de todo un comentario DESTINO:/UBICACIÓN: que te dice en qué archivo y en qué punto va. Resumen:

FragmentoDestinoDónde
routes__api-client.phproutes/api-client.phpdentro del grupo /servers/{server}, justo antes del grupo /startup
routes__admin.phproutes/admin.phpdentro del grupo prefix('nodes'), junto a las demás rutas GET/POST de /view/{node}
app_Models__Permission.phpapp/Models/Permission.phpconstantes junto a las demás ACTION_*, y entrada 'domain' => [...] como última clave del array $permissions
app_Models__Node.phpapp/Models/Node.phpjunto a las demás relaciones (después de allocations()); no requiere ningún use adicional
resources_scripts_routers__routes.tsresources/scripts/routers/routes.tsimport del componente DomainsContainer + entrada en el array server.routes, después de Backups
resources_views_admin_nodes_view__TABS.blade.phplos 5 blades de admin/nodes/view/ (index.blade.php, settings.blade.php, configuration.blade.php, allocation.blade.php, servers.blade.php)como último <li> del <ul class="nav nav-tabs">

Paso 3: Migrar la base de datos

bash
cd /ruta/al/panel
php artisan migrate

Esto crea las tablas server_domains y node_proxy_settings, aplica el fix del índice único (2026_05_29_000001_fix_server_domains_unique_index.php), agrega las columnas de certificado propio y allocation (2026_09_16_000001_...), y agrega la columna y el estado de verificación de dominio (2026_09_17_000001_...).

No te saltes la migración del fix. Sin ella, borrar un dominio y volver a crearlo (incluso en otro servidor) puede chocar con la restricción UNIQUE(domain) de la tabla y tirar un error de duplicado. Ver Solución de problemas.

Paso 4: Regenerar el autoloader de Composer

bash
composer dump-autoload -o

Si tu panel fue instalado con el autoloader optimizado (composer install --optimize-autoloader, el modo recomendado para producción), Laravel arma un mapa fijo de clase → archivo al instalar. Ese mapa no se entera solo de las clases nuevas que acabás de copiar: si te saltás este paso, VerifyDomainRequest y compañía tiran "Class not found" en cuanto algo intenta usarlas, aunque el archivo esté en el lugar correcto. Si tu panel no usa autoloader optimizado podés saltear este paso, pero correrlo de todas formas no rompe nada.

Paso 5: Compilar el frontend

bash
yarn install
yarn run build:production

En un servidor con poca RAM (menos de 1-2 GB libres) el build puede fallar por out-of-memory antes de terminar. Si pasa eso, corré:

bash
NODE_OPTIONS="--max-old-space-size=2048" yarn run build:production

Paso 6: Limpiar cachés y reiniciar la cola

bash
php artisan config:clear
php artisan route:clear
php artisan view:clear
php artisan queue:restart

Si usás supervisor o systemd para queue:work, confirmá que el proceso se reinicia solo (Restart=always o equivalente). queue:restart solo le avisa al worker que termine el ciclo actual, no lo vuelve a levantar por sí mismo.

Verificación

  1. Entrá a cualquier servidor del panel → debería aparecer la pestaña Proxy.
  2. Andá a Admin → Nodes → (un nodo) → Proxy → debería cargar la vista de configuración sin error 404 ni 500.

Siguiente: Instalación: Wings →