# Canlı öncesi: `php scripts/verify-go-live-env.php` (değer yazdırmaz). Şema: `php scripts/verify-commerce-schema.php`. # Hepsi birden (kök + vitrin): frontend içinde `npm run go-live:check`. # # --- Üretim şema (tekincil yol) --- # Şema sapmalarını tekrarlamamak için canlıda önce her zaman migration zinciri: # ./scripts/run-database-migrations.sh # (Uzak DB: FAUNAMIX_ENV_FILE=api/.env.railway … veya konteynerde FAUNAMIX_MIGRATE_FROM_ENV=1 — ayrıntı aşağıda.) # Elle parça SQL yalnız son çare; migration dosyaları database/migration_*.sql altında versiyonlanır. # Doğrulama: `php scripts/verify-commerce-schema.php` (e-ticaret + vitrin ticaret tabloları). # İsteğe bağlı hızlı tablo kontrolü (mysql istemci, DB_NAME ile): SHOW TABLES LIKE 'product_variants'; # SHOW TABLES LIKE 'home_hero_slides'; DESCRIBE products; (panel / filter.php beklenen kolonlar için) # # İlk kurulum — varsayılan admin seed yok. İlk panel hesabını bilinçli oluşturun: # php scripts/create-admin-user.php '' [email] [role] # Canlıya almadan önce admin hesabı, DB kimliği ve SMTP sırları ayrı ayrı güçlü olmalı. # MySQL — api/lib/db.php ile uyumlu # Yerelde root’un şifresi varsa mutlaka doldur: boş DB_PASS ile (export|xargs) bazen gönderilmez. # Pratik: `cp api/env.example api/.env` → DB_PASS’i yaz → kökten: `set -a && . api/.env && set +a && php -S localhost:8080` # Railway: yerel makineden migration/CLI için MYSQL_PUBLIC_URL içindeki host ve portu kullanın # (ör. *.proxy.rlwy.net). mysql.railway.internal yalnızca Railway ağı içindeki servislerde çalışır. # Uzak migration: public host/port ile api/.env.railway oluşturup repoya eklemeden: # FAUNAMIX_ENV_FILE=api/.env.railway ./scripts/run-database-migrations.sh # Alternatif (şifreyi dosyada tutmamak; geçmişe yazılabilir): RAILWAY_DB_PASS='…' ile aynı komut # Public TCP 1045 verirse: deploy’ta Dockerfile database/ + scripts/ kopyalıyor; sonra # konteyner içi: `railway ssh --service Faunamix` ardından (api/.env yok + RAILWAY_*: betik DB_* platformdan alır) # bash --noprofile --norc -c '/app/scripts/run-database-migrations.sh' # PTY / canlı log: script -q -e -c 'FAUNAMIX_MIGRATE_FROM_ENV=1 exec /app/scripts/run-database-migrations.sh' /dev/null # (`railway run` yerelde çalışır; /app/scripts orada olmaz.) # Private repo: raw GitHub URL 404 — yerel script’i konteynere: ./scripts/sync-migration-script-to-railway.sh # (Bağlı servis yeterli; gerekirse FAUNAMIX_RAILWAY_SERVICE=Faunamix. railway ssh --deployment-instance ile # status JSON’daki id’leri kullanma — sunucu "Deployment instance not found" verir.) # prod-bootstrap.sh (start.sh → Apache öncesi): konteyner açılışında run-database-migrations.sh çalışır (Railway UI shell yok). # Kapatmak: FAUNAMIX_RUN_DB_MIGRATIONS=0 # Konteyner içi mysql.railway.internal: migration script varsayılan `mysql --skip-ssl` (MariaDB istemci + ERROR 2026). # Sunucu TLS zorunlu tutuyorsa: FAUNAMIX_MYSQL_SSL=1 (TLS dalı: --ssl --ssl-verify-server-cert=0). # Docker (php:*-apache) üretim: `Authorization: Bearer …` bazen PHP’de boş kalır; repo `api/apache/faunamix-authorization.conf` # + `api/lib/request_auth.php` ile düzeltilir (panel girişi / admin_verify 401 döngüsü). DB_HOST=127.0.0.1 DB_PORT=3306 DB_NAME=faunamix DB_USER=root DB_PASS= # Ürün araması (filter.php): migration_products_fulltext_search.sql sonrası FULLTEXT kullanımı. # 0 veya tanımsız = title/slug/description LIKE ile uyumlu geri dönüş; 1 = MATCH ... AGAINST (NATURAL LANGUAGE). # FULLTEXT dizini yokken 1 yapmayın (sorgu hata verir). FAUNAMIX_PRODUCT_SEARCH_FULLTEXT=0 # Railway: MySQL plugin aynı projede ise çoğu zaman MYSQL_HOST, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD # gelir; DB_* tanımlamazsan db.php bunları kullanır. # CORS — tarayıcı Origin tam eşleşmesi (virgülle). Boş ve FRONTEND_BASE_URL de boşsa yerelde localhost:3000 kullanılır. # FAUNAMIX_FRONTEND_BASE_URL kökeni otomatik eklenir; iki parçalı apex alan adlarında (örn. faunamix.com) www eşiği de eklenir. # *.vercel.app / *.railway.app / api.* alt alanlarında otomatik www üretilmez — özel alan kullanıyorsanız kanonik vitrin kökünü # ALLOWED veya FRONTEND ile verin (yalnızca .vercel.app bırakıp www.faunamix.com’da gezmek CORS’a takılır). # Örnek: FAUNAMIX_ALLOWED_ORIGINS=https://www.faunamix.example,https://faunamix.example # Railway + Vercel önizleme: FAUNAMIX_ALLOWED_ORIGINS=https://faunamix.vercel.app # Üretim: kanonik vitrin köken(ler)i + gerekirse önizleme kökenleri — FAUNAMIX_ALLOW_ANY_ORIGIN=1 kullanmayın. FAUNAMIX_ALLOWED_ORIGINS= # --- Önerilen canlı (www + api.faunamix.com) — örnek; gerçek anahtarları panel/Railway’de ayarlayın --- # Tarayıcı Origin tam eşleşmesi: kanonik www + apex (preconnect / yönlendirme öncesi istekler için). # FAUNAMIX_ALLOWED_ORIGINS=https://www.faunamix.com,https://faunamix.com # FAUNAMIX_FRONTEND_BASE_URL=https://www.faunamix.com # Ödeme callback kökü API ile aynı host olmalı (path /api/payment_callback_iyzico.php): # FAUNAMIX_IYZI_CALLBACK_URL=https://api.faunamix.com/api/payment_callback_iyzico.php # Railway / ters vekil arkasında doğru istemci IP ve oran sınırlaması için üretimde açın. # FAUNAMIX_TRUST_PROXY=1 # Sadece geliştirme / acil: Access-Control-Allow-Origin: * (üretimde kullanmayın) # FAUNAMIX_ALLOW_ANY_ORIGIN=1 # Oran sınırlama — IP başına (varsayılan: açık) # FAUNAMIX_RATE_LIMIT_ENABLED=0 FAUNAMIX_RATE_LIMIT_MAX=120 FAUNAMIX_RATE_LIMIT_WINDOW=60 # Kamu katalog (filter.php, product.php) bucket'ları — boşsa yukarıdaki MAX/WINDOW kullanılır # FAUNAMIX_RATE_LIMIT_PUBLIC_MAX=60 # FAUNAMIX_RATE_LIMIT_PUBLIC_WINDOW=60 # Ters vekil arkasında gerçek IP için (nginx real_ip vb. yapılandırıldıysa) # FAUNAMIX_TRUST_PROXY=1 # İsteğe bağlı özel hata günlüğü yolu (yazılabilir dizin) # FAUNAMIX_LOG_PATH=/var/log/faunamix/php-error.log # Railway değişkenlerinde FAUNAMIX_SMTP_HOST tek satır olmalı (sonunda gizli \n kırık host üretir). # SMTP yedeği — önce panel (Site ayarları > Genel) kullanılır; alan boşsa burası dolar. # Müşteri akışı: panele yaz; yerelde de aynı şekilde çalıştırmak için api/.env’de SMTP satırı olmasın. # FAUNAMIX_SMTP_HOST=smtp.gmail.com # FAUNAMIX_SMTP_PORT=587 # FAUNAMIX_SMTP_USER=you@gmail.com # FAUNAMIX_SMTP_PASS=app-password # FAUNAMIX_SMTP_FROM=you@gmail.com # Geliştirmede posta göndermeden kodu günlüğe yaz: FAUNAMIX_MAIL_LOG_ONLY=1 # TLS/sertifika hatası (yalnızca yerel deneme): FAUNAMIX_SMTP_SSL_VERIFY=0 — üretimde kullanmayın # İletişim formu ops bildirimi (SMTP + geçerli alıcı; yoksa panel İletişim > e-posta) # FAUNAMIX_CONTACT_OPS_EMAIL=ops@example.com # FAUNAMIX_CONTACT_OPS_NOTIFY=0 # bildirimi kapat # Panel şifresi — son kaç eski şifre tekrar kullanılamaz (1–24; varsayılan kodda 12) # FAUNAMIX_ADMIN_PASSWORD_HISTORY_COUNT=12 # Panel giriş — ardışık yanlış şifre sonrası geçici kilit (migration: migration_admin_login_lockout.sql) # FAUNAMIX_ADMIN_LOGIN_MAX_FAILURES=5 # FAUNAMIX_ADMIN_LOGIN_LOCK_MINUTES=15 # --- E-ticaret / iyzico --- # Sandbox: https://sandbox-api.iyzipay.com — Canlı: https://api.iyzipay.com FAUNAMIX_IYZI_BASE_URL=https://sandbox-api.iyzipay.com FAUNAMIX_IYZI_API_KEY= FAUNAMIX_IYZI_SECRET_KEY= # Ödeme sonrası tarayıcı yönlendirmesi + Checkout Form callback (API köküne işaret etmeli). # Örn: https://api.faunamix.example/api/payment_callback_iyzico.php FAUNAMIX_IYZI_CALLBACK_URL= # Callback gövdesinde HMAC imza doğrulaması (sandbox uyumsuzluğunda geçici: FAUNAMIX_IYZI_VERIFY_CALLBACK_SIGNATURE=0) # FAUNAMIX_IYZI_VERIFY_CALLBACK_SIGNATURE=1 # Panel iadesinde iyzico API ile gerçek para iadesi (1 = açık; provider_payment_id gerekir) # FAUNAMIX_IYZI_REFUND_ENABLED=0 # Sipariş özeti sayfası için (PHP redirect): müşteri yüzü kök URL FAUNAMIX_FRONTEND_BASE_URL=https://www.faunamix.example # Checkout sonrası "sipariş alındı / ödeme bekleniyor" e-postası (SMTP yapılandırılmışsa). Kapatmak için: FAUNAMIX_MAIL_ORDER_PENDING=0 # FAUNAMIX_MAIL_ORDER_PENDING=0 # Checkout’ta müşterinin işaretlediği yasal onaylar (mesafeli satış, ön bilgilendirme, vb.) ilgili migration ile ecommerce_orders.checkout_legal_json alanında saklanır. # Sepet terk e-postası — scripts/faunamix-abandoned-cart.php (cron). SMTP panel veya api/.env gerekir. # FAUNAMIX_ABANDON_CART_ENABLED=0 # FAUNAMIX_ABANDON_CART_MIN_STALE_HOURS=2 # FAUNAMIX_ABANDON_CART_MAX_STALE_HOURS=168 # FAUNAMIX_ABANDON_CART_ORDER_COOLDOWN_HOURS=24 # --- Route resolve önbelleği (opsiyonel) --- # Dosya önbelleği: FAUNAMIX_ROUTE_CACHE_DIR boşsa sys_get_temp_dir altında kullanılır. # FAUNAMIX_ROUTE_CACHE_DIR=/var/cache/faunamix/routes # FAUNAMIX_ROUTE_CACHE_TTL=300 # ext-redis ile (üretim): route cache + rate limit shared state # Uretim (coklu replika): FAUNAMIX_REDIS_HOST zorunlu — release gate REDIS_REQUIRED_PROD. # Yerelde bos birakilabilir (dosya fallback). # FAUNAMIX_REDIS_HOST=127.0.0.1 FAUNAMIX_REDIS_PORT=6379 # FAUNAMIX_REDIS_PASSWORD= # FAUNAMIX_REDIS_PREFIX=faunamix: # Rate limit: Redis+dosya ikisi de yoksa varsayilan fail-open; uretimde ZORUNLU: # FAUNAMIX_RATE_LIMIT_FAIL_CLOSED=1 # FAUNAMIX_RATE_LIMIT_STRICT_MAX=12 # Ops / izleme: health.php ic gorunurluk (bos = herkese acik — uretimde token verin) # FAUNAMIX_HEALTH_PROBE_TOKEN= # Istek: X-FAUNAMIX-HEALTH-TOKEN: # Railway platform healthcheck: /live.php (token yok, hassas veri yok) # RUM ham olay TTL (scripts/rum-retention.php cron) # FAUNAMIX_RUM_RAW_RETENTION_DAYS=14 # --- Backup / restore / PITR --- # Varsayılan snapshot dizini: .local/backups/mysql (gitignore altında). Dilersen mutlak yol ver. # FAUNAMIX_DB_BACKUP_DIR=/var/backups/faunamix/mysql # Snapshot retention (backup-database.sh eski dump/meta/checksum dosyalarını temizler) FAUNAMIX_DB_BACKUP_RETENTION_DAYS=14 # Restore rehearsal rapor dizini (varsayılan: .local/restore-rehearsals) # FAUNAMIX_RESTORE_REHEARSAL_REPORT_DIR=/var/backups/faunamix/restore-rehearsals # MySQL binary log kapalıysa point-in-time recovery yok kabul edin. # Doğrulama: php scripts/verify-disaster-recovery.php # --- Panel medya yükleme (api/uploads, genel yol öneki /api/uploads/…) --- # FAUNAMIX_MEDIA_UPLOAD_DIR= (boşsa api/uploads) # FAUNAMIX_MEDIA_PUBLIC_PATH_PREFIX=/api/uploads # FAUNAMIX_MEDIA_MAX_BYTES=5242880 # FAUNAMIX_MEDIA_PATH_PREFIXES=/api/uploads # İsteğe bağlı: https ile yapıştırılan eski görseller için host listesi (virgülle) # FAUNAMIX_MEDIA_ALLOWED_HOSTS= # # --- ÜRETİM: /api/uploads dosyaları veritabanından bağımsız (Railway / Docker / K8s) --- # Panel yükleme başarılı olunca DB’de `/api/uploads/.` yolu yazılır; dosya o anki konteyner # diskinde durur. Çoğu PaaS’te yeni deploy = yeni dosya sistemi → eski yüklemeler silinir → tarayıcıda 404, # vitrinde kırık görsel. MySQL’deki yol “silindi” değildir; dosya artık diskte yoktur. # Çözüm (birini seçin): # 1) Railway: Service → Volumes → Add Volume → Mount path tam olarak: /app/api/uploads # (bu repodaki api/Dockerfile: WORKDIR /app, yüklemeler /app/api/uploads altına yazılır) # 2) Kalıcı nesne depolama (S3/R2 vb.) — ayrı entegrasyon gerekir # 3) Slider’da yalnızca vitrine gömülü görseller: `/hero/hero-1.svg` gibi (Next public/; PHP diski gerekmez) # Volume sonrası: eksik dosyalar geri gelmez; ilgili slayt görselini panelden yeniden yükleyin veya yolu düzeltin. # --- Canlı öncesi betikler (değer sızdırmaz) --- # php scripts/verify-commerce-schema.php → e-ticaret + vitrin ticaret tabloları # php scripts/verify-go-live-env.php → DB, CORS, iyzico, SMTP, FRONTEND_BASE_URL özeti (çıkış 2 = yalnız uyarı) # Ödeme uçtan uca (manuel): sandbox anahtarlarıyla sepet → Güvenli ödemeye geç → iyzico → /odeme/sonuc; # iyzico panelinde callback URL = FAUNAMIX_IYZI_CALLBACK_URL ile birebir aynı olmalı. Canlıya geçerken # FAUNAMIX_IYZI_BASE_URL=https://api.iyzipay.com ve canlı API/secret kullanın. # Sipariş e-postasındaki vitrin bağlantıları için FAUNAMIX_FRONTEND_BASE_URL dolu olmalı (HTTPS). # Canlı kontrol listesi: NEXT_PUBLIC_SITE_URL, NEXT_PUBLIC_API_URL, CORS, iyzico prod anahtarları, # güçlü admin şifresi, yedekleme. İlk admin hesabı default seed ile gelmez; bilinçli oluşturun: # php scripts/create-admin-user.php '' [email] [role] # Hızlı tarama: kökte `php scripts/verify-go-live-env.php` veya vitrin `npm run go-live:check` # (şema + bu betik). DR taraması: `php scripts/verify-disaster-recovery.php` # # Ters vekil (nginx, Railway, Cloudflare) arkasında gerçek istemci IP + oran sınırı için: # FAUNAMIX_TRUST_PROXY=1 # # Oran sınırı (api/lib/http.php) Redis tanımlı ve ext-redis açıksa paylaşımlı sayaç kullanır. # Redis yoksa dosya tabanlı fallback devam eder; birden fazla PHP replikasında edge veya Redis önerilir. # # Sepet terk e-postası (cron: scripts/faunamix-abandoned-cart.php veya eşdeğeri) — ayrıntılar yukarıdaki # FAUNAMIX_ABANDON_CART_* bloğunda; burada sadece canlı hatırlatma. # # Gözlemlenebilirlik (isteğe bağlı) — Sentry: Next.js `NEXT_PUBLIC_SENTRY_DSN`, PHP: # FAUNAMIX_SENTRY_DSN= # FAUNAMIX_SENTRY_ENVIRONMENT=production # Anasayfa vitrini (`home_only`): stok 0 ürünleri vitrinden çıkar # FAUNAMIX_HOME_IN_STOCK_ONLY=1 # İsteğe bağlı APM örnekleme 0.0–1.0 (varsayılan betikte 0) # FAUNAMIX_SENTRY_TRACES_SAMPLE_RATE=0 # Metrik satırı error_log’a (api/lib/observability.php) # FAUNAMIX_METRICS_LOG=0 # --- Çok dilli vitrin (Railway + Vercel birlikte) --- # Migration zinciri: migration_site_pages_locale, migration_nav_footer_locale, # migration_site_pages_seed_en_locale, migration_i18n_en_empty_content (EN metinleri boşaltır). # FAUNAMIX_RUN_DB_MIGRATIONS=1 ile bir redeploy, sonra 0. # Doğrulama: API_BASE=https://… ./scripts/verify-i18n-deploy.sh # Vercel (build zamanı): NEXT_PUBLIC_I18N_LOCALES=tr,en # # Canlı içerik (kod dışı): hero TR+EN (baslik_*_en, image_path_en); ürün/kategori title_en+slug_en; # Fırsatlar’da silinmiş ürün kaydı varsa panelden Sil. # Google: İşletme Profili web sitesi + adres tutarlılığı; Search Console sitemap.