Eigen opslag + CDN
Koppel je eigen objectopslag en je eigen CDN op de API-abonnementen Velocity en Momentum: instellen per provider, minimale machtigingen, de verbindingscontrole en wat er gebeurt als je van modus wisselt.
Beschikbaar op: de API-abonnementen Velocity en Momentum. Niet beschikbaar op Ignite (dat heeft geen CDN), in de ontwikkelaarssandbox (sandboxbestanden zijn tijdelijk) en op WordPress-abonnementen (die gebruiken het beheerde smallPict-CDN).
Kort gezegd: In BYO-modus schrijft smallPict je originelen en geoptimaliseerde afbeeldingen naar jouw bucket, en jouw CDN levert ze uit. Opslag en CDN worden altijd samen gekoppeld: je kunt het een niet zonder het ander meebrengen.
Wat BYO is
Velocity en Momentum hebben twee leveringsmodi. Je kiest er een in Dashboard → CDN en opslag.
- Beheerd (de standaard): smallPict bewaart je originelen in zijn versleutelde opslag (na 90 dagen verplaatst naar langetermijnarchief) en levert geoptimaliseerde afbeeldingen vanaf
cdn.smallpict.app. Niets in te stellen. - Eigen opslag + CDN (BYO): je koppelt een S3-compatibele bucket in je eigen account en een CDN in je eigen account. Elke nieuwe taak schrijft het origineel en het geoptimaliseerde bestand naar je bucket, en de API geeft URL’s op je CDN-domein terug.
De koppelregel bestaat omdat smallPict beide helften van de levering moet kunnen uitvoeren: bestanden schrijven en verouderde kopieën uit de cache verwijderen. Een bucket zonder CDN zou cachepurges nergens naartoe kunnen sturen; een CDN zonder bucket zou niets te leveren hebben.
Beheerd vs. BYO
| Beheerd (standaard) | Eigen opslag + CDN | |
|---|---|---|
| Originelen | Versleutelde opslag van smallPict | originals/<job_id>/<file> in je bucket |
| Geoptimaliseerde bestanden | Geleverd vanaf cdn.smallpict.app | optimized/<job_id>.<ext> in je bucket, geleverd vanaf je CDN-domein |
| Opslagquotum | Velocity 50 GB, Momentum 100 GB | Telt niet mee. Je betaalt je opslagprovider. |
| CDN-bandbreedte | Velocity 30 GB/maand, Momentum 200 GB/maand | Telt niet mee. Je betaalt je CDN-provider. |
| Transformaties | Tellen mee voor je abonnement | Tellen mee voor je abonnement |
| Kopie bewaard door smallPict | Ja, zolang je account actief is | Geen. Alleen de tijdelijke upload voor verwerking, die binnen 24 uur wordt verwijderd. |
| Cachepurge | Automatisch | Automatisch, via de API van je CDN |
| CDN-prestaties, domein en kosten | smallPict | Jij. smallPict is niet verantwoordelijk voor de prestaties, domeinen of rekeningen van je CDN. |
Ondersteunde providers
Opslag (nu beschikbaar): Amazon S3, Cloudflare R2, Google Cloud Storage (S3-interoperabiliteit), Alibaba Cloud OSS, Tencent Cloud COS, DigitalOcean Spaces, SumoPod Storage, MinIO en elke andere S3-compatibele dienst via een aangepast endpoint (bijvoorbeeld Hetzner, Vultr of Wasabi).
CDN (nu beschikbaar): Cloudflare en Amazon CloudFront.
Gepland: Azure Blob Storage en andere CDN’s. Je kunt vroege toegang aanvragen op de pagina Cloudproviders.
Voordat je begint
- Je zit op API Velocity of Momentum en bent ingelogd als accountbeheerder.
- Je hebt een bucket, en een CDN dat bestanden uit die bucket via HTTPS levert.
- Het opslag-endpoint is via HTTPS bereikbaar vanaf internet. Privé-, interne en gewone HTTP-endpoints worden geweigerd.
- Je hebt beperkte sleutels voor smallPict aangemaakt (zie Minimale machtigingen hieronder). Gebruik niet de root- of beheerderssleutels van je account.
Open daarna Dashboard → CDN en opslag, kies Eigen opslag + CDN, vul beide delen in en selecteer Opslag + CDN opslaan. smallPict voert de verbindingscontrole uit (hieronder beschreven) en schakelt je alleen over naar BYO als die slaagt.
Installatiehandleidingen
A. Amazon S3 + Amazon CloudFront
- Maak de bucket aan in de gewenste regio, bijvoorbeeld
my-imagesinap-southeast-1. Laat Block Public Access aan staan. - Maak een CloudFront-distributie aan met de bucket als origin. Gebruik Origin access control (OAC) zodat CloudFront de bucket kan lezen terwijl die privé blijft, en pas het bucketbeleid toe dat CloudFront je aanbiedt.
- Optioneel: je eigen domein. Voeg een alternatieve domeinnaam (bijvoorbeeld
images.example.com) en een certificaat toe aan de distributie, en laat een DNS-record naar de distributie wijzen. - Maak een IAM-gebruiker (of rol) voor opslag aan met dit beleid:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::my-images/*" } ]}- Maak een IAM-gebruiker voor CloudFront aan (dit mag dezelfde gebruiker zijn) met dit beleid.
cloudfront:GetDistributionis optioneel; daarmee kan smallPict het domein van de distributie detecteren als je het CDN-domein leeg laat.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudfront:CreateInvalidation", "cloudfront:GetDistribution" ], "Resource": "arn:aws:cloudfront::123456789012:distribution/E2QWRUHAPOMQZL" } ]}- In het dashboard:
- Opslagprovider Amazon S3, bucket
my-images, regioap-southeast-1, endpoint leeg (het standaard-endpoint van de regio wordt gebruikt), en de access key ID en het secret voor opslag. - CDN Amazon CloudFront, de distributie-ID (bijvoorbeeld
E2QWRUHAPOMQZL), de access key ID en het secret voor CloudFront, en optioneel het CDN-domein (https://images.example.com). Laat het domein leeg om het eigen*.cloudfront.net-domein van de distributie te gebruiken.
- Opslagprovider Amazon S3, bucket
B. Cloudflare R2 + Cloudflare
- Maak een R2-bucket aan, bijvoorbeeld
my-images. - Koppel een aangepast domein aan de bucket (R2 → je bucket → Settings → Custom Domains), bijvoorbeeld
images.example.com, op een zone in hetzelfde Cloudflare-account. Verzoeken naar dat domein gaan via de Cloudflare-cache. Gebruik de ontwikkel-URLr2.devniet voor productie. - Maak een R2 API-token aan (R2 → Manage API tokens) met Object Read & Write, beperkt tot alleen deze bucket. Kopieer de Access Key ID en Secret Access Key die worden getoond.
- Maak een Cloudflare API-token aan (My Profile → API Tokens) voor de zone met Zone → Cache Purge → Purge. Zone → Zone → Read is optioneel.
- In het dashboard:
- Opslagprovider Cloudflare R2, bucket
my-images, endpointhttps://<account_id>.r2.cloudflarestorage.com(staat bij de S3 API-gegevens van je bucket), regioauto, en de R2 Access Key ID en Secret Access Key. - CDN Cloudflare, de zone-ID (Overview-pagina van het domein, onderdeel API), het API-token en het CDN-domein
https://images.example.com.
- Opslagprovider Cloudflare R2, bucket
C. Google Cloud Storage + Cloudflare
Google Cloud Storage wordt gekoppeld via de S3-compatibele XML API met HMAC-sleutels.
- Maak de bucket aan, bijvoorbeeld
my-images. - Maak een serviceaccount aan en geef het Storage Object User (
roles/storage.objectUser) op alleen deze bucket. - Maak een HMAC-sleutel aan voor het serviceaccount: Cloud Storage → Settings → Interoperability → Create a key for a service account. Kopieer de access-ID en het secret.
- Maak de geoptimaliseerde bestanden leesbaar voor je CDN. Cloudflare haalt bestanden via HTTPS op uit Cloud Storage, dus objecten onder
optimized/moeten openbaar leesbaar zijn. Met uniforme toegang op bucketniveau maakt het toekennen van de rol Storage Object Viewer aanallUsersde hele bucket leesbaar, inclusieforiginals/. Als je originelen privé moeten blijven, zet er dan een authenticerende laag voor (bijvoorbeeld een Cloudflare Worker die verzoeken aan de bucket ondertekent). - Laat een geproxied Cloudflare-DNS-record naar Cloud Storage wijzen, bijvoorbeeld
images.example.com. Geef de bucket de naam van de hostnaam en gebruik een geproxiede CNAME naarc.storage.googleapis.com, of gebruik een Cloudflare Origin Rule die verzoeken naarstorage.googleapis.comstuurt met de bucketnaam aan het begin van het pad. - Maak een Cloudflare API-token aan voor de zone met Zone → Cache Purge → Purge (Zone → Zone → Read optioneel).
- In het dashboard: opslagprovider Google Cloud Storage, bucket, endpoint
https://storage.googleapis.com, regioauto, de HMAC-access-ID en het secret; CDN Cloudflare, zone-ID, API-token en CDN-domeinhttps://images.example.com.
D. MinIO of andere S3-compatibele opslag + Cloudflare
Dit geldt voor MinIO en S3-compatibele diensten zoals Hetzner, Wasabi, Vultr, SumoPod, Alibaba Cloud OSS, Tencent Cloud COS en DigitalOcean Spaces.
| Provider | Kies in het dashboard | Endpoint | Opmerkingen |
|---|---|---|---|
| MinIO | MinIO | Je server, bijv. https://minio.example.com | Path-style-verzoeken aan. De server moet via HTTPS bereikbaar zijn vanaf internet. |
| Hetzner Object Storage | Aangepast S3-compatibel | https://<location>.your-objectstorage.com | |
| Wasabi | Aangepast S3-compatibel | https://s3.<region>.wasabisys.com | |
| Vultr Object Storage | Aangepast S3-compatibel | https://<region>.vultrobjects.com | |
| SumoPod Storage | SumoPod Storage | Uit je SumoPod-opslagdashboard | Path-style standaard aan. |
| Alibaba Cloud OSS | Alibaba Cloud OSS | https://oss-<region>.aliyuncs.com | Alleen virtual-hosted-stijl. |
| Tencent Cloud COS | Tencent Cloud COS | https://cos.<region>.myqcloud.com | De bucketnaam bevat je APPID, bijv. my-images-1250000000. |
| DigitalOcean Spaces | DigitalOcean Spaces | https://<region>.digitaloceanspaces.com |
- Maak de bucket aan en een sleutel die beperkt is tot die bucket, met put, get en delete op objecten (zie Minimale machtigingen hieronder).
- Maak
optimized/leesbaar voor je CDN, bijvoorbeeld met een bucketbeleid dat anoniemes3:GetObjectalleen opoptimized/*toestaat. Op MinIO:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "*" ] }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::my-images/optimized/*" ] } ]}- Zet Cloudflare voor de bucket: een geproxied DNS-record voor
images.example.comdat naar de openbare host van de bucket wijst. Als de provider zijn eigen hostnaam in het verzoek nodig heeft, voeg dan een Cloudflare Origin Rule toe die de Host-header herschrijft (en bij path-style-hosts de bucketnaam aan het pad toevoegt). - Maak een Cloudflare API-token aan voor de zone met Zone → Cache Purge → Purge (Zone → Zone → Read optioneel).
- In het dashboard: kies de provider uit de tabel, vul de bucket, het endpoint, de regio (
autoals de provider er geen heeft) en de sleutels in; zet path-style-verzoeken aan waar de tabel dat aangeeft; daarna CDN Cloudflare, zone-ID, API-token en CDN-domein.
Minimale machtigingen
Geef smallPict sleutels die alleen kunnen wat nodig is, op één bucket.
| Provider | Machtigingen |
|---|---|
| Amazon S3 | s3:PutObject, s3:GetObject, s3:DeleteObject op arn:aws:s3:::<bucket>/* |
| Amazon CloudFront | cloudfront:CreateInvalidation op de distributie; optioneel cloudfront:GetDistribution zodat het domein kan worden gedetecteerd |
| Cloudflare R2 | R2 API-token met Object Read & Write, beperkt tot de bucket |
| Cloudflare (CDN) | API-token voor de zone met Zone → Cache Purge → Purge; optioneel Zone → Zone → Read |
| Google Cloud Storage | HMAC-sleutel voor een serviceaccount met roles/storage.objectUser op de bucket |
| Alibaba Cloud OSS | RAM-gebruiker met oss:PutObject, oss:GetObject, oss:DeleteObject op de bucket |
| Tencent Cloud COS | CAM-subgebruiker met cos:PutObject, cos:GetObject, cos:DeleteObject op de bucket (de bucketnaam bevat de APPID) |
| DigitalOcean Spaces | Spaces-toegangssleutel beperkt tot de bucket, met lezen, schrijven en verwijderen |
| MinIO / aangepast S3-compatibel | Put, get en delete op <bucket>/*; het endpoint moet openbare HTTPS zijn |
De verbindingscontrole
Telkens wanneer je opslaat (en wanneer je Opnieuw controleren selecteert), controleert smallPict de hele verbinding voordat die wordt gebruikt:
- Opslag: schrijft een klein testbestand onder
.smallpict-probe/in je bucket, leest het terug en verwijdert het. - Cloudflare: stuurt één testpurge voor één URL naar je zone.
- CloudFront: maakt één testinvalidatie aan voor een pad
/.smallpict-probe/.... Die telt mee voor je CloudFront-invalidatiepaden van die maand.
Als een stap mislukt, wordt er niets overgeschakeld. Het dashboard toont de reden naast het betreffende veld, bijvoorbeeld de bucketnaam of het API-token. De verbindingscontrole is beperkt tot 5 pogingen per minuut.
Buckettoegang voor je CDN
optimized/moet leesbaar zijn voor je CDN: openbaar leesbaar op dat prefix, of CDN-origintoegang tot een privébucket (CloudFront origin access control of een aangepast R2-domein).originals/kan privé blijven. Je CDN heeft het nooit nodig.- CORS is alleen nodig als browsers de afbeeldingen cross-origin ophalen vanuit JavaScript (bijvoorbeeld
fetch()of een canvas). Gewone<img>-tags hebben het niet nodig. Als je het wel nodig hebt, sta danGETenHEADtoe vanaf de origin van je site.
Objectindeling en URL’s
| Wat | Sleutel in je bucket | URL |
|---|---|---|
| Origineel | originals/<job_id>/<file> | Niet geleverd |
| Geoptimaliseerd bestand | optimized/<job_id>.<ext> | <cdn_domain>/optimized/<job_id>.<ext> |
Het CDN-domein mag een padprefix bevatten, bijvoorbeeld https://example.com/images; de URL wordt dan https://example.com/images/optimized/<job_id>.<ext>.
Cacheheaders
Geoptimaliseerde bestanden worden geschreven met Cache-Control: public, max-age=31536000, immutable. Elke taak krijgt een unieke sleutel, dus een nieuw resultaat heeft altijd een nieuwe URL en purgen is zelden nodig. Zorg dat de cacheregels van je CDN deze header niet overschrijven met een kortere tijd.
Cachepurge
- Purgeverzoeken via de API (
POST /v1/purge) gaan gebundeld naar jouw CDN. - Bij Cloudflare worden bestanden per URL gepurged. "Alles purgen" purget alleen je leveringshost en padprefix, niet je hele zone.
- Bij CloudFront worden bestanden gepurged met invalidaties. "Alles purgen" maakt een invalidatie
/*aan. Invalidatiepaden boven de maandelijkse gratis hoeveelheid van CloudFront worden door AWS aan je account gefactureerd.
Van modus wisselen
Van modus wisselen verplaatst geen bestaande bestanden. Bestanden die al zijn geleverd, houden hun huidige URL’s; alleen nieuwe taken gebruiken de nieuwe modus.
- Beheerd → BYO: nieuwe taken gaan naar je bucket en worden door je CDN geleverd. Bestanden die al op
cdn.smallpict.appstaan, blijven daar. - BYO → beheerd: nieuwe taken gebruiken weer beheerde opslag en CDN. Je BYO-instellingen en sleutels blijven opgeslagen maar ongebruikt, zodat je terug kunt schakelen zonder ze opnieuw in te vullen, totdat je Ontkoppelen selecteert.
- Ontkoppelen: verwijdert de opgeslagen sleutels en BYO-instellingen en zet je terug op beheerd. Bestanden in je bucket worden niet aangeraakt.
Als er iets misgaat
- Als smallPict niet naar je bucket kan schrijven, probeert het opnieuw en laat het daarna de taak mislukken met een reden die je in het API-antwoord kunt lezen.
- Het dashboard toont de laatste fout en wanneer die optrad, met een knop Opnieuw controleren.
- Je krijgt één e-mail per incident, niet één per mislukte taak.
- smallPict valt nooit terug op beheerde opslag. Je bestanden worden nooit opgeslagen op een plek die je niet zelf hebt gekozen.
Beveiliging
- Sleutels worden bewaard in een versleutelde opslag voor geheimen. Ze worden nooit meer getoond, nooit door de API teruggegeven en nooit naar logs geschreven.
- Om een sleutel te roteren, vul je de nieuwe in en sla je op; de verbindingscontrole wordt met de nieuwe sleutel uitgevoerd. Laat een sleutelveld leeg om de opgeslagen sleutel te behouden.
- Opslag- en CDN-endpoints moeten HTTPS gebruiken. Endpoints die verwijzen naar privé-, loopback-, link-local- of andere interne adressen worden geweigerd.
- Gebruik aparte, beperkte sleutels voor smallPict en trek ze in via de console van je provider als je stopt met BYO.