Skip to content

Commit 2763a95

Browse files
authored
cdn (#230)
1 parent 008bc43 commit 2763a95

File tree

4 files changed

+327
-0
lines changed

4 files changed

+327
-0
lines changed

apps/docs/content/features/cdn.mdx

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
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!*

apps/docs/sidebars.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,15 @@ module.exports = {
135135
},
136136
className: 'homepage-sidebar-item',
137137
},
138+
{
139+
type: 'doc',
140+
id: 'features/cdn',
141+
label: 'CDN',
142+
customProps: {
143+
sidebar_icon: 'cdn',
144+
},
145+
className: 'homepage-sidebar-item',
146+
},
138147
{
139148
type: 'html',
140149
value: 'Perfectly suited for',
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { IconProps } from '@medusajs/icons/dist/types';
2+
import clsx from 'clsx';
3+
import React from 'react';
4+
5+
const IconCdn = (props: IconProps) => {
6+
return (
7+
<svg
8+
version="1.1"
9+
fill="currentColor"
10+
width={props.width || 20}
11+
height={props.height || 20}
12+
viewBox="0 0 32 32"
13+
xmlns="http://www.w3.org/2000/svg"
14+
{...props}
15+
className={clsx('text-ui-fg-subtle', props.className)}
16+
>
17+
<path d="M27 21.75c-0.795 0.004-1.538 0.229-2.169 0.616l0.018-0.010-2.694-2.449c0.724-1.105 1.154-2.459 1.154-3.913 0-1.572-0.503-3.027-1.358-4.212l0.015 0.021 3.062-3.062c0.57 0.316 1.249 0.503 1.971 0.508h0.002c2.347 0 4.25-1.903 4.25-4.25s-1.903-4.25-4.25-4.25c-2.347 0-4.25 1.903-4.25 4.25v0c0.005 0.724 0.193 1.403 0.519 1.995l-0.011-0.022-3.062 3.062c-1.147-0.84-2.587-1.344-4.144-1.344-0.868 0-1.699 0.157-2.467 0.443l0.049-0.016-0.644-1.17c0.726-0.757 1.173-1.787 1.173-2.921 0-2.332-1.891-4.223-4.223-4.223s-4.223 1.891-4.223 4.223c0 2.332 1.891 4.223 4.223 4.223 0.306 0 0.605-0.033 0.893-0.095l-0.028 0.005 0.642 1.166c-1.685 1.315-2.758 3.345-2.758 5.627 0 0.605 0.076 1.193 0.218 1.754l-0.011-0.049-0.667 0.283c-0.78-0.904-1.927-1.474-3.207-1.474-2.334 0-4.226 1.892-4.226 4.226s1.892 4.226 4.226 4.226c2.334 0 4.226-1.892 4.226-4.226 0-0.008-0-0.017-0-0.025v0.001c-0.008-0.159-0.023-0.307-0.046-0.451l0.003 0.024 0.667-0.283c1.303 2.026 3.547 3.349 6.1 3.349 1.703 0 3.268-0.589 4.503-1.574l-0.015 0.011 2.702 2.455c-0.258 0.526-0.41 1.144-0.414 1.797v0.001c0 2.347 1.903 4.25 4.25 4.25s4.25-1.903 4.25-4.25c0-2.347-1.903-4.25-4.25-4.25v0zM8.19 5c0-0.966 0.784-1.75 1.75-1.75s1.75 0.784 1.75 1.75c0 0.966-0.784 1.75-1.75 1.75v0c-0.966-0.001-1.749-0.784-1.75-1.75v-0zM5 22.42c-0.966-0.001-1.748-0.783-1.748-1.749s0.783-1.749 1.749-1.749c0.966 0 1.748 0.782 1.749 1.748v0c-0.001 0.966-0.784 1.749-1.75 1.75h-0zM27 3.25c0.966 0 1.75 0.784 1.75 1.75s-0.784 1.75-1.75 1.75c-0.966 0-1.75-0.784-1.75-1.75v0c0.001-0.966 0.784-1.749 1.75-1.75h0zM11.19 16c0-0.001 0-0.002 0-0.003 0-2.655 2.152-4.807 4.807-4.807 1.328 0 2.53 0.539 3.4 1.409l0.001 0.001 0.001 0.001c0.87 0.87 1.407 2.072 1.407 3.399 0 2.656-2.153 4.808-4.808 4.808s-4.808-2.153-4.808-4.808c0-0 0-0 0-0v0zM27 27.75c-0.966 0-1.75-0.784-1.75-1.75s0.784-1.75 1.75-1.75c0.966 0 1.75 0.784 1.75 1.75v0c-0.001 0.966-0.784 1.749-1.75 1.75h-0z"></path>
18+
</svg>
19+
);
20+
};
21+
22+
export default IconCdn;

apps/docs/src/theme/Icon/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ import IconGitlab from './Gitlab';
156156
import IconTypesense from './Typesense';
157157
import IconDocker from './Docker';
158158
import IconCurlyBraces from './CurlyBraces';
159+
import IconCdn from './Cdn';
159160

160161
export default {
161162
'academic-cap-solid': AcademicCapSolid,
@@ -316,4 +317,5 @@ export default {
316317
cloudok: IconCloudOk,
317318
typesense: IconTypesense,
318319
'curly-braces': IconCurlyBraces,
320+
cdn: IconCdn,
319321
};

0 commit comments

Comments
 (0)