Laravel uygulamanızı yerel makinede php artisan serve ile çalıştırmak kolaydır; ancak canlı ortamda bu komut kullanılmaz. Gerçek bir sunucuda istekleri Nginx karşılar, PHP kodunu PHP-FPM çalıştırır, kuyruk işlerini sürekli ayakta duran worker süreçleri işler, zamanlanmış görevleri ise dakikada bir tetiklenen tek bir cron satırı yönetir. Bu parçalardan biri eksik kaldığında site açılır ama e-postalar gitmez, raporlar üretilmez ya da ilk yoğunlukta 502 hatası görürsünüz.

Bu rehberde temiz bir Ubuntu 24.04 LTS sunucuya, Docker kullanmadan, Laravel belgelerindeki resmî Nginx yapılandırmasıyla bir uygulamayı adım adım yayına alacağız: paket kurulumu, kullanıcı ve dizin düzeni, izinler, .env, önbellekleme, Supervisor ile kuyruk, scheduler cron satırı, Let's Encrypt ve güncelleme akışı. Komutlar Laravel 13.x belgelerine göre hazırlandı; alan adı yerine ornek.com, şifre yerine GUCLU_BIR_SIFRE yazdık.

Gereksinimler ve sürüm seçimi

Gereksinimler ve sürüm seçimi: İşletim sistemi, php8.3-fpm, Web sunucusu, Kuyruk yöneticisi

Laravel 13, 17 Mart 2026'da yayımlandı ve en az PHP 8.3 ister; desteklenen aralık PHP 8.3 - 8.5'tir. Laravel 12 ise PHP 8.2 - 8.5 ile çalışır ve güvenlik yamaları 24 Şubat 2027'ye kadar sürer. Ubuntu 24.04 deposundaki PHP sürümü 8.3 olduğu için iki sürüm de ek depo eklemeden kurulabilir. Laravel her major sürüme 18 ay hata düzeltmesi, 2 yıl güvenlik düzeltmesi verir.

BileşenBu rehberdeki seçimNot
İşletim sistemiUbuntu 24.04 LTSDepoda PHP 8.3 bulunur
PHPphp8.3-fpmLaravel 13 için asgari sürüm
Web sunucusuNginxLaravel belgelerindeki örnek yapılandırma
Kuyruk yöneticisiSupervisorLaravel belgelerinin anlattığı yöntem
ZamanlayıcıcronDakikada bir schedule:run
VeritabanıMySQL veya PostgreSQLAynı sunucuda, yalnızca localhost

Laravel belgelerine göre gerekli PHP eklentileri Ctype, cURL, DOM, Fileinfo, Filter, Hash, Mbstring, OpenSSL, PCRE, PDO, Session, Tokenizer ve XML'dir. Ubuntu'da bunların bir kısmı php8.3-common ile gelir; geri kalanını aşağıdaki paketler tamamlar.

1. Paketleri kurun

bash
sudo apt update
sudo apt install nginx php8.3-fpm php8.3-cli php8.3-mbstring php8.3-xml \
  php8.3-curl php8.3-mysql php8.3-zip php8.3-intl php8.3-bcmath unzip git

# Eklentileri doğrulayın
php -m | grep -Ei "ctype|curl|dom|fileinfo|filter|hash|mbstring|openssl|pcre|pdo|session|tokenizer|xml"

PostgreSQL kullanacaksanız php8.3-mysql yerine php8.3-pgsql kurun. Composer için Ubuntu deposunda bir composer paketi vardır, ancak sürümü geride kalır. Composer: Download sayfasındaki resmî kurulum betiğini kullanın; sayfa her sürümde değişen bir SHA-384 doğrulaması içerdiği için komutları oradan kopyalayın ve çıkan composer.phar dosyasını /usr/local/bin/composer olarak taşıyın.

Veritabanını MySQL veya PostgreSQL rehberine göre kurun ve uygulamaya özel bir kullanıcı açın. MySQL için örnek:

sql
CREATE DATABASE laravel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'laravel'@'localhost' IDENTIFIED BY 'GUCLU_BIR_SIFRE';
GRANT ALL PRIVILEGES ON laravel.* TO 'laravel'@'localhost';
FLUSH PRIVILEGES;

2. Kullanıcı ve dizin düzeni

Kodu root ile değil, ayrı bir deploy kullanıcısıyla yönetin. Ubuntu'da PHP-FPM varsayılan havuzu www-data kullanıcısıyla çalışır. Düzen şöyle olsun: dosyaların sahibi deploy, grubu www-data; PHP yalnızca yazması gereken iki dizine yazabilsin.

bash
sudo adduser --disabled-password --gecos "" deploy
sudo usermod -aG www-data deploy
sudo mkdir -p /var/www/laravel
sudo chown deploy:www-data /var/www/laravel

# Kodu deploy kullanıcısıyla çekin
sudo -u deploy git clone https://github.com/KULLANICI/PROJE.git /var/www/laravel
cd /var/www/laravel
sudo -u deploy composer install --no-dev --optimize-autoloader --no-interaction

Composer belgelerine göre --no-dev, require-dev paketlerini atlar; --optimize-autoloader ise PSR-4 yüklemesini classmap'e çevirir ve özellikle canlı ortam için önerilir.

3. .env ve uygulama anahtarı

bash
sudo -u deploy cp .env.example .env
sudo -u deploy nano .env
ini
APP_NAME=Laravel
APP_ENV=production
APP_DEBUG=false
APP_URL=https://ornek.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=GUCLU_BIR_SIFRE
bash
# Yalnızca ilk kurulumda
sudo -u deploy php artisan key:generate

4. İzinler: storage ve bootstrap/cache

4. İzinler: storage ve bootstrap/cache

Laravel belgelerine göre uygulama storage ve bootstrap/cache dizinlerine yazmak zorundadır ve web sunucusu sürecinin sahibi bu dizinlere yazabilmelidir. Tüm projeye 777 vermek yerine yalnızca bu iki dizini grup için yazılabilir yapın. Setgid biti (2775) sayesinde içeride oluşan yeni dosyalar da www-data grubunu devralır.

bash
cd /var/www/laravel
sudo chown -R deploy:www-data /var/www/laravel
sudo find storage bootstrap/cache -type d -exec chmod 2775 {} \;
sudo find storage bootstrap/cache -type f -exec chmod 664 {} \;
sudo chmod 640 .env

Bundan sonra çalışma anında dosya üreten Artisan komutlarını PHP-FPM ile aynı kullanıcıyla, yani sudo -u www-data php artisan ... şeklinde çalıştırın. Böylece log ve önbellek dosyaları farklı sahiplerle oluşmaz. İzin mantığı için chmod rehberine göz atabilirsiniz.

bash
sudo -u www-data php artisan migrate --force
sudo -u deploy php artisan storage:link
sudo -u www-data php artisan optimize

optimize komutu yapılandırma, olay, rota ve view önbelleklerini tek seferde üretir; tek tek config:cache, event:cache, route:cache ve view:cache de çalıştırabilirsiniz. Temizlemek için php artisan optimize:clear kullanılır.

5. Nginx yapılandırması

Laravel belgelerindeki örneği temel alıyoruz. En önemli kural: belge kökü projenin kendisi değil public dizinidir. index.php dosyasını proje köküne taşımak .env gibi hassas dosyaları internete açar. Server block mantığı için Nginx server block rehberine bakabilirsiniz.

bash
sudo nano /etc/nginx/sites-available/laravel
nginx
server {
    listen 80;
    listen [::]:80;
    server_name ornek.com www.ornek.com;
    root /var/www/laravel/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;
    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_buffer_size 32k;
        fastcgi_buffers 8 32k;
        fastcgi_busy_buffers_size 64k;
        fastcgi_hide_header X-Powered-By;
    }

    location ~ \.php$ {
        return 404;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
bash
sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Bu yapılandırmada yalnızca index.php PHP-FPM'e gider; public içine yanlışlıkla bırakılmış başka bir .php dosyası 404 döner. $realpath_root kullanımı ileride sembolik bağlantıyla sürüm değiştirdiğinizde PHP'nin doğru dizini görmesini sağlar. PHP-FPM havuz ayarları (pm.max_children vb.) için PHP-FPM yapılandırma rehberine bakın.

6. Let's Encrypt ile HTTPS

DNS kaydı sunucuya yönlendikten sonra Certbot'un resmî talimatındaki snap kurulumunu kullanın. Ayrıntılı anlatım Let's Encrypt SSL kurulumu yazısında.

bash
sudo ufw allow 'Nginx Full'
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
sudo certbot --nginx -d ornek.com -d www.ornek.com
sudo certbot renew --dry-run

7. Kuyruk worker'ları: Supervisor

queue:work uzun ömürlü bir süreçtir; zaman aşımı veya queue:restart komutu gibi nedenlerle durabilir. Laravel belgeleri bu yüzden süreçleri izleyip otomatik yeniden başlatan bir süreç yöneticisi ister ve Linux için Supervisor yapılandırmasını anlatır.

bash
sudo apt install supervisor
sudo nano /etc/supervisor/conf.d/laravel-worker.conf
ini
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/laravel/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/laravel/storage/logs/worker.log
stopwaitsecs=3600
bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start "laravel-worker:*"
sudo supervisorctl status

8. Scheduler için cron satırı

Laravel'in zamanlayıcısı, dakikada bir çalışan tek bir cron girdisiyle tetiklenir. Belgelerdeki satır şudur; yalnızca proje yolunu kendinize göre değiştirin ve www-data kullanıcısının crontab'ına ekleyin:

bash
sudo crontab -u www-data -e
bash
* * * * * cd /var/www/laravel && php artisan schedule:run >> /dev/null 2>&1

Görevlerin listesini sudo -u www-data php artisan schedule:list ile kontrol edebilirsiniz. Cron sözdizimi için crontab rehberine bakın.

9. Güncelleme (deploy) akışı

Tek dizinde çalışan basit bir kurulum için aşağıdaki sıra güvenlidir. php artisan down bakım modunu açar; Laravel belgeleri, Composer bağımlılıkları güncellenirken bakım sayfasının bile hata verebileceğini, bunun için --render="errors::503" seçeneğiyle önceden derlenmiş bir sayfa kullanılabileceğini belirtir.

bash
cd /var/www/laravel
sudo -u www-data php artisan down --render="errors::503"
sudo -u deploy git pull
sudo -u deploy composer install --no-dev --optimize-autoloader --no-interaction
sudo -u www-data php artisan migrate --force
sudo -u www-data php artisan optimize
sudo -u www-data php artisan reload
sudo systemctl reload php8.3-fpm
sudo -u www-data php artisan up

php artisan reload, Laravel 13 belgelerinde kuyruk worker'ları gibi uzun ömürlü servisleri yeni kodu kullanmaları için sonlandıran komut olarak geçer; Supervisor onları yeniden başlatır. Eski sürümlerde bunun yerine php artisan queue:restart kullanın; bu komut worker'ların mevcut işi bitirip çıkmasını sağlar ve yeniden başlatma sinyali için çalışan bir önbellek sürücüsü ister.

Kesintisiz dağıtım istiyorsanız her sürümü releases/ altında ayrı bir dizine kurup hazır olunca current adlı sembolik bağlantıyı yeni dizine çevirebilirsiniz. Bu durumda Nginx kökü /var/www/laravel/current/public olur, storage ve .env ise sürümler arasında paylaşılan bir dizinden bağlanır. Bu süreci otomatikleştirmek için GitHub Actions ile VPS'e deploy rehberine bakın.

10. Loglar ve izleme

10. Loglar ve izleme: Laravel uygulama logu, Kuyruk worker çıktısı, Nginx, PHP-FPM
Ne?Nerede?
Laravel uygulama logu/var/www/laravel/storage/logs/laravel.log
Kuyruk worker çıktısı/var/www/laravel/storage/logs/worker.log
Nginx/var/log/nginx/error.log, access.log
PHP-FPMjournalctl -u php8.3-fpm ve /var/log/php8.3-fpm.log
Supervisor/var/log/supervisor/

Laravel varsayılan olarak /up adresinde bir sağlık rotası sunar; uygulama hatasız açılırsa 200, aksi hâlde 500 döner. Bu adresi Uptime Kuma gibi bir izleme aracına ekleyin. Büyüyen log dosyaları için logrotate rehberine bakın.

Sık karşılaşılan hatalar

  • 502 Bad Gateway: PHP-FPM çalışmıyor veya Nginx'teki soket yolu yanlış. systemctl status php8.3-fpm ve ls /var/run/php/ ile kontrol edin. Genel teşhis için 502/504 rehberi.
  • laravel.log: Permission denied: Artisan komutunu root ile çalıştırdığınızda log veya önbellek dosyası root'a ait oluşur. Sahipliği chown -R deploy:www-data storage bootstrap/cache ile düzeltin ve komutları www-data ile çalıştırın. single ve daily log kanallarında permission seçeneğiyle dosya izni de ayarlanabilir.
  • 500 hatası ve boş sayfa: APP_KEY boş, .env okunamıyor ya da önbellekte eski yapılandırma kalmış olabilir. storage/logs/laravel.log dosyasına bakın, gerekirse optimize:clear ardından optimize çalıştırın.
  • Kuyruk işleri eski kodla çalışıyor: Deploy sonrası worker'lar yeniden başlatılmamış. reload veya queue:restart adımını atlamayın.
  • Zamanlanmış görevler çalışmıyor: Cron satırı yanlış kullanıcıda veya proje yolu hatalı. grep CRON /var/log/syslog ile tetiklenip tetiklenmediğine bakın.
  • 413 Request Entity Too Large: Nginx'te client_max_body_size, PHP'de upload_max_filesize ve post_max_size değerlerini birlikte artırın.

Yedekleme

Kod Git'te durur; asıl yedeklemeniz gerekenler veritabanı, .env dosyası ve storage/app altındaki kullanıcı yüklemeleridir. Veritabanı dökümü için veritabanı yedekleme stratejileri, dosyaları başka bir sunucuya kopyalamak için rsync ile yedekleme yazılarına bakın. Büyük bir güncellemeden önce snapshot almak da iyi bir alışkanlıktır.

Sık Sorulan Sorular

Laravel 12 kullanıyorum, bu rehber geçerli mi?

Büyük ölçüde evet. Nginx yapılandırması, izinler, Supervisor ve cron satırı aynıdır. Laravel 12 PHP 8.2 ile de çalışır; php artisan reload yerine queue:restart kullanmanız gerekebilir. Komutlardan emin değilseniz php artisan list çıktısına bakın.

Supervisor yerine systemd kullanabilir miyim?

Kullanabilirsiniz; önemli olan süreç çıktığında otomatik olarak yeniden başlatılmasıdır. Ancak Laravel belgeleri Supervisor'ı örnekler ve numprocs ile birden çok worker'ı tek dosyadan yönetmek orada daha kolaydır.

route:cache her projede güvenli mi?

Laravel belgeleri route:cache komutunu özellikle çok sayıda rotası olan uygulamalar için önerir. Rotalarınız düzgün tanımlıysa sorun çıkmaz; bir hata görürseniz route:clear ile önbelleği silip logu inceleyin.

Aynı sunucuda Laravel Octane veya FrankenPHP kullanabilir miyim?

Laravel belgeleri FrankenPHP'yi de bir seçenek olarak anar. Bu rehber klasik Nginx + PHP-FPM düzenini anlatır; Octane uzun ömürlü süreçlerle çalıştığı için farklı bir yapılandırma ve bellek yönetimi gerektirir.

Yazılım ve hizmet adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen projeler veya şirketlerle ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: Next.js VPS deploy · Django + Gunicorn + Nginx · FastAPI + Uvicorn deploy · GitHub Actions ile VPS deploy · PHP-FPM yapılandırması · Nginx server block · Let's Encrypt kurulumu · VPS güvenlik sertleştirme