Bunny Storage Zone Entegrasyonu

Kod Değişikliği Analizi ve Migration Planı

8 Dosya Değişecek ~280 GB Migration ~2-3 Gün İş v2 - Güncel

SON KARAR — Kesinleşen Mimari

HİBRİT MOD

Dosyalar hem sunucuda hem Bunny'de tutulacak. Sunucu = Master, Bunny = CDN Kopyası

LOCAL MASTER

Sunucudaki dosyalar HER ZAMAN kalacak. Asla silinmeyecek. Bunny sadece kopya.

ŞİFRELEME AYNI

Mevcut AES-128 encryption sistemi değişmeyecek. Key endpoint aynen kalacak.

Kesinleşen Veri Akışı

Şarkı Upload
HLS Convert
Local ✅
Bunny ✅
Kullanıcı
Bunny CDN Öncelik
veya
Local Fallback
2x
Depolama (Local + Bunny)
%100
Uptime Garantisi
0
Şifreleme Değişikliği
~$3
Ek Maliyet/ay

Şifreleme Sistemi — Değişiklik YOK

Mevcut Sistem (Aynen Kalacak)

  • AES-128 Encryption: Her şarkı için unique key
  • Key Storage: enc.bin dosyası local'de
  • Key Endpoint: /hls-key/muzibu/songs/{id}
  • DB Field: encryption_key (hex, 32 char)

Bunny Entegrasyonunda

  • enc.bin Bunny'e YÜKLENMEZ — Güvenlik için local'de kalır
  • Key endpoint değişmez — Sunucudan serve edilmeye devam
  • HLS.js key request — Aynen çalışır
  • CORS ayarları — Mevcut config yeterli

Bunny'e Yüklenecek vs Yüklenmeyecek

Bunny'e YÜKLENİR:
  • • playlist.m3u8 (ana playlist)
  • • master.m3u8 (ABR master)
  • • segment-*.ts (tüm chunk'lar)
  • • ultralow/, low/, mid/ klasörleri
  • • mp3_128/*.mp3, mp3_64/*.mp3
Bunny'e YÜKLENMEZ:
  • enc.bin (encryption key)
  • enc.keyinfo (key metadata)
  • • Orijinal şarkı dosyaları (opsiyonel)
Şifreleme Akışı (Değişmez)

HLS.js → Bunny'den .m3u8 çeker → Key URI görür → /hls-key/... endpoint'ine istek → Sunucu DB'den key döner → HLS.js decrypt eder → Şarkı çalar

~4,000
HLS Dönüştürülmüş Şarkı
~280 GB
Toplam Dosya Boyutu
8
Değişecek Dosya
3
Yeni Dosya

Maliyet Karşılaştırması

Cloudflare + Argo Mevcut
Pro Plan $25/ay
Argo Base $5/ay
Argo Traffic (8-10TB) $800-1,000/ay
TOPLAM ~$830-1,030/ay
Bunny Pull Zone Kuruldu
Avrupa (%70) $56-70/ay
Ortadoğu (%30) $144-180/ay
Burrow $9.50/ay
TOPLAM ~$210-260/ay
Bunny Hibrit SEÇİLDİ ✓
Pull Zone $210-260/ay
Storage (280GB) +$2.80/ay
Local disk Mevcut
TOPLAM ~$215-265/ay
Aylık Tasarruf: $600-800

Hibrit modda dosyalar iki yerde tutulsa bile Cloudflare'a göre çok daha ucuz.

Mevcut Sistem Mimarisi

Dosya Yapısı

storage/tenant1001/app/public/muzibu/
├── songs/                    # Orijinal dosyalar
│   ├── song_xxx.mp3
│   ├── mp3_128/              # Fallback 128k
│   │   └── {song_id}.mp3
│   └── mp3_64/               # Fallback 64k
│       └── {song_id}.mp3
└── hls/                      # HLS Streaming
    └── {song_id}/
        ├── playlist.m3u8     # Ana playlist
        ├── master.m3u8       # ABR master
        ├── segment-*.ts      # 4sn chunk'lar
        ├── enc.bin           # AES-128 key ⚠️
        ├── enc.keyinfo       # Key metadata ⚠️
        ├── ultralow/         # 32 kbps
        ├── low/              # 64 kbps
        └── mid/              # 128 kbps

enc.bin ve enc.keyinfo Bunny'e yüklenmez!

Dosya Boyutları (Per Song)

Orijinal MP3 5-10 MB
HLS (orijinal kalite) ~22 MB
HLS Variant'lar ~27 MB
MP3 Fallback'lar ~3.5 MB
TOPLAM ~60-70 MB

Değişecek Dosyalar (8 Dosya)

MODIFY Modules/Muzibu/App/Jobs/ConvertToHLSJob.php
Ana HLS Job

HLS dönüşümü sonrası dosyaları Bunny'e yükle (enc.bin HARİÇ).

// MEVCUT: Sadece local storage'a yazıyor
$hlsPath = $this->convertToHLS($song);

// YENİ: Local + Bunny'e yaz (enc.bin HARİÇ)
$hlsPath = $this->convertToHLS($song);
app(BunnyStorageService::class)->uploadDirectory(
    $localHlsPath,
    "hls/{$song->song_id}",
    ['exclude' => ['enc.bin', 'enc.keyinfo']]  // Şifreleme dosyaları hariç!
);
MODIFY app/Services/Muzibu/HLSService.php
HLS Teknik İşlemler

MP3 fallback üretimi sonrası Bunny'e yükleme ekle.

// generateMp3() fonksiyonuna ekle:
public function generateMp3($song, $bitrate)
{
    // Mevcut FFmpeg kodu...

    // YENİ: Bunny'e de yükle
    if (config('services.bunny.enabled')) {
        app(BunnyStorageService::class)->upload(
            $localPath,
            "songs/mp3_{$bitrate}/{$song->song_id}.mp3"
        );
    }
}
MODIFY Modules/Muzibu/App/Observers/SongObserver.php
Silme İşlemleri

forceDeleted() event'inde Bunny'den de silme ekle. Local dosyalar da silinir (mevcut davranış).

protected function cleanupAudioFiles(Song $song): void
{
    // Mevcut local silme kodu (AYNEN KALIR)...

    // YENİ: Bunny'den de sil
    if (config('services.bunny.enabled')) {
        $bunny = app(BunnyStorageService::class);
        $bunny->deleteDirectory("hls/{$song->song_id}");
        $bunny->delete("songs/mp3_128/{$song->song_id}.mp3");
        $bunny->delete("songs/mp3_64/{$song->song_id}.mp3");
    }
}
MODIFY Modules/Muzibu/App/Http/Controllers/Api/SongStreamController.php
Playback URL'leri

Stream endpoint'inde Bunny CDN URL'lerini döndür. Key endpoint DEĞİŞMEZ!

// stream() response'unda URL'leri değiştir:

// HLS URL → Bunny'den
'hls' => config('services.bunny.enabled')
    ? "https://muzibu-audio.b-cdn.net/hls/{$id}/master.m3u8"
    : "/storage/tenant1001/public/muzibu/hls/{$id}/master.m3u8",

// Key URL → LOCAL'DEN (DEĞİŞMEZ!)
'key' => "/hls-key/muzibu/songs/{$id}",  // ⚠️ Aynen kalır!
MODIFY Modules/Muzibu/App/Http/Livewire/Admin/SongManageComponent.php
Upload Handler

Değişiklik minimal — HLS job zaten Bunny'e yükleyecek. Opsiyonel: Orijinal dosya da yüklenebilir.

public function updatedAudioFile()
{
    // Mevcut validasyon ve local kayıt (AYNEN KALIR)...

    // OPSİYONEL: Orijinal dosyayı da Bunny'e yükle
    if (config('services.bunny.upload_originals')) {
        app(BunnyStorageService::class)->upload(
            $this->audioFile->getRealPath(),
            "songs/originals/{$filename}"
        );
    }
}
MODIFY Modules/Muzibu/App/Models/Song.php
URL Getter'lar

getHlsUrl() ve benzeri metodlarda Bunny URL desteği.

public function getHlsUrl(): ?string
{
    if (!$this->hls_path) return null;

    // YENİ: Bunny URL kontrolü
    if (config('services.bunny.enabled')) {
        return config('services.bunny.cdn_url') . '/' . $this->hls_path;
    }

    return $this->getStorageUrl($this->hls_path);
}
MODIFY config/filesystems.php
Disk Tanımı

Bunny Storage disk driver'ı ekle.

'disks' => [
    // Mevcut diskler...

    'bunny' => [
        'driver' => 'bunny',
        'api_key' => env('BUNNY_STORAGE_API_KEY'),
        'storage_zone' => env('BUNNY_STORAGE_ZONE'),
        'region' => env('BUNNY_STORAGE_REGION', 'de'),
    ],
],
MODIFY config/services.php
Servis Config

Bunny servis ayarları.

'bunny' => [
    'enabled' => env('BUNNY_STORAGE_ENABLED', false),
    'mode' => 'hybrid',  // Local her zaman master!
    'api_key' => env('BUNNY_STORAGE_API_KEY'),
    'storage_zone' => env('BUNNY_STORAGE_ZONE'),
    'cdn_url' => env('BUNNY_CDN_URL'),
    'upload_originals' => env('BUNNY_UPLOAD_ORIGINALS', false),
    'fallback_to_local' => true,  // Bunny fail → Local
],

Yeni Oluşturulacak Dosyalar (3 Dosya)

NEW app/Services/Bunny/BunnyStorageService.php
~150 satır

Bunny Storage API wrapper servisi.

class BunnyStorageService
{
    public function upload($localPath, $remotePath): bool;
    public function uploadDirectory($localDir, $remoteDir, $exclude = []): bool;
    public function delete($remotePath): bool;
    public function deleteDirectory($remoteDir): bool;
    public function exists($remotePath): bool;
    public function getUrl($remotePath): string;
}
NEW app/Console/Commands/MigrateToBunnyCommand.php
~200 satır

Mevcut dosyaları Bunny'e migrate eden artisan komutu. enc.bin dosyalarını ATLAR!

// Kullanım:
php artisan muzibu:migrate-to-bunny --all          # Tüm şarkılar
php artisan muzibu:migrate-to-bunny --song=123     # Tek şarkı
php artisan muzibu:migrate-to-bunny --chunk=100    # 100'lük gruplar
php artisan muzibu:migrate-to-bunny --dry-run      # Test modu

// ⚠️ enc.bin ve enc.keyinfo dosyaları otomatik olarak hariç tutulur!
NEW app/Providers/BunnyServiceProvider.php
~50 satır

Bunny servislerini register eden provider.

class BunnyServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(BunnyStorageService::class);
    }

    public function boot()
    {
        // Custom filesystem driver
        Storage::extend('bunny', function($app, $config) {
            return new BunnyStorageAdapter($config);
        });
    }
}

Yeni ENV Değişkenleri

# Bunny Storage Zone
BUNNY_STORAGE_ENABLED=false
BUNNY_STORAGE_API_KEY=your-storage-api-key
BUNNY_STORAGE_ZONE=muzibu-audio
BUNNY_STORAGE_REGION=de

# Bunny CDN (Pull Zone)
BUNNY_CDN_URL=https://muzibu-audio.b-cdn.net

# Hibrit Mod Ayarları
BUNNY_MODE=hybrid                   # hybrid | bunny_only | local_only
BUNNY_UPLOAD_ORIGINALS=false      # Orijinal MP3'leri de yükle?
BUNNY_FALLBACK_TO_LOCAL=true     # Bunny fail → Local'e düş

Migration Stratejisi (Hibrit Mod)

1

Hazırlık (Gün 1)

  • Bunny Storage Zone oluştur
  • API key al
  • BunnyStorageService kodunu yaz
  • ENV değişkenlerini ekle
2

Dual-Write Aktif Et (Gün 1-2)

  • ConvertToHLSJob'u güncelle (local + Bunny, enc.bin HARİÇ)
  • HLSService MP3 fallback'ları güncelle
  • SongObserver silme işlemlerini güncelle
  • Test: Yeni şarkı yükle, Bunny'de görün
3

Batch Migration (Gün 2-3)

  • MigrateToBunnyCommand yaz
  • --dry-run ile test et
  • Chunk chunk migrate et (100'lük gruplar)
  • ~280 GB transfer (~4-8 saat)
  • enc.bin dosyaları yüklenmez!
4

Cutover (Gün 3)

  • SongStreamController URL'leri Bunny'e çevir
  • BUNNY_STORAGE_ENABLED=true yap
  • Cache temizle
  • Test: Şarkı çal, Bunny'den geldiğini doğrula
  • Key endpoint'in local'den çalıştığını doğrula
5

İzleme (Sonraki Hafta)

  • Bunny Statistics'i izle
  • Cache HIT oranını kontrol et
  • Hata loglarını takip et
  • Local dosyalar yerinde kalır (silinmez!)

Özet — Kesinleşen Plan

Sunucu

  • ✅ Tüm dosyalar kalır
  • ✅ Master kopya
  • ✅ enc.bin burada
  • ✅ Key endpoint burada

Bunny

  • ✅ HLS dosyaları (enc.bin hariç)
  • ✅ MP3 fallback'lar
  • ✅ CDN öncelikli serve
  • ❌ Şifreleme dosyaları yok

Şifreleme

  • ✅ AES-128 aynen
  • ✅ Key endpoint aynen
  • ✅ enc.bin local'de
  • ✅ Kod değişikliği yok

Sonuç: Hibrit mod ile hem güvenlik hem performans. Sunucudaki dosyalar her zaman yedek olarak kalır, Bunny sadece CDN katmanı. Şifreleme sistemi hiç değişmez, enc.bin asla Bunny'e yüklenmez.