Basit Anlatım (Herkes İçin)
Tenant Nedir?
Tenant, sistemde bağımsız çalışan bir "kiracı site"dir. Her tenant'ın kendi veritabanı, dosyaları ve ayarları vardır. Örneğin: muzibu.com bir tenant, ixtif.com başka bir tenant'tır.
Ne Oluyor?
Yeni tenant oluşturulduğunda: veritabanı yaratılır, tablolar oluşturulur, dosya klasörleri hazırlanır, domain Plesk'e kaydedilir ve SSL sertifikası yenilenir.
Ne Kadar Sürer?
Tüm işlemler senkron (anında) çalışır. SSL sertifikası yenileme de dahil - wildcard DNS sayesinde *.tuufi.com subdomain'leri için bekleme gerekmez.
Neden Önemli?
Her site izole çalışır - birinin verileri diğerini etkilemez. Plesk entegrasyonu sayesinde domain yönetimi ve SSL otomatiktir.
Genel Akış Şeması
Detaylı Adımlar
Tenant::create() - Central DB'ye Kayıt
Kullanıcı yeni tenant oluşturduğunda başlangıç noktası
Tetikleyen Dosya
Central DB - tenants Tablosu
| Alan | Açıklama |
|---|---|
id | Auto increment |
title | Tenant adı |
tenancy_db_name | tenant_[slug]_[6hex] (unique) |
is_active | Boolean |
theme_id | FK → themes |
ai_credits_balance | AI kredi bakiyesi |
data | JSON ek veriler |
DB Name Oluşturma: tenant_[title_slug]_[6_hex_random] formatında unique isim üretilir. Örnek: tenant_kirmizi_a5f2c1
Otomatik Tema Sistemi (t-{id})
Tema seçiminde "Otomatik (t-{id})" seçildiğinde:
- Tenant ID'ye göre otomatik tema oluşturulur (örn: t-3)
- Central DB'de
themestablosuna kayıt eklenir resources/views/themes/t-{id}/klasörü oluşturulur- config.json, layouts/app.blade.php, homepage.blade.php dosyaları üretilir
- Tema
simpletemasını extend eder (fallback)
Metodlar: createAutoTheme(), createAutoThemeFiles()
TenantCreated Event → JobPipeline
Tenant kaydedilince otomatik tetiklenen event ve job'lar
CreateDatabase
MySQL'de yeni veritabanı oluşturur: CREATE DATABASE tenant_xxx
MigrateDatabase
php artisan tenants:migrate ile tüm tenant migration'ları çalıştırır
SeedDatabase
php artisan tenants:seed ile başlangıç verilerini ekler
Tenant Database Migration'ları
Tenant DB'de oluşturulan tüm tablolar
Base Migrations (database/migrations/tenant/)
users- Kullanıcılarcache- Cache tablosujobs- Queue jobssessions- Session'larmedia- Medya dosyalarıactivity_log- Activity logmodule_tenant_settingstenant_usage_logstags,taggables
Modül Migrations (Modules/*/database/migrations/tenant/)
- UserManagement: permissions, roles
- LanguageManagement: tenant_languages
- MenuManagement: menus, menu_items
- Page: pages
- Blog: blog_categories, blogs
- Portfolio: portfolio_categories, portfolios
- Shop: 30+ tablo (products, orders vb.)
- Cart, Payment, Coupon, AI...
Toplam: ~100+ migration dosyası, tüm modüllerin tenant tabloları otomatik oluşturulur.
TenantDatabaseSeeder - Başlangıç Verileri
Tenant DB'ye eklenen varsayılan veriler
Varsayılan Kullanıcılar
nurullah@nurullah.net/ g0nulcelen → rootinfo@turkbilisim.com.tr/ gonu1celen → admin
Varsayılan Roller
- root - Tüm yetkiler
- admin - view, create, update (delete hariç)
- editor - view, create, update
- user - Sadece view
DatabaseMigrated Event → Storage + Plesk DB
Migration tamamlanınca tetiklenen işlemler
Storage Klasörleri Oluşturma
storage/tenant{ID}/
├── framework/
│ ├── cache/
│ ├── sessions/
│ └── views/
├── app/
│ └── public/
└── logs/
Symlink: public/storage/tenant{ID} → storage/tenant{ID}/app/public
Plesk Veritabanı Kaydı
3 deneme, 2 saniye bekleme (retry logic)
Domain Ekleme → Central DB
Tenant'a domain eklendiğinde tetiklenen işlemler
| Alan | Açıklama |
|---|---|
id | Auto increment |
tenant_id | FK → tenants.id (cascade delete) |
domain | Domain adı (unique) |
is_primary | Primary domain flag |
DomainCreated Event → Otomatik WWW + Plesk Alias
Domain oluşturulunca tetiklenen listener'lar
CreateTenantDomains
Dosya: app/Listeners/CreateTenantDomains.php
- •
yenisite.comeklenince - • Otomatik
www.yenisite.comeklenir - • Central tenant'lara ekleme yapmaz
RegisterDomainAliasInPlesk
Dosya: app/Listeners/RegisterDomainAliasInPlesk.php
Önemli: Tüm domain'ler tuufi.com'a alias olarak bağlanır. Plesk alias oluşturulunca www subdomain'i otomatik eklenir.
SSL Sertifikası Yenileme (Let's Encrypt)
Yeni domain eklenince SSL sertifikası otomatik ve senkron olarak yenilenir
Job Özellikleri
$tries = 2- 2 deneme$timeout = 120- 2 dakika timeout$backoff = 30- 30 sn retry bekleme- Senkron - Tenant kayıt bitmeden SSL hazır
Çalışma Mantığı
- 1. Central DB'den tüm domain'leri al
- 2. Her domain için -d parametresi ekle
- 3. www. subdomain'leri de ekle
- 4. Plesk Let's Encrypt CLI çalıştır
Wildcard DNS: *.tuufi.com wildcard DNS kaydı sayesinde subdomain'ler (örn: panjur.tuufi.com) için DNS propagation beklemeye gerek kalmaz.
Rate Limit: Let's Encrypt rate limit'e takılırsa warning log yazılır ve daha sonra tekrar denenir.
TenancyInitialized Event - Runtime Konfigürasyonu
Tenant context'e geçildiğinde yapılan ayarlar
Tenant/Domain Silme İşlemleri
Tenant Silindiğinde
- Veritabanı güvenli silinir
- Plesk data_bases kaydı silinir
- Domain'ler cascade delete ile silinir
Domain Silindiğinde
- Plesk alias silinir (
domalias --delete) - Senkron çalışır (domain silinmeden önce)
- SSL'den otomatik çıkar (bir sonraki yenilemede)
Kritik Dosyalar Özet
| Dosya | Rol | Açıklama |
|---|---|---|
app/Models/Tenant.php |
Model | Tenant modeli, relationships, AI helpers |
app/Models/Domain.php |
Model | Domain modeli (stancl/tenancy) |
app/Providers/TenancyServiceProvider.php |
Provider | Tüm event → listener mapping'leri |
app/Listeners/RegisterTenantDatabaseToPlesk.php |
Listener | Storage oluşturma + Plesk DB kaydı |
app/Listeners/RegisterDomainAliasInPlesk.php |
Listener | Plesk domain alias oluşturma |
app/Listeners/CreateTenantDomains.php |
Listener | Otomatik www.domain ekleme |
app/Jobs/ReissueLetsEncryptCertificate.php |
Job | SSL sertifikası yenileme (queue) |
app/Jobs/UnregisterDomainAliasFromPlesk.php |
Job | Plesk domain alias silme |
app/Jobs/UnregisterDatabaseFromPlesk.php |
Job | Plesk DB kaydı silme |
database/seeders/TenantDatabaseSeeder.php |
Seeder | Tenant başlangıç verileri |
Modules/TenantManagement/.../Controller.php |
Controller | CRUD API endpoints |
Plesk Komutları Özet
Oluşturma Komutları
Domain Alias Oluştur:
sudo /usr/sbin/plesk bin domalias --create {domain} -domain tuufi.com -web true -mail true -dns true -seo-redirect false
DB Kaydı (SQL):
sudo /usr/sbin/plesk db "INSERT INTO data_bases (name, type, dom_id, db_server_id) VALUES ('{dbName}', 'mysql', {domainId}, {serverId})"
SSL Yenile:
sudo /usr/sbin/plesk bin extension --exec letsencrypt cli.php -d domain1 -d domain2 ... -m ssl@tuufi.com
Silme Komutları
Domain Alias Sil:
sudo /usr/sbin/plesk bin domalias --delete {domain}
DB Kaydı Sil (SQL):
sudo /usr/sbin/plesk db "DELETE FROM data_bases WHERE name = '{dbName}'"
Alias Kontrol:
sudo /usr/sbin/plesk bin domalias --info {domain}
Özet: Tüm Oluşturulan Kaynaklar
Central DB
- • tenants tablosu
- • domains tablosu
- • module_tenants
Tenant DB
- • MySQL database
- • 100+ tablo
- • Başlangıç verileri
Dosya Sistemi
- • storage/tenant{ID}/
- • public symlink
- • logs klasörü
Plesk
- • data_bases kaydı
- • Domain alias
- • SSL sertifikası
Yeni Tenant Oluşturma TODO Checklist
Otomatik Yapılanlar (Sistem)
Central DB - tenants tablosuna kayıt
id, title, tenancy_db_name, theme_id, is_active...
MySQL veritabanı oluştur
tenant_[slug]_[6hex] formatında unique isim
Tenant migration'ları çalıştır
php artisan tenants:migrate (100+ tablo)
Seeder çalıştır (başlangıç verileri)
Diller, roller, kullanıcılar, menü, anasayfa
Storage klasörleri oluştur
storage/tenant{ID}/ (cache, sessions, views, logs, app/public)
Public symlink oluştur
public/storage/tenant{ID} → storage/tenant{ID}/app/public
Plesk veritabanı kaydı
INSERT INTO data_bases (tuufi.com domain'ine bağlı)
Otomatik tema oluştur (opsiyonel)
"Otomatik (t-{id})" seçildiyse: t-{id} teması + dosyaları oluşturulur
Domain Eklendiğinde (Otomatik)
Central DB - domains tablosuna kayıt
domain (unique), tenant_id (FK)
Otomatik www. subdomain ekle
yenisite.com → www.yenisite.com otomatik eklenir
Plesk domain alias oluştur
plesk bin domalias --create (web, mail, dns enabled)
SSL sertifikası yenile (Let's Encrypt)
Senkron çalışır - tenant kaydı bitmeden SSL hazır olur
Manuel Kontroller (Opsiyonel)
DNS kayıtları kontrol et
Domain'in tuufi.com sunucusuna yönlendirildiğinden emin ol
SSL sertifikası kontrolü
https://yenisite.com açılıyor mu? Sertifika geçerli mi?
Tenant CSS oluştur (gerekirse)
npm run prod veya npm run css:tenant{ID}
Admin panele giriş test et
nurullah@nurullah.net / g0nulcelen ile giriş yap
Hızlı Kontrol Komutları
# Plesk alias kontrol:
sudo /usr/sbin/plesk bin domalias --info yenisite.com
# SSL sertifika kontrol:
curl -vI https://yenisite.com 2>&1 | grep -i "SSL\|expire"
# Tenant DB kontrol:
mysql -e "SHOW DATABASES LIKE 'tenant_%'"
# Storage symlink kontrol:
ls -la public/storage/ | grep tenant
Oluşturma Akışı Özeti
Olası Problemler ve Hızlı Çözümler v2 - 20 Ocak 2026
SSL Sertifika Hatası (ERR_CERT_COMMON_NAME_INVALID)
Tarayıcıda "Bağlantınız gizli değil" hatası alınıyor.
Neden: Nginx/Apache config'e domain eklenmemiş veya SSL sertifikası yenilenmemiş.
Çözüm Adımları:
grep "domain.com" /etc/nginx/plesk.conf.d/vhosts/tuufi.com.conf
sudo sed -i '/server_name www.soneklenen.com;/a\\tserver_name domain.com;\\n\\tserver_name www.domain.com;' /etc/nginx/plesk.conf.d/vhosts/tuufi.com.conf
sudo sed -i '/ServerAlias "www.soneklenen.com"/a\\t\\tServerAlias "domain.com"\\n\\t\\tServerAlias "www.domain.com"' /var/www/vhosts/system/tuufi.com/conf/httpd.conf
sudo systemctl reload nginx && sudo systemctl reload httpd
sudo certbot certonly --webroot -w /var/www/vhosts/default/htdocs -d tuufi.com -d www.tuufi.com -d domain.com -d www.domain.com --cert-name tuufi-all --expand
sudo bash -c 'cat /etc/letsencrypt/live/tuufi-all/fullchain.pem /etc/letsencrypt/live/tuufi-all/privkey.pem > /usr/local/psa/var/certificates/scffm1s7qbch4jnfprJ4Ox' && sudo chmod 600 /usr/local/psa/var/certificates/scffm1s7qbch4jnfprJ4Ox && sudo systemctl reload nginx
HTTP 500 Internal Server Error
Site açılmıyor, 500 hatası alınıyor.
Olası Nedenler: Tenant DB tabloları eksik, tema dosyaları yok, veya config hatası.
Kontrol ve Çözüm:
tail -100 storage/logs/laravel-*.log | grep -i error
tail -100 storage/tenant{ID}/logs/tenant-*.log
php artisan tinker --execute="Tenant::find({ID})->run(fn() => DB::select('SHOW TABLES'));"
php artisan tenants:migrate --tenants={ID} --force
php artisan cache:clear && php artisan view:clear && php artisan config:clear
404 Not Found
Domain açılıyor ama 404 hatası alınıyor.
Neden: Apache ServerAlias eksik veya domain tenant'a bağlı değil.
Kontrol ve Çözüm:
grep "domain.com" /var/www/vhosts/system/tuufi.com/conf/httpd.conf
php artisan tinker --execute="Domain::where('domain', 'domain.com')->first();"
sudo sed -i '/UseCanonicalName Off/i\\t\\tServerAlias "domain.com"\\n\\t\\tServerAlias "www.domain.com"' /var/www/vhosts/system/tuufi.com/conf/httpd.conf
sudo apachectl configtest && sudo systemctl reload httpd
Cloudflare Domain SSL Hatası
Certbot çalışırken "unauthorized" hatası alınıyor.
Neden: Cloudflare proxy aktifken webroot doğrulaması çalışmaz.
Çözüm:
Cloudflare arkasındaki domain'ler SSL listesinden çıkarılmalı:
# isRedirectDomain() metoduna ekle:
$excludedDomains = ['cloudflare-domain.com'];
Cloudflare kendi SSL sertifikasını sağlar, sunucu tarafında SSL gerekmez.
Domain/SSL İşlemleri İçin Kritik Dosyalar
app/Jobs/RegisterDomainInWebServer.php
Nginx/Apache config'e domain ekler (dinamik, son domain'den sonra)
app/Jobs/RenewSSLCertificate.php
Let's Encrypt ile SSL sertifikası yeniler, Cloudflare domain'leri filtreler
/etc/nginx/plesk.conf.d/vhosts/tuufi.com.conf
Nginx vhost config - server_name satırları
/var/www/vhosts/system/tuufi.com/conf/httpd.conf
Apache vhost config - ServerAlias satırları
Hızlı Tanı Komutları
# HTTP durum kodu kontrolü:
curl -sI https://domain.com | head -1
# SSL sertifika domain kontrolü:
echo | openssl s_client -servername domain.com -connect domain.com:443 2>/dev/null | openssl x509 -noout -text | grep DNS:
# System log kontrolü:
tail -50 storage/logs/system-*.log | grep domain.com
# Nginx config syntax test:
sudo nginx -t