Kategori: Kod

Kendi işimi kolaylaştırmak için yazdığım ufak scriptler ve yazılım projeleri.

  • Resend ile Mail Kurulumu (Coolify + PocketBase)

    Resend ile Mail Kurulumu (Coolify + PocketBase)

    Kendi sunucumda (Coolify) PocketBase ile yeni bir proje ayağa kaldırırken, işin o sıkıcı “mail gönderim (SMTP)” aşaması her seferinde zamanımı çalıyordu. “Mailler spam’e düşer mi?” gerginliğini sonsuza dek bitirmek için sistemi Resend üzerine kurmaya başladım. Bir sonraki projede ayarları sıfırdan düşünmemek ve hızlıca kopyala-yapıştır yapabilmek için kendi kurulum adımlarımı buraya sabitliyorum.

    1. Resend Tarafını Çözmek

    Modern bir mail servisi olan Resend’de hesabı açıp domain’i (alan adını) bağlamak işin ilk adımı.

    • Bölge Seçimi: Gecikmeyi önlemek için bölgeyi her zaman Ireland (eu-west-1) seçiyorum.
    • DNS Ayarları: Resend’in verdiği DNS kayıtlarını, domain’i aldığım paneldeki ayarlara giriyorum.
    • Doğrulama: Resend panelinde “Verified” yazısını görmeden diğer adımlara geçmek yok.

    2. Coolify’a Uyarı Maillerini Bağlamak

    Sunucunun çökme veya sistem uyarılarında beni haberdar etmesi kritik. Coolify’ı kör bırakmamak için şu ayarları giriyorum:

    • Coolify içinde Settings > Email kısmına geçiyorum.
    • Resend bölümüne, oradan aldığım API Key kodunu yapıştırıyorum.
    • “From Address” kısmına ise genelde sistem@siteadim.com gibi profesyonel duran bir adres tanımlayıp kaydediyorum.

    3. PocketBase SMTP Ayarlarını Oturtmak

    Kullanıcıların şifre sıfırlama veya doğrulama maillerini sorunsuz alabilmesi için PocketBase tarafına girdiğim fix SMTP ayarları şunlar:

    • Host: smtp.resend.com
    • Port: 465 (veya duruma göre 587)
    • Username: resend
    • Password: Resend’den aldığım API Key.
    • Encryption: SSL/TLS (Bunu kesinlikle unutmuyorum).

    Güvenlik İçin Ufak Bir Hatırlatma

    Hem Coolify hem de PocketBase için tek bir API Key kullanmak işin kolayı gibi görünse de, güvenlik ve kullanım takibi açısından her ikisi için ayrı ayrı API Key oluşturmak her zaman daha sağlıklı. İki dakika fazla uğraşıyorum ama kafam rahat ediyor.

  • WhatsApp Webhook Gelmiyor: Terminalden Çözdüm

    WhatsApp Webhook Gelmiyor: Terminalden Çözdüm

    WhatsApp Business API entegrasyonu yaparken saatlerimi çalan en sinir bozucu sorunlardan biriyle cebelleştim: Webhook kurulumu tamam, test butonu çalışıyor ama gerçek WhatsApp mesajları sunucuya bir türlü düşmüyor. Meta Developer Console arayüzüne güvenmenin bedelini zamanımla ödedikten sonra, işi manuel olarak API üzerinden nasıl çözdüğümü bir daha unutmamak için buraya not alıyorum.

    Sorunun Kaynağı: Arayüzdeki Kopukluk

    Sunucu ayakta, Meta panelindeki “Test” butonundan gelen sahte veriler sunucuya ulaşıyor ama gerçek mesajlarda log’larda yaprak kımıldamıyordu. Sorunun temel kaynağının Abonelik (Subscription) kopukluğu olduğunu fark ettim. Arayüzdeki “Subscribe” butonuna basmama rağmen işlem sadece uygulama seviyesinde kalıyor, arka planda WhatsApp Business Hesabı (WABA) ile uygulama arasındaki bağlantı bir türlü kurulamıyordu.

    Benim Çözümüm: cURL ile Manuel Abonelik (Force Subscribe)

    Arayüzdeki butonlar işe yaramayınca, Meta Graph API’yi kullanarak bu “el sıkışmayı” terminalden manuel olarak zorunlu kıldım. İhtiyacım olanlar sadece WABA ID ve tam yetkili bir Access Token‘dı.

    Terminalde şu komutu kendi bilgilerimle çalıştırarak bağlantıyı zorla kurdum:

    curl -X POST "https://graph.facebook.com/v22.0/{WABA_ID}/subscribed_apps" \
    -H "Authorization: Bearer {ACCESS_TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{
    "subscribed_fields": ["messages", "message_template_status_update", "messages_preview"]
    }'

    Karşılığında {"success": true} yanıtını aldığım an, webhook nihayet gerçek mesajlarla tetiklenmeye başladı.

    Sağlama Yapmak İçin: Aboneliğin gerçekten kurulup kurulmadığını görmek için öncesinde ve sonrasında şu GET isteğini atarak listeyi kontrol ettim:

    curl -X GET "https://graph.facebook.com/v22.0/{WABA_ID}/subscribed_apps" \
    -H "Authorization: Bearer {ACCESS_TOKEN}"

    Özetle: Meta arayüzüne güvenmiyorum. Her şey doğru görünmesine rağmen veri akmıyorsa, terminalden subscribed_apps endpoint’ine istek atmak hayat kurtarıyor.

    Production İçin Ek Not: Kalıcı Token (System User) Ayarlarım

    Projeyi canlıya (production) alırken 24 saatlik geçici token’larla uğraşmamak için süresi asla dolmayan bir token üretmem gerekiyordu. İleride tekrar aramayayım diye Business Settings üzerindeki adımlarımı da özetliyorum:

    1. business.facebook.com/settings adresinden “System Users” (Sistem Kullanıcıları) kısmına girip “Admin” rolünde yeni bir kullanıcı oluşturdum.
    2. Oluşturduğum kullanıcının “Add Assets” bölümünden projeye ait WhatsApp uygulamasını seçip “Full Control” verdim.
    3. “Generate New Token” derken süreyi Never (Asla) olarak ayarladım.
    4. İzinler listesinde whatsapp_business_management ve whatsapp_business_messaging yetkilerini seçip token’ı ürettim.

    Meta bu kalıcı token’ı ekranda sadece bir kez gösterdiği için hemen kopyalayıp sunucudaki .env dosyama (TOKEN=EAARLL…) yapıştırdım. Artık token süresi doldu krizleriyle uğraşmak yok.

  • Hetzner Sunucum Neden Kasıyordu?

    Hetzner Sunucum Neden Kasıyordu?

    Hetzner Cloud üzerinde tuttuğum ve Coolify ile yönettiğim sunucuda son zamanlarda can sıkıcı bir yavaşlama, SSH bağlantılarında donmalar ve panel kilitlenmeleri yaşamaya başladım. Sunucuya terminalden bağlandığımda harflerin bile ekrana gecikmeli düştüğünü görünce, mecburen işi gücü bırakıp terminalde detektifliğe soyunmak zorunda kaldım. İleride aynı krizi yaşarsam sıfırdan düşünmemek için süreci buraya not düşüyorum.

    Terminalde Hata Avı: Suçluyu Bulmak

    Sunucu kasıyorsa olağan şüpheliler bellidir: CPU, RAM veya Disk. Analize şu sırayla başladım:

    1. Kaynak Tüketimi (htop)
    Önce htop ile anlık duruma baktım. İşlemci yükü (Load Average) 0.25 civarındaydı, yani CPU rahattı. Ancak RAM tam dolmamasına rağmen SWAP (Sanal Bellek) kullanımı tehlikeli şekilde yüksekti. Sistem, RAM’de yer açmak için verileri diske yazmaya çalışıyor (Swap in/out) ve bu da sistemi boğuyordu.

    2. Disk Performans Testi (I/O)
    Hetzner disklerinde fiziksel bir arıza var mı diye doğrudan diski test ettim:

    dd if=/dev/zero of=testfile bs=1G count=1 oflag=direct

    Sonuç: 1.1 GB/s yazma hızı. Disk performansı mükemmeldi, sorun kesinlikle donanımda değil, benim yazılımlarımdan birindeydi.

    3. Docker İstatistikleri
    Coolify altındaki hangi konteynerin sistemi sömürdüğünü bulmak için Docker verilerini çektim:

    docker stats --no-stream --format "table {{.Name}}\t{{.MemPerc}}\t{{.MemUsage}}"

    Suçlu bulundu: Kendi geliştirdiğim “Face Swap” (AI/Python) uygulamasının tek başına ~2 GB RAM sömürdüğünü gördüm. Uygulama ani yüklenmelerde RAM’i dolduruyor, sunucu da panikleyip paneli Swap’e (diske) atıyordu. Kilitlenmenin sebebi buydu.

    Çözüm: Docker’ı Kafeslemek ve Saçma Limit Hataları

    Uygulamanın 8GB’lık sunucunun tamamını rehin almasını engellemek için Coolify üzerinden (Project > Settings > Resource Limits) konteyneri kafeslemem gerekiyordu. Ancak Docker’ın limit belirleme mantığı oldukça sinir bozucuydu. Karşılaştığım hatalar ve doğruları şöyle:

    Hata 1: “Minimum memory limit allowed is 6MB”
    Tavan RAM miktarını 2300 olarak girdiğimde hata verdi. Çünkü birim yazmadığım için Docker bunu 2300 Bayt sandı. Sonuna mutlaka 2300MB yazmak gerekiyor.

    Hata 2: “Minimum memoryswap limit should be larger than memory limit”
    Memory limitine 2300MB, Swap’e ise 1024MB yazdığımda yine hata verdi. Çünkü Docker, Swap kutusuna sadece istediğiniz “ekstra” swap miktarını değil; (RAM + SWAP) toplamını yazmanızı istiyor.

    İdeal Yapılandırma Notum

    Sunucuyu rahatlatan ve sistemi stabil hale getiren nihai ayarlarımı şöyle sabitledim:

    • Limit CPUs: 1.5 (Uygulama tüm çekirdekleri sömüremesin, 1.5 çekirdek ona yetsin.)
    • CPU Weight: 1024
    • Maximum Memory Limit: 2300MB (Uygulamanın çıkabileceği maksimum RAM)
    • Maximum Swap Limit: 3324MB (2300 MB RAM + İstediğim 1024 MB Swap = 3324 MB toplam limit)

    Ayarları Deploy ettikten sonra Docker’ı tekrar kontrol ettiğimde uygulamanın artık sunucunun tamamına değil, sadece 2.24GiB‘lık bir kafese erişebildiğini gördüm. Artık o Python uygulaması bellek sızıntısı yapsa bile sadece kendi kafesinde yeniden başlıyor, sunucum ve Coolify panelim saat gibi çalışmaya devam ediyor.