|
| 1 | +--- |
| 2 | +title: Content Delivery Network (CDN) |
| 3 | +description: A comprehensive guide to using Zerops CDN to deliver your content globally with minimal latency. |
| 4 | +--- |
| 5 | + |
| 6 | +import Image from '/src/components/Image'; |
| 7 | + |
| 8 | +Zerops CDN is a global content delivery network that brings your static content closer to your users, resulting in faster load times and improved user experience. Built on Nginx and Cloudflare geo-steering technology, our CDN automatically routes users to the nearest server location based on their DNS request. |
| 9 | + |
| 10 | +## Key Benefits |
| 11 | + |
| 12 | +- **Global Reach**: Serve content from strategic locations across the world |
| 13 | +- **Reduced Latency**: Content is delivered from the server closest to your users |
| 14 | +- **Simple Integration**: No complex configuration required |
| 15 | + |
| 16 | +## Global CDN Infrastructure |
| 17 | + |
| 18 | +Zerops CDN operates across **6 strategic regions** to ensure your content is always delivered from a location close to your users: |
| 19 | + |
| 20 | +<table className="w-full my-1.5 whitespace-nowrap"> |
| 21 | + <thead> |
| 22 | + <tr> |
| 23 | + <th className="w-fit" colspan="2">Region</th> |
| 24 | + <th className="w-fit">Location</th> |
| 25 | + <th className="w-fit">Coverage Area</th> |
| 26 | + </tr> |
| 27 | + </thead> |
| 28 | + <tbody> |
| 29 | + <tr> |
| 30 | + <td className="w-fit font-semibold" rowspan="2">EU</td> |
| 31 | + <td className="w-fit font-semibold">CZ</td> |
| 32 | + <td className="w-fit">Prague, Czech Republic</td> |
| 33 | + <td className="w-full" rowspan="2">Primary European coverage + failover for all regions</td> |
| 34 | + </tr> |
| 35 | + <tr> |
| 36 | + <td className="w-fit font-semibold">DE</td> |
| 37 | + <td className="w-fit">Falkenstein, Germany</td> |
| 38 | + </tr> |
| 39 | + <tr> |
| 40 | + <td className="w-fit font-semibold" colspan="2">UK</td> |
| 41 | + <td className="w-fit">London, United Kingdom</td> |
| 42 | + <td className="w-full">UK and surrounding areas</td> |
| 43 | + </tr> |
| 44 | + <tr> |
| 45 | + <td className="w-fit font-semibold" colspan="2">AU</td> |
| 46 | + <td className="w-fit">Sydney, Australia</td> |
| 47 | + <td className="w-full">Australia and Oceania</td> |
| 48 | + </tr> |
| 49 | + <tr> |
| 50 | + <td className="w-fit font-semibold" colspan="2">SG</td> |
| 51 | + <td className="w-fit">Singapore, Singapore</td> |
| 52 | + <td className="w-full">Southeast Asia</td> |
| 53 | + </tr> |
| 54 | + <tr> |
| 55 | + <td className="w-fit font-semibold" colspan="2">CA</td> |
| 56 | + <td className="w-fit">Beauharnois, Canada</td> |
| 57 | + <td className="w-full">North America</td> |
| 58 | + </tr> |
| 59 | + </tbody> |
| 60 | +</table> |
| 61 | + |
| 62 | +### Geo-Steering Technology |
| 63 | +Zerops CDN's geo-steering technology automatically routes users to the server location closest to them. Here's how it works: |
| 64 | + |
| 65 | +* **Automatic routing**: Users are directed to the optimal CDN node based on their geographic location |
| 66 | +* **Quick failover**: The DNS TTL is set to just 30 seconds, allowing fast recovery if a node fails |
| 67 | +* **Redundancy**: If any node becomes unavailable, Cloudflare automatically redirects traffic to the next closest node |
| 68 | +* **Reliable backup**: The EU region serves as the ultimate fallback - if all other nodes go down, EU will always be served in DNS |
| 69 | + |
| 70 | +## CDN Modes and Implementation |
| 71 | + |
| 72 | +Zerops CDN currently supports two distinct usage modes (with a third mode coming soon), each designed for specific content delivery needs. |
| 73 | + |
| 74 | +### Object Storage Mode |
| 75 | + |
| 76 | +Perfect for efficiently delivering media files, documents, and other static assets stored in Zerops [Object Storage](/object-storage/overview) to users across different geographical regions. |
| 77 | + |
| 78 | +**Setup process:** |
| 79 | +1. Create an Object Storage service or select an existing one |
| 80 | +2. Enable the CDN option for this service |
| 81 | +3. Set appropriate public read access policies for objects you want to serve via CDN |
| 82 | + |
| 83 | +**Accessing content:** |
| 84 | +```txt |
| 85 | +https://storage.cdn.zerops.app/your-bucket/path/to/file |
| 86 | +``` |
| 87 | + |
| 88 | +:::tip |
| 89 | +Access the storage CDN URL via the `storageCdnUrl` **project** environment variable `${storageCdnUrl}/your-bucket/path/to/file`. |
| 90 | +::: |
| 91 | + |
| 92 | +### Static Mode |
| 93 | + |
| 94 | +Ideal for caching and delivering static website assets like HTML, CSS, JavaScript, and images served from your custom domains. |
| 95 | + |
| 96 | +**Setup process:** |
| 97 | +1. Configure domain access for your service |
| 98 | +2. Ensure your domains are DNS-verified and have active SSL certificates |
| 99 | +3. Enable CDN for the domain group |
| 100 | + |
| 101 | +**Accessing content:** |
| 102 | +```txt |
| 103 | +https://static.cdn.zerops.app/your-domain.com/path/to/file |
| 104 | +``` |
| 105 | + |
| 106 | +:::tip |
| 107 | +Access the static CDN URL via the `staticCdnUrl` **project** environment variable `${staticCdnUrl}/your-domain.com/path/to/file`. |
| 108 | +::: |
| 109 | + |
| 110 | +:::warning Wildcard Domains Not Supported |
| 111 | +Static CDN cannot be activated for wildcard domains (e.g., *.example.com). You must use specific domain names. |
| 112 | +::: |
| 113 | + |
| 114 | +### API Mode *(Coming Soon)* |
| 115 | + |
| 116 | +Designed for caching API responses to reduce load on your backend services and deliver faster responses to clients. |
| 117 | + |
| 118 | +**Environment variable:** Once available, you'll be able to access the API CDN URL via the `apiCdnUrl` **project** environment variable. |
| 119 | + |
| 120 | +:::warning |
| 121 | +API Mode is currently under development and will be available in a future release. |
| 122 | +::: |
| 123 | + |
| 124 | +### HTML Implementation Examples |
| 125 | + |
| 126 | +Here's how to integrate CDN URLs in your HTML code: |
| 127 | + |
| 128 | +```html |
| 129 | +<!-- Compare: Direct Object Storage vs. CDN-accelerated Storage --> |
| 130 | +<!-- Direct from Object Storage --> |
| 131 | +<img src="https://storage-prg1.zerops.io/my-bucket/logo.png"/> |
| 132 | + |
| 133 | +<!-- Via CDN for faster global delivery --> |
| 134 | +<img src="https://storage.cdn.zerops.app/my-bucket/logo.png"/> |
| 135 | + |
| 136 | +<!-- Using environment variables in templates --> |
| 137 | +<img src="{{ osGetEnv "storageCdnUrl" }}/assets/hero-image.jpg"/> |
| 138 | + |
| 139 | +<!-- Compare: Direct Domain vs. CDN-accelerated Domain --> |
| 140 | +<!-- Direct from your domain --> |
| 141 | +<script src="/static/js/main.js"></script> |
| 142 | + |
| 143 | +<!-- Via CDN for faster global delivery --> |
| 144 | +<script src="https://static.cdn.zerops.app/your-domain.com/static/js/main.js"></script> |
| 145 | +``` |
| 146 | + |
| 147 | +### Testing Specific CDN Nodes |
| 148 | + |
| 149 | +For testing or debugging purposes, you can bypass the automatic geo-steering and access a specific CDN node directly: |
| 150 | + |
| 151 | +``` |
| 152 | +https://{region}-{mode}.cdn.zerops.app/path/to/content |
| 153 | +``` |
| 154 | + |
| 155 | +Available region prefixes: `cz`, `de`, `au`, `sg`, `uk`, and `ca` |
| 156 | + |
| 157 | +**Examples:** |
| 158 | +- Test Australia node: `https://au-storage.cdn.zerops.app/my-bucket/test.jpg` |
| 159 | +- Test UK node: `https://uk-static.cdn.zerops.app/my-domain.com/index.html` |
| 160 | + |
| 161 | +## Managing CDN Content |
| 162 | + |
| 163 | +### Cache Lifecycle |
| 164 | + |
| 165 | +Content served through Zerops CDN follows this lifecycle: |
| 166 | + |
| 167 | +1. **First Request**: When a user requests content not yet in the CDN cache, the request goes to the origin server (your Zerops service), and the response is cached at the CDN node |
| 168 | +2. **Subsequent Requests**: Further requests for the same content are served directly from the CDN cache, reducing latency and origin server load |
| 169 | +3. **Cache Expiration**: By default, content remains cached for 30 days unless explicitly purged |
| 170 | +4. **Automatic Management**: When CDN storage reaches capacity, the least recently used content is automatically removed |
| 171 | + |
| 172 | +:::note Important Cache Behavior |
| 173 | +Zerops CDN implements a fixed 30-day TTL policy. Currently, HTTP caching headers such as `Cache-Control`, `Expires`, `Pragma`, etc. do not influence CDN caching behavior. To refresh content sooner than the 30-day period, use the [purge API](#api-reference). |
| 174 | + |
| 175 | +Your `Cache-Control` headers will still affect browser caching behavior. |
| 176 | +::: |
| 177 | + |
| 178 | +### When to Purge Cache |
| 179 | + |
| 180 | +You should consider purging cached content when: |
| 181 | + |
| 182 | +- **Content Updates**: You've updated content but kept the same URL (e.g., updated images, CSS files) |
| 183 | +- **Deployment Rollouts**: You've deployed a new version of your application |
| 184 | +- **Emergency Removal**: You need to immediately remove content that was accidentally made public |
| 185 | +- **Testing Changes**: You want to ensure users see the latest version during testing |
| 186 | + |
| 187 | +### Purging Cached Content |
| 188 | + |
| 189 | +Zerops provides a simple [API](#api-reference) to manage and purge cached content before its normal expiration. You can use wildcard patterns to target specific content sets: |
| 190 | + |
| 191 | +#### Purge Pattern Examples |
| 192 | + |
| 193 | +<table className="w-full my-1.5 whitespace-nowrap"> |
| 194 | + <thead> |
| 195 | + <tr> |
| 196 | + <th className="w-fit">Pattern</th> |
| 197 | + <th className="w-fit">Description</th> |
| 198 | + <th className="w-fit">Example</th> |
| 199 | + </tr> |
| 200 | + </thead> |
| 201 | + <tbody> |
| 202 | + <tr> |
| 203 | + <td className="w-fit font-semibold">`/*`</td> |
| 204 | + <td className="w-fit">Purges all content</td> |
| 205 | + <td className="w-full">Useful after major updates</td> |
| 206 | + </tr> |
| 207 | + <tr> |
| 208 | + <td className="w-fit font-semibold">`/images/*`</td> |
| 209 | + <td className="w-fit">Purges all content in a directory</td> |
| 210 | + <td className="w-full">Clear all cached images</td> |
| 211 | + </tr> |
| 212 | + <tr> |
| 213 | + <td className="w-fit font-semibold">`/css/main.css$`</td> |
| 214 | + <td className="w-fit">Purges a specific file</td> |
| 215 | + <td className="w-full">Update a single CSS file</td> |
| 216 | + </tr> |
| 217 | + <tr> |
| 218 | + <td className="w-fit font-semibold">`/2023*`</td> |
| 219 | + <td className="w-fit">Purges content starting with pattern</td> |
| 220 | + <td className="w-full">Clear content with date prefix</td> |
| 221 | + </tr> |
| 222 | + </tbody> |
| 223 | +</table> |
| 224 | + |
| 225 | +:::warning Pattern Rules |
| 226 | +- Wildcards (`*`) must be at the end of the pattern |
| 227 | +- Specific files must include `$` at the end |
| 228 | +- Nested wildcards (e.g., `/dir/*.jpg`) are not supported |
| 229 | +::: |
| 230 | + |
| 231 | +## API Reference |
| 232 | + |
| 233 | +Zerops provides a comprehensive set of API endpoints to manage your CDN configuration and content. For complete information about base URLs, authorization, and general API usage, please refer to our [API specification](/references/api). |
| 234 | + |
| 235 | +The endpoint links below will take you to the Swagger documentation with detailed request/response schemas and examples: |
| 236 | + |
| 237 | +### CDN Management API |
| 238 | + |
| 239 | +- **[Enable CDN for Storage ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicServiceStack/EnableStorageCdn)** `PUT /api/rest/public/service-stack/{id}/cdn` |
| 240 | +- **[Disable CDN for Storage ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicServiceStack/DisableStorageCdn)** `DELETE /api/rest/public/service-stack/{id}/cdn` |
| 241 | +- **[Create Object Storage with CDN ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicServiceStackObjectStorage/CreateObjectStorageV1)** `POST /api/rest/public/service-stack/object_storage_v1` |
| 242 | +- **[Create Domain Routing with CDN ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicPublicHttpRouting/CreatePublicHttpRouting)** `POST /api/public/public-http-routing` |
| 243 | +- **[Update Domain Routing with CDN ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicPublicHttpRouting/UpdatePublicHttpRouting)** `PUT /api/public/public-http-routing/{id}` |
| 244 | + |
| 245 | +### Cache Purge API |
| 246 | + |
| 247 | +- **[Purge Storage Mode Cache ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicServiceStack/PurgeStorageCdn)** `PUT /api/rest/public/service-stack/{id}/purge-cdn/{path}` |
| 248 | +- **[Purge Static Mode Cache ↗](https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicProject/PurgeStaticCdn)** `PUT /api/rest/public/project/{id}/purge-cdn/static/{domain}/{path}` |
| 249 | +- **Purge Api Mode Cache *(Coming soon)*** {/*(https://api.app-prg1.zerops.io/api/rest/public/swagger/#/PublicProject/PurgeApiCdn)** `PUT /api/rest/public/project/{id}/purge-cdn/api/{domain}/{path}` */} |
| 250 | + |
| 251 | +## Troubleshooting |
| 252 | + |
| 253 | +Having issues with your CDN? Here are solutions to the most common problems: |
| 254 | + |
| 255 | +#### Content Not Updated After Changes |
| 256 | +* **Issue:** You've updated content, but users still see the old version. |
| 257 | +* **Possible Cause:** The CDN cache is continuing to serve the previously cached version. |
| 258 | +* **Solution:** |
| 259 | + - Use the [purge API](#api-reference) with the specific content path |
| 260 | + - For immediate changes, use versioned file names (e.g., `style.v2.css` instead of just `style.css`) |
| 261 | + |
| 262 | +#### Content Not Being Cached |
| 263 | +* **Issue:** Your content isn't being cached by the CDN. |
| 264 | +* **Possible Cause:** Missing public read permissions on objects. |
| 265 | +* **Solution:** |
| 266 | + - For object storage: Check bucket and object access policies |
| 267 | + - Verify the object is accessible directly before attempting CDN access |
| 268 | + |
| 269 | +:::note |
| 270 | +Remember that only publicly accessible objects will be cached by the CDN. Private objects will always be fetched directly from the origin. |
| 271 | +::: |
| 272 | + |
| 273 | +#### Environment Variables Not Available |
| 274 | +* **Issue:** You can't access the new CDN-related project level environment variables in your containers. |
| 275 | +* **Possible Cause:** When new environment variables are created, existing services need to be restarted to access them. Services created before the CDN feature release require special handling. |
| 276 | +* **Solution:** |
| 277 | + - For services created after CDN release: Restart the service to apply the new environment variables |
| 278 | + - For services created before CDN release: Add and then remove a dummy environment variable in the project settings adn restart the service |
| 279 | + |
| 280 | +#### Unexpected 404 Errors |
| 281 | +* **Issue:** Users receive 404 errors when accessing content via CDN. |
| 282 | +* **Possible Cause:** Incorrect CDN URL formatting or missing content at origin. |
| 283 | +* **Solution:** |
| 284 | + - Double-check your [URL structure](#) (pay attention to domain names and paths) |
| 285 | + - Verify content exists at the origin before attempting CDN access |
| 286 | + - Test accessing the content directly from origin first |
| 287 | + |
| 288 | +**Correct URL patterns:** |
| 289 | +- Object Storage: `https://storage.cdn.zerops.app/your-bucket/path/to/file` |
| 290 | +- Static Mode: `https://static.cdn.zerops.app/your-domain.com/path/to/file` |
| 291 | + |
| 292 | +--- |
| 293 | + |
| 294 | +*Need help implementing CDN in your project? Join our [Discord community](https://discord.gg/zerops) where our team and other Zerops users can assist you!* |
0 commit comments