La copia de seguridad termina y el hosting vuelve a avisar: la biblioteca multimedia ocupa la mayor parte del disco, las subidas tardan más y cada imagen de producto o entrada suma consumo. Mover archivos con prisa parece una solución sencilla, hasta que una imagen antigua devuelve un error 404 porque se borró antes de comprobar su nueva URL.
Puedes hacer offload imagenes wordpress a s3 paso a paso conectando un bucket privado, un usuario IAM con permisos mínimos y un plugin como WP Offload Media. Reducirás carga en el hosting, pero S3 no acelera por sí solo: para entregar imágenes con rapidez global conviene usar CloudFront. Antes de borrar medios locales, valida archivos nuevos y antiguos, prepara una alternativa de migración y conserva un rollback verificable.
Evalúa tu web antes de mover los medios
Calcula el problema real y decide si el traslado resolverá la carga del hosting. Abre el panel de tu hosting y revisa el uso de disco, el tráfico mensual y el tamaño de wp-content/uploads. Si esa carpeta ocupa entre 5 y 20 GB, o crece cada mes por fotos de producto, subir medios a S3 suele liberar bastante espacio local.
S3 guarda objetos, que son archivos como JPG, PNG, WebP o PDF con una ruta interna. No corrige un tema lento, consultas pesadas de WooCommerce ni plugins que consumen CPU. Si tu página tarda entre 3 y 6 segundos aunque las imágenes pesen poco, revisa primero caché, servidor y plugins activos.
La decisión más segura es separar tres tareas: almacenar archivos en S3, servirlos por CloudFront y conservar una copia recuperable. WordPress seguirá guardando datos de cada adjunto en su base de datos, mientras el archivo físico podrá vivir fuera del servidor.
Mide la biblioteca y el tráfico
Haz un inventario antes de tocar AWS. En WordPress entra en Medios > Biblioteca, cambia a vista de lista y anota el número de elementos. Desde el gestor de archivos del hosting, descarga o comprime wp-content/uploads y apunta su tamaño total.
Guarda una lista de entre 15 y 25 URLs actuales de imágenes. Incluye una imagen destacada, una galería, una foto de producto, una miniatura, una imagen WebP y una entrada publicada hace más de un año. Esa muestra será tu prueba de que las rutas antiguas siguen funcionando.
El error más frecuente en este punto es contar solo los originales JPG. WordPress crea tamaños como -300x300, -768x512 o -1536x1024, y los temas pueden crear otros propios. Es como archivar una foto con todas sus copias impresas, no solo el negativo.
Decide si S3 necesita CloudFront
Usa S3 para guardar y CloudFront para repartir imágenes con caché geográfica. Una URL directa de S3 recupera el archivo desde la región elegida. Una distribución de Amazon CloudFront guarda copias temporales en nodos de su CDN, una red de servidores de entrega, para reducir distancia y tiempo de carga.
Si la mayoría de tus visitas está en España y el hosting ya incluye una CDN bien configurada, comprueba antes si puedes usar esa CDN como capa de entrega. Si tienes visitantes de varios países, catálogo amplio o picos de tráfico, S3 con CloudFront da más control sobre origen, caché y costes.
| Opción | Qué libera | Entrega al visitante | Cuándo encaja |
|---|
| Medios locales | Nada | Hosting | Biblioteca pequeña y hosting sobrado |
| S3 directo | Disco y tráfico del hosting | Región AWS | Prueba técnica o poco tráfico |
| S3 y CloudFront | Disco y tráfico del hosting | CDN con caché | Producción con visitas recurrentes |
Prepara copias, pruebas y un entorno seguro
Crea una copia restaurable y un punto de comparación antes de cambiar cualquier URL. Haz una copia completa de la base de datos y de todos los archivos de WordPress desde el panel de hosting. Descarga una copia separada de wp-content/uploads, porque será tu red de seguridad si un plugin elimina archivos de forma inesperada.
Comprueba que la copia se puede abrir. Un ZIP descargado que pesa 0 KB no sirve, y una copia automática sin base de datos no permite restaurar adjuntos ni contenido. Conserva al menos dos copias en lugares distintos durante entre 14 y 30 días tras la migración.
Programa el trabajo en una franja con poco tráfico. Para una biblioteca de entre 2 y 10 GB, la preparación suele llevar entre 30 y 60 minutos; la copia puede tardar mucho más según el ancho de banda del hosting y el número de archivos pequeños.
Identifica qué crea, reescribe o comprime imágenes en tu sitio. En Plugins > Plugins instalados, anota los plugins de caché, compresión, WebP, AVIF, galerías, constructores visuales y WooCommerce. LiteSpeed Cache, por ejemplo, puede servir copias WebP desde una ruta distinta de la imagen original.
Prueba también las páginas hechas con Elementor, Divi o bloques personalizados. Algunos constructores guardan URLs completas en datos internos, por lo que una simple sustitución global en la base de datos puede dañar contenido serializado. La forma rápida es reemplazar URLs a ciegas; la forma correcta es dejar que el plugin de offload gestione las rutas de adjuntos.
Como especialistas en mantenimiento WordPress para empresas, profesionales y tiendas online, hemos visto casos en que una tienda movió solo los JPG originales y mantuvo los WebP locales: las fichas parecían correctas al administrador, pero los móviles recibían errores 404 al cargar tamaños responsive.
Elige región y registra decisiones
Elige una región AWS y documenta por qué alojas allí los medios. Para proyectos en España puedes valorar la Región AWS Europa (España) eu-south-2, Irlanda eu-west-1 o Fráncfort eu-central-1. La cercanía no sustituye a CloudFront, pero ayuda a que el origen esté dentro de Europa y simplifica algunas decisiones internas.
Si las imágenes incluyen caras, documentos, matrículas u otros datos personales, revisa tu registro de tratamiento. El RGPD, la LOPDGDD y la LSSI-CE no prohíben usar AWS, pero obligan a controlar acceso, conservación y contratos aplicables al tratamiento de datos.
Amazon Web Services publica sus opciones de seguridad y regiones en su portal oficial de AWS. Documenta el nombre del bucket, la región, la persona responsable, el coste esperado y la fecha prevista de revisión.
Crea un bucket privado para producción
Crea un bucket privado que almacene los medios sin exponerlos directamente a Internet. En la consola de AWS busca S3, pulsa Crear bucket y escribe un nombre único, por ejemplo midominio-es-media-prod. Los nombres son globales en AWS, así que imagenes-wordpress casi siempre estará ocupado.
Elige la región decidida en el paso anterior y deja activado Bloquear todo el acceso público. Marca también ACL desactivadas u Object Ownership: Bucket owner enforced cuando AWS muestre esa opción. Una ACL es una lista antigua de permisos por archivo; evitarla reduce conflictos.
Un bucket privado funciona con WordPress cuando CloudFront tiene acceso controlado al origen. Abrir el bucket al público es como dejar la puerta del almacén sin cerrar porque el repartidor necesita entrar: parece fácil, pero no es necesario.
Separa producción de pruebas
Usa buckets distintos para producción y pruebas cuando puedas. Crea, por ejemplo, midominio-es-media-staging para una copia de pruebas y midominio-es-media-prod para la web publicada. Así una prueba de borrado o una regla de ciclo de vida no afectará archivos que ven clientes.
Si el presupuesto o la estructura obligan a usar un solo bucket, separa por prefijos. Un prefijo es la parte inicial de la ruta, como produccion/uploads/ o staging/uploads/. No es una carpeta real, pero AWS y las políticas IAM lo tratan como una zona separada.
Activa etiquetas como Entorno=produccion, Proyecto=wordpress y Responsable=marketing-web. Las etiquetas ayudan a clasificar gasto en AWS Cost Explorer cuando hay más servicios en la misma cuenta.
Prepara el origen para CloudFront
Crea una distribución de CloudFront después de tener el bucket privado. En la consola busca CloudFront, pulsa Crear distribución y elige tu bucket S3 como origen. Cuando AWS proponga crear un control de acceso al origen, acepta la opción recomendada para que CloudFront pueda leer objetos sin hacer público el bucket.
En la distribución, establece la redirección de HTTP a HTTPS. Usa una política de caché pensada para archivos estáticos y no reenvíes cookies ni cabeceras innecesarias al origen. Para imágenes públicas, una caché de entre 7 y 30 días suele ser razonable si tus nombres de archivo cambian al sustituir una imagen.
Guarda el dominio de distribución, parecido a d123abc.cloudfront.net. Más adelante podrás usar ese dominio o crear media.tudominio.es con DNS y un certificado SSL/TLS. La propagación inicial de CloudFront puede tardar entre 10 y 30 minutos.
Recorrido seguro de una imagen
WordPress
registra el adjunto
→
S3 privado
guarda el archivo
→
CloudFront
lee como origen autorizado
→
Visitante
recibe HTTPS y caché
El bucket permanece cerrado al público; CloudFront es la puerta controlada.
Limita IAM al bucket y prefijo necesarios
Crea credenciales IAM que solo puedan leer y escribir en la ruta de medios de WordPress. IAM significa gestión de identidades y accesos: define quién puede entrar en AWS y qué puede hacer. En la consola busca IAM, entra en Usuarios y crea un usuario técnico como wordpress-media-prod.
No le asignes AmazonS3FullAccess. Esa política permite administrar todos los buckets de la cuenta, no solo el de esta web. Para un plugin que no admite roles, crea una clave de acceso para ese usuario y guárdala en un gestor de contraseñas o como variable de entorno del servidor.
La política siguiente permite listar únicamente el prefijo produccion/uploads/, y leer, subir y borrar archivos dentro de él. Sustituye NOMBRE-DEL-BUCKET por el nombre exacto del bucket. Si usas otra ruta, cambia también ambas apariciones de produccion/uploads/.
Copia una política IAM mínima
Pega esta política en IAM y adapta solo el bucket y el prefijo. Ve a IAM > Políticas > Crear política > JSON, borra el contenido y pega este bloque. Después pulsa Siguiente, llámala WordPressMediaProdPolicy y asígnala al usuario técnico.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListOnlyWordPressPrefix",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::NOMBRE-DEL-BUCKET",
"Condition": {
"StringLike": {
"s3:prefix": ["produccion/uploads/"]
}
}
},
{
"Sid": "ManageWordPressMediaObjects",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::NOMBRE-DEL-BUCKET/produccion/uploads/"
}
]
}
Version indica el formato de política. Statement contiene las reglas, Effect: Allow autoriza, Action define acciones y Resource limita el lugar. La condición de ListBucket evita que el usuario enumere rutas ajenas dentro del mismo bucket.
Guarda credenciales fuera del panel
Define las claves de AWS en wp-config.php si tu servidor permite editarlo. Añade estas líneas antes de la frase /* That's all, stop editing! */, sustituyendo cada valor. No pegues claves en el tema, en un plugin propio ni en un repositorio Git.
php
define( 'AS3CF_SETTINGS', serialize( array(
'provider' => 'aws',
'access-key-id' => 'TU_ACCESS_KEY_ID',
'secret-access-key' => 'TU_SECRET_ACCESS_KEY'
) ) );
Algunos alojamientos gestionados bloquean la edición de wp-config.php o permiten variables de entorno. En ese caso, usa el método documentado por el plugin, pero elimina las credenciales del panel de WordPress si ya quedan definidas en el servidor.
Como especialistas en mantenimiento WordPress para empresas, profesionales y tiendas online, hemos visto casos en que una clave IAM se dejó dentro de un plugin de código subido a Git: al rotarla, las nuevas subidas fallaron hasta actualizar el servidor y el sitio mostró errores de permisos verificables en el registro.
Conecta WordPress con S3 y CloudFront
Instala un plugin de offload y prueba una sola imagen antes de migrar la biblioteca. WP Offload Media, de Delicious Brains, es una opción conocida para conectar WordPress con Amazon S3. La edición gratuita puede servir para nuevas subidas según sus funciones vigentes, pero la migración masiva de medios existentes suele requerir una licencia Pro o una alternativa que debes probar en staging.
En Plugins > Añadir nuevo, busca el plugin elegido, instálalo y actívalo. En su pantalla de ajustes selecciona AWS, indica región, bucket y el prefijo produccion/uploads/. Si reconoce las constantes de wp-config.php, no escribas de nuevo las claves en el panel.
La recomendación directa es probar primero nuevas subidas con S3 y CloudFront, mantener el original local y migrar archivos históricos después. Excepto en sitios muy pequeños, copiar toda la biblioteca sin una prueba de URL, miniaturas y caché convierte un cambio reversible en una incidencia difícil de localizar.
Configura el dominio de entrega
Indica a WordPress que sirva las imágenes mediante el dominio de CloudFront. En los ajustes del plugin, activa el uso de CDN o dominio personalizado e introduce el dominio de distribución de CloudFront sin https:// si el campo lo pide. Guarda y sube una imagen llamada, por ejemplo, prueba-s3-julio.jpg.
Abre la imagen en la biblioteca y pulsa Copiar URL. La dirección debe contener tu dominio de CloudFront o media.tudominio.es, no la ruta local https://tudominio.es/wp-content/uploads/. Abre esa URL en una ventana privada y confirma que el navegador no muestra error 403.
Si usarás media.tudominio.es, crea un registro CNAME en tu proveedor DNS hacia el dominio CloudFront. Solicita el certificado en AWS Certificate Manager en la región requerida por CloudFront, normalmente Norte de Virginia para certificados de distribución, y asígnalo a la distribución.
Ajusta caché sin ocultar errores
Vacía las capas de caché después de cambiar URLs de medios. Purga la caché del plugin de WordPress, la caché del hosting y la de CloudFront si ya hubo archivos servidos con una configuración incorrecta. Haz las pruebas en ventana privada, porque el navegador también guarda imágenes durante horas o días.
En LiteSpeed Cache entra en LiteSpeed Cache > Toolbox y usa la purga total cuando sea necesario. No borres caché cada vez que subas una foto normal: hazlo durante el cambio inicial y cuando sustituyas un archivo manteniendo exactamente el mismo nombre.
Si gestionas una web crítica y quieres que revisemos la arquitectura, permisos y pruebas antes de mover medios, el mantenimiento WordPress profesional permite hacer el cambio con una ventana de reversión definida y sin abrir el bucket al público.
Resuelve los errores de acceso antes de iniciar la migración masiva. Cuando una imagen muestra AccessDenied, identifica primero si el error procede de la URL de S3 o de CloudFront: en una distribución con bucket privado, CloudFront necesita un control de acceso al origen y una política de bucket que permita leer los objetos solicitados. Si AWS devuelve InvalidAccessKeyId o SignatureDoesNotMatch, revisa que la clave esté activa, que el secreto corresponda a esa clave y que el usuario IAM tenga permisos sobre el bucket y prefijo configurados. Si las URLs no se reescriben, confirma que el plugin está activo, que el bucket, la región y el dominio CDN coinciden con la configuración real, y que la imagen fue subida o migrada mediante el plugin.
Configura CORS solo cuando JavaScript necesite leer imágenes desde otro dominio, por ejemplo con canvas; para mostrar una imagen normal mediante una etiqueta <img> no suele ser la causa del problema.
Migra y valida los archivos históricos
Migra la biblioteca por lotes y conserva los medios locales hasta verificar cada tipo de imagen. Las nuevas subidas no significan que WordPress haya movido lo que ya existía. Los adjuntos antiguos pueden seguir en wp-content/uploads, aunque las imágenes nuevas ya viajen correctamente al bucket.
Si tienes WP Offload Media Pro, usa la herramienta de migración en un lote pequeño, por ejemplo entre 20 y 50 adjuntos. Revisa el registro, abre las URLs de esos archivos y solo entonces aumenta el lote. Esta fase tarda más de lo que parece con miles de miniaturas, porque cada original puede tener entre 3 y 15 tamaños derivados.
Las alternativas gratuitas con WP-CLI o scripts pueden servir a equipos técnicos, pero exigen pruebas previas en staging. No ejecutes un comando de sincronización que borre destino u origen sin leer sus opciones. --delete es una orden peligrosa si la ruta está mal escrita.
Comprueba contenido y tamaños responsive
Valida imágenes nuevas y antiguas en páginas reales, no solo en la biblioteca. Abre las 15 a 25 URLs que guardaste al principio y revisa una entrada antigua, una página de servicios, una ficha de WooCommerce, una galería y una imagen destacada. En cada página pulsa F12, abre Red, filtra por Img y confirma que las solicitudes devuelven 200.
Inspecciona el atributo srcset. Es la lista de tamaños que WordPress entrega al navegador para que un móvil descargue una imagen menor. Comprueba que las rutas de src, srcset y, si existe, source para WebP o AVIF usan el dominio configurado.
Un caso habitual: una web corporativa validó la portada y borró los originales locales, pero sus artículos de 2019 tenían URLs escritas a mano dentro del editor. El resultado fue una mezcla de imágenes nuevas correctas y fotos históricas con 404. Busca en la base de datos o con un rastreador interno las URLs que aún contengan /wp-content/uploads/ antes de borrar nada.
Define el rollback antes de limpiar
Escribe un plan de vuelta atrás antes de activar el borrado local. Si aparecen errores masivos, desactiva primero la opción de servir desde S3 o CDN en el plugin. Después purga caché y verifica que WordPress vuelve a entregar los archivos desde la carpeta local que conservaste.
Guarda la fecha de la migración, el nombre del bucket, el prefijo y la copia de uploads asociada. Mantén el original local al menos entre 14 y 30 días, según el ritmo de publicación y el riesgo del proyecto. Cuando termines, prueba restaurar un archivo concreto desde la copia, no des por buena la copia solo porque existe.
Puedes activar la eliminación de archivos locales solo si todas las pruebas pasan, las copias están verificadas y el equipo sabe revertir el ajuste. En sitios con mucha edición de fotos, conservar una réplica local puede costar más disco, pero reduce el tiempo de recuperación ante una mala configuración.
Preguntas frecuentes
¿Necesito un bucket S3 público?
No. Un bucket privado con CloudFront y control de acceso al origen permite servir imágenes sin abrir el almacenamiento a todo Internet. Mantén activado el bloqueo de acceso público salvo una necesidad documentada.
¿S3 acelera por sí solo mi WordPress?
No necesariamente. S3 libera disco y transferencia del hosting, pero CloudFront es la capa que suele reducir latencia para visitas de distintas zonas. Si no hay CDN, el archivo sigue saliendo desde una región concreta de AWS.
¿Puedo migrar imágenes existentes gratis?
Depende del plugin y de su versión vigente. Muchas ediciones gratuitas gestionan nuevas subidas, mientras la migración masiva exige licencia Pro o un proceso técnico probado en staging. Haz primero un lote de entre 20 y 50 archivos.
¿Por qué recibo AccessDenied en CloudFront?
Suele ocurrir porque el bucket sigue privado y CloudFront no tiene permiso de origen, o porque el objeto está fuera del prefijo autorizado. Revisa el control de acceso al origen, la política del bucket y que la URL apunte a la ruta correcta.
¿Cuándo puedo borrar las imágenes locales?
Solo después de validar URLs nuevas y antiguas, srcset, WebP o AVIF, caché y una restauración desde copia. Conserva los originales locales entre 14 y 30 días en una migración de producción.
Mantén una entrega de medios verificable
Revisa S3, CloudFront y WordPress como un conjunto, no como piezas aisladas. Cada mes comprueba el gasto de AWS, errores 403 o 404, tamaño del bucket y estado de las copias. Configura alertas de presupuesto para detectar un aumento anormal de transferencia o solicitudes.
Renueva las credenciales IAM cuando cambie la persona responsable, elimina usuarios que ya no se usan y conserva MFA en la cuenta administrativa. Las credenciales del plugin deben poder leer y escribir solo su prefijo, no administrar todos los recursos de Amazon S3.
Un offload bien hecho mantiene el bucket privado, entrega por CloudFront, conserva un rollback temporal y valida los medios publicados. Esa combinación protege la continuidad de la web mientras reduces la dependencia del disco y ancho de banda del hosting.
⚠️ Si una imagen deja de cargar semanas después, no borres objetos ni cambies permisos por intuición. Comprueba primero la URL, el código HTTP, la caché y el registro del plugin para localizar la capa que falla.