Web Hosting & cPanel

    Laravel Projesini Paylaşımlı Hostinge Yükleme: cPanel Adım Adım

    Laravel'i paylaşımlı hostinge güvenle kurmanın yolu: proje kökünü public_html dışında tutmak, index.php yollarını düzeltmek ve izinleri doğru vermek.

    12 dk okuma Güncellendi: 18 Ağustos 2026

    Yerelde php artisan serve ile kusursuz çalışan proje, cPanel'e yüklendikten sonra ya bomboş bir dizin listesi ya da tek satırlık bir 500 Internal Server Error veriyor. İlk refleks arama kutusuna "laravel cpanel kurulum" yazmak oluyor ve karşınıza çıkan onlarca rehber neredeyse aynı şeyi söylüyor: projeyi olduğu gibi public_html içine at, public klasörünün içindekileri bir üst dizine taşı, index.php içindeki iki satırı düzelt, bitti.

    Bu yöntem gerçekten çalışır. Site açılır, formlar gönderilir, hiçbir hata görünmez. Görünmeyen şey şudur: aynı anda https://siteniz.com/.env adresi de açılır ve tarayıcı veritabanı şifrenizi, APP_KEY değerinizi, varsa ödeme sağlayıcısı ve mail servisi anahtarlarınızı düz metin olarak indirir. Yanına storage/logs/laravel.log da gelir — içinde geçmiş hataların stack trace'leri, bazen kullanıcı e-postaları ve sorgu parametreleri vardır.

    Bu rehber iki şeyi yapar: önce neden bu kadar yaygın bir tavsiyenin bu kadar riskli olduğunu somut olarak gösterir, sonra paylaşımlı bir cPanel hesabında Laravel'i doğru dizin yapısıyla kurmanın tam adımlarını verir. SSH erişiminiz varsa da yoksa da uygulanabilecek iki ayrı yol anlatılıyor.

    Laravel Neden Doğrudan public_html'e Atılmaz?#

    Laravel, "tek giriş noktası" (front controller) mimarisiyle çalışır. Web sunucusuna gelen her istek public/index.php dosyasına düşer; framework yönlendirmeyi, oturumu ve yanıtı oradan yönetir. Bu tasarımın doğal sonucu şudur: web kökünde sadece public klasörünün içeriği bulunmalıdır. Diğer her şey — uygulama kodu, konfigürasyon, bağımlılıklar, loglar — bir üst dizinde, tarayıcının hiç ulaşamadığı yerde durur.

    Paylaşımlı hostingte web kökü genellikle /home/kullanici/public_html klasörüdür ve bu klasörün altındaki her dosya, aksi belirtilmedikçe, bir URL ile indirilebilir. Laravel projesinin tamamını buraya kopyaladığınızda aşağıdaki dosyalar da adreslenebilir hale gelir:

    Dosya / klasörİçinde ne varSızarsa sonucu
    .envDB şifresi, APP_KEY, API anahtarlarıVeritabanına doğrudan erişim, oturum çerezlerinin taklit edilmesi
    storage/logs/laravel.logHata izleri, sorgu parametreleriDosya yolları, tablo isimleri, bazen kullanıcı verisi
    composer.json / composer.lockPaket sürümleriBilinen açığı olan sürümlerin tespiti
    database/migrationsTam şemaTablo ve kolon isimleri, saldırı yüzeyi haritası
    .git/Sürüm geçmişiSilinmiş şifrelerin eski commit'lerden çıkarılması
    .env.backup, .env.exampleDeğişken adlarıHangi servislerin kullanıldığı

    Bu liste teorik bir risk tarifi değil; internette otomatik tarayıcılar tam olarak bu yolları saniyeler içinde deneyerek gezinir. Yeni bir alan adı yayına alındıktan sonra ilk .env isteğinin gelmesi genellikle birkaç saati bulmaz.

    "public Klasörünü public_html'e Kopyala" Tavsiyesi Ne Zarar Verir?#

    Yaygın anlatımın iki varyantı var ve ikisi de aynı yere çıkıyor:

    Varyant 1 — Her şeyi public_html içine atmak. Site siteniz.com/public/ gibi çirkin bir adresten açılır. Kaynak kodun tamamı web kökündedir.

    Varyant 2 — Her şeyi public_html içine atıp public içeriğini bir üst dizine taşımak. URL düzelir, ancak app/, config/, vendor/, .env hâlâ public_html altındadır. Görüntü temizdir, risk aynıdır.

    Kurulumunuzun hangi durumda olduğunu tahmin etmeyin, ölçün. Kendi sunucunuza şu isteği atın:

    # 200 dönüyorsa .env dosyanız internete açıktır
    curl -s -o /dev/null -w "%{http_code}\n" https://siteniz.com/.env
    
    # Log dosyası ve Composer manifesti de kontrol edilmeli
    curl -s -o /dev/null -w "%{http_code}\n" https://siteniz.com/storage/logs/laravel.log
    curl -s -o /dev/null -w "%{http_code}\n" https://siteniz.com/composer.json
    

    403 veya 404 beklenen cevaptır. 200 görüyorsanız kurulum aynı gün düzeltilmeli, ardından veritabanı şifresi ve tüm API anahtarları değiştirilmelidir — dosya bir kez indirildiyse geri alınamaz.

    .htaccess ile Kapatmak Neden Yeterli Bir Çözüm Değil?#

    Bu noktada akla gelen ilk çözüm, public_html/.htaccess dosyasına birkaç Deny kuralı yazmaktır:

    <FilesMatch "^\.env|composer\.(json|lock)$">
        Require all denied
    </FilesMatch>
    

    Bu kural işe yarar, ama tek başına güvenlik katmanı olarak kabul edilemez. Nedenleri:

    • Tek dosyaya bağlı. .htaccess yanlışlıkla silinir, bir eklenti tarafından üzerine yazılır veya yedekten geri yüklenirken kaybolursa koruma sessizce ortadan kalkar. Yanlış bir yönlendirme kuralı yazdığınızda site çöker; kural yanlış olduğunda ise hiçbir alarm vermez.
    • Liste tutmak gerekir. .env engellersiniz, .env.bak unutulur. storage/ kapatılır, bootstrap/cache unutulur.
    • Sunucu yazılımına bağlıdır. Apache'nin AllowOverride ayarı kısıtlıysa kurallarınız hiç okunmaz. LiteSpeed büyük ölçüde uyumludur ama Nginx tabanlı bir kurulumda .htaccess tamamen yok sayılır.

    Dosyayı web kökünün dışına koymak ise bir yapılandırmaya değil, dizin yapısına dayanır. Yanlışlıkla "kapanması" mümkün değildir. .htaccess kurallarının nasıl yazıldığını merak ediyorsanız .htaccess yönlendirme kuralları yazısı ayrı bir konu olarak bunu ele alıyor.

    Kuruluma Başlamadan Önce: Hosting Gereksinimleri#

    Laravel'in bir paylaşımlı hesapta çalışıp çalışmayacağı, dosyaları yüklemeden önce beş dakikada anlaşılır. Sürüm gereksinimleri Laravel'in kendi sürümüne göre değişir: Laravel 11 ve 12 en az PHP 8.2, Mart 2026'da çıkan Laravel 13 ise en az PHP 8.3 ister (13.3 ve sonrası pratikte PHP 8.4 gerektiren Symfony bileşenleri getirir).

    GereksinimNasıl kontrol edilirEksikse
    PHP 8.2+cPanel → MultiPHP ManagerAlan adı için sürümü yükseltin
    mbstring, openssl, pdo_mysql, tokenizer, xml, ctype, json, bcmath, fileinfo, curlcPanel → Select PHP Version → ExtensionsEksik olanı işaretleyin
    SSH / TerminalcPanel → Terminal veya SSH AccessComposer'ı yerelde çalıştırın
    symlink() fonksiyonuphp -r "var_dump(function_exists('symlink'));"storage:link yerine gerçek klasör kullanın
    proc_open, proc_get_statusComposer sunucuda çalışacaksa gerekirYerelde vendor üretip yükleyin
    Bellek limiti ≥ 256 MBphp -i | grep memory_limitComposer sunucuda çalışmayabilir

    Kontrolleri terminalden yapmak en hızlısıdır:

    # cPanel'de PHP CLI sürümü, web sürümünden FARKLI olabilir
    php -v
    /opt/cpanel/ea-php83/root/usr/bin/php -v
    
    # Yüklü eklentileri listele
    php -m | sort
    
    # Composer var mı?
    composer --version || php ~/composer.phar --version
    

    Terminal sekmesini hiç görmediyseniz cPanel'de SSH erişimi ve terminal kullanımı yazısı erişimi açmayı anlatıyor. PHP sürümünü alan adı bazında değiştirme konusunda ise PHP sürüm yönetimi rehberi işinizi görür.

    Doğru Dizin Yapısı: Proje Kökü public_html Dışında#

    Hedeflediğimiz yerleşim şu:

    /home/kullanici/
    ├── laravel-app/            <-- proje kökü, WEB'DEN ERİŞİLEMEZ
    │   ├── app/
    │   ├── bootstrap/
    │   ├── config/
    │   ├── database/
    │   ├── resources/
    │   ├── routes/
    │   ├── storage/
    │   ├── vendor/
    │   ├── artisan
    │   └── .env
    └── public_html/            <-- web kökü, SADECE public içeriği
        ├── index.php           (yolları düzeltilmiş)
        ├── .htaccess
        ├── robots.txt
        ├── favicon.ico
        └── build/  (Vite çıktısı)
    

    Ek alan adı (addon domain) kullanıyorsanız web kökü genellikle /home/kullanici/public_html/ikincisite.com olur. Mantık değişmez: proje kökü o klasörün dışında, örneğin /home/kullanici/ikincisite-app içinde durur.

    Adım Adım Kurulum (SSH Erişimi Varsa)#

    1. Projeyi sunucuya alın#

    Git kullanıyorsanız en temiz yol doğrudan klonlamaktır. cPanel'in kendi Git arayüzü de aynı işi görür; ayrıntılar cPanel Git sürüm kontrolü yazısında.

    cd ~
    git clone https://github.com/kullanici/projem.git laravel-app
    cd laravel-app
    

    Git yoksa projeyi yerelde zip'leyip File Manager ile yükleyin ve ~/laravel-app içine çıkarın. Zip'e node_modules klasörünü koymayın; sunucuda hiçbir işe yaramaz ve inode kotanızı tüketir.

    2. Bağımlılıkları kurun#

    composer install --no-dev --optimize-autoloader
    

    --no-dev bayrağı test ve geliştirme paketlerini atlar; bu hem yükleme süresini hem de disk ve inode kullanımını ciddi biçimde düşürür. Bellek hatası alırsanız:

    php -d memory_limit=-1 ~/composer.phar install --no-dev --optimize-autoloader
    

    3. .env dosyasını oluşturun ve anahtarı üretin#

    cp .env.example .env
    php artisan key:generate
    chmod 600 .env
    

    chmod 600 ikinci bir savunma katmanıdır: dosya zaten web kökünün dışındadır, ama aynı sunucudaki diğer hesaplardan okunmasını da engeller.

    4. public içeriğini web köküne taşıyın#

    # Varsa eski içeriği yedekleyin
    mv ~/public_html ~/public_html_eski
    mkdir ~/public_html
    
    # Sadece public klasörünün İÇİNDEKİLERİ kopyalanır
    cp -r ~/laravel-app/public/. ~/public_html/
    

    Dikkat edin: public klasörünün kendisi değil, içeriği kopyalanıyor. Sondaki /. ifadesi gizli dosyaların (.htaccess) da kopyalanmasını sağlar; unutulursa yönlendirme kuralları gelmez ve ana sayfa dışındaki her adres 404 verir.

    5. index.php içindeki yolları düzeltin#

    Bu, tüm kurulumun kilit adımıdır. ~/public_html/index.php dosyasını açın. Laravel 11, 12 ve 13'te ilgili satırlar şöyle görünür:

    if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
        require $maintenance;
    }
    
    require __DIR__.'/../vendor/autoload.php';
    
    $app = require_once __DIR__.'/../bootstrap/app.php';
    
    $app->handleRequest(Request::capture());
    

    Proje kökü artık bir üst dizinde değil, kardeş dizinde olduğu için üç yolun da güncellenmesi gerekir. Yolu tek bir değişkende toplamak, ileride taşıma yaparken tek satır değiştirmenizi sağlar:

    $base = __DIR__.'/../laravel-app';
    
    if (file_exists($maintenance = $base.'/storage/framework/maintenance.php')) {
        require $maintenance;
    }
    
    require $base.'/vendor/autoload.php';
    
    $app = require_once $base.'/bootstrap/app.php';
    
    $app->handleRequest(Request::capture());
    

    Laravel 10 ve öncesindeyseniz dosyanın sonu $kernel = $app->make(Kernel::class); ile devam eder; o satırlara dokunmanız gerekmez, sadece yukarıdaki üç __DIR__ yolunu değiştirin.

    6. İzinleri ayarlayın#

    Paylaşımlı hostingte PHP, hesabınızın kullanıcısı olarak çalışır. Bu nedenle 777 vermeye gerek yoktur ve verilmemelidir; klasörü sunucudaki diğer süreçlere de açar.

    cd ~/laravel-app
    find . -type d -exec chmod 755 {} \;
    find . -type f -exec chmod 644 {} \;
    chmod -R 775 storage bootstrap/cache
    chmod 600 .env
    chmod 755 ~/public_html
    

    İzin bitlerinin ne anlama geldiğini tazelemek isterseniz Linux dosya izinleri yazısı sayı-harf karşılıklarını ayrıntılı anlatıyor.

    7. storage bağlantısını kurun#

    php artisan storage:link komutu, sembolik bağı public/storage altına oluşturur — ama sizin web kökünüz artık public değil. Bağı elle kurun:

    ln -s /home/kullanici/laravel-app/storage/app/public /home/kullanici/public_html/storage
    ls -l ~/public_html/storage
    

    ls -l çıktısında ok işaretiyle hedef yol görünmelidir. Hedef yolu mutlak yazın; göreli yol (../laravel-app/...) File Manager üzerinden yapılan taşımalarda kolayca kırılır. Sunucuda symlink() kapalıysa alternatif, FILESYSTEM_DISK ayarını değiştirip yüklemeleri doğrudan public_html/uploads altına almaktır.

    SSH Yoksa: Composer'sız Kurulum#

    Ekonomik paketlerde terminal kapalı olabilir. Bu durumda ağır işleri yerelde yapıp sunucuya hazır çıktı gönderirsiniz:

    1. Yerelde composer install --no-dev --optimize-autoloader çalıştırın — vendor/ klasörü oluşsun.
    2. Yerelde php artisan key:generate --show ile bir anahtar üretin ve çıktıyı not edin.
    3. node_modules hariç tüm projeyi zip'leyin. vendor/ dahil olmalı.
    4. cPanel File Manager ile zip'i /home/kullanici/ altına yükleyip laravel-app klasörüne çıkarın.
    5. .env dosyasını File Manager'ın "Edit" özelliğiyle oluşturun; APP_KEY alanına 2. adımdaki değeri yapıştırın.
    6. public içeriğini public_htmle kopyalayın ve index.php yollarını yukarıdaki gibi düzeltin.
    7. Migration'ları çalıştıramayacağınız için şemayı yerelde mysqldump ile alıp phpMyAdmin üzerinden içe aktarın.

    Bu yöntemin tek dezavantajı, her güncellemede vendor klasörünü yeniden yüklemek zorunda kalmanızdır. Uzun vadede terminal erişimi olan bir pakete geçmek hem hızlı hem de daha az hataya açıktır.

    Veritabanı ve Üretim Ayarları#

    cPanel'de veritabanı ve kullanıcı adları hesap adınızla ön eklenir: kullanici_laravel gibi. Bu ön eki .env içine olduğu gibi yazın; kullanıcıyı veritabanına eklemeyi ve "ALL PRIVILEGES" vermeyi unutmayın. Bağlantı bilgilerini nereden alacağınız konusunda veritabanı bilgileri nereden bulunur yazısı kısa bir referans.

    AnahtarÜretim değeriNeden
    APP_ENVproductionGeliştirme uyarılarını ve bazı debug davranışlarını kapatır
    APP_DEBUGfalseHata sayfasında dosya yolları ve .env içeriği gösterilmez
    APP_URLhttps://siteniz.comasset() ve url() yardımcılarının doğru adres üretmesi için
    LOG_LEVELerrorLog dosyasının diski ve inode kotasını doldurmasını önler
    SESSION_DRIVERdatabase veya filePaylaşımlı hostingte Redis genellikle yoktur
    QUEUE_CONNECTIONdatabaseDaemon çalıştırılamadığı için Redis/SQS uygun değildir

    Ardından şema ve önbellek:

    php artisan migrate --force
    php artisan optimize
    

    --force bayrağı, production ortamında onay sorusunu atlar; bu yüzden migration dosyalarınızın doğruluğundan emin olun. php artisan optimize komutu Laravel 11+ sürümlerinde config, route, view ve event önbelleklerini birlikte üretir. Her .env düzenlemesinden sonra php artisan config:clear çalıştırmayı unutmayın — önbellek üretildikten sonra .env okunmaz ve değişiklikleriniz görünmez hale gelir. Bu, kurulum sonrası en sık yaşanan kafa karışıklığıdır.

    Zamanlanmış Görevler ve Kuyruklar: Paylaşımlı Hostingin Sınırları#

    Laravel'in zamanlayıcısı tek bir cron kaydıyla çalışır. cPanel → Cron Jobs bölümüne dakikalık bir görev ekleyin ve web PHP'sini değil, CLI yolunu kullanın:

    * * * * * /opt/cpanel/ea-php83/root/usr/bin/php /home/kullanici/laravel-app/artisan schedule:run >> /dev/null 2>&1
    

    Kuyruklar farklı bir hikâye. php artisan queue:work kalıcı bir süreçtir; paylaşımlı hostingte uzun ömürlü süreçler genellikle birkaç dakika içinde sonlandırılır. Pratik çözüm, kuyruğu cron ile aralıklı boşaltmaktır:

    */5 * * * * /opt/cpanel/ea-php83/root/usr/bin/php /home/kullanici/laravel-app/artisan queue:work --stop-when-empty --max-time=240 >> /dev/null 2>&1
    

    Horizon, Reverb, WebSocket sunucusu ve Octane paylaşımlı pakette çalışmaz — hepsi kalıcı süreç ister. Uygulamanız bunlara bağımlıysa doğru adım hosting ayarlarıyla uğraşmak değil, bir sanal sunucuya geçmektir.

    Sık Karşılaşılan Hatalar ve Çözümleri#

    BelirtiSebepÇözüm
    Bembeyaz sayfa, 500storage/logs yazılamıyorchmod -R 775 storage bootstrap/cache
    No application encryption key has been specifiedAPP_KEY boşphp artisan key:generate, sonra config:clear
    Failed to open stream: vendor/autoload.phpindex.php yolları düzeltilmemiş5. adımdaki $base değişikliği
    Ana sayfa açılıyor, alt sayfalar 404.htaccess kopyalanmamışcp ~/laravel-app/public/.htaccess ~/public_html/
    CSS/JS 404, karışık içerik uyarısıAPP_URL yanlış veya http://APP_URL düzelt + php artisan optimize:clear
    419 Page ExpiredSession yazılamıyorSESSION_DRIVER=database + sessions tablosu
    Yüklenen görseller 404storage symlink yok/kırıkMutlak yolla ln -s yeniden kur
    .env değişikliği etkisizConfig önbelleği eskiphp artisan config:clear

    Hata mesajını hiç göremiyorsanız kaynak, uygulama logu değil web sunucusu logudur. cPanel → Errors ekranı veya ~/logs altındaki dosyalar genellikle asıl PHP hatasını verir; cPanel hata kayıtlarını okuma yazısı bu ekranı ayrıntılı anlatıyor.

    Son bir güvenlik kontrolü: kurulum bittikten sonra makalenin başındaki curl testlerini tekrar çalıştırın. .env, composer.json ve log dosyası artık 404 dönmelidir. Dönüyorsa yapı doğru; dönmüyorsa public_html içinde hâlâ proje dosyaları var demektir.

    Sıkça Sorulan Sorular#

    Laravel paylaşımlı hostingte gerçekten sorunsuz çalışır mı?#

    Standart bir web uygulaması için evet. Yönlendirme, Blade şablonları, Eloquent, oturum yönetimi ve dosya yükleme paylaşımlı bir cPanel hesabında sorunsuz çalışır. Sınır, kalıcı süreç gerektiren bileşenlerdedir: Horizon, Reverb, Octane ve sürekli çalışan kuyruk işçileri paylaşımlı pakette desteklenmez. Trafiğiniz arttıkça PHP işlem limiti de darboğaza dönüşür.

    Proje kökünü public_html dışına koyamıyorsam ne yapmalıyım?#

    Bazı çok kısıtlı paketlerde ana dizine yazma yetkisi olmayabilir. Bu durumda proje kökünü public_html/uygulama gibi bir alt klasöre koyup o klasörü .htaccess ile tamamen kapatmak geçici bir çözümdür. Ancak koruma tek bir dosyaya bağlı kalır; kalıcı çözüm ana dizine yazma izni veren bir pakete geçmektir.

    vendor klasörünü FTP ile yüklemek neden çok uzun sürüyor?#

    vendor içinde on binlerce küçük dosya bulunur ve FTP her dosya için ayrı bir bağlantı turu yapar. Klasörü tek bir zip olarak yükleyip sunucuda çıkarmak süreyi dakikalara indirir. Ayrıca --no-dev bayrağıyla kurulum yapmak dosya sayısını gözle görülür biçimde azaltır ve inode kotanızı korur.

    php artisan komutlarını terminal olmadan çalıştırabilir miyim?#

    Doğrudan hayır. Bazı geliştiriciler bunun için geçici bir rota tanımlayıp Artisan::call() kullanır, ancak bu rota internete açık kalırsa ciddi bir güvenlik açığıdır. Daha güvenli yol, komutu cPanel'in Cron Jobs ekranından tek seferlik çalıştırıp ardından kaydı silmektir; çıktıyı e-posta olarak alabilirsiniz.

    Deploy sonrası site eski hâlini gösteriyorsa ne yapmalıyım?#

    Neredeyse her zaman önbellek kaynaklıdır. php artisan optimize:clear komutu config, route, view ve event önbelleklerini birlikte temizler. Sunucuda LiteSpeed ya da opcode önbelleği varsa cPanel üzerinden onu da sıfırlayın. Tarayıcı tarafında sert yenileme yapmadan önce sunucu tarafını temizlemek zaman kazandırır.

    Laravel için hangi PHP sürümünü seçmeliyim?#

    Laravel 11 ve 12 için PHP 8.2 alt sınırdır; Laravel 13 en az PHP 8.3 ister. Ancak alt sınırı seçmek yerine, hosting panelinizde bulunan en güncel kararlı sürümü tercih edin — güvenlik yamaları ve performans iyileştirmeleri oradadır. Sürümü değiştirdikten sonra gerekli eklentilerin yeni sürümde de işaretli olduğunu mutlaka kontrol edin.

    LaravelcPanelPHP

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.