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

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şen | Bu rehberdeki seçim | Not |
|---|---|---|
| İşletim sistemi | Ubuntu 24.04 LTS | Depoda PHP 8.3 bulunur |
| PHP | php8.3-fpm | Laravel 13 için asgari sürüm |
| Web sunucusu | Nginx | Laravel belgelerindeki örnek yapılandırma |
| Kuyruk yöneticisi | Supervisor | Laravel belgelerinin anlattığı yöntem |
| Zamanlayıcı | cron | Dakikada bir schedule:run |
| Veritabanı | MySQL veya PostgreSQL | Aynı 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
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:
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.
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-interactionComposer 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ı
sudo -u deploy cp .env.example .env
sudo -u deploy nano .envAPP_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# Yalnızca ilk kurulumda
sudo -u deploy php artisan key:generate4. İ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.
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 .envBundan 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.
sudo -u www-data php artisan migrate --force
sudo -u deploy php artisan storage:link
sudo -u www-data php artisan optimizeoptimize 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.
sudo nano /etc/nginx/sites-available/laravelserver {
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;
}
}sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxBu 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.
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-run7. 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.
sudo apt install supervisor
sudo nano /etc/supervisor/conf.d/laravel-worker.conf[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=3600sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start "laravel-worker:*"
sudo supervisorctl status8. 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:
sudo crontab -u www-data -e* * * * * cd /var/www/laravel && php artisan schedule:run >> /dev/null 2>&1Gö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.
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 upphp 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

| 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-FPM | journalctl -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-fpmvels /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/cacheile düzeltin ve komutlarıwww-dataile çalıştırın.singlevedailylog kanallarındapermissionseçeneğiyle dosya izni de ayarlanabilir. - 500 hatası ve boş sayfa:
APP_KEYboş,.envokunamıyor ya da önbellekte eski yapılandırma kalmış olabilir.storage/logs/laravel.logdosyasına bakın, gerekirseoptimize:clearardındanoptimizeçalıştırın. - Kuyruk işleri eski kodla çalışıyor: Deploy sonrası worker'lar yeniden başlatılmamış.
reloadveyaqueue:restartadı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/syslogile tetiklenip tetiklenmediğine bakın. - 413 Request Entity Too Large: Nginx'te
client_max_body_size, PHP'deupload_max_filesizevepost_max_sizedeğ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