Open the CDN zone → Settings tab in my.cubepath.com.
Custom domain
Every zone gets a system-generated domain (<name>.cubecdn.io) that works immediately. To serve traffic on your own hostname instead:
- 1Point a CNAME at the zoneIn your DNS, create a CNAME from your hostname (e.g.
cdn.example.com) to the zone's system domain. - 2Set the custom domainEnter the hostname in Custom Domain and save.
- 3Wait for SSLA certificate is requested automatically once the CNAME resolves.
NoteDo the CNAME first. If the record isn't live when the certificate is requested, issuance fails — use Re-request SSL once DNS has propagated.
SSL
SSL Status shows Valid, Pending, Error or Not configured. Two types are available:
- Automatic (Let's Encrypt) — free, provisioned and renewed for you. The right choice unless you have a specific reason not to use it.
- Custom Certificate — pick one of your own from SSL Certificates, or upload a new one. Available on higher plans, and needed for EV certificates or a certificate that must match one you use elsewhere.
Signed URLs (Token Auth)
Token Auth serves the zone's content only to people you authorize. Every link you publish carries a cryptographic signature and an expiry; anyone requesting without a valid signed URL gets 403 Forbidden.
It's the standard pattern for paid video, gated downloads, private galleries, time-limited shares, and for keeping content out of search engines and away from hotlinkers.
How it works
When you enable Token Auth, CubePath generates a shared secret for the zone. Your backend computes an HMAC-SHA256 over the path plus an expiry timestamp plus the secret, base64url-encodes it, and appends ?token=...&expires=... to the URL. The edge recomputes the same HMAC with its copy of the secret and compares: match, we serve; mismatch, 403. The secret itself never travels in the URL.
Enable it
Open the Signed URLs (Token Auth) card and toggle Enable Token Auth. The secret is generated and shown once.
WarningCopy the secret immediately into a secrets manager or environment variable. We store it encrypted so the edge can validate signatures, but we never display it again. If you lose it, your only option is to rotate — which invalidates every URL already in circulation.
Sign URLs in your backend
The math is HMAC-SHA256(secret, path + str(expires)), base64url-encoded without padding.
import hmac, hashlib, base64, time
SECRET = "<your_zone_secret>"
def sign(path: str, ttl_seconds: int = 3600) -> str:
expires = int(time.time()) + ttl_seconds
msg = f"{path}{expires}".encode()
mac = hmac.new(SECRET.encode(), msg, hashlib.sha256).digest()
token = base64.urlsafe_b64encode(mac).rstrip(b"=").decode()
return f"https://your-zone.cubecdn.io{path}?token={token}&expires={expires}"
const crypto = require('crypto');
const SECRET = process.env.CDN_SECRET;
function sign(path, ttlSeconds = 3600) {
const expires = Math.floor(Date.now() / 1000) + ttlSeconds;
const mac = crypto.createHmac('sha256', SECRET).update(`${path}${expires}`).digest();
const token = mac.toString('base64url').replace(/=+$/, '');
return `https://your-zone.cubecdn.io${path}?token=${token}&expires=${expires}`;
}
function sign($path, $ttlSeconds = 3600) {
$secret = getenv('CDN_SECRET');
$expires = time() + $ttlSeconds;
$mac = hash_hmac('sha256', $path . $expires, $secret, true);
$token = rtrim(strtr(base64_encode($mac), '+/', '-_'), '=');
return "https://your-zone.cubecdn.io{$path}?token={$token}&expires={$expires}";
}
The Settings card also has a Generate signed URL subform: paste a path, set a validity window, and get a ready-to-use URL. It's for testing and one-off shares — production traffic should sign in your backend, with no API round-trip per URL.
Choosing an expiry
| Validity | Use case | Trade-off |
|---|---|---|
| 5 minutes | One-off downloads, secured API responses | Refreshing after the window means re-signing |
| 1 hour | Video playback sessions | Long videos outlive it; the player must re-sign |
| 24 hours | Daily content rotation | A leaked URL works for a day |
| 7 days | Static cacheable media, app bundles | Long exposure if leaked; consider IP binding |
Validity is capped at 7 days (604800 s) to limit the damage from a leak.
Bind tokens to the client IP
The Bind tokens to client IP toggle folds the request's source IP into the signature, so a leaked URL only works from the IP it was issued to. It's a strong defence against links being shared in chats and forums.
The cost is real: clients whose IP changes mid-session — mobile networks on CGNAT, hotel WiFi, VPNs, roaming between 4G and home WiFi — lose access mid-stream.
ImportantFor consumer video streaming this is usually a bad trade. A short expiry achieves most of the benefit without breaking mobile viewers.
If you enable it, pass the client's public IP when signing (typically the first entry of X-Forwarded-For if you're behind a proxy). IPv6 must be in canonical compressed form (2001:db8::1, not [2001:db8::1]).
Rotating the secret
- 1RotateClick Rotate secret and confirm.
- 2Copy the new secretSame one-shot reveal rule as the first time.
- 3Update your backendReplace
CDN_SECRETand redeploy so the app picks it up.
Rotation is instant and retroactive: every URL signed with the old secret starts returning 403 immediately, and content being streamed at that moment breaks. Plan rotations for a low-traffic window, or keep expiry windows short so the disruption is small.
What Token Auth doesn't do
- It isn't a WAF. No bot filtering, no rate limiting, no country blocking — that's WAF rules.
- It isn't user authentication. It authorizes one URL against a shared secret; anyone holding that URL can use it, unless IP binding is on.
- It doesn't encrypt content. Transport is HTTPS, but the bytes are the same ones in your origin.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| 403 on every URL | Token Auth is on but requests carry no ?token=, or the token used the wrong secret |
| 403 on some URLs | The signed path and the requested path differ — trailing slash, case, or percent-encoding. Sign and request the exact same string |
| 403 right after rotating | URLs signed with the old secret. Re-sign them |
| Works on desktop, fails on mobile | IP binding is on and the client changed network. Disable it or shorten the expiry |
| Random 403s during playback | The URL expired mid-stream. Lengthen the expiry, or have the player fetch a fresh URL before it lapses |
CORS
CORS (cross-origin fetch) lets JavaScript on other domains fetch content from this zone. You need it for HLS/DASH players, fetch() calls and any cross-domain XHR — without it the browser blocks the response even though the CDN served it correctly.
Enable it and set Allowed origins: either * for any origin, or a list of fully-qualified origins, one per line or comma-separated. Each must include the scheme (https://example.com) and no path.
NoteYou must add at least one allowed origin (or
*) before the toggle can be enabled. With CORS on, responses includeAccess-Control-Allow-Originand the edge answersOPTIONSpreflight requests for you.
TipPrefer an explicit list over
*when the content isn't meant to be embeddable everywhere.*lets any site on the internet build a page out of your assets — on your bandwidth.