chore: reorganizar carpetas de backups y archivar scripts/logs

- Unificar backup/ + backups/ + Akeeba sueltos en backups/ etiquetados por fecha
  (pre-incidente Enero, Marzo, INFECTED 25-mayo, clean 25-mayo, wp-local-dumps)
- Mover scripts de setup-inicial (Feb 2026) y logs de migración a archive/
- Mover kickstart.* a tools/akeeba-kickstart/
- Borrar joomla-php83-old-local-20260525/ (6.3 GB) y google-chrome.deb
- Conservar solo 2 de 8 dumps WP del 25-mayo (los hotfixes ya están consolidados)
- README de inventario con MD5 en backups/README.md y archive/README.md
- .gitignore: trackear los README dentro de carpetas gitignored
This commit is contained in:
2026-05-26 08:38:22 -04:00
parent 08d203249d
commit 39431c98e3
23 changed files with 442 additions and 19201 deletions
+10 -3
View File
@@ -12,14 +12,18 @@ wordpress/wp-content/languages/
# Joomla original # Joomla original
joomla/ joomla/
joomla-php83/ joomla-php83/
joomla-php83-old-local-20260525/
# Backups pesados # Backups pesados (GBs) — inventario en backups/README.md
backup/ backups/*
!backups/README.md
# Capturas de pantalla # Capturas de pantalla
capturas/ capturas/
# Archivo (scripts/logs históricos de la migración) — pesa poco, pero no es código vivo
archive/*
!archive/README.md
# Binarios y instaladores # Binarios y instaladores
*.deb *.deb
*.zip *.zip
@@ -43,3 +47,6 @@ __pycache__/
# E2E suite — deps + run output # E2E suite — deps + run output
tools/e2e/node_modules/ tools/e2e/node_modules/
tools/e2e/out/ tools/e2e/out/
# Akeeba Kickstart (tool de restauración, no es código del repo)
tools/akeeba-kickstart/
+7
View File
@@ -22,9 +22,16 @@ Working tree del proyecto feadulta.org. WordPress nuevo, scripts de migración K
├── wordpress/ WP local (Docker) ├── wordpress/ WP local (Docker)
│ └── wp-content/mu-plugins/ fea-homepage.php, carta-semana-plugin.php (trackeados) │ └── wp-content/mu-plugins/ fea-homepage.php, carta-semana-plugin.php (trackeados)
├── joomla/ Joomla legacy restaurado (solo lectura, port 8080) ├── joomla/ Joomla legacy restaurado (solo lectura, port 8080)
├── joomla-php83/ Joomla con PHP 8.3 (deploy compat, port 8081)
├── scripts/ Importadores, fixers, cutover ├── scripts/ Importadores, fixers, cutover
├── tools/
│ ├── e2e/ Suite Playwright + Gemma vision
│ └── akeeba-kickstart/ Kickstart.php para restaurar .jpa
├── backups/ Backups históricos (gitignored, ~22 GB) — ver backups/README.md
├── archive/ Scripts setup-inicial y logs migración (gitignored)
├── analisis-cartas/ Histórico de cartas semanales ├── analisis-cartas/ Histórico de cartas semanales
├── evangelios_html/ HTML de los evangelios ├── evangelios_html/ HTML de los evangelios
├── capturas/ PNGs de referencia (gitignored)
└── docker-compose.yml └── docker-compose.yml
``` ```
-66
View File
@@ -1,66 +0,0 @@
Mes,Visitantes distintos,Número de visitas,Páginas,Solicitudes,Tráfico,,,,,,
ene-22,0,0,0,0,0,,,,,,
feb-22,0,0,0,0,0,,,,,,
mar-22,0,0,0,0,0,,,,,,
abr-22,0,0,0,0,0,,,,,,
may-22,0,0,0,0,0,,,,,,
jun-22,"16,923","25,698","111,422","817,525",17.66 GB,,,,,,
jul-22,"45,776","84,329","355,940","2,560,649",57.32 GB,,,,,,
ago-22,"44,505","82,570","322,492","2,448,663",51.85 GB,,,,,,
sep-22,"45,768","85,852","332,686","2,703,005",53.96 GB,,,,,,
oct-22,"51,266","96,955","398,699","3,030,333",62.98 GB,,,,,,
nov-22,"53,000","101,104","396,966","3,057,764",64.35 GB,,,,,,
dic-22,"47,982","88,676","411,427","2,807,866",59.00 GB,,,,,,
Total,"305,220","565,184","2,329,632","17,425,805",367.13 GB,367,Visitantes distintos,Número de visitas,Páginas,Solicitudes,Tráfico
ene-23,"45,536","89,488","383,738","2,810,246",62.64 GB,,,,,,
feb-23,"43,782","86,511","372,179","2,911,673",67.22 GB,,,,,,
mar-23,"55,986","105,102","423,425","3,221,407",69.79 GB,,,,,,
abr-23,"65,846","118,160","478,889","3,471,429",73.77 GB,,,,,,
may-23,"54,474","108,678","437,054","2,906,214",66.04 GB,,,,,,
jun-23,"52,981","105,172","439,792","2,869,429",64.62 GB,,213%,309%,295%,251%,
jul-23,"57,117","113,116","450,584","2,731,793",64.58 GB,,25%,34%,27%,7%,
ago-23,"63,045","140,871","539,030","2,758,926",58.61 GB,,42%,71%,67%,13%,
sep-23,"65,034","149,379","624,236","3,415,006",71.86 GB,,42%,74%,88%,26%,
oct-23,"68,357","145,445","627,761","3,286,952",75.66 GB,,33%,50%,57%,8%,
nov-23,"179,885","280,554","700,147","3,733,807",83.00 GB,,239%,177%,76%,22%,
dic-23,"168,737","262,167","686,086","3,820,063",80.91 GB,,252%,196%,67%,36%,
Total,"920,780","1,704,643","6,162,921","37,936,945",838.71 GB,839,202%,202%,165%,118%,
ene-24,"57,564","115,929","562,340","3,088,039",72.19 GB,,26%,30%,47%,10%,
feb-24,"57,205","109,038","425,194","3,727,900",70.84 GB,,31%,26%,14%,28%,
mar-24,"69,773","122,603","472,614","3,552,316",75.36 GB,,25%,17%,12%,10%,
abr-24,"63,547","110,030","411,731","4,681,196",65.85 GB,,-3%,-7%,-14%,35%,
may-24,"56,307","99,833","392,265","2,997,908",55.69 GB,,3%,-8%,-10%,3%,
jun-24,"55,469","99,185","442,986","2,917,033",57.32 GB,,5%,-6%,1%,2%,
jul-24,"49,692","93,499","367,264","2,648,605",51.12 GB,,-13%,-17%,-18%,-3%,
ago-24,"114,945","166,981","417,570","2,740,774",62.03 GB,,82%,19%,-23%,-1%,
sep-24,"355,202","554,139","813,140","3,199,298",60.50 GB,,446%,271%,30%,-6%,
oct-24,"187,600","278,615","542,990","3,189,553",62.89 GB,,174%,92%,-14%,-3%,
nov-24,"59,377","108,646","424,075","3,132,767",60.30 GB,,-67%,-61%,-39%,-16%,
dic-24,"56,023","107,088","504,305","3,208,170",63.42 GB,,-67%,-59%,-26%,-16%,
Total,"1,182,704","1,965,586","5,776,474","39,083,559",757.51 GB,758,28%,15%,-6%,3%,
ene-25,"56,982","110,202","428,157","2,948,989",53.10 GB,,-1%,-5%,-24%,-5%,
feb-25,"69,402","123,938","383,399","2,845,281",53.42 GB,,21%,14%,-10%,-24%,
mar-25,"117,640","172,505","490,562","3,092,838",60.35 GB,,69%,41%,4%,-13%,
abr-25,"92,716","130,272","483,715","3,326,492",57.98 GB,,46%,18%,17%,-29%,
may-25,"114,625","196,343","535,100","3,029,376",56.46 GB,,104%,97%,36%,1%,
jun-25,"170,480","231,388","469,297","2,722,487",50.77 GB,,207%,133%,6%,-7%,
jul-25,"268,644","384,981","603,933","2,745,958",53.12 GB,,441%,312%,64%,4%,
ago-25,"220,312","354,493","622,225","2,730,778",52.20 GB,,92%,112%,49%,0%,
sep-25,"153,816","260,971","580,237","2,583,824",49.71 GB,,-57%,-53%,-29%,-19%,
oct-25,"239,797","324,028","636,156","2,705,455",57.14 GB,,28%,16%,17%,-15%,
nov-25,"257,319","362,900","709,905","2,449,443",53.82 GB,,333%,234%,67%,-22%,
dic-25,"13,630","105,996","509,377","942,256",17.14 GB,,-76%,-1%,1%,-71%,
Total,"1,775,363","2,758,017","6,452,063","32,123,177",615.20 GB,615,50%,40%,12%,-18%,
ene-26,"15,252","111,282","548,774","1,148,935",21.44 GB,,-73%,1%,28%,-61%,
feb-26,"12,629","94,621","444,378","863,611",16.11 GB,,-82%,-24%,16%,-70%,
mar-26,"6,253","40,611","152,049","284,284",7.01 GB,,-95%,-76%,-69%,-91%,
abr-26,0,0,0,0,0,,,,,,
may-26,0,0,0,0,0,,,,,,
jun-26,0,0,0,0,0,,,,,,
jul-26,0,0,0,0,0,,,,,,
ago-26,0,0,0,0,0,,,,,,
sep-26,0,0,0,0,0,,,,,,
oct-26,0,0,0,0,0,,,,,,
nov-26,0,0,0,0,0,,,,,,
dic-26,0,0,0,0,0,,,,,,
Total,"34,134","246,514","1,145,201","2,296,830",44.56 GB,45,,,,,
1 Mes Visitantes distintos Número de visitas Páginas Solicitudes Tráfico
2 ene-22 0 0 0 0 0
3 feb-22 0 0 0 0 0
4 mar-22 0 0 0 0 0
5 abr-22 0 0 0 0 0
6 may-22 0 0 0 0 0
7 jun-22 16,923 25,698 111,422 817,525 17.66 GB
8 jul-22 45,776 84,329 355,940 2,560,649 57.32 GB
9 ago-22 44,505 82,570 322,492 2,448,663 51.85 GB
10 sep-22 45,768 85,852 332,686 2,703,005 53.96 GB
11 oct-22 51,266 96,955 398,699 3,030,333 62.98 GB
12 nov-22 53,000 101,104 396,966 3,057,764 64.35 GB
13 dic-22 47,982 88,676 411,427 2,807,866 59.00 GB
14 Total 305,220 565,184 2,329,632 17,425,805 367.13 GB 367 Visitantes distintos Número de visitas Páginas Solicitudes Tráfico
15 ene-23 45,536 89,488 383,738 2,810,246 62.64 GB
16 feb-23 43,782 86,511 372,179 2,911,673 67.22 GB
17 mar-23 55,986 105,102 423,425 3,221,407 69.79 GB
18 abr-23 65,846 118,160 478,889 3,471,429 73.77 GB
19 may-23 54,474 108,678 437,054 2,906,214 66.04 GB
20 jun-23 52,981 105,172 439,792 2,869,429 64.62 GB 213% 309% 295% 251%
21 jul-23 57,117 113,116 450,584 2,731,793 64.58 GB 25% 34% 27% 7%
22 ago-23 63,045 140,871 539,030 2,758,926 58.61 GB 42% 71% 67% 13%
23 sep-23 65,034 149,379 624,236 3,415,006 71.86 GB 42% 74% 88% 26%
24 oct-23 68,357 145,445 627,761 3,286,952 75.66 GB 33% 50% 57% 8%
25 nov-23 179,885 280,554 700,147 3,733,807 83.00 GB 239% 177% 76% 22%
26 dic-23 168,737 262,167 686,086 3,820,063 80.91 GB 252% 196% 67% 36%
27 Total 920,780 1,704,643 6,162,921 37,936,945 838.71 GB 839 202% 202% 165% 118%
28 ene-24 57,564 115,929 562,340 3,088,039 72.19 GB 26% 30% 47% 10%
29 feb-24 57,205 109,038 425,194 3,727,900 70.84 GB 31% 26% 14% 28%
30 mar-24 69,773 122,603 472,614 3,552,316 75.36 GB 25% 17% 12% 10%
31 abr-24 63,547 110,030 411,731 4,681,196 65.85 GB -3% -7% -14% 35%
32 may-24 56,307 99,833 392,265 2,997,908 55.69 GB 3% -8% -10% 3%
33 jun-24 55,469 99,185 442,986 2,917,033 57.32 GB 5% -6% 1% 2%
34 jul-24 49,692 93,499 367,264 2,648,605 51.12 GB -13% -17% -18% -3%
35 ago-24 114,945 166,981 417,570 2,740,774 62.03 GB 82% 19% -23% -1%
36 sep-24 355,202 554,139 813,140 3,199,298 60.50 GB 446% 271% 30% -6%
37 oct-24 187,600 278,615 542,990 3,189,553 62.89 GB 174% 92% -14% -3%
38 nov-24 59,377 108,646 424,075 3,132,767 60.30 GB -67% -61% -39% -16%
39 dic-24 56,023 107,088 504,305 3,208,170 63.42 GB -67% -59% -26% -16%
40 Total 1,182,704 1,965,586 5,776,474 39,083,559 757.51 GB 758 28% 15% -6% 3%
41 ene-25 56,982 110,202 428,157 2,948,989 53.10 GB -1% -5% -24% -5%
42 feb-25 69,402 123,938 383,399 2,845,281 53.42 GB 21% 14% -10% -24%
43 mar-25 117,640 172,505 490,562 3,092,838 60.35 GB 69% 41% 4% -13%
44 abr-25 92,716 130,272 483,715 3,326,492 57.98 GB 46% 18% 17% -29%
45 may-25 114,625 196,343 535,100 3,029,376 56.46 GB 104% 97% 36% 1%
46 jun-25 170,480 231,388 469,297 2,722,487 50.77 GB 207% 133% 6% -7%
47 jul-25 268,644 384,981 603,933 2,745,958 53.12 GB 441% 312% 64% 4%
48 ago-25 220,312 354,493 622,225 2,730,778 52.20 GB 92% 112% 49% 0%
49 sep-25 153,816 260,971 580,237 2,583,824 49.71 GB -57% -53% -29% -19%
50 oct-25 239,797 324,028 636,156 2,705,455 57.14 GB 28% 16% 17% -15%
51 nov-25 257,319 362,900 709,905 2,449,443 53.82 GB 333% 234% 67% -22%
52 dic-25 13,630 105,996 509,377 942,256 17.14 GB -76% -1% 1% -71%
53 Total 1,775,363 2,758,017 6,452,063 32,123,177 615.20 GB 615 50% 40% 12% -18%
54 ene-26 15,252 111,282 548,774 1,148,935 21.44 GB -73% 1% 28% -61%
55 feb-26 12,629 94,621 444,378 863,611 16.11 GB -82% -24% 16% -70%
56 mar-26 6,253 40,611 152,049 284,284 7.01 GB -95% -76% -69% -91%
57 abr-26 0 0 0 0 0
58 may-26 0 0 0 0 0
59 jun-26 0 0 0 0 0
60 jul-26 0 0 0 0 0
61 ago-26 0 0 0 0 0
62 sep-26 0 0 0 0 0
63 oct-26 0 0 0 0 0
64 nov-26 0 0 0 0 0
65 dic-26 0 0 0 0 0
66 Total 34,134 246,514 1,145,201 2,296,830 44.56 GB 45
+35
View File
@@ -0,0 +1,35 @@
# Archive — scripts y logs históricos
Material **no vivo** de la migración Joomla → WordPress. Conservado por si hace falta volver a consultarlo. Esta carpeta está gitignored (excepto este README).
Movido aquí el 2026-05-26 desde la raíz del repo.
## setup-inicial/
Scripts usados en Feb 2026 para arrancar la migración: instalar PHP en el contenedor Joomla, restaurar el Akeeba inicial, parchear permisos, deshabilitar SSL en el Docker, etc.
| Script | Función |
|--------|---------|
| `setup.sh`, `start-containers.sh` | Arranque inicial Docker |
| `install-php-extensions.sh` | Instalar extensiones PHP en contenedor Joomla |
| `restore-backup.sh`, `restore-htaccess.sh` | Restaurar Akeeba inicial + htaccess |
| `fix-config.sh`, `fix-joomla-config.sh`, `fix-database-config.sh`, `fix-kickstart-security.sh`, `fix-permissions.sh` | Hotfixes de la fase inicial |
| `check-config.sh`, `disable-ssl.sh` | Diagnóstico / ajustes de entorno |
## logs-migracion/
Logs y CSVs de la fase de auditoría/migración inicial (Marzo 2026):
| Fichero | Origen |
|---------|--------|
| `detectar_estricto.log`, `detectar_gemma.log` | Detección de imágenes con Gemma vision |
| `renombrar_idiomas_gemma.log`, `renombrar_por_slug.log` | Renombrado de uploads |
| `backup_nombres_20260302_2131.txt` | Mapa pre-renombrado |
| `links_no_resueltos.txt` | Enlaces sin resolución en migración |
| `clasificacion_articulos.csv` | Clasificación de los 24.778 posts (categorías + autor) |
| `Trafico_FeAdulta.csv` | Export tráfico web pre-migración |
| `carta_8949.txt` | Texto suelto de una carta (no migrada) |
## configuration.php
Fichero `configuration.php` de Joomla legacy que quedó suelto en la raíz del repo. Conservado por si hace falta recuperar parámetros (DB, host, secrets antiguos del .org desmontado).
File diff suppressed because it is too large Load Diff
+108
View File
@@ -0,0 +1,108 @@
# Backups de feadulta — inventario
Organizado por fecha y propósito. Esta carpeta está **gitignored** (volúmenes en GBs). Mantén este README al día cuando añadas o elimines archivos.
Reorganizado: 2026-05-26 (consolidación de `backup/` + `backups/` + Akeeba sueltos en `capturas/`).
## Estructura
```
backups/
├── feadulta-20260111-pre-incidente/ 2.8 G Akeeba Enero (último limpio antes del malware)
├── feadulta-20260306-akeeba/ 2.8 G Akeeba Marzo (referencia migración)
├── feadulta-20260525-INFECTED/ 11 G Estado pre-limpieza + dump DB + hotfixes PHP83
├── feadulta-clean-20260525/ 5.4 G Estado post-limpieza (limpio) + Akeeba post-limpieza
├── wp-local-dumps-20260525/ 47 M Dumps WP local (Docker) del día de las mejoras
└── README.md Este fichero
```
Total: ~22 GB.
## feadulta-20260111-pre-incidente/
Akeeba Backup de Enero 2026, **antes** de que el escáner antimalware del hosting reportara las detecciones (issue #49). Probablemente la cuenta `ssmith` ya estaba creada (12 enero) pero el malware más reciente (`com_aimysitemap` con fecha Oct 25 2025) aún no había sido depositado o lo había sido muy poco antes. **No es garantía de limpieza** — usar solo como referencia histórica.
| Fichero | Tamaño | MD5 |
|---------|--------|-----|
| `site-www.feadulta.com-20260111-201614-DP_213gSrB86EMc_.j01` | 2.0 G | `43ff49190faecd5c49f6668d7ec3b818` |
| `site-www.feadulta.com-20260111-201614-DP_213gSrB86EMc_.jpa` | 803 M | `0b41e9559e064c211ba52f7d5bb5fc80` |
## feadulta-20260306-akeeba/
Akeeba Backup de Marzo 2026, ya con el malware presente en el filesystem. Útil como referencia del estado durante la migración K2→WP.
| Fichero | Tamaño | MD5 |
|---------|--------|-----|
| `site-www.feadulta.com-20260306-011457-1os52_Qdg5-vCycH.j01` | 2.0 G | `4859ea1e8f707a96ab553830f5123146` |
| `site-www.feadulta.com-20260306-011457-1os52_Qdg5-vCycH.jpa` | 807 M | `c442753105c62c79e27f6e031e956a9f` |
## feadulta-20260525-INFECTED/
Estado **infectado** capturado el 25-mayo, antes de las fases B+C+D de limpieza (issue #49). Contiene también los snapshots intermedios del deploy PHP 8.3 (issues #46, #47).
| Fichero | Tamaño | MD5 | Propósito |
|---------|--------|-----|-----------|
| `feadulta-web-20260525.INFECTED.tar.gz` | 11 G | `f74edeaff2e11feb7593f95c47331f84` | Filesystem completo `/web/` antes de limpiar |
| `fejoomla3-20260525.sql.gz` | 64 M | `0671407797c5bcd62129dc8dd8e9129e` | Dump DB pre-limpieza |
| `pre-step1-20260525-184255*` | <1 M | — | Snapshot antes del deploy PHP83 step 1 |
| `pre-hotfix-itemlistfilter-20260525-190134/` | <1 M | — | Snapshot pre-hotfix #47 |
| `pre-hotfix-search-20260525-191650/` | <1 M | — | Snapshot pre-hotfix buscador |
| `pre-malware-cleanup-20260525-194000.INFECTED*` | <1 M | — | Snapshot justo antes de la limpieza |
**Restauración:** este directorio contiene el último estado conocido íntegro antes del cambio. **Solo restaurar en una instalación aislada** — no es un estado limpio.
## feadulta-clean-20260525/
Estado **limpio** tras ejecutar las fases B+C+D de limpieza (24 horas antes del cutover previsto). Contiene tanto un tar.gz mío del filesystem como el Akeeba oficial post-limpieza.
| Fichero | Tamaño | MD5 | Propósito |
|---------|--------|-----|-----------|
| `feadulta-com-web-clean-20260525.tar.gz` | 2.7 G | `2aef9448238da8bccbbdcede15f2654a` | Filesystem `/web/` excluyendo `administrator/components/com_akeeba/backup/`, `cache/`, `tmp/`, `logs/` |
| `akeeba/site-www.feadulta.com-20260526-061340-rPlHC3AhISdZpLnb.j01` | 2.0 G | `8ea195c112541b298bf2abe54c6dceac` | Akeeba parte 1 (verificado md5 contra el servidor el 2026-05-26) |
| `akeeba/site-www.feadulta.com-20260526-061340-rPlHC3AhISdZpLnb.jpa` | 772 M | `0aa321822d537b2b097c48e848441e8e` | Akeeba parte 2 + manifest |
| `evidencia/malware-backup-20260525.tar.gz` | 5.5 M | — | Fase B v1 (3 extensiones iniciales) |
| `evidencia/malware-backup-20260525-v2.tar.gz` | 5.5 M | — | Fase B v2 (9 extensiones tras descubrir sub-paquetes) |
| `evidencia/malware-fase-c-20260525.tar.gz` | 111 K | — | Fase C (ficheros sueltos) |
| `evidencia/malware-fase-d-residuales-20260525.tar.gz` | 2.8 M | — | Fase D (residuales frontend + .ini) |
| `evidencia/local-malware-quarantine-20260525-200939.tar.gz` | 71 K | — | Cuarentena del WP local Docker |
| `evidencia/ssess_d45d182b50f80a5a9b73503603ffb552.bak` | 78 B | — | Sesión Joomla expirada (falso positivo) |
**Restauración del Akeeba post-limpieza:** copiar las dos partes (`.j01` + `.jpa`) al mismo directorio en el destino + `tools/akeeba-kickstart/kickstart.php`, abrir `kickstart.php` en el navegador y seguir las instrucciones.
## wp-local-dumps-20260525/
Dos snapshots de la BD WordPress local Docker del día de las mejoras (issue #38 corrección de enlaces Joomla, issue #43 nextend slider, etc.). Conservados como referencia.
| Fichero | Propósito |
|---------|-----------|
| `wp_db_pre_image_fix_20260525-062643.sql.gz` | Dump completo antes de la primera ronda de fix de imágenes |
| `wp_term_pre_clasif_20260525-154817.sql.gz` | Tablas de términos antes de reclasificación final |
Los 6 dumps intermedios entre estas dos marcas se descartaron el 2026-05-26 (eran snapshots de hotfixes ya consolidados).
## Restauración rápida
| Quiero... | Usa... |
|-----------|--------|
| Recuperar el estado de producción **antes** del incidente | `feadulta-20260111-pre-incidente/` (Akeeba) |
| Recuperar el estado **infectado** (forense) | `feadulta-20260525-INFECTED/feadulta-web-20260525.INFECTED.tar.gz` |
| Recuperar el estado **limpio** post-limpieza (filesystem) | `feadulta-clean-20260525/feadulta-com-web-clean-20260525.tar.gz` |
| Recuperar el estado **limpio** + DB (Akeeba) | `feadulta-clean-20260525/akeeba/*.j01 + *.jpa` |
| Volver al WP local de antes de las mejoras del 25-mayo | `wp-local-dumps-20260525/wp_db_pre_image_fix_*.sql.gz` |
## Verificación de integridad
```bash
cd /home/rafa/joomla-migration/backups
md5sum -c <<'EOF'
43ff49190faecd5c49f6668d7ec3b818 feadulta-20260111-pre-incidente/site-www.feadulta.com-20260111-201614-DP_213gSrB86EMc_.j01
0b41e9559e064c211ba52f7d5bb5fc80 feadulta-20260111-pre-incidente/site-www.feadulta.com-20260111-201614-DP_213gSrB86EMc_.jpa
4859ea1e8f707a96ab553830f5123146 feadulta-20260306-akeeba/site-www.feadulta.com-20260306-011457-1os52_Qdg5-vCycH.j01
c442753105c62c79e27f6e031e956a9f feadulta-20260306-akeeba/site-www.feadulta.com-20260306-011457-1os52_Qdg5-vCycH.jpa
f74edeaff2e11feb7593f95c47331f84 feadulta-20260525-INFECTED/feadulta-web-20260525.INFECTED.tar.gz
0671407797c5bcd62129dc8dd8e9129e feadulta-20260525-INFECTED/fejoomla3-20260525.sql.gz
2aef9448238da8bccbbdcede15f2654a feadulta-clean-20260525/feadulta-com-web-clean-20260525.tar.gz
8ea195c112541b298bf2abe54c6dceac feadulta-clean-20260525/akeeba/site-www.feadulta.com-20260526-061340-rPlHC3AhISdZpLnb.j01
0aa321822d537b2b097c48e848441e8e feadulta-clean-20260525/akeeba/site-www.feadulta.com-20260526-061340-rPlHC3AhISdZpLnb.jpa
EOF
```
-2
View File
@@ -1,2 +0,0 @@
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'fulltext FROM ew4r_content WHERE id = 8949' at line 1
-4
View File
@@ -1,4 +0,0 @@
#!/bin/bash
echo "Revisando configuración de Joomla..."
echo ""
docker exec joomla-web cat /var/www/html/configuration.php | grep -E "(tmp_path|log_path|session_handler)"
File diff suppressed because it is too large Load Diff
-108
View File
@@ -1,108 +0,0 @@
<?php
class JConfig {
public $MetaAuthor = '1';
public $MetaDesc = 'Este portal aspira a ser una ayuda global para el cristiano que quiere poner al día su fe. En sus textos va conformando el pensamiento de una renovada teología ajustada al mensajede Jesús de Nazaret y aporta distintas herramientas para vivir la fe y la espiritualidad a nivel individual y en comunidad.
Cumple ya 6 años. Nos alegra saber que conectamos con el sentir de muchos miles de cristianos que han evolucionado y madurado su fe. ';
public $MetaKeys = 'nuevo cristianismo, renovacion, cristianismo, renovacion cristiana, renovacion iglesia, renovacion doctrina, iglesia actual, espiritu vaticano segundo, espiritu vaticano ii, concilio vaticano ii, concilio vaticano segundo, espiritu vaticano 2, concilio vaticano 2, espiritualidad madura, fe madura, maduracion fe, actualizar fe, iglesia evangelica, raices evangelicas, evangelio puro, evangelio, evangelio domingo, comentarios evangelios, espiritu evangelico, espiritu evangelio, nueva liturgia, celebraciones comunitarias, celebraciones eucaristicas, renovacion celebraciones, guia celebraciones, nuevos paradigmas, nueva teologia, religion, espiritualidad, oracion, peliculas religiosas, fe, ateismo, dios, jesus, no dualidad, problema, mal, pecado, pecado original, mas alla, verdadera salvación, jesus persona, jesus hombre, vida jesus, milagros, movimiento jesus, fundamentalismo, sectas, laicidad, anticlericalismo, nueva catequesis, nuevo catecismo, catequesis, comunion, catequesis, confirmacion, catequesis adultos, grupos fe, grupos matrimonios, clase religión, otras religiones, religiones orientales, dialogo interreligioso, religion posmodernidad, iglesia catolica, iglesias cristianas, primeras comunidades, vaticano, curia, obispos, concilio vaticano, crisis actual iglesia, crisis religiosa, pluralidad iglesia, teologos censurados, nueva inquisición, mujer iglesia, laicos iglesia, sacramentos, bautismo, penitencia, sacerdocio, sacerdocio femenino, curas casados, mujeres sacerdotes, celibato, matrimonio, divorcio, matrimonio civil, eucaristía, liturgia eucaristica, celebracion sin sacerdote, oraciones eucaristicas, nuevos salmos, renovacion salmos, salmos renovados, nuevas plegarias, nuevas oraciones, adviento, reino dios, testimonios evangelicos, testigos Jesús, mision, justicia social, teologia liberación, solidaridad empobrecidos, justicia penitenciaria, visitas carceles, visitas enfermos, ecologia, derechos humanos, relaciones humanas, psicologia social, espiritu social, espiritualidad, etica, oracion, meditacion, vida interior, petición, mandamiento amor, tolerancia, perdon mutuo, perdon dios, etica propia conciencia, derecho natural, obrar conciencia, sexualidad, homosexualidad, pederastia, curas pederastas, aborto, eutanasia, poemas religiosos, poesia religiosa, cantos entrada, canciones plegaria, himnos gloria, cantos accion gracias, cantos marianos, villancicos, canciones populares, brotes olivo, Escuela de Formacion en fe adulta';
public $MetaRights = '';
public $MetaTitle = '1';
public $MetaVersion = '0';
public $access = '1';
public $cache_handler = 'file';
public $cachetime = '15';
public $caching = '0';
public $captcha = 'recaptcha';
public $cookie_domain = '';
public $cookie_path = '';
public $db = 'joomla_db';
public $dbprefix = 'ew4r_';
public $dbtype = 'mysqli';
public $debug = '0';
public $debug_lang = '0';
public $display_offline_message = '1';
public $editor = 'jce';
public $error_reporting = 'none';
public $feed_email = 'author';
public $feed_limit = '10';
public $force_ssl = '0';
public $fromname = 'Fe Adulta';
public $ftp_enable = '0';
public $ftp_host = '127.0.0.1';
public $ftp_pass = 'Pantonera12';
public $ftp_port = '21';
public $ftp_root = '';
public $ftp_user = 'admin';
public $gzip = '0';
public $helpurl = 'https://help.joomla.org/proxy?keyref=Help{major}{minor}:{keyref}&lang={langcode}';
public $host = 'joomla-db';
public $lifetime = '90';
public $list_limit = '50';
public $live_site = 'https://farmer.taild3aaf6.ts.net:8080';
public $log_path = '/var/www/html/administrator/logs';
public $mailer = 'mail';
public $mailfrom = 'inma@tyve.es';
public $memcache_compress = '1';
public $memcache_persist = '1';
public $memcache_server_host = 'localhost';
public $memcache_server_port = '11211';
public $offline = '0';
public $offline_image = '';
public $offline_message = 'Este sitio está cerrado por mantenimiento.<br /> Por favor, visítenos más tarde.';
public $offset = 'Europe/Madrid';
public $offset_user = 'UTC';
public $password = 'joomla_pass';
public $robots = '';
public $secret = '0jrKgW5fXRRoR2vgDUsYYryNPJiaXHdn';
public $sef = '1';
public $sef_rewrite = '1';
public $sef_suffix = '1';
public $sendmail = '/usr/sbin/sendmail';
public $session_handler = 'database';
public $sitename = 'Fe Adulta - para poner al día la Fe';
public $sitename_pagetitles = '0';
public $smtpauth = '0';
public $smtphost = 'localhost';
public $smtppass = '';
public $smtpport = '25';
public $smtpsecure = 'none';
public $smtpuser = '';
public $tmp_path = '/var/www/html/tmp';
public $unicodeslugs = '0';
public $user = 'joomla_user';
public $memcached_persist = '1';
public $memcached_compress = '0';
public $memcached_server_host = 'localhost';
public $memcached_server_port = '11211';
public $redis_persist = '1';
public $redis_server_host = 'localhost';
public $redis_server_port = '6379';
public $redis_server_auth = '';
public $redis_server_db = '0';
public $cache_platformprefix = '0';
public $proxy_enable = '0';
public $proxy_host = '';
public $proxy_port = '';
public $proxy_user = '';
public $proxy_pass = '';
public $mailonline = '1';
public $massmailoff = '1';
public $replyto = '';
public $replytoname = '';
public $session_memcache_server_host = 'localhost';
public $session_memcache_server_port = '11211';
public $session_memcached_server_host = 'localhost';
public $session_memcached_server_port = '11211';
public $shared_session = '0';
public $frontediting = '1';
public $asset_id = '1';
public $session_redis_server_host = 'localhost';
public $session_redis_server_port = '6379';
public $session_redis_persist = '1';
public $session_redis_server_auth = '';
public $session_redis_server_db = '0';
public $debug_lang_const = '1';
public $behind_loadbalancer = '0';
}
-15
View File
@@ -1,15 +0,0 @@
#!/bin/bash
echo "Desactivando forzado de SSL en Joomla..."
docker exec joomla-web bash -c "
sed -i \"s|public \\\$force_ssl = '.*'|public \\\$force_ssl = '0'|g\" /var/www/html/configuration.php
"
echo ""
echo "✓ SSL desactivado"
echo ""
echo "Verificando cambio..."
docker exec joomla-web cat /var/www/html/configuration.php | grep "force_ssl"
echo ""
echo "Recarga http://localhost:8080 en tu navegador (modo incógnito)"
-15
View File
@@ -1,15 +0,0 @@
#!/bin/bash
echo "Actualizando rutas en configuration.php..."
docker exec joomla-web bash -c "
sed -i \"s|public \\\$log_path = '.*'|public \\\$log_path = '/var/www/html/administrator/logs'|g\" /var/www/html/configuration.php
sed -i \"s|public \\\$tmp_path = '.*'|public \\\$tmp_path = '/var/www/html/tmp'|g\" /var/www/html/configuration.php
"
echo "Creando carpeta de logs si no existe..."
docker exec joomla-web mkdir -p /var/www/html/administrator/logs
docker exec joomla-web chmod 777 /var/www/html/administrator/logs
echo ""
echo "✓ Configuración actualizada"
echo "Recarga http://localhost:8080 en tu navegador"
-18
View File
@@ -1,18 +0,0 @@
#!/bin/bash
echo "Actualizando configuración de base de datos en configuration.php..."
docker exec joomla-web bash -c "
sed -i \"s|public \\\$host = '.*'|public \\\$host = 'joomla-db'|g\" /var/www/html/configuration.php
sed -i \"s|public \\\$db = '.*'|public \\\$db = 'joomla_db'|g\" /var/www/html/configuration.php
sed -i \"s|public \\\$user = '.*'|public \\\$user = 'joomla_user'|g\" /var/www/html/configuration.php
sed -i \"s|public \\\$password = '.*'|public \\\$password = 'joomla_pass'|g\" /var/www/html/configuration.php
"
echo ""
echo "✓ Configuración de base de datos actualizada"
echo ""
echo "Verificando cambios..."
docker exec joomla-web cat /var/www/html/configuration.php | grep -E "^\s*public \\\$(host|db|user|password) ="
echo ""
echo "Recarga http://localhost:8080 en tu navegador"
-23
View File
@@ -1,23 +0,0 @@
#!/bin/bash
echo "Corrigiendo configuración de Joomla para Docker..."
docker exec joomla-web bash -c "
cd /var/www/html
# Crear carpetas necesarias
mkdir -p tmp logs administrator/logs
chown -R www-data:www-data tmp logs administrator/logs
chmod -R 777 tmp logs administrator/logs
# Actualizar configuration.php con rutas correctas
sed -i \"s|public \\\$tmp_path = '.*';|public \\\$tmp_path = '/var/www/html/tmp';|g\" configuration.php
sed -i \"s|public \\\$log_path = '.*';|public \\\$log_path = '/var/www/html/logs';|g\" configuration.php
sed -i \"s|public \\\$session_handler = '.*';|public \\\$session_handler = 'database';|g\" configuration.php
echo 'Configuración actualizada:'
grep -E '(tmp_path|log_path|session_handler)' configuration.php
"
echo ""
echo "✓ Configuración corregida"
echo "Recarga http://localhost:8080 en tu navegador"
-7
View File
@@ -1,7 +0,0 @@
#!/bin/bash
docker cp ~/joomla-migration/backup/kickstart.json.php joomla-web:/var/www/html/
docker exec joomla-web chown www-data:www-data /var/www/html/kickstart.json.php
echo "✓ Archivo de seguridad copiado"
echo ""
echo "Recarga http://localhost:8080/kickstart.php en tu navegador"
echo "Contraseña: P-]a4hi&_c![9{Ew"
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
echo "Arreglando permisos de Joomla..."
docker exec joomla-web bash -c "
chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
chmod -R 777 /var/www/html/tmp
chmod -R 777 /var/www/html/cache
chmod -R 777 /var/www/html/administrator/cache
chmod -R 777 /var/www/html/logs
chmod 644 /var/www/html/configuration.php
"
echo ""
echo "✓ Permisos arreglados"
echo "Recarga http://localhost:8080 en tu navegador"
-14
View File
@@ -1,14 +0,0 @@
#!/bin/bash
echo "Instalando extensiones PHP en el contenedor Joomla..."
echo ""
docker exec joomla-web bash -c "apt-get update -qq && apt-get install -y -qq libpng-dev libjpeg-dev libzip-dev && docker-php-ext-configure gd --with-jpeg && docker-php-ext-install -j\$(nproc) gd mysqli pdo pdo_mysql zip"
echo ""
echo "Reiniciando Apache para aplicar cambios..."
docker exec joomla-web apache2ctl restart
echo ""
echo "✓ Extensiones instaladas!"
echo ""
echo "Recarga la página del instalador en tu navegador (F5)"
-42
View File
@@ -1,42 +0,0 @@
K2 ID=790 not found in map (post 17914: A MODO DE SALMO) | original: href="es/buscadoravanzado/item/790-si-se-pierde-un-hermano.html"
jos_content ID=60 not found (post 17930: Nuestros archivos)
jos_content ID=54 not found (post 17930: Nuestros archivos)
jos_content ID=58 not found (post 17930: Nuestros archivos)
K2 ID=2568 not found in map (post 17941: Eucaristía) | original: href="es/buscadoravanzado/item/2568-carta-de-un-padre-la-preparaci%C3%B3n-para-la-primera-comuni%C3%
K2 ID=2568 not found in map (post 18302: Rafa Rodrigo Ferrandis) | original: href="es/buscadoravanzado/item/2568-carta-de-un-padre-la-preparaci%C3%B3n-para-la-primera-comuni%C3%
K2 ID=2568 not found in map (post 18740: PRIMERA COMUNIÓN) | original: href="es/buscadoravanzado/item/2568-carta-de-un-padre-la-preparaci%C3%B3n-para-la-primera-comuni%C3%
K2 ID=1307 not found in map (post 18795: La mies y los obreros) | original: href="es/indice-multimedia/1307-pedro-y-pablo.html"
K2 ID=2883 not found in map (post 19893: Temario) | original: href="es/effa/91-sec4cat/2883-sec4col1.html"
K2 ID=2568 not found in map (post 20049: Florecimiento de vida nueva) | original: href="https://farmer.taild3aaf6.ts.net/fea/es/cantoral-de-salome-arricibita/2568-mas-sencilla.html"
K2 ID=2883 not found in map (post 20372: Desigualdad hombre-mujer) | original: href="https://farmer.taild3aaf6.ts.net/fea/es/effa/91-sec4cat/2883-sec4col1.html"
K2 ID=2883 not found in map (post 20372: Desigualdad hombre-mujer) | original: href="https://farmer.taild3aaf6.ts.net/fea/es/effa/91-sec4cat/2883-sec4col1.html"
K2 ID=3100 not found in map (post 20577: Vino nuevo) | original: href="https://farmer.taild3aaf6.ts.net/fea/es/indice-multimedia/3100-achispados.html"
K2 ID=2883 not found in map (post 20627: Carta con enlaces a las 37 clases en vídeo disponibles) | original: href="https://farmer.taild3aaf6.ts.net/fea/es/effa/94-secc4cat/2883-secc4col2.html"
K2 ID=3165 not found in map (post 20646: Transfiguraciones) | original: href="es/cantoral-de-salome-arricibita/3165-mi-luz.html"
K2 ID=2883 not found in map (post 20684: Acusadas, asesinadas, silenciadas) | original: href="es/effa/94-secc4cat/2883-secc4col2.html"
K2 ID=2883 not found in map (post 20754: BALANCE DEL SEGUNDO SEMESTRE) | original: href="es/effa/94-secc4cat/2883-secc4col2.html"
K2 ID=2883 not found in map (post 20864: BALANCE FIN DE CURSO 2015-2016) | original: href="es/effa/94-secc4cat/2883-secc4col2.html"
K2 ID=3413 not found in map (post 20893: El prójimo no se elige) | original: href="https://farmer.taild3aaf6.ts.net/fea/es/cantoral-de-salome-arricibita/3413-oracion-del-samarit
K2 ID=2883 not found in map (post 21073: Temario (3)) | original: href="es/effa/91-sec4cat/2883-sec4col1.html"
K2 ID=790 not found in map (post 21464: Julio-Agosto-Septiembre 2017) | original: href="https://farmer.taild3aaf6.ts.net/fea/es/buscadoravanzado/item/790-si-se-pierde-un-hermano.html
K2 ID=790 not found in map (post 21553: 07-09-2017) | original: href="https://farmer.taild3aaf6.ts.net/fea/es/buscadoravanzado/item/790-si-se-pierde-un-hermano.html
jos_content ID=52 not found (post 21807: Plenitud de humanidad)
K2 ID=2883 not found in map (post 22155: Temario (copia del antiguo temario por semestres)) | original: href="es/effa/91-sec4cat/2883-sec4col1.html"
K2 ID=2883 not found in map (post 22404: Temario (3)) | original: href="es/effa/91-sec4cat/2883-sec4col1.html"
K2 ID=3165 not found in map (post 22382: Este es mi hijo amado) | original: href="es/cantoral-de-salome-arricibita/3165-mi-luz.html"
K2 ID=4919 not found in map (post 22392: ¿Castigos divinos?, no gracias) | original: href="es/indice-multimedia/4919-adoramus-te-domine.html"
K2 ID=3413 not found in map (post 22561: Buenos samaritanos) | original: href="es/cantoral-de-salome-arricibita/3413-oracion-del-samaritano.html"
K2 ID=5948 not found in map (post 23423: Respira tu ser) | original: href="es/indice-multimedia/5948-el-taller-de-san-jose.html"
K2 ID=5947 not found in map (post 23423: Respira tu ser) | original: href="es/indice-multimedia/5947-comienza.html"
K2 ID=5946 not found in map (post 23423: Respira tu ser) | original: href="es/indice-multimedia/5946-de-la-superficie-a-lo-profundo.html"
K2 ID=6026 not found in map (post 23500: El sueño de Jesús) | original: href="es/indice-multimedia/6026-con-amor-eterno-2.html"
K2 ID=3413 not found in map (post 24113: ¿Vivo la proximidad?) | original: href="es/cantoral-de-salome-arricibita/3413-oracion-del-samaritano.html"
K2 ID=6919 not found in map (post 24393: Hacer presente el Reino) | original: href="es/indice-multimedia/6919-dejarnos-encontrar.html"
K2 ID=8621 not found in map (post 26091: Hacia Jesús) | original: href="es/indice-multimedia/8621-santo-por-siempre.html"
K2 ID=3413 not found in map (post 26197: Cinismo religioso) | original: href="es/cantoral-de-salome-arricibita/3413-oracion-del-samaritano.html"
K2 ID=8777 not found in map (post 26245: Predicación incómoda) | original: href="es/indice-multimedia/8777-habitare-4.html"
K2 ID=8802 not found in map (post 26271: Con rostro de Padre y Madre) | original: href="es/indice-multimedia/8802-sobre-la-autentica-meditacion.html"
K2 ID=8801 not found in map (post 26271: Con rostro de Padre y Madre) | original: href="es/indice-multimedia/8801-como-pan-pequeno-3.html"
K2 ID=8803 not found in map (post 26271: Con rostro de Padre y Madre) | original: href="es/videos/8803-en-mi-getsemani-mas-alla-de-mis-miedos-2.html"
K2 ID=8806 not found in map (post 26278: Dios y el dinero) | original: href="es/indice-multimedia/8806-crea-ti-vos.html"
K2 ID=8966 not found in map (post 26717: Un jarro de agua fría) | original: href="es/indice-multimedia/8966-carta-a-los-reyes-magos.html"
-34
View File
@@ -1,34 +0,0 @@
#!/bin/bash
set -e
echo "================================"
echo "Restaurando Backup de Joomla con Akeeba"
echo "================================"
echo
# Copiar archivos del backup al contenedor
echo "[1/3] Copiando archivos al contenedor..."
docker cp ~/joomla-migration/backup/kickstart.php joomla-web:/var/www/html/
docker cp ~/joomla-migration/backup/site-www.feadulta.com-20260111-201614-DP_213gSrB86EMc_.jpa joomla-web:/var/www/html/
docker cp ~/joomla-migration/backup/site-www.feadulta.com-20260111-201614-DP_213gSrB86EMc_.j01 joomla-web:/var/www/html/
echo "[2/3] Ajustando permisos..."
docker exec joomla-web chown -R www-data:www-data /var/www/html
echo "[3/3] Listo!"
echo
echo "================================"
echo "✓ Archivos copiados!"
echo "================================"
echo
echo "Accede a Kickstart en tu navegador:"
echo "👉 http://localhost:8080/kickstart.php"
echo
echo "Datos de la base de datos para Kickstart:"
echo " Host: joomla-db"
echo " Database: joomla_db"
echo " User: joomla_user"
echo " Password: joomla_pass"
echo
echo "Después de restaurar con Kickstart, elimínalo por seguridad:"
echo " docker exec joomla-web rm /var/www/html/kickstart.php"
-16
View File
@@ -1,16 +0,0 @@
#!/bin/bash
echo "Restaurando .htaccess..."
docker exec joomla-web cp /var/www/html/htaccess.bak /var/www/html/.htaccess
docker exec joomla-web chmod 644 /var/www/html/.htaccess
echo ""
echo "✓ .htaccess restaurado"
echo ""
echo "Habilitando mod_rewrite en Apache..."
docker exec joomla-web a2enmod rewrite
docker exec joomla-web apache2ctl restart
echo ""
echo "✓ Apache reiniciado"
echo "Recarga http://localhost:8080 en tu navegador"
+282
View File
@@ -0,0 +1,282 @@
#!/usr/bin/env bash
# Paso 1 del upgrade PHP 8.3 en feadulta.com (issue #46):
# subir 5 ficheros parcheados + limpieza malware, manteniendo PHP 7.4.
#
# Modos:
# --dry-run imprime lo que haría sin tocar nada (default)
# --apply ejecuta el despliegue real
# --rollback BACKUP_DIR restaura desde un backup pre-step1 concreto
#
# Pre-flight estricto: aborta si los 5 ficheros remotos no coinciden con el
# hash esperado (el que verificamos hoy 2026-05-25). Si en prod cambió algo
# entre planning y ejecución, hay que rehacer la planificación.
set -euo pipefail
# ─── Config ────────────────────────────────────────────────────────────────
SSH_USER="feadulta"
SSH_HOST="134.0.10.170"
SSH_PASS='6Rm2qOF@eundwpda'
REMOTE_WEB_ROOT="/web"
LOCAL_SRC_ROOT="/home/rafa/joomla-migration/joomla-php83"
BACKUP_ROOT="/home/rafa/joomla-migration/backup/prod-20260525-php83-compat"
# Mapa: ruta_relativa | hash_local_esperado | hash_remoto_esperado_actual
# (verificado 2026-05-25 con md5sum local + ssh + tar -xzO del backup)
declare -a FILES=(
"modules/mod_featcats/helper.php|01ae5ad40e13abdcd5852897786d3733|744922888ae533b090eb34effe3bb469"
"templates/fe_adulta_1/functions.php|06b2c26a618dbceefa5d8d5f0293c2cf|6318edec84cdf7a6b84a1d07f063c6c0"
"templates/fe_adulta_1/index.php|dc318909b9ae5976e5c4f01c06c35f66|9793dfa3c880eba37ad5ad35e6988705"
"modules/mod_k2_filter/helper.php|0d9767a0d8d67aa420baefe38382a87c|8530a4e70043973fd2d625c6f8de6ce9"
"modules/mod_k2_filter/tmpl/Default/template.php|a62a39dacafa0748528268b9f04aa844|008465147acdeb442eca6f64311fb23d"
)
# URLs de smoke test (deben devolver HTTP 200 antes y después del cambio)
declare -a SMOKE_URLS=(
"https://www.feadulta.com/"
"https://www.feadulta.com/es/"
"https://www.feadulta.com/es/ayuda.html"
"https://www.feadulta.com/es/quienessomos/colaboradores.html"
"https://www.feadulta.com/es/buscadoravanzado/itemlist/"
"https://www.feadulta.com/es/buscadoravanzado/itemlist/user/43-fraymarcos.html"
"https://www.feadulta.com/es/comentcol2.html"
)
# Patrones de spam que deben dar 0 hits en las respuestas tras el paso 1
SPAM_REGEX="(apuestadeportiva|vavada\.mobi|inkabet|betsafe|betcris|botbotbot)"
# IP del origen para bypass de Cloudflare (la web está detrás de CF managed challenge,
# las peticiones curl normales reciben 403). --resolve nos lleva directo al origen.
ORIGIN_IP="134.0.10.170"
SMOKE_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36"
# ─── Utilidades ────────────────────────────────────────────────────────────
# Logs van a stderr; stdout queda libre para "datos" (p.ej. ruta del backup
# para capturar con $(...) sin contaminación). Bug detectado en revisión #46.
log() { printf '%s [%s] %s\n' "$(date +'%H:%M:%S')" "$1" "$2" >&2; }
info() { log "INFO" "$1"; }
warn() { log "WARN" "$1"; }
err() { log "ERR " "$1"; }
ok() { log "OK " "$1"; }
ssh_run() {
SSHPASS="$SSH_PASS" sshpass -e ssh -o StrictHostKeyChecking=no -o ConnectTimeout=15 \
"$SSH_USER@$SSH_HOST" "$@"
}
# El cPanel jail rechaza scp y sftp ("Connection closed"). Usamos cat-over-ssh,
# que sí funciona (cat está en /usr/bin/cat). Verificación 2026-05-25: download
# de un fichero conocido reproduce el mismo MD5; upload de bytes y verificación
# por re-lectura sin pérdidas.
scp_get() {
local remote="$1" local_target="$2"
SSHPASS="$SSH_PASS" sshpass -e ssh -o StrictHostKeyChecking=no -o ConnectTimeout=15 \
"$SSH_USER@$SSH_HOST" "cat '$remote'" > "$local_target"
}
scp_put() {
local local_src="$1" remote_target="$2"
SSHPASS="$SSH_PASS" sshpass -e ssh -o StrictHostKeyChecking=no -o ConnectTimeout=15 \
"$SSH_USER@$SSH_HOST" "cat > '$remote_target'" < "$local_src"
}
remote_md5() {
ssh_run "md5sum '$1' 2>/dev/null | cut -d' ' -f1"
}
# ─── Pre-flight checks ─────────────────────────────────────────────────────
preflight() {
info "Pre-flight: verificar hashes locales y remotos"
local fail=0
for entry in "${FILES[@]}"; do
IFS='|' read -r rel hl hr_expected <<<"$entry"
local local_path="$LOCAL_SRC_ROOT/$rel"
local remote_path="$REMOTE_WEB_ROOT/$rel"
if [[ ! -f "$local_path" ]]; then
err "Local no existe: $local_path"; fail=1; continue
fi
local hl_actual
hl_actual=$(md5sum "$local_path" | cut -d' ' -f1)
if [[ "$hl_actual" != "$hl" ]]; then
err "Local $rel: hash $hl_actual ≠ esperado $hl"; fail=1
else
ok "Local $rel coincide ($hl)"
fi
local hr_actual
hr_actual=$(remote_md5 "$remote_path")
if [[ -z "$hr_actual" ]]; then
err "Remoto no existe o vacío: $remote_path"; fail=1
elif [[ "$hr_actual" != "$hr_expected" ]]; then
err "Remoto $rel: hash $hr_actual ≠ esperado $hr_expected (algo cambió en prod, replanificar)"; fail=1
else
ok "Remoto $rel coincide ($hr_actual)"
fi
done
if [[ $fail -eq 1 ]]; then
err "Pre-flight FAIL → abortando"
exit 2
fi
ok "Pre-flight OK"
}
# ─── Backup pre-cambio (los 5 ficheros remotos) ────────────────────────────
backup_pre_step1() {
local ts; ts=$(date +'%Y%m%d-%H%M%S')
local dir="$BACKUP_ROOT/pre-step1-$ts"
if [[ "$MODE" == "dry-run" ]]; then
info "[dry-run] Crearía directorio: $dir"
info "[dry-run] Descargaría ${#FILES[@]} ficheros remotos a ese directorio + md5sums.txt + tar.gz"
echo "$dir" # imprime para usar después
return
fi
info "Creando backup pre-step1 en $dir"
mkdir -p "$dir"
for entry in "${FILES[@]}"; do
IFS='|' read -r rel _ hr_expected <<<"$entry"
local remote_path="$REMOTE_WEB_ROOT/$rel"
local local_target="$dir/$rel"
mkdir -p "$(dirname "$local_target")"
info " Descargando $remote_path"
scp_get "$remote_path" "$local_target"
if [[ ! -s "$local_target" ]]; then
err "Descarga vacía: $local_target — ABORT (revisar acceso SSH)"
exit 6
fi
local h_after
h_after=$(md5sum "$local_target" | cut -d' ' -f1)
if [[ "$h_after" != "$hr_expected" ]]; then
err "Backup $rel: md5 $h_after ≠ esperado $hr_expected — ABORT"
exit 6
fi
ok " Backup $rel verificado ($h_after)"
done
(cd "$dir" && find . -type f -name '*.php' -exec md5sum {} \; > md5sums.txt)
tar -czf "$dir.tar.gz" -C "$BACKUP_ROOT" "pre-step1-$ts"
ok "Backup pre-step1 creado: $dir"
ok "Backup tar.gz: $dir.tar.gz"
echo "$dir"
}
# ─── Subida de los 5 ficheros ──────────────────────────────────────────────
upload_files() {
for entry in "${FILES[@]}"; do
IFS='|' read -r rel hl _ <<<"$entry"
local local_path="$LOCAL_SRC_ROOT/$rel"
local remote_path="$REMOTE_WEB_ROOT/$rel"
if [[ "$MODE" == "dry-run" ]]; then
info "[dry-run] scp $local_path$remote_path"
continue
fi
info "Subiendo $rel"
scp_put "$local_path" "$remote_path"
local hr_after; hr_after=$(remote_md5 "$remote_path")
if [[ "$hr_after" != "$hl" ]]; then
err "Subida de $rel: hash remoto post-subida $hr_after ≠ local $hl"
err "ABORT — el fichero remoto no coincide con el local. Considerar rollback."
exit 3
fi
ok "Subido + verificado $rel ($hr_after)"
done
}
# ─── Smoke test HTTP ───────────────────────────────────────────────────────
# allow_spam=1 → solo validar HTTP code (uso post-rollback, donde los ficheros
# restaurados llevan las inyecciones spam originales y un spam>0 es esperado).
smoke_test() {
local allow_spam="${1:-0}"
if [[ "$allow_spam" -eq 1 ]]; then
info "Smoke test HTTP (post-rollback: solo validar HTTP, spam>0 esperado)"
else
info "Smoke test HTTP (HTTP 200/3xx + spam=0)"
fi
local fail=0
for url in "${SMOKE_URLS[@]}"; do
if [[ "$MODE" == "dry-run" ]]; then
info "[dry-run] curl $url + grep spam"
continue
fi
local code body_spam tmp
tmp=$(mktemp)
code=$(curl -ksL -A "$SMOKE_UA" --resolve "www.feadulta.com:443:$ORIGIN_IP" \
-o "$tmp" -w "%{http_code}" "$url" || echo "ERR")
body_spam=$(grep -cE "$SPAM_REGEX" "$tmp" || true)
rm -f "$tmp"
if [[ "$code" != "200" && "$code" != "301" && "$code" != "302" ]]; then
err " $url → HTTP $code"; fail=1
elif [[ "$allow_spam" -eq 0 && "$body_spam" -gt 0 ]]; then
err " $url → HTTP $code, $body_spam strings spam"; fail=1
else
ok " $url → HTTP $code, $body_spam spam"
fi
done
if [[ $fail -eq 1 ]]; then
err "Smoke test FAIL → considerar rollback manual con --rollback <backup-dir>"
exit 4
fi
ok "Smoke test OK"
}
# ─── Rollback desde backup ─────────────────────────────────────────────────
rollback() {
local dir="$1"
if [[ ! -d "$dir" ]]; then
err "Backup dir no existe: $dir"; exit 5
fi
info "Rollback desde $dir"
for entry in "${FILES[@]}"; do
IFS='|' read -r rel _ _ <<<"$entry"
local local_src="$dir/$rel"
local remote_path="$REMOTE_WEB_ROOT/$rel"
if [[ ! -f "$local_src" ]]; then
err " No hay backup para $rel — saltando"; continue
fi
info " Restaurando $rel"
scp_put "$local_src" "$remote_path"
ok " Restaurado $rel"
done
ok "Rollback completado"
}
# ─── Main ──────────────────────────────────────────────────────────────────
MODE="dry-run"
ROLLBACK_DIR=""
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run) MODE="dry-run"; shift ;;
--apply) MODE="apply"; shift ;;
--rollback) MODE="rollback"; ROLLBACK_DIR="${2:-}"; shift 2 ;;
-h|--help) sed -n '1,12p' "$0"; exit 0 ;;
*) err "Flag desconocido: $1"; exit 1 ;;
esac
done
info "Modo: $MODE"
if [[ "$MODE" == "rollback" ]]; then
if [[ -z "$ROLLBACK_DIR" ]]; then err "--rollback requiere ruta del backup"; exit 1; fi
rollback "$ROLLBACK_DIR"
smoke_test 1 # allow_spam=1: ficheros restaurados aún tienen las inyecciones
exit 0
fi
preflight
backup_dir=$(backup_pre_step1)
upload_files
smoke_test
ok "Paso 1 finalizado en modo: $MODE"
if [[ "$MODE" == "apply" ]]; then
ok "Backup pre-step1: $backup_dir"
ok "Para rollback: $0 --rollback $backup_dir"
fi
-50
View File
@@ -1,50 +0,0 @@
#!/bin/bash
set -e
echo "================================"
echo "Setup Joomla Migration Environment"
echo "================================"
echo
# Instalar dependencias si faltan
echo "[1/5] Verificando dependencias..."
if ! command -v unzip &> /dev/null; then
echo "Instalando unzip..."
sudo apt-get install -y unzip
fi
# Descargar Akeeba Kickstart
echo "[2/5] Descargando Akeeba Kickstart..."
cd ~/joomla-migration/backup
if [ ! -f "kickstart.php" ]; then
wget -q https://github.com/akeeba/kickstart/releases/download/7.0.7/kickstart-core-7.0.7.zip -O kickstart.zip
unzip -q kickstart.zip
rm kickstart.zip
echo "✓ Kickstart descargado"
else
echo "✓ Kickstart ya existe"
fi
# Iniciar contenedores
echo "[3/5] Iniciando contenedores Docker..."
cd ~/joomla-migration
docker compose up -d
echo
echo "[4/5] Esperando a que MySQL esté listo..."
sleep 10
# Instalar extensiones PHP necesarias en el contenedor
echo "[5/5] Instalando extensiones PHP en el contenedor..."
docker exec joomla-web bash -c "apt-get update -qq && apt-get install -y -qq libpng-dev libjpeg-dev libzip-dev && docker-php-ext-configure gd --with-jpeg && docker-php-ext-install -j\$(nproc) gd mysqli pdo pdo_mysql zip"
echo
echo "================================"
echo "✓ Setup completado!"
echo "================================"
echo
echo "Contenedores corriendo:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo
echo "Próximo paso: copiar archivos de Kickstart al contenedor"
echo "Ejecuta: bash ~/joomla-migration/restore-backup.sh"
-16
View File
@@ -1,16 +0,0 @@
#!/bin/bash
set -e
echo "Iniciando contenedores Docker..."
cd ~/joomla-migration
docker compose up -d
echo "Esperando a que MySQL esté listo..."
sleep 15
echo "Instalando extensiones PHP en el contenedor Joomla..."
docker exec joomla-web bash -c "apt-get update -qq && apt-get install -y -qq libpng-dev libjpeg-dev libzip-dev && docker-php-ext-configure gd --with-jpeg && docker-php-ext-install -j\$(nproc) gd mysqli pdo pdo_mysql zip"
echo ""
echo "✓ Contenedores listos!"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"