Güvenlik ve Optimizasyon
Video güvenliği (Bunny CDN imzalı URL), Cloudflare Zero Trust ile admin güvenliği, dinamik robots.txt ve sitemap üretimi.
Bu sayfa Coursio’da video güvenliği (Bunny CDN imzalı URL), Cloudflare Zero Trust ile admin panelinin güvenliğe alınması ve SEO için dinamik robots.txt ile sitemap üretimini açıklar.
Video Güvenliği — Bunny CDN İmzalı (Signed) URL
Section titled “Video Güvenliği — Bunny CDN İmzalı (Signed) URL”Videolar Bunny.net Stream üzerinden sunulur. Doğrudan indirmeyi ve yetkisiz erişimi engellemek için imzalı (signed) URL kullanılır.
Nasıl Çalışır?
Section titled “Nasıl Çalışır?”- Dosya:
app/lib/video-security.ts - Fonksiyon:
generateSignedVideoUrl(videoId, libraryId, securityKey, expirationSeconds?) - Algoritma: Bunny’nin beklediği formatta token üretilir:
expires = now + expirationSeconds(varsayılan 3600 saniye = 1 saat)tokenData = securityKey + videoId + expires- SHA-256 hash alınır → hex string =
token - URL:
https://iframe.mediadelivery.net/embed/{libraryId}/{videoId}?token={token}&expires={expires}
Bunny CDN, gelen istekteki token ve expires değerini aynı mantıkla doğrular; süre dolmuş veya token yanlışsa içerik verilmez.
Ortam Değişkenleri
Section titled “Ortam Değişkenleri”| Değişken | Açıklama |
|---|---|
BUNNY_LIBRARY_ID | Bunny Stream Library ID |
BUNNY_VIDEO_SECURITY_KEY | Bunny panelinden alınan Pull Zone → Remote Auth / Security Key (imza için kullanılır) |
Kullanıldığı Yerler
Section titled “Kullanıldığı Yerler”- Öğrenme sayfası:
app/routes/learn.$slug.tsx— kayıtlı derslerde sadece erişim hakkı olan kullanıcılarasignedVideoUrlüretilir (preview dersler + enroll edilmiş kullanıcılar). - Kurs detay sayfası:
app/routes/course.$id.tsx— önizleme (preview) dersler içinsignedPreviewUrlüretilir.
BUNNY_VIDEO_SECURITY_KEY tanımlı değilse imzalı URL üretilmez; eski embed URL’i (token olmadan) kullanılır — bu durumda videolar doğrudan paylaşılabilir ve indirilebilir, production’da güvenlik anahtarı kullanılması önerilir.
Cloudflare Zero Trust — Admin Panelinin Güvenliğe Alınması
Section titled “Cloudflare Zero Trust — Admin Panelinin Güvenliğe Alınması”Uygulamadaki Mevcut Koruma
Section titled “Uygulamadaki Mevcut Koruma”Admin paneli uygulama seviyesinde şu şekilde korunur:
- Dosya:
app/routes/admin.tsx(layout loader) - Kontrol: Better Auth session alınır;
session?.user?.idyoksa veya veritabanındaki kullanıcırole !== "admin"ise 404’e yönlendirilir. - Tüm admin alt sayfaları bu layout’tan geçer; yani sadece role = admin olan kullanıcılar
/admin/*sayfalarına erişebilir.
Önerilen: Cloudflare Zero Trust (Access)
Section titled “Önerilen: Cloudflare Zero Trust (Access)”Production’da admin panelini ek bir katmanla korumak için Cloudflare Zero Trust (Access) kullanılabilir:
- Cloudflare Dashboard → Zero Trust → Access → Applications ile yeni bir uygulama tanımlanır.
- Protected hostname:
admin.yourdomain.comveyayourdomain.com/admin(path bazlı kural ile). - Policy: Örneğin sadece belirli e-posta alanları, GitHub/Google SSO veya One-time PIN ile giriş zorunlu tutulur.
- Böylece sunucuya istek ulaşmadan önce Cloudflare, kimlik doğrulamayı yapar; yetkisiz kullanıcılar login sayfasına yönlendirilir.
Dökümantasyon: Cloudflare Zero Trust — Application Access ve Protect a self-hosted application resmi dokümanlarından path/host bazlı kurulum yapılabilir.
Özet: Uygulama içi koruma (session + admin role) şu an tek katman; Cloudflare Access ile /admin (veya admin subdomain’i) ikinci katman olarak kilitlenebilir.
SEO & Sitemap — Dinamik robots.txt ve Sitemap Üretimi
Section titled “SEO & Sitemap — Dinamik robots.txt ve Sitemap Üretimi”robots.txt (Dinamik)
Section titled “robots.txt (Dinamik)”- Route:
GET /robots.txt(dil prefix’i yok) - Dosya:
app/routes/robots[.]txt.ts - İçerik: Loader içinde
request.urlilehostveprotocolalınır;baseUrldinamik oluşturulur. Aynı kod Cloudflare Workers veya farklı domain’de çalışır.
Kurallar özeti:
- User-agent: * — Genel kurallar: public sayfalar (ana sayfa,
/tr/,/en/,/de/, pricing, teaching, courses, course) Allow; admin, instructor, account, my-courses, cart, payment, login, register, onboarding, learn, verify, api, 404/500 Disallow. - Googlebot / Bingbot / Yandex — Aynı public sayfalar Allow; isteğe bağlı
Crawl-delay(bazı botlar için). - Sitemap: Response’ta
Sitemap: ${baseUrl}/sitemap.xmlve dil bazlısitemap-tr.xml,sitemap-en.xml,sitemap-de.xmlreferansları yer alır.
Not: Dil bazlı sitemap URL’leri (sitemap-tr.xml vb.) robots.txt’te belirtilmiş olabilir; şu an routes.ts içinde yalnızca tek sitemap.xml route’u vardır. Dil bazlı ayrı sitemap’ler istenirse ek route’lar eklenebilir.
Sitemap XML (Dinamik)
Section titled “Sitemap XML (Dinamik)”- Route:
GET /sitemap.xml - Dosya:
app/routes/sitemap[.]xml.ts - Veri:
getDb(env.DATABASE_URL)ile veritabanına bağlanılır;coursestablosundanstatus = 'published'olan kurslarınslugdeğerleri alınır. - URL’ler:
- Statik sayfalar:
baseUrl/{lang}{page}— diller: tr, en, de, es; sayfalar:"",/courses,/pricing,/teaching,/terms/privacy. Her biri içinchangefreq: weekly,priority: ana sayfa 1.0, diğerleri 0.8. - Kurs sayfaları:
baseUrl/{lang}/course/{slug}— sadece yayında olan kurslar;changefreq: daily,priority: 0.9.
- Statik sayfalar:
- Response:
Content-Type: application/xml,Cache-Control: public, max-age=3600.
Base URL: Sitemap içinde base URL sabit veya env’den okunabilir. Production’da canlı adres https://lms.techsider.co kullanılmalıdır; kodda örnek olarak coursio.co geçiyorsa env (örn. SITE_URL) ile lms.techsider.co yapılabilir. Bkz. Ortam Değişkenleri — Production URL.
Kullanıcı Tarafı Sitemap Sayfası
Section titled “Kullanıcı Tarafı Sitemap Sayfası”- Route:
/:lang/sitemap(ör./tr/sitemap) - Dosya:
app/routes/$lang.sitemap.tsx - İçerik: HTML sitemap sayfası — platform bölümü (ana sayfa, tüm kurslar, fiyatlandırma, eğitmen ol), popüler kurslar (ör. kategori bazlı linkler), yasal (gizlilik, kullanım şartları, çerez politikası) linkleri. Arama motorları için ek bilgi; XML sitemap’in yerine geçmez.
| Konu | Açıklama |
|---|---|
| Video güvenliği | app/lib/video-security.ts — generateSignedVideoUrl ile Bunny CDN imzalı URL (SHA-256 token + expires). learn ve course sayfalarında kullanılır. Env: BUNNY_LIBRARY_ID, BUNNY_VIDEO_SECURITY_KEY. |
| Admin güvenliği | Uygulama: session + user.role === "admin" (admin.tsx loader). Önerilen ek katman: Cloudflare Zero Trust (Access) ile /admin veya admin hostname koruması. |
| robots.txt | Dinamik, request.url ile baseUrl. Allow/Disallow + Sitemap referansları; dil bazlı sitemap URL’leri isteğe bağlı. |
| sitemap.xml | Dinamik; DB’den yayındaki kurslar + statik sayfalar; diller (tr, en, de, es); XML; cache 1 saat. |
| /:lang/sitemap | HTML sitemap sayfası (kullanıcı ve SEO için). |
İlgili: Ortam Değişkenleri (Bunny ve diğer env), Admin Console (panel yetkilendirmesi), Eğitmen ve Kurs Yönetimi (video yükleme ve Bunny kullanımı).
İlgili Dosyalar
Section titled “İlgili Dosyalar”app/lib/video-security.ts—generateSignedVideoUrl; Bunny CDN imzalı URL.app/routes/robots[.]txt.ts— Dinamik robots.txt.app/routes/sitemap[.]xml.ts— Dinamik sitemap XML.app/routes/$lang.sitemap.tsx— HTML sitemap sayfası.app/routes/admin.tsx— Admin layout; session ve role kontrolü.