Nextcloud kurulduğu hafta hızlıdır. Sorun genellikle iki ay sonra başlar: dosyalar sekmesi açılırken üç saniye beklersiniz, masaüstü istemcisi "senkronize ediliyor" durumunda takılı kalır, 400 MB'lık bir video yüklerken ilerleme çubuğu %90'da durup hata verir ve yönetim panelinin "Genel Bakış" bölümünde biriken sarı uyarıların sayısı yediye çıkmıştır.
Bu yavaşlığın tek bir sebebi yoktur; üst üste binmiş dört beş varsayılan ayarın toplamıdır. İyi haber şu: neredeyse hepsi yapılandırma dosyalarında çözülür, donanım büyütmeden. Kötü haberse sırayı yanlış tutarsanız haftalarca yanlış yerde arama yapabilirsiniz — çoğu kişi doğrudan PHP-FPM ayarlarına dalar, oysa asıl suçlu genelde arka planda çalışan zamanlanmış görevin nasıl tetiklendiğidir.
Aşağıda önce ölçüm yapacağız, sonra en sık rastlanandan en nadire doğru altı ayarı sırayla kapatacağız: AJAX cron, bellek önbelleği ve dosya kilitleme, PHP-FPM havuz boyutu, eksik veritabanı indeksleri, yükleme limitleri ve son olarak yönetim panelindeki uyarı listesini yol haritası olarak kullanacağız. Nextcloud'a yeni başlıyorsanız ve mimarisini henüz oturtmadıysanız Nextcloud nedir yazısını önce okumanız işinizi kolaylaştırır.
Önce Ölçün: Yavaşlık Sunucudan mı Tarayıcıdan mı Geliyor?#
Ayar değiştirmeden önce sorunun nerede olduğunu belirleyin. Tarayıcıda F12 ile geliştirici araçlarını açıp Ağ (Network) sekmesinde dosya listesi isteğinin süresine bakın.
- Sunucu yanıt süresi (TTFB) 1 saniyenin üzerindeyse sorun PHP veya veritabanı tarafındadır; bu yazının tamamı sizin için.
- TTFB düşük ama sayfa geç oturuyorsa sorun aktarım tarafındadır: sıkıştırma kapalı olabilir, çok sayıda küçük JS/CSS dosyası tek tek indiriliyor olabilir. nginx'te gzip ve brotli sıkıştırma bu tarafı toparlar.
Sunucu tarafında hızlı bir kontrol:
# Nextcloud dizininde, web sunucusu kullanıcısıyla
sudo -u www-data php occ status
sudo -u www-data php occ config:list system | head -40
# Anlık yük ve bekleyen G/Ç
uptime
iostat -x 2 3
# PHP-FPM'de bekleyen istek var mı?
sudo systemctl status php8.3-fpm --no-pager
uptime çıktısındaki yük ortalaması çekirdek sayınızın altındaysa CPU darboğaz değildir. iostat çıktısında %util sürekli 90'ın üzerindeyse disk darboğazdır — bu genelde önizleme üretimi ya da antivirüs taramasıdır, sona bırakacağız. Sunucuyu sürekli izlemek istiyorsanız Netdata ile sunucu izleme kurulumu bu tür sorunları tahmin işi olmaktan çıkarır.
AJAX Cron: Nextcloud Yavaşlığının En Sık Nedeni#
Nextcloud'un arka plan işleri vardır: dosya taraması, önizleme temizliği, bildirim gönderimi, çöp kutusu boşaltma, federasyon senkronizasyonu. Bu işlerin nasıl tetikleneceğini kurulum sırasında seçersiniz ve varsayılan seçenek AJAX'tır.
AJAX modunda arka plan işleri, bir kullanıcı sayfa açtığında o kullanıcının isteği içinde çalışır. Yani kullanıcı dosya listesini görmek isterken, sunucu aynı anda çöp kutusunu temizlemeye çalışır ve kullanıcı bekler. Kurulumun ilk haftasında dosya sayısı azken bu fark edilmez; on binlerce dosyaya çıktığınızda her sayfa açılışı arka plan kuyruğunun bir kısmını sırtlanmaya başlar.
Çözüm, işi kullanıcı isteğinden ayırıp sistem cron'una devretmektir.
1. Nextcloud'a cron modunu bildirin:
sudo -u www-data php occ background:cron
2. Web sunucusu kullanıcısının crontab'ına ekleyin:
sudo crontab -u www-data -e
*/5 * * * * php -f /var/www/nextcloud/cron.php > /dev/null 2>&1
3. Çalıştığını doğrulayın. Yönetim → Temel Ayarlar bölümündeki "Son görev çalıştırma" zaman damgası 5 dakikadan eski görünmemelidir.
Görev tanımlandığı hâlde çalışmıyorsa neredeyse her zaman kullanıcı ya da yol hatasıdır: cron.php dosyası mutlaka web sunucusunun çalıştığı kullanıcıyla (www-data, dağıtıma göre nginx veya apache) çalıştırılmalıdır, root ile çalıştırırsanız dosya sahiplikleri bozulur. Cron sözdizimi ve hata ayıklama için Linux cron görevleri yazısı elinizin altında dursun.
Bu tek değişiklik, 15-20 kullanıcılı kurulumlarda arayüz gecikmesini gözle görülür biçimde düşürür. Diğer ayarlara geçmeden önce bunu yapın; yoksa yaptığınız iyileştirmelerin etkisini ölçemezsiniz.
Redis ve APCu: Bellek Önbelleği ile Dosya Kilitleme#
Nextcloud varsayılan olarak hiçbir bellek önbelleği kullanmaz. Yapılandırma değerlerini, uygulama listesini ve dosya meta verilerini her istekte veritabanından okur. Üstüne bir de dosya kilitleme (transactional file locking) varsayılanda veritabanı üzerinden yürür; birden çok istemci aynı anda senkronize olduğunda veritabanı kilit tablosu darboğaza dönüşür. "Dosya kilitli, lütfen bekleyin" hatasının kaynağı budur.
Doğru kurulum iki katmanlıdır:
| Katman | Ne yapar | Önerilen |
|---|---|---|
memcache.local | Tek sunucudaki yerel önbellek (yapılandırma, uygulama verisi) | APCu |
memcache.distributed | Birden çok sunucu arasında paylaşılan önbellek | Redis |
memcache.locking | İşlemsel dosya kilitleme | Redis (zorunlu) |
Memcached bu iş için uygun değildir: kilitleri saklamak üzere tasarlanmamıştır, veriyi istediği an düşürebilir ve düşen bir kilit veri bozulmasına yol açar. Kilitleme için Redis kullanın.
Kurulum:
sudo apt install -y redis-server php-redis php-apcu
sudo systemctl enable --now redis-server
# PHP-FPM'in redis soketine erişebilmesi için
sudo usermod -aG redis www-data
sudo systemctl restart php8.3-fpm
config/config.php içine ekleyin:
'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
'host' => '/run/redis/redis-server.sock',
'port' => 0,
'timeout' => 1.5,
],
'filelocking.enabled' => true,
TCP yerine unix soketi kullanmak, aynı makinedeki iletişimde ağ katmanını tamamen atlar ve ölçülebilir bir kazanç sağlar. Soket yolunuz farklıysa redis-cli config get unixsocket ile doğrulayın; boş dönerse /etc/redis/redis.conf içinde unixsocket /run/redis/redis-server.sock ve unixsocketperm 770 satırlarını etkinleştirin.
Bir tuzak: occ komutları komut satırından çalışır ve APCu varsayılan olarak CLI'da kapalıdır. php.ini içinde apc.enable_cli = 1 yapmazsanız occ çalıştırdığınızda "APCu is not available" uyarısı alırsınız. Redis'in genel çalışma mantığı ve bellek yönetimi için Redis nedir yazısına bakabilirsiniz.
⚠️ Redis'i asla dışarıya açık portta, parolasız bırakmayın. Varsayılan yapılandırmada kimlik doğrulama yoktur; unix soketi kullanmak bu riski baştan ortadan kaldırır.
PHP-FPM Havuzu 5 Süreçle 20 Kullanıcıyı Taşımaz#
Nextcloud, PHP-FPM havuzunun varsayılan ayarlarıyla dağıtımdan gelir ve bu ayarlar küçük bir web sitesi için tasarlanmıştır. pm.max_children = 5 ile çalışan bir kurulumda, aynı anda senkronize olan altı istemci altıncıyı kuyruğa alır. Kullanıcı bunu "yavaşlık" olarak görür; loglara bakarsanız server reached pm.max_children setting satırını bulursunuz.
Önce gerçekten sınıra dayandığınızı doğrulayın:
sudo grep -i "max_children" /var/log/php8.3-fpm.log | tail -20
Bu satır varsa havuz küçüktür. Yeni değeri tahminle değil hesapla belirleyin:
pm.max_children = (PHP'ye ayırabileceğiniz RAM) ÷ (ortalama süreç belleği)
Ortalama süreç belleğini ölçün:
ps -ylC php-fpm8.3 --sort:rss | awk '{sum+=$8; n++} END {printf "ortalama: %d MB\n", sum/n/1024}'
Nextcloud'da bir PHP süreci tipik olarak 80-160 MB tutar. 8 GB RAM'li bir sunucuda veritabanı ve Redis'e 3 GB ayırdıktan sonra PHP'ye 4 GB kalıyorsa: 4096 ÷ 120 ≈ 34.
; /etc/php/8.3/fpm/pool.d/nextcloud.conf
pm = dynamic
pm.max_children = 34
pm.start_servers = 8
pm.min_spare_servers = 6
pm.max_spare_servers = 12
pm.max_requests = 500
php_admin_value[memory_limit] = 512M
php_admin_value[upload_max_filesize] = 16G
php_admin_value[post_max_size] = 16G
php_admin_value[max_execution_time] = 3600
php_admin_value[max_input_time] = 3600
php_admin_value[output_buffering] = 0
; OPcache — Nextcloud'un uyarı verdiği değerler
php_admin_value[opcache.enable] = 1
php_admin_value[opcache.memory_consumption] = 256
php_admin_value[opcache.interned_strings_buffer] = 32
php_admin_value[opcache.max_accelerated_files] = 20000
php_admin_value[opcache.revalidate_freq] = 60
php_admin_value[opcache.save_comments] = 1
Üç değer özellikle Nextcloud'a özgüdür: memory_limit 512M olmalıdır (Nextcloud süreç başına en az 512 MB önerir ve altındaysa panelde uyarı çıkarır), output_buffering = 0 olmalıdır (aksi halde büyük dosya indirmeleri belleğe yığılır) ve opcache.save_comments = 1 olmalıdır — Nextcloud kod açıklamalarını çalışma anında okur, kapatırsanız kurulum bozulur.
opcache.interned_strings_buffer varsayılanda 8 MB'dır ve Nextcloud bunu neredeyse her zaman doldurur; panelde gördüğünüz "dizgi arabelleği dolmak üzere" uyarısının çözümü budur. PHP-FPM havuz mantığının ayrıntıları için PHP-FPM pool ayarları ve nginx tarafındaki bağlantı için nginx + PHP-FPM yapılandırması yazılarına bakın.
Değişiklikten sonra: sudo systemctl restart php8.3-fpm.
Eksik Veritabanı İndeksleri ve Yarım Kalmış Dönüşümler#
Nextcloud sürüm yükseltmelerinde bazı indeksleri ve sütun dönüşümlerini otomatik uygulamaz; büyük tablolarda uzun sürecekleri için yöneticinin elle çalıştırmasını bekler. Uygulanmadıklarında oc_filecache üzerinde yapılan her sorgu tam tablo taramasına döner — 200 bin dosyalı bir kurulumda bu, dosya listesini açmanın saniyelerce sürmesi demektir.
Bakım moduna alıp sırayla çalıştırın:
sudo -u www-data php occ maintenance:mode --on
sudo -u www-data php occ db:add-missing-indices
sudo -u www-data php occ db:add-missing-columns
sudo -u www-data php occ db:add-missing-primary-keys
sudo -u www-data php occ db:convert-filecache-bigint
sudo -u www-data php occ maintenance:repair --include-expensive
sudo -u www-data php occ maintenance:mode --off
db:convert-filecache-bigint büyük kurulumlarda uzun sürer ve tabloyu kilitler; iş saatleri dışında çalıştırın. Bu komut atlanmışsa dosya sayınız 32-bit sınırına yaklaştığında yükleme hataları başlar.
MariaDB/MySQL kullanıyorsanız iki ek kontrol yapın: dört baytlı karakter desteği (utf8mb4) açık olmalı, aksi halde emoji içeren dosya adları hata verir; ve innodb_buffer_pool_size varsayılan 128 MB'da kalmamalıdır. Veritabanı tarafındaki ayarlar için MySQL/MariaDB performans optimizasyonu yazısı ayrıntılı bir başlangıç noktasıdır.
-- Nextcloud tablolarının gerçekte kapladığı alan
SELECT table_name,
ROUND((data_length + index_length)/1024/1024) AS mb
FROM information_schema.tables
WHERE table_schema = 'nextcloud'
ORDER BY (data_length + index_length) DESC
LIMIT 10;
Bu sorguda oc_filecache ve oc_activity tablolarının başı çekmesi normaldir. oc_activity yüzlerce MB'a ulaşmışsa etkinlik geçmişi saklama süresini kısaltmak (activity_expire_days) tabloyu ve dolayısıyla sorguları küçültür.
Büyük Dosya Yüklemeleri Yarıda Kesiliyor#
Belirti tanıdıktır: küçük dosyalar sorunsuz gider, 2 GB'lık arşiv %90'larda "Dosya yüklenemedi" ya da 504 hatasıyla düşer. Bunun tek bir ayarı yoktur; zincirdeki en düşük limit kazanır ve zincir üç halkalıdır.
| Katman | Ayar | Önerilen |
|---|---|---|
| nginx | client_max_body_size | 0 (sınırsız) veya 16G |
| nginx | fastcgi_read_timeout, proxy_read_timeout | 3600 |
| PHP | upload_max_filesize, post_max_size | 16G |
| PHP | max_execution_time, max_input_time | 3600 |
| PHP | memory_limit | 512M |
| Nextcloud | .htaccess / config.php | dokunmayın, PHP'den okur |
nginx tarafı:
server {
client_max_body_size 0;
client_body_timeout 3600s;
fastcgi_read_timeout 3600s;
fastcgi_buffers 64 4K;
# istemcilerin parça yüklemesi için gereklidir
fastcgi_request_buffering off;
}
fastcgi_request_buffering off satırı sık atlanır: açık kaldığında nginx yüklenen dosyanın tamamını önce kendi geçici dizinine yazar, sonra PHP'ye aktarır. Büyük dosyalarda bu hem diski iki katı yorar hem de aktarım süresi zaman aşımına yaklaşır.
Masaüstü ve mobil istemciler dosyaları zaten parçalara bölerek gönderir, bu yüzden çoğu sorun tarayıcıdan yükleme sırasında görülür. Sunucuda /tmp alanının dolması da aynı belirtiyi verir; yükleme sırasında df -h /tmp çıktısını kontrol edin. Disk doluluğunu ölçmenin pratik yolları df, du ve ncdu rehberinde anlatılıyor.
Yönetim Panelindeki Uyarı Listesini Yol Haritası Olarak Kullanın#
Yönetim → Genel Bakış ekranındaki liste bir "uyarı yığını" değil, sıralı bir görev listesidir. Sık karşılaşılanlar ve karşılıkları:
"Arka plan işleri AJAX ile çalışıyor" → Sistem cron bölümüne dönün. Listedeki en pahalı maddedir.
"Bellek önbelleği yapılandırılmamış" → APCu + Redis bölümü.
"Veritabanında bazı indeksler eksik" → occ db:add-missing-indices.
"PHP bellek sınırı önerilenin altında" → memory_limit = 512M.
"Ters vekil başlıkları doğru yapılandırılmamış" → Nextcloud istemcinin gerçek IP'sini göremiyor demektir. Kaba kuvvet koruması bu yüzden tüm kullanıcıları aynı IP'den geliyor sanır ve yanlışlıkla engeller:
'trusted_proxies' => ['127.0.0.1', '10.0.0.5'],
'overwriteprotocol' => 'https',
'overwritehost' => 'bulut.ornek.com',
"Strict-Transport-Security başlığı ayarlanmamış" → nginx sunucu bloğuna ekleyin. HSTS'yi ilk kez açıyorsanız süreyi kısa başlatın; TLS yapılandırmasının bütünü için nginx SSL yapılandırması yazısına bakın.
"/.well-known/carddav yönlendirmesi yapılmamış" → Takvim ve kişi senkronizasyonu bu yönlendirme olmadan istemcilerde kurulmaz:
location ^~ /.well-known {
location = /.well-known/carddav { return 301 /remote.php/dav/; }
location = /.well-known/caldav { return 301 /remote.php/dav/; }
return 301 /index.php$request_uri;
}
"MIME tipi veritabanı güncel değil" → sudo -u www-data php occ maintenance:mimetype:update-db.
Uyarıları teker teker kapatmak, sistemin hangi bileşeninin eksik ayarlandığını size baştan söyleyen ücretsiz bir denetim raporudur; listeyi boşaltmak neredeyse her zaman performansı da düzeltir.
Hâlâ Yavaşsa: Önizleme Üretimi, Antivirüs ve Disk#
Yukarıdakileri uyguladıysanız ve sistem hâlâ ağırsa, geriye üç tipik CPU/disk yiyici kalır.
Önizleme üretimi. Nextcloud, bir klasördeki görselleri açtığınızda küçük resimleri o anda üretir. Fotoğraf arşivi barındıran kurulumlarda bu, klasör her açıldığında CPU'yu doldurur. Çözüm, üretimi arka plana almak ve boyut sayısını sınırlamaktır:
'enable_previews' => true,
'preview_max_x' => 2048,
'preview_max_y' => 2048,
'preview_max_memory' => 256,
'enabledPreviewProviders' => [
'OC\Preview\PNG', 'OC\Preview\JPEG', 'OC\Preview\GIF',
'OC\Preview\HEIC', 'OC\Preview\MP4', 'OC\Preview\TXT',
'OC\Preview\MarkDown', 'OC\Preview\PDF',
],
Sağlayıcı listesini kısıtlamak önemlidir: varsayılanda ofis belgeleri ve büyük video biçimleri de önizlenmeye çalışılır ve bunlar en pahalı işlemlerdir. previewgenerator uygulamasını kurup cron ile toplu üretim yaparsanız kullanıcı hiç beklemez.
Antivirüs uygulaması. files_antivirus uygulaması ClamAV'ı her yüklenen dosya için çağırır. ClamAV tek başına 1 GB'ın üzerinde bellek tutar ve tarama süresi yükleme süresine eklenir. Gereksinim yoksa kapatın; gerekiyorsa ClamAV'ı daemon modunda (clamd) çalıştırın, her seferinde imza veritabanını yeniden yükleyen tek seferlik tarama modunda değil.
Disk türü. Nextcloud iş yükü küçük ve çok sayıda rastgele okuma üretir; bu, dönen disklerin en zayıf olduğu profildir. Aynı yapılandırma HDD'de saniyeler, NVMe'de milisaniyeler sürer. iostat -x çıktısında await değeri 20 ms'nin üzerinde takılıyorsa yazılım ayarıyla kazanacağınız yer kalmamış demektir.
Son olarak occ files:scan --all komutunu alışkanlık hâline getirmeyin. Dosya sisteminde el ile değişiklik yaptıysanız gereklidir, ama düzenli cron'a konduğunda büyük kurulumlarda saatlerce disk ve veritabanı yorar.
Sıkça Sorulan Sorular#
Nextcloud için Redis şart mı, sadece APCu yetmez mi?#
Tek kullanıcılı küçük bir kurulumda APCu tek başına belirgin fayda sağlar. Ancak APCu dosya kilitleme için kullanılamaz; birden fazla istemci aynı anda senkronize olduğunda kilit yönetimi veritabanına düşer ve "dosya kilitli" hataları başlar. İki veya daha fazla aktif kullanıcınız varsa Redis'i kilitleme katmanı olarak eklemek pratikte zorunludur.
Cron'u 5 dakikada bir çalıştırmak fazla sık değil mi?#
Değil, Nextcloud'un önerdiği aralık budur. Görev her çalıştığında kuyruktaki işlerin bir kısmını alır; aralık uzarsa kuyruk birikir ve tek bir çalıştırma çok uzun sürmeye başlar. Sunucu yükü sorunuysa çözüm aralığı açmak değil, önizleme üretimi gibi pahalı işleri ayrı bir zamanlamaya taşımaktır.
pm.max_children değerini olabildiğince yüksek yapsam olmaz mı?#
Olmaz. Her PHP süreci bellek tutar; toplam RAM'i aşan bir değer, yoğun anda sunucuyu swap'e sokar ya da OOM killer'ın süreçleri öldürmesine yol açar. Bu durumda yavaşlık yerine kesinti alırsınız. Ortalama süreç belleğini ölçüp PHP'ye ayırdığınız RAM'e bölmek doğru yöntemdir.
Yükleme %90'da hata veriyor, hangi ayarı değiştirmeliyim?#
Genellikle tek bir ayar değil, zincirin en düşük halkası suçludur. Sırayla nginx client_max_body_size, PHP upload_max_filesize ve post_max_size, ardından max_execution_time ve zaman aşımı değerlerini kontrol edin. Yüzde 90 gibi geç bir noktada kesilmesi çoğunlukla bir boyut sınırını değil, zaman aşımını işaret eder.
occ komutları "APCu is not available" uyarısı veriyor, sorun mu?#
Bu uyarı, APCu'nun komut satırı (CLI) için kapalı olmasından gelir ve web arayüzünü etkilemez. Yine de occ komutlarının önbellekten yararlanması ve bazı bakım işlerinin doğru çalışması için php.ini içinde apc.enable_cli = 1 yapmanız önerilir. Değişiklikten sonra PHP-FPM'i yeniden başlatmanız gerekmez, CLI ayrı okur.
Bütün ayarları yaptım ama hâlâ yavaş, donanım mı büyütmeliyim?#
Donanıma geçmeden önce iostat -x ile disk bekleme süresine ve top ile hangi sürecin CPU tükettiğine bakın. Yük PHP süreçlerindeyse ayarlarda hâlâ eksik vardır; yük clamd ya da önizleme üretimindeyse o özelliği sınırlamak donanım büyütmekten ucuzdur. Disk await süresi yüksekse ve sistem dönen diskteyse, tek doğru yatırım NVMe'ye geçmektir.