Tu propio almacenamiento + CDN
Conecta tu propio almacenamiento de objetos y tu propia CDN en los planes API Velocity y Momentum: configuración por proveedor, permisos mínimos, la comprobación de la conexión y qué ocurre al cambiar de modo.
Disponible en: los planes API Velocity y Momentum. No disponible en Ignite (no tiene CDN), en el sandbox para desarrolladores (los archivos del sandbox son temporales) ni en los planes de WordPress (usan la CDN gestionada de smallPict).
En resumen: en el modo BYO, smallPict escribe tus originales y tus imágenes optimizadas en tu bucket, y tu CDN las sirve. El almacenamiento y la CDN siempre se conectan juntos: no puedes traer uno sin el otro.
Qué es BYO
Velocity y Momentum tienen dos modos de entrega. Eliges uno en Panel → CDN y almacenamiento.
- Gestionado (el predeterminado): smallPict guarda tus originales en su almacenamiento cifrado (se mueven a un archivo a largo plazo después de 90 días) y sirve las imágenes optimizadas desde
cdn.smallpict.app. No hay nada que configurar. - Usa tu propio almacenamiento + CDN (BYO): conectas un bucket compatible con S3 en tu propia cuenta y una CDN en tu propia cuenta. Cada trabajo nuevo escribe el original y el archivo optimizado en tu bucket, y la API devuelve URL en el dominio de tu CDN.
La regla de ir juntos existe porque smallPict tiene que poder hacer las dos mitades de la entrega: escribir archivos y eliminar de la caché las copias obsoletas. Un bucket sin CDN dejaría las purgas de caché sin destino; una CDN sin bucket no tendría nada que servir.
Gestionado frente a BYO
| Gestionado (predeterminado) | Usa tu propio almacenamiento + CDN | |
|---|---|---|
| Originales | Almacenamiento cifrado de smallPict | originals/<job_id>/<file> en tu bucket |
| Archivos optimizados | Servidos desde cdn.smallpict.app | optimized/<job_id>.<ext> en tu bucket, servidos desde el dominio de tu CDN |
| Cuota de almacenamiento | Velocity 50 GB, Momentum 100 GB | No se cuenta. Pagas a tu proveedor de almacenamiento. |
| Ancho de banda de la CDN | Velocity 30 GB/mes, Momentum 200 GB/mes | No se cuenta. Pagas a tu proveedor de CDN. |
| Transformaciones | Cuentan para tu plan | Cuentan para tu plan |
| Copia que guarda smallPict | Sí, mientras tu cuenta esté activa | Ninguna. Solo la subida temporal de procesamiento, que se elimina en un plazo de 24 horas. |
| Purga de caché | Automática | Automática, a través de la API de tu CDN |
| Rendimiento, dominio y costes de la CDN | smallPict | Tú. smallPict no es responsable del rendimiento, los dominios ni las facturas de tu CDN. |
Proveedores compatibles
Almacenamiento (disponible hoy): Amazon S3, Cloudflare R2, Google Cloud Storage (interoperabilidad S3), Alibaba Cloud OSS, Tencent Cloud COS, DigitalOcean Spaces, SumoPod Storage, MinIO y cualquier otro servicio compatible con S3 mediante un endpoint personalizado (por ejemplo Hetzner, Vultr o Wasabi).
CDN (disponible hoy): Cloudflare y Amazon CloudFront.
Previsto: Azure Blob Storage y otras CDN. Puedes solicitar acceso anticipado en la página Proveedores en la nube.
Antes de empezar
- Tienes el plan API Velocity o Momentum y has iniciado sesión como administrador de la cuenta.
- Tienes un bucket y una CDN que sirve archivos de ese bucket por HTTPS.
- El endpoint de almacenamiento es accesible desde internet por HTTPS. Los endpoints privados, internos o solo HTTP se rechazan.
- Has creado claves restringidas para smallPict (consulta Permisos mínimos más abajo). No uses las claves raíz ni de administrador de tu cuenta.
Después abre Panel → CDN y almacenamiento, elige Usa tu propio almacenamiento + CDN, completa las dos partes y selecciona Guardar almacenamiento + CDN. smallPict ejecuta la comprobación de la conexión (descrita más abajo) y solo te cambia a BYO si se supera.
Guías de configuración
A. Amazon S3 + Amazon CloudFront
- Crea el bucket en la región que quieras, por ejemplo
my-imagesenap-southeast-1. Deja activado Block Public Access. - Crea una distribución de CloudFront con el bucket como origen. Usa Origin access control (OAC) para que CloudFront pueda leer el bucket mientras este sigue siendo privado, y aplica la política de bucket que te ofrece CloudFront.
- Opcional: tu propio dominio. Añade a la distribución un nombre de dominio alternativo (por ejemplo
images.example.com) y un certificado, y apunta un registro DNS a la distribución. - Crea un usuario (o rol) de IAM para el almacenamiento con esta política:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::my-images/*" } ]}- Crea un usuario de IAM para CloudFront (puede ser el mismo usuario) con esta política.
cloudfront:GetDistributiones opcional; con él, smallPict puede detectar el dominio de la distribución cuando dejas vacío el dominio de la CDN.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudfront:CreateInvalidation", "cloudfront:GetDistribution" ], "Resource": "arn:aws:cloudfront::123456789012:distribution/E2QWRUHAPOMQZL" } ]}- En el panel:
- Proveedor de almacenamiento Amazon S3, bucket
my-images, regiónap-southeast-1, endpoint vacío (se usa el endpoint estándar de la región), y el access key ID y el secreto del almacenamiento. - CDN Amazon CloudFront, el Distribution ID (por ejemplo
E2QWRUHAPOMQZL), el access key ID y el secreto de CloudFront y, opcionalmente, el dominio de la CDN (https://images.example.com). Deja el dominio vacío para usar el dominio*.cloudfront.netpropio de la distribución.
- Proveedor de almacenamiento Amazon S3, bucket
B. Cloudflare R2 + Cloudflare
- Crea un bucket de R2, por ejemplo
my-images. - Conecta un dominio personalizado al bucket (R2 → tu bucket → Settings → Custom Domains), por ejemplo
images.example.com, en una zona de la misma cuenta de Cloudflare. Las solicitudes a ese dominio pasan por la caché de Cloudflare. No uses la URL de desarrollor2.deven producción. - Crea un token de API de R2 (R2 → Manage API tokens) con Object Read & Write, limitado solo a este bucket. Copia el Access Key ID y el Secret Access Key que muestra.
- Crea un token de API de Cloudflare (My Profile → API Tokens) para la zona con Zone → Cache Purge → Purge. Zone → Zone → Read es opcional.
- En el panel:
- Proveedor de almacenamiento Cloudflare R2, bucket
my-images, endpointhttps://<account_id>.r2.cloudflarestorage.com(se muestra en los detalles de la API de S3 de tu bucket), regiónauto, y el Access Key ID y el Secret Access Key de R2. - CDN Cloudflare, el Zone ID (página Overview del dominio, sección API), el token de API y el dominio de la CDN
https://images.example.com.
- Proveedor de almacenamiento Cloudflare R2, bucket
C. Google Cloud Storage + Cloudflare
Google Cloud Storage se conecta mediante su API XML compatible con S3, con claves HMAC.
- Crea el bucket, por ejemplo
my-images. - Crea una cuenta de servicio y concédele Storage Object User (
roles/storage.objectUser) solo en este bucket. - Crea una clave HMAC para la cuenta de servicio: Cloud Storage → Settings → Interoperability → Create a key for a service account. Copia el ID de acceso y el secreto.
- Haz que tu CDN pueda leer los archivos optimizados. Cloudflare obtiene los archivos de Cloud Storage por HTTPS, así que los objetos de
optimized/deben poder leerse públicamente. Con el acceso uniforme a nivel de bucket, conceder aallUsersel rol Storage Object Viewer hace legible todo el bucket, incluidooriginals/. Si tus originales deben seguir siendo privados, coloca delante una capa que autentique (por ejemplo un Cloudflare Worker que firme las solicitudes al bucket). - Apunta un registro DNS de Cloudflare con proxy a Cloud Storage, por ejemplo
images.example.com. Puedes nombrar el bucket como el nombre de host y usar un CNAME con proxy haciac.storage.googleapis.com, o usar una Origin Rule de Cloudflare que envíe las solicitudes astorage.googleapis.comcon el nombre del bucket al principio de la ruta. - Crea un token de API de Cloudflare para la zona con Zone → Cache Purge → Purge (Zone → Zone → Read opcional).
- En el panel: proveedor de almacenamiento Google Cloud Storage, bucket, endpoint
https://storage.googleapis.com, regiónauto, el ID de acceso y el secreto HMAC; CDN Cloudflare, Zone ID, token de API y dominio de la CDNhttps://images.example.com.
D. MinIO o cualquier almacenamiento compatible con S3 + Cloudflare
Esto cubre MinIO y servicios compatibles con S3 como Hetzner, Wasabi, Vultr, SumoPod, Alibaba Cloud OSS, Tencent Cloud COS y DigitalOcean Spaces.
| Proveedor | Qué elegir en el panel | Endpoint | Notas |
|---|---|---|---|
| MinIO | MinIO | Tu servidor, p. ej. https://minio.example.com | Solicitudes path-style activadas. El servidor debe ser accesible desde internet por HTTPS. |
| Hetzner Object Storage | Personalizado compatible con S3 | https://<location>.your-objectstorage.com | |
| Wasabi | Personalizado compatible con S3 | https://s3.<region>.wasabisys.com | |
| Vultr Object Storage | Personalizado compatible con S3 | https://<region>.vultrobjects.com | |
| SumoPod Storage | SumoPod Storage | En tu panel de almacenamiento de SumoPod | Path-style activado por defecto. |
| Alibaba Cloud OSS | Alibaba Cloud OSS | https://oss-<region>.aliyuncs.com | Solo estilo virtual-hosted. |
| Tencent Cloud COS | Tencent Cloud COS | https://cos.<region>.myqcloud.com | El nombre del bucket incluye tu APPID, p. ej. my-images-1250000000. |
| DigitalOcean Spaces | DigitalOcean Spaces | https://<region>.digitaloceanspaces.com |
- Crea el bucket y una clave limitada a ese bucket con permisos de put, get y delete sobre los objetos (consulta Permisos mínimos más abajo).
- Haz que tu CDN pueda leer
optimized/, por ejemplo con una política de bucket que permitas3:GetObjectanónimo solo enoptimized/*. En MinIO:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "*" ] }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::my-images/optimized/*" ] } ]}- Pon Cloudflare delante del bucket: un registro DNS con proxy para
images.example.comque apunte al host público del bucket. Si el proveedor necesita su propio nombre de host en la solicitud, añade una Origin Rule de Cloudflare que reescriba la cabecera Host (y, en hosts path-style, añada el nombre del bucket a la ruta). - Crea un token de API de Cloudflare para la zona con Zone → Cache Purge → Purge (Zone → Zone → Read opcional).
- En el panel: elige el proveedor de la tabla, introduce el bucket, el endpoint, la región (
autosi el proveedor no tiene) y las claves; activa las solicitudes path-style donde la tabla lo indique; después CDN Cloudflare, Zone ID, token de API y dominio de la CDN.
Permisos mínimos
Da a smallPict claves que solo puedan hacer lo que necesita, en un único bucket.
| Proveedor | Permisos |
|---|---|
| Amazon S3 | s3:PutObject, s3:GetObject, s3:DeleteObject en arn:aws:s3:::<bucket>/* |
| Amazon CloudFront | cloudfront:CreateInvalidation en la distribución; cloudfront:GetDistribution opcional para poder detectar el dominio |
| Cloudflare R2 | Token de API de R2 con Object Read & Write, limitado al bucket |
| Cloudflare (CDN) | Token de API para la zona con Zone → Cache Purge → Purge; Zone → Zone → Read opcional |
| Google Cloud Storage | Clave HMAC para una cuenta de servicio con roles/storage.objectUser en el bucket |
| Alibaba Cloud OSS | Usuario RAM con oss:PutObject, oss:GetObject, oss:DeleteObject en el bucket |
| Tencent Cloud COS | Subusuario CAM con cos:PutObject, cos:GetObject, cos:DeleteObject en el bucket (el nombre del bucket incluye el APPID) |
| DigitalOcean Spaces | Clave de acceso de Spaces limitada al bucket con lectura, escritura y eliminación |
| MinIO / personalizado compatible con S3 | Put, get y delete en <bucket>/*; el endpoint debe ser HTTPS público |
La comprobación de la conexión
Cada vez que guardas (y cuando seleccionas Repetir comprobación), smallPict comprueba toda la conexión antes de usarla:
- Almacenamiento: escribe un pequeño archivo de prueba en
.smallpict-probe/de tu bucket, lo vuelve a leer y lo elimina. - Cloudflare: envía a tu zona una purga de prueba de una sola URL.
- CloudFront: crea una invalidación de prueba para una ruta
/.smallpict-probe/.... Cuenta para tus rutas de invalidación de CloudFront del mes.
Si falla cualquier paso, no se cambia nada. El panel muestra el motivo junto al campo afectado, por ejemplo el nombre del bucket o el token de API. La comprobación de la conexión está limitada a 5 intentos por minuto.
Acceso de tu CDN al bucket
optimized/debe poder leerlo tu CDN: o bien lectura pública en ese prefijo, o bien acceso de origen de la CDN a un bucket privado (Origin access control de CloudFront o un dominio personalizado de R2).originals/puede seguir siendo privado. Tu CDN nunca lo necesita.- CORS solo hace falta si los navegadores obtienen las imágenes entre orígenes desde JavaScript (por ejemplo con
fetch()o un canvas). Las etiquetas<img>normales no lo necesitan. Si lo necesitas, permiteGETyHEADdesde el origen de tu sitio.
Estructura de objetos y URL
| Qué | Clave en tu bucket | URL |
|---|---|---|
| Original | originals/<job_id>/<file> | No se sirve |
| Archivo optimizado | optimized/<job_id>.<ext> | <cdn_domain>/optimized/<job_id>.<ext> |
El dominio de la CDN puede incluir un prefijo de ruta, por ejemplo https://example.com/images; la URL queda entonces https://example.com/images/optimized/<job_id>.<ext>.
Cabeceras de caché
Los archivos optimizados se escriben con Cache-Control: public, max-age=31536000, immutable. Cada trabajo recibe una clave única, así que un resultado nuevo siempre tiene una URL nueva y rara vez hace falta purgar. Evita que las reglas de caché de tu CDN sustituyan esta cabecera por una duración más corta.
Purga de caché
- Las solicitudes de purga hechas a través de la API (
POST /v1/purge) van a tu CDN, agrupadas en lotes. - En Cloudflare, los archivos se purgan por URL. «Purge all» purga solo tu host de entrega y tu prefijo de ruta, no toda tu zona.
- En CloudFront, los archivos se purgan con invalidaciones. «Purge all» crea una invalidación
/*. AWS factura a tu cuenta las rutas de invalidación que superen la asignación mensual gratuita de CloudFront.
Cambiar de modo
Cambiar de modo no mueve los archivos existentes. Los archivos ya entregados conservan sus URL actuales; solo los trabajos nuevos usan el nuevo modo.
- Gestionado → BYO: los trabajos nuevos van a tu bucket y los sirve tu CDN. Los archivos que ya están en
cdn.smallpict.appse quedan allí. - BYO → gestionado: los trabajos nuevos vuelven a usar el almacenamiento y la CDN gestionados. Tus ajustes y claves de BYO siguen guardados pero sin usar, para que puedas volver sin introducirlos de nuevo, hasta que selecciones Desconectar.
- Desconectar: elimina las claves y los ajustes de BYO guardados y te devuelve al modo gestionado. Los archivos de tu bucket no se tocan.
Cuando algo falla
- Si smallPict no puede escribir en tu bucket, lo reintenta y después marca el trabajo como fallido con un motivo que puedes leer en la respuesta de la API.
- El panel muestra el último error y cuándo ocurrió, con un botón Repetir comprobación.
- Recibes un correo por incidente, no uno por cada trabajo fallido.
- smallPict nunca recurre al almacenamiento gestionado. Tus archivos nunca se guardan en un lugar que no hayas elegido.
Seguridad
- Las claves se guardan en un almacén de secretos cifrado. Nunca se vuelven a mostrar, la API nunca las devuelve y nunca se escriben en los registros.
- Para rotar una clave, introduce la nueva y guarda; la comprobación de la conexión se ejecuta con la clave nueva. Deja vacío un campo de clave para conservar la clave guardada.
- Los endpoints de almacenamiento y de CDN deben usar HTTPS. Se rechazan los endpoints que resuelven a direcciones privadas, de loopback, link-local u otras direcciones internas.
- Usa claves separadas y restringidas para smallPict, y revócalas en la consola de tu proveedor si dejas de usar BYO.