Setting up KeyCDN
KeyCDN—European CDN with simple pay-as-you-go pricing ($0.04/GB), 35+ PoPs, specialization in static file delivery. Good choice for small projects and European-first audience.
Create Zone
Zone in KeyCDN—configuration for one source. Types:
- Pull Zone—KeyCDN pulls content from origin on first request (recommended)
- Push Zone—files uploaded directly via rsync/FTP/API
Pull Zone via API
curl -X POST \
-u api_key: \
-H "Content-Type: application/json" \
-d '{
"name": "example-assets",
"type": "pull",
"origins": [{"url": "https://example.ru"}],
"ssl": true,
"cors_headers": true,
"cache_headers": true,
"expire": 2592000,
"custom_domains": ["cdn.example.ru"]
}' \
https://api.keycdn.com/zones.json
DNS setup
After zone creation, KeyCDN provides CNAME (e.g. example-assets-1234.kxcdn.com). Add CNAME:
cdn.example.ru → example-assets-1234.kxcdn.com
SSL for custom domain—KeyCDN issues Let's Encrypt automatically.
Laravel integration
// config/cdn.php
return [
'url' => env('CDN_URL', ''),
'enabled' => env('CDN_ENABLED', false),
];
// AppServiceProvider
public function boot(): void {
if (config('cdn.enabled') && $cdnUrl = config('cdn.url')) {
URL::forceRootUrl($cdnUrl);
}
}
<img src="{{ asset('images/logo.png') }}" alt="Logo">
<!-- Outputs: https://cdn.example.ru/images/logo.png -->
Cache invalidation
use Illuminate\Support\Facades\Http;
class KeyCdnService {
public function purge(array $urls): void {
Http::withBasicAuth($this->apiKey, '')
->delete("https://api.keycdn.com/zones/purgeurl/{$this->zoneId}.json", [
'urls' => $urls,
]);
}
}
Setup time: few hours for CNAME setup.







