Private links¶
A private zone serves nothing without a signature. The URL still looks ordinary; it carries an expiry and a signature, and after the expiry it stops working.
Set a zone's visibility to private on its settings page, or at creation. Then:
Without those parameters the same path answers 403.
What a signature covers¶
The path and the expiry, with the zone's own signing key. Each zone has its own key, so a link leaked from one zone opens that zone and nothing else, and a link to one file does not open its neighbours.
The expiry is in the URL and covered by the signature, so it cannot be edited — pushing the date out invalidates the signature rather than extending the link.
Where to get one¶
| CLI | cdn url <zone> <path> --expires 30m |
| HTTP API | POST /_/api/v1/zones/<zone>/objects/<path>/sign |
| browser | the Sign button beside each file |
Durations are written the way you would say them: 90 (seconds), 30m, 2h, 7d.
What it is not¶
A signed URL is a bearer link: anyone holding it can fetch the file until it expires. It is the right tool for "send this to a client for the afternoon" and the wrong one for "only these five people, ever". There is no per-person access control, and a link is not pinned to an IP address — that would need a trusted-proxy configuration this service does not have, and believing X-Forwarded-For without one is a header anybody can write.
Keep expiries short. That is the whole control surface.
Public zones can still be narrowed¶
A public zone serves anyone with the URL, but two lists on its settings page limit where that URL works from:
- Referrers — an allowlist of hostnames allowed to embed the zone's objects, so another site cannot use your images and bill you for the traffic. Empty means anyone, which is usually what a CDN is for.
- CORS origins — the origins allowed to fetch these objects from a script. Fonts and modules need this;
*by default on a public zone, empty on a private one.
Neither is a security boundary: a Referer header is trivially set by anything that is not a browser. They stop casual hotlinking, not a determined fetch.