Takip et

Kendi Blog Yayınlama Sunucunuzu Kurmak: Bir Hata Ayıklama Günlüğü

Dijital dünyada kişisel veya kurumsal bir varlık oluşturmanın en etkili yollarından biri blog yazmaktır.

Kendi Blog Yayınlama Sunucunuzu Kurmak: Bir Hata Ayıklama Günlüğü

Dijital dünyada kişisel veya kurumsal bir varlık oluşturmanın en etkili yollarından biri blog yazmaktır. Ancak içerik üretmek kadar, bu içeriği hızlı, güvenli ve verimli bir şekilde yayınlamak da büyük bir zorluk teşkil edebilir. Manuel yayınlama süreçleri, hem zaman alıcı hem de hata yapmaya açık olduğundan, otomasyon ihtiyacı kaçınılmaz hale gelir. İşte bu noktada, kendi özel içerik yayınlama sunucumu (My Custom Publisher – MCP) geliştirme serüvenim başladı. Bu makalede, bir Git deposundaki Markdown dosyalarını alıp, statik bir site jeneratörü aracılığıyla HTML’e dönüştürerek otomatik olarak bir web sunucusuna dağıtan bir sistemi nasıl kurduğumu, bu süreçte karşılaştığım zorlukları ve onlarla nasıl başa çıktığımı adım adım anlatacağım. Amacım, hem kendi yayınlama süreçlerimi optimize etmek hem de benzer bir ihtiyacı olan geliştiricilere yol göstermekti.

Neden Kendi Blog Yayınlama Sunucuma İhtiyaç Duydum?

Günümüzde birçok popüler blog platformu (WordPress, Medium, Blogger vb.) mevcut. Bunlar, hızlı başlangıç yapma ve teknik bilgi gerektirmeden içerik yayınlama konusunda büyük kolaylıklar sunar. Ancak, bu platformların getirdiği bazı kısıtlamalar, özellikle benim gibi tam kontrol ve esneklik arayan geliştiriciler için yetersiz kalabilir. Mevcut platformlar genellikle belirli bir tasarıma, eklenti ekleme sınırlamalarına ve veri sahipliği konusunda soru işaretlerine sahiptir. Kendi içerik stratejimi, performans beklentilerimi ve güvenlik standartlarımı tam olarak karşılayacak bir çözüme ihtiyacım vardı.

Statik site jeneratörleri (Jekyll, Hugo, Gatsby gibi), bu kısıtlamaların çoğunu ortadan kaldırıyor. Markdown gibi basit metin formatlarında içerik yazma imkanı sunarken, bu içerikleri hızlı ve güvenli statik HTML dosyalarına dönüştürüyorlar. Bu sayede, sunucu tarafında veritabanı veya karmaşık bir uygulama katmanı olmadığı için güvenlik açıkları azalıyor ve sayfa yükleme hızları inanılmaz derecede artıyor. Ancak statik site jeneratörlerini kullanmanın da kendine göre bir zahmeti var: Her içerik güncellemesinde, jeneratörü çalıştırmanız, dosyaları derlemeniz ve ardından bunları bir web sunucusuna (genellikle SSH veya FTP aracılığıyla) manuel olarak yüklemeniz gerekiyor. Birkaç blog yazısı için bu kabul edilebilir olsa da, düzenli olarak içerik yayınladığınızda bu tekrarlayan ve zaman alıcı bir göreve dönüşüyor. İşte tam da bu noktada, bir otomasyon çözümü geliştirmek kaçınılmaz hale geldi. Amacım, sadece bir git push komutuyla, yeni blog yazılarımın veya güncellemelerimin saniyeler içinde yayında olmasını sağlamaktı. Bu vizyon, beni kendi özel yayınlama sunucumu, yani MCP sunucumu inşa etmeye itti.

Bu otomasyon, sadece zaman tasarrufu sağlamakla kalmayacak, aynı zamanda insan hatası riskini de minimize edecekti. Manuel dosya transferlerinde yanlış dizine kopyalama, eski dosyaları unutma veya izin hataları gibi sorunlar sıkça yaşanabilir. Otomatik bir sistemle, bu tür hataların önüne geçmek ve yayınlama sürecini standartlaştırmak mümkündü. Ayrıca, kendi sunucumu kurmak, hangi programlama dillerini ve araçlarını kullanacağım konusunda bana tam bir özgürlük tanıyordu. Böylece, en iyi bildiğim ve en verimli çalıştığım teknolojileri kullanarak, tamamen kendi ihtiyaçlarıma göre şekillendirilmiş bir çözüm ortaya çıkarabilirdim. Bu, sadece bir blog yayınlama aracı değil, aynı zamanda bir öğrenme ve geliştirme projesi olacaktı.

MCP Sunucusu Nedir ve Temel Mimari Tasarımı Nasıl Yapıldı?

MCP, bu makale özelinde geliştirdiğim “My Custom Publisher” (Kendi Özel Yayınlayıcım) sunucusunun kısaltmasıdır. Temel amacı, bir Git deposundaki (örneğin GitHub veya GitLab) değişiklikleri otomatik olarak algılamak, bu değişiklikleri kullanarak statik bir web sitesi oluşturmak ve son olarak bu siteyi bir web sunucusuna dağıtmaktır. Bu sistem, bir nevi kişisel ve hafif bir sürekli entegrasyon/sürekli dağıtım (CI/CD) hattı görevi görür. Projenin kalbinde, Git entegrasyonu, bir webhook dinleyicisi ve statik site jeneratörü ile sorunsuz bir etkileşim yatar.

MCP sunucusunun mimarisini tasarlarken, esneklik, güvenilirlik ve düşük bakım maliyeti önceliklerim arasındaydı. Bu hedefler doğrultusunda, aşağıdaki ana bileşenlerden oluşan bir yapı oluşturmaya karar verdim:

  • Git Deposu: Blog yazılarımın ve web sitesi kaynak kodunun bulunduğu merkezi bir depo. GitHub veya GitLab gibi platformlar bu amaç için idealdir, çünkü webhook (web kancası) özelliğini desteklerler.
  • Webhook Dinleyicisi (MCP Sunucusu): Bu, Node.js ve Express.js (veya Python ve Flask) ile yazılmış küçük bir web uygulamasıdır. Git deposunda bir değişiklik (örneğin bir git push) olduğunda, Git platformu bu sunucuya önceden tanımlanmış bir URL üzerinden bir HTTP POST isteği (webhook) gönderir. MCP sunucusu bu isteği dinler ve gerekli aksiyonları tetikler.
  • Statik Site Jeneratörü: Markdown formatındaki blog yazılarını ve şablon dosyalarını alarak nihai statik HTML, CSS ve JavaScript dosyalarını üreten araç. Ben Hugo’yu tercih ettim çünkü hızı, esnekliği ve geniş topluluk desteği beni etkiledi.
  • Hedef Web Sunucusu: Oluşturulan statik dosyaların barındırılacağı ve son kullanıcılara sunulacağı Nginx veya Apache gibi bir web sunucusu.
  • Dosya Senkronizasyon Mekanizması: Statik site jeneratörü tarafından üretilen dosyaları, hedef web sunucusunun servis ettiği dizine kopyalamak için kullanılan bir araç (örneğin rsync veya basit cp komutları).

Bu bileşenler arasındaki iletişim akışı şu şekilde işler:

  1. Blog yazarı, yeni bir blog yazısını Markdown formatında yazar veya mevcut bir yazıyı günceller.
  2. Değişiklikler Git deposuna git push ile gönderilir.
  3. Git platformu (GitHub/GitLab), önceden yapılandırılmış MCP sunucusunun webhook URL’ine bir POST isteği gönderir.
  4. MCP sunucusu bu isteği alır, isteğin geçerliliğini kontrol eder (güvenlik için) ve bir dizi komut çalıştırır.
  5. Bu komutlar sırasıyla: Git deposundaki en son değişiklikleri sunucuya çeker (git pull), statik site jeneratörünü (Hugo) çalıştırarak web sitesini yeniden derler, ve son olarak derlenen dosyaları hedef web sunucusunun dizinine kopyalar.
  6. Kullanıcılar, web sunucusu üzerinden güncellenmiş blog içeriğine anında erişebilir.

Bu mimari, manuel müdahaleyi minimuma indirerek, içerik yayınlama sürecini son derece verimli ve hatasız hale getirmeyi amaçlar. Node.js’i tercih etmemin nedeni, asenkron yapısıyla eş zamanlı işlemleri kolayca yönetebilmesi ve geniş bir paket ekosistemine sahip olmasıydı. Bu sayede, webhook işleme, komut çalıştırma ve hata yönetimi gibi görevleri etkili bir şekilde yerine getirebildim. Ayrıca, bu yaklaşım, sistemin ölçeklenebilirliğini de artırır; gelecekte daha fazla blog veya statik site eklemek istediğimde, mevcut altyapıyı kolayca genişletebilirim.

Adım Adım Kurulum ve İlk Geliştirme Süreci

MCP sunucusunu hayata geçirmek için ilk adım, uygun bir sunucu ortamı hazırlamaktı. Genellikle sanal bir özel sunucu (VPS) veya kendi yerel makinenizde bir Linux dağıtımı (Ubuntu, Debian) bu iş için yeterli olacaktır. Benim tercihim, maliyet etkinliği ve esnekliği nedeniyle bir bulut tabanlı VPS oldu. Kurulum süreci aşağıdaki adımları içeriyordu:

  1. Sunucu Ortamı Hazırlığı:
    • İşletim sistemi olarak Ubuntu 20.04 LTS kurdum.
    • Gerekli temel paketleri güncelledim: sudo apt update && sudo apt upgrade.
    • Node.js ve npm’i kurdum. Bu, webhook dinleyicisini geliştirmek için gerekliydi. curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash – && sudo apt install -y nodejs.
    • Git’i kurdum: sudo apt install git.
    • Statik site jeneratörü olarak Hugo’yu kurdum. Hugo’nun son sürümünü GitHub üzerinden indirip /usr/local/bin dizinine kopyaladım.
    • Nginx web sunucusunu kurdum ve temel bir yapılandırma yaptım: sudo apt install nginx. Blog dosyalarının servis edileceği dizini (/var/www/blog gibi) oluşturdum ve Nginx’in bu dizini göstermesini sağladım.
  2. Temel Sunucu İskeleti (Node.js ile):

    Bir Node.js projesi başlattım ve express ile body-parser paketlerini kurdum. Bu paketler, gelen HTTP isteklerini yönetmek ve JSON gövdelerini ayrıştırmak için kullanılacaktı.

    
            // server.js
            const express = require('express');
            const bodyParser = require('body-parser');
            const { exec } = require('child_process'); // Harici komutları çalıştırmak için
            const app = express();
            const port = 3000; // MCP sunucusu bu portta dinleyecek
    
            // Gelen JSON isteklerini ayrıştırmak için
            app.use(bodyParser.json());
    
            // Ana dizine basit bir GET isteği ile sunucunun çalıştığını kontrol edelim
            app.get('/', (req, res) => {
              res.send('MCP Sunucusu aktif ve bekliyor...');
            });
    
            // Webhook endpoint'i
            app.post('/webhook', (req, res) => {
              console.log('Webhook tetiklendi!');
              // Burada Git platformundan gelen isteği doğrulamak için güvenlik kontrolleri yapılabilir.
              // Örneğin, req.headers['x-github-event'] veya req.headers['x-gitlab-event'] kontrol edilebilir.
    
              // Blog deposunun bulunduğu dizine geçiş yapalım
              const blogRepoPath = '/home/user/my-blog-repo'; // Kendi Git deponuzun yolu
              const publishPath = '/var/www/blog'; // Nginx'in blogu servis ettiği yol
    
              exec(cd ${blogRepoPath} && git pull origin main && hugo --minify -d ${publishPath}, (error, stdout, stderr) => {
                if (error) {
                  console.error(Yayınlama hatası: ${error.message});
                  return res.status(500).send('Yayınlama başarısız. Detaylar için sunucu loglarına bakın.');
                }
                if (stderr) {
                  console.error(Stderr: ${stderr});
                }
                console.log(Stdout: ${stdout});
                res.status(200).send('Blog başarıyla yayınlandı!');
              });
            });
    
            app.listen(port, () => {
              console.log(MCP Sunucusu http://localhost:${port} adresinde çalışıyor);
            });
                  

    Yukarıdaki kod, basit bir webhook dinleyicisi oluşturur. /webhook adresine POST isteği geldiğinde, git pull ile depoyu günceller ve hugo –minify -d ${publishPath} komutuyla Hugo’yu çalıştırarak statik dosyaları doğrudan Nginx’in servis ettiği /var/www/blog dizinine derler. Bu, rsync kullanmaktan daha doğrudan bir yaklaşımdır, ancak Hugo’nun çıkış dizinini doğrudan hedef olarak ayarlamanızı gerektirir.

  3. Git Deposu ve Webhook Kurulumu:

    Blog kaynak kodumun bulunduğu Git deposunu sunucuya klonladım: git clone https://github.com/myuser/my-blog-repo.git /home/user/my-blog-repo. Daha sonra, GitHub veya GitLab arayüzünden, projenin “Settings” (Ayarlar) bölümündeki “Webhooks” kısmına giderek yeni bir webhook ekledim. Payload URL olarak http://your_server_ip:3000/webhook adresini girdim ve tetikleyici olarak sadece “Push events” (Gönderme olayları) seçeneğini işaretledim. Güvenlik için bir “Secret” (Gizli anahtar) belirlemeyi de unutmadım, bu konuya daha sonra değineceğim.

  4. MCP Sunucusunu Arka Planda Çalıştırma:

    MCP sunucusunun sürekli çalışır durumda kalması için pm2 gibi bir süreç yöneticisi kullandım: npm install -g pm2 ve ardından pm2 start server.js. Bu, sunucunun çökmesi durumunda otomatik olarak yeniden başlamasını da sağlar.

Bu adımlarla, temel bir otomasyon akışı kurulmuş oldu. Artık, Git deposuna yeni bir blog yazısı gönderdiğimde, webhook tetiklenecek ve sunucum otomatik olarak blogumu güncelleyecekti. Ancak, her projede olduğu gibi, bu ilk kurulum sürecinde de çeşitli zorluklarla karşılaştım ve hata ayıklama süreçleri kaçınılmaz oldu.

Karşılaşılan İlk Zorluklar ve Hata Ayıklama Stratejileri

Her geliştirme projesi gibi, MCP sunucusu kurulumu da beklenmedik sorunlarla doluydu. İlk başarılı git push denememde blogumun otomatik olarak güncellenmemesi, beni bir hata ayıklama maratonuna sürükledi. İşte karşılaştığım başlıca zorluklar ve bunları aşmak için kullandığım stratejiler:

  • Webhook Tetikleme Sorunları ve Güvenlik Doğrulaması

    İlk başta, Git platformundan gelen webhook’ların sunucuma ulaşıp ulaşmadığından emin olamadım. Bazen, webhook’lar hiç tetiklenmiyor ya da sunucuya ulaştığında doğru şekilde işlenmiyordu. Bu sorunu çözmek için aşağıdaki adımları izledim:

    • Loglama: İlk olarak, MCP sunucuma gelen her isteği ve özellikle /webhook endpoint’ine gelen isteklerin başlıklarını ve gövdesini logladım. Bu sayede, isteğin gelip gelmediğini ve içeriğini görebildim.
    • Güvenlik Anahtarı (Secret): Git platformları, webhook isteklerinin gerçekten kendilerinden geldiğini doğrulamak için bir “secret” (gizli anahtar) kullanır. Bu anahtar ile istek gövdesinden bir hash (karma) hesaplanır ve isteğin başlığındaki imza ile karşılaştırılır. İlk kodumda bu kontrol eksikti. Bu nedenle, rastgele gelen veya kötü niyetli istekler de sunucumu tetikleyebilirdi. Bu kontrolü eklemek, hem güvenliği artırdı hem de sadece yetkili webhook’ların işlenmesini sağladı.
      
              const crypto = require('crypto');
              // ... diğer kodlar ...
      
              app.post('/webhook', (req, res) => {
                const signature = req.headers['x-hub-signature-256'] || req.headers['x-gitlab-token'];
                const secret = process.env.WEBHOOK_SECRET; // Ortam değişkeninden alınmalı
      
                if (!signature || !secret) {
                  console.warn('Webhook güvenlik anahtarı veya imza eksik.');
                  return res.status(403).send('Yetkilendirme başarısız.');
                }
      
                const hmac = crypto.createHmac('sha256', secret);
                const digest = 'sha256=' + hmac.update(JSON.stringify(req.body)).digest('hex');
      
                if (digest !== signature) {
                  console.warn('Webhook imza doğrulama hatası.');
                  return res.status(403).send('Webhook imza doğrulaması başarısız.');
                }
      
                console.log('Webhook başarıyla doğrulandı.');
                // ... yayınlama komutları ...
              });
                            

  • Dosya İzinleri ve Kullanıcı Yetkilendirmesi

    En sık karşılaşılan sorunlardan biri, sunucunun Git deposunu çekmek ve hedef dizine dosya yazmak için yeterli yetkiye sahip olmamasıydı. exec komutları genellikle sunucuyu çalıştıran kullanıcı altında çalışır. Eğer MCP sunucusunu root olmayan bir kullanıcıyla çalıştırıyorsanız (ki bu en iyi güvenlik uygulamasıdır), o kullanıcının Git deposu dizinine okuma/yazma ve hedef yayınlama dizinine yazma izinleri olmalıdır.

    • Kullanıcı ve Grup Ayarları: MCP sunucusunu çalıştıran kullanıcıya (www-data veya özel bir kullanıcı) Git deposu dizini ve /var/www/blog dizini üzerinde gerekli yetkileri verdim. Örneğin: sudo chown -R www-data:www-data /var/www/blog ve sudo chmod -R 775 /var/www/blog.
    • SSH Anahtarları: Git deposunu https yerine ssh üzerinden çekmek daha güvenli ve pratik olabilir. Bu durumda, sunucuyu çalıştıran kullanıcının bir SSH anahtarı olmalı ve bu anahtar Git platformunda (GitHub/GitLab) depoya erişim izni olan bir dağıtım anahtarı (deploy key) olarak eklenmelidir.
  • Statik Site Jeneratörü Entegrasyon Hataları ve Ortam Değişkenleri

    Hugo’nun exec komutu aracılığıyla çalıştırılması bazen beklenen şekilde sonuç vermiyordu. En yaygın sorun, hugo komutunun sistemin PATH değişkeninde bulunamamasıydı. Bu durumda exec komutu command not found (komut bulunamadı) hatası döndürür.

    • Tam Yol Belirtme: hugo komutu yerine /usr/local/bin/hugo gibi tam yolu belirterek bu sorunu aştım.
    • Hata Çıktılarını Yakalama: exec fonksiyonunun stderr çıktısını yakalamak, Hugo’nun neden başarısız olduğunu anlamak için kritikti. Genellikle yapılandırma hataları veya eksik dosyalar bu çıktılarda görünürdü.
  • Zaman Aşımı Sorunları

    Büyük blog siteleri için Hugo’nun derleme süreci birkaç saniye sürebilir. Eğer webhook isteği bu süreden daha uzun sürerse, Git platformu bir zaman aşımı hatası bildirebilir ve isteği başarısız olarak işaretleyebilir. Bu, aslında yayınlama başarılı olsa bile, Git platformunun arayüzünde hatalı bir durum görmenize neden olurdu.

    • Arka Plan Görevleri: Bu sorunu çözmek için, webhook isteği geldiğinde yayınlama işlemini hemen bir arka plan görevine (child_process.spawn veya bir iş kuyruğu) devretmek ve webhook isteğine hızlıca 200 OK yanıtı dönmek en iyi yaklaşımdır. Böylece, Git platformu isteği başarılı olarak görürken, yayınlama işlemi arka planda devam eder.

Vaka Analizi: “Bir Gece Yayınlanmayan Blog Postu”

Bir keresinde, yeni bir blog yazısı yayımlamak için git push yaptım, ancak sabah uyandığımda blogumda görünmediğini fark ettim. GitHub’ın webhook geçmişine baktığımda, isteğin “başarısız” olarak işaretlendiğini gördüm. Sunucu loglarını kontrol ettiğimde, git pull komutunun “Permission denied (publickey)” (İzin reddedildi (genel anahtar)) hatası verdiğini fark ettim. Sorun, sunucuyu çalıştıran kullanıcının SSH anahtarının GitHub’da dağıtım anahtarı olarak doğru şekilde eklenmemiş olmasıydı. Anahtarı ekledikten ve doğru izinleri ayarladıktan sonra sorun çözüldü. Bu olay, loglama ve hata çıktılarını dikkatle incelemenin ne kadar önemli olduğunu bir kez daha gösterdi.

Performans Optimizasyonu ve Güvenlik Önlemleri

Bir içerik yayınlama sunucusu kurarken, sadece işlevsellik değil, aynı zamanda performans ve güvenlik de kritik öneme sahiptir. Blogumun hızlı yüklenmesini sağlamak ve olası saldırılara karşı korumak için bir dizi optimizasyon ve güvenlik önlemi aldım.

Performans Optimizasyonu:

  1. Statik Site Jeneratörü Optimizasyonu:
    • Minify (Küçültme): Hugo gibi jeneratörler, HTML, CSS ve JavaScript dosyalarını küçültme (minify) yeteneğine sahiptir. Bu, dosya boyutlarını azaltarak yükleme sürelerini kısaltır. Hugo için config.toml dosyasında minify = true ayarını veya hugo –minify komutunu kullandım.
    • Resim Optimizasyonu: Blog yazılarındaki resimlerin optimize edilmiş boyutlarda ve modern formatlarda (WebP gibi) servis edilmesi, sayfa yükleme hızını önemli ölçüde artırır. Hugo’nun resim işleme yeteneklerini veya harici araçları kullandım.
    • Önbellekleme (Caching): Tarayıcıların statik dosyaları (CSS, JS, resimler) önbelleğe almasını sağlamak için uygun HTTP önbellekleme başlıkları (Cache-Control, Expires) ayarladım. Bu, tekrarlayan ziyaretlerde sayfanın çok daha hızlı yüklenmesini sağlar.
  2. Web Sunucusu Yapılandırması (Nginx):
    • Gzip Sıkıştırma: Nginx’i, metin tabanlı dosyaları (HTML, CSS, JS) istemciye göndermeden önce gzip ile sıkıştırmak üzere yapılandırdım. Bu, bant genişliği kullanımını azaltır ve yükleme sürelerini hızlandırır.
    • Tarayıcı Önbellekleme: Nginx yapılandırmasına, belirli dosya türleri için uzun süreli önbellekleme başlıkları ekledim. Örneğin, location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ bloğunda expires 30d; gibi ayarlar kullandım.
  3. CDN (İçerik Dağıtım Ağı) Entegrasyonu:

    Eğer blogunuz küresel bir kitleye hitap ediyorsa, bir CDN kullanmak performansı büyük ölçüde artırır. CDN’ler, içeriğinizi coğrafi olarak dağıtılmış sunucularda önbelleğe alarak, kullanıcılara en yakın sunucudan servis edilmesini sağlar. Cloudflare gibi ücretsiz veya uygun fiyatlı CDN hizmetleri bu iş için idealdir. Bu, özellikle resimler ve diğer büyük statik varlıklar için faydalıdır.

Güvenlik Önlemleri:

  1. Webhook Gizli Anahtarı (Secret) Kullanımı:

    Daha önce de bahsettiğim gibi, webhook isteklerinin geçerliliğini doğrulamak için bir gizli anahtar kullanmak zorunludur. Bu, sadece yetkili Git deposundan gelen isteklerin işlenmesini sağlar ve sunucunuzun rastgele POST istekleriyle kötüye kullanılmasını engeller.

  2. Gelen IP Adreslerini Kısıtlama:

    Eğer Git platformunuzun webhook isteklerini gönderdiği IP adres aralıkları biliniyorsa (GitHub ve GitLab bu bilgiyi sağlar), sunucunuzun güvenlik duvarını (UFW veya firewalld) sadece bu IP adreslerinden gelen isteklere izin verecek şekilde yapılandırabilirsiniz. Bu, ek bir güvenlik katmanı sağlar.

  3. Sunucu Güvenlik Duvarı (UFW/Firewalld):

    Sunucuda gereksiz tüm portları kapattım ve sadece SSH (22), HTTP (80) ve HTTPS (443) portlarına izin verdim. MCP sunucumun çalıştığı 3000 numaralı portu ise sadece yerel ağdan veya belirli IP’lerden erişilebilir hale getirdim. sudo ufw allow 22/tcp, sudo ufw allow 80/tcp, sudo ufw allow 443/tcp gibi komutlarla.

  4. En Az Yetki Prensibi:

    MCP sunucusu uygulamasını, mümkün olan en düşük yetkilere sahip bir kullanıcı altında çalıştırdım. root kullanıcısı veya sudo yetkileriyle çalıştırmaktan kaçındım. Bu, olası bir güvenlik açığı durumunda sistem üzerindeki zararı sınırlar.

  5. SSH Anahtar Tabanlı Kimlik Doğrulama:

    Sunucuma SSH ile bağlanırken parola yerine anahtar tabanlı kimlik doğrulama kullandım. Bu, parolanın tahmin edilmesi veya kaba kuvvet saldırılarına karşı çok daha güvenlidir.

  6. HTTPS Kullanımı (Let’s Encrypt):

    Blogumun ve MCP sunucumun güvenliğini artırmak için tüm trafiği HTTPS üzerinden şifreledim. Let’s Encrypt ve Certbot, ücretsiz SSL/TLS sertifikaları almak ve bunları otomatik olarak yenilemek için harika araçlardır. Bu, hem veri bütünlüğünü sağlar hem de SEO açısından önemlidir.

  7. Loglama ve İzleme:

    Sunucu loglarını düzenli olarak izlemek ve anormallikleri tespit etmek için log yönetim araçları kullandım. Ayrıca, MCP sunucusunun kendi loglarını da detaylı tutarak, herhangi bir yayınlama hatası durumunda hızlıca müdahale edebildim.

Bu performans ve güvenlik önlemleri, MCP sunucumu sadece işlevsel değil, aynı zamanda sağlam ve güvenilir bir içerik yayınlama platformu haline getirdi. Her bir adım, hem kullanıcı deneyimini iyileştirmeye hem de potansiyel riskleri minimize etmeye yönelikti.

İleri Düzey Otomasyon ve Sürekli Dağıtım (CI/CD) Entegrasyonu

MCP sunucusunun temel işlevselliğini kurduktan ve performans/güvenlik önlemlerini aldıktan sonra, sistemi daha da güçlendirmek ve bir adım öteye taşımak için ileri düzey otomasyon ve sürekli dağıtım (CI/CD) entegrasyonlarına yöneldim. Bu, sadece bir git push ile blogu yayınlamanın ötesine geçerek, daha karmaşık iş akışlarını ve daha güvenilir dağıtım süreçlerini mümkün kıldı.

Test Ortamları ve Otomatik Testler:

Üretim ortamına doğrudan yayınlama yapmak riskli olabilir. Bu nedenle, geliştirme, test ve üretim olmak üzere farklı ortamlar tanımladım. Örneğin, develop dalına yapılan push’lar bir test sunucusuna, main dalına yapılan push’lar ise canlı üretim sunucusuna yayınlanacak şekilde MCP sunucumu yapılandırdım. Bu, yeni özelliklerin veya blog yazılarının canlıya çıkmadan önce test edilmesine olanak tanır.

  • Otomatik Testler: Her yayınlamadan önce, statik site jeneratörünün çıktısını kontrol eden basit testler ekledim. Örneğin, link-checker gibi araçlarla bozuk bağlantıları (broken links) kontrol edebilir veya HTMLProofer ile HTML geçerliliğini test edebilirim. Bu testler, yayınlama komutlarından önce çalıştırılır ve herhangi bir hata durumunda dağıtımı durdurur.
  • Linting: Markdown dosyalarımı veya HTML/CSS/JS dosyalarımı belirli stil kurallarına göre kontrol eden linting araçlarını (örneğin markdownlint) entegre ettim. Bu, kod kalitesini ve tutarlılığını artırır.

Dockerizasyon:

MCP sunucusunu ve tüm bağımlılıklarını bir Docker konteynerine taşımak, projenin taşınabilirliğini, izole edilmesini ve dağıtımını büyük ölçüde kolaylaştırdı. Docker kullanarak, sunucumun farklı ortamlarda (yerel geliştirme, test sunucusu, üretim sunucusu) tutarlı bir şekilde çalışmasını sağlayabildim. Ayrıca, bağımlılık çakışmalarını önledi ve kurulum sürecini basitleştirdi.


        # Dockerfile örneği
        # Node.js 18 Alpine tabanlı bir imaj kullanıyoruz, hafif ve verimli
        FROM node:18-alpine

        # Çalışma dizinini belirliyoruz
        WORKDIR /app

        # package.json ve package-lock.json dosyalarını kopyalıyoruz
        # Bu sayede bağımlılıklar değişmediğinde Docker katmanı önbellekten kullanılır
        COPY package*.json ./

        # Bağımlılıkları yüklüyoruz
        RUN npm install

        # Geri kalan uygulama kodunu kopyalıyoruz
        COPY . .

        # MCP sunucusunun dinleyeceği portu belirtiyoruz
        EXPOSE 3000

        # Sunucuyu başlatma komutunu tanımlıyoruz
        CMD ["node", "server.js"]
      

Bu Dockerfile ile, docker build -t mcp-server . komutuyla bir Docker imajı oluşturabilir ve docker run -p 3000:3000 -e WEBHOOK_SECRET=your_secret mcp-server komutuyla çalıştırabilirim. Bu yaklaşım, sunucu ortamını hazırlama karmaşıklığını ortadan kaldırır ve dağıtım sürecini standartlaştırır.

Gelişmiş İş Akışları:

Daha sofistike iş akışları oluşturmak için, webhook payload’undaki bilgilere dayanarak farklı eylemleri tetikleyebilirim. Örneğin:

  • Dal Bazlı Dağıtım: req.body.ref alanını kontrol ederek, hangi dalla ilgili bir push geldiğini tespit edip, ona göre farklı komut setleri çalıştırabilirim. Örneğin, refs/heads/main dalına push geldiğinde üretim ortamına, refs/heads/dev dalına geldiğinde ise geliştirme ortamına yayın yapabilirim.
  • Yazar Bazlı Yetkilendirme: Daha ileri senaryolarda, webhook payload’ındaki yazar bilgilerine bakarak belirli kişilerin belirli dallara veya ortamlara yayın yapmasına izin verebilirim.
  • Geri Alma Mekanizmaları: Bir yayınlama hatası durumunda, önceki çalışan sürüme otomatik olarak geri dönme (rollback) mekanizmaları tasarlayabilirim. Bu, genellikle dağıtım dizinlerinin versiyonlanması veya Docker imajlarının etiketlenmesiyle mümkün olur.

Bu ileri düzey otomasyon ve CI/CD entegrasyonları, MCP sunucumu sadece basit bir yayınlama aracından, tam teşekküllü, güvenilir ve esnek bir içerik dağıtım sistemine dönüştürdü. Bu sayede, içerik üretimine daha fazla odaklanabilir ve teknik detaylarla daha az uğraşabilirim.

Sonuç: Kendi Yayınlama Sunucunuzla Elde Edilenler

Kendi özel içerik yayınlama sunucumu (MCP) inşa etme serüvenim, sadece teknik bir proje olmanın ötesinde, bana paha biçilmez deneyimler kazandırdı. Bu süreçte, Node.js ile web sunucusu geliştirme, Git ile otomasyon entegrasyonu, Linux sunucu yönetimi, güvenlik pratikleri ve hata ayıklama stratejileri gibi birçok alanda bilgi ve becerilerimi derinleştirme fırsatı buldum. En önemlisi, içerik yayınlama sürecim üzerinde tam kontrol sağladım ve manuel iş yükünü sıfıra indirerek verimliliğimi artırdım.

MCP sunucusu sayesinde, artık yeni bir blog yazısını yazdıktan veya mevcut bir yazıyı güncelledikten sonra tek yapmam gereken, değişiklikleri Git depoma göndermek. Geri kalan tüm adımlar – depoyu çekmek, statik siteyi derlemek ve web sunucusuna dağıtmak – tam otomatik olarak gerçekleşiyor. Bu otomasyon, bana yaratıcı süreçlere daha fazla odaklanma özgürlüğü tanırken, aynı zamanda blogumun her zaman güncel ve hatasız kalmasını sağlıyor. Kendi altyapınızı kurmanın getirdiği öğrenme eğrisi zorlayıcı olsa da, elde edilen özgürlük, esneklik ve verimlilik bu çabaya kesinlikle değiyor.

Gelecekteki geliştirmeler arasında, MCP sunucusuna bir yönetim paneli ekleyerek yayınlama geçmişini görselleştirmek, farklı bloglar veya projeler için çoklu depo desteği sunmak ve belki de içerik yönetimini daha da kolaylaştırmak için basit bir web tabanlı editör entegrasyonu yer alıyor. Bu proje, kendi ihtiyaçlarınıza özel çözümler geliştirmenin ve teknolojiyi kendi lehinize kullanmanın gücünü bir kez daha gösterdi.

Sıkça Sorulan Sorular (SSS)

S1: Bu tür bir sunucuyu kurmak için hangi teknik bilgilere sahip olmalıyım?
C1: Temel Linux komutları (terminal kullanımı, dosya izinleri), Git versiyon kontrol sistemi, bir programlama dili (Node.js veya Python gibi), basit bir web sunucusu (Nginx veya Apache) yapılandırması ve seçtiğiniz statik site jeneratörünün (Hugo, Jekyll) kullanımı hakkında bilgi sahibi olmak faydalıdır. Ancak, bu makaledeki gibi adım adım rehberlerle öğrenerek de ilerleyebilirsiniz.
S2: Kendi yayınlama sunucumu kurmanın güvenlik riskleri nelerdir?
C2: Başlıca riskler arasında yanlış yapılandırılmış webhook’lar (yetkisiz kişilerin sunucunuzu tetiklemesi), dosya izinleri sorunları (uygulamanın hassas dosyalara erişimi), zayıf kimlik doğrulama/yetkilendirme ve sunucu güvenlik açıkları bulunur. Bu riskleri azaltmak için webhook gizli anahtarları, güvenlik duvarı, en az yetki prensibi ve düzenli güncellemeler hayati öneme sahiptir.
S3: Mevcut bir blog platformu (WordPress gibi) yerine neden bu yolu seçmeliyim?
C3: Kendi sunucunuzu kurmak, içerik üzerinde tam kontrol, sınırsız özelleştirme esnekliği, daha yüksek performans (statik siteler sayesinde), daha iyi güvenlik (daha az hareketli parça) ve uzun vadede maliyet tasarrufu gibi avantajlar sunar. Ayrıca, otomasyon yetenekleri sayesinde yayınlama süreciniz çok daha verimli hale gelir. Ancak, ilk kurulum ve bakım için daha fazla teknik bilgi gerektirir.
S4: Bu sistem sadece bloglar için mi kullanılabilir?
C4: Hayır, kesinlikle değil. Bu tür bir otomatik yayınlama sistemi, statik web siteleri, dokümantasyon siteleri, portföy siteleri veya düzenli olarak güncellenen ve statik olarak sunulabilecek herhangi bir içerik için uyarlanabilir. Prensip, Git deposundaki kaynak koddan nihai çıktıyı otomatik olarak oluşturup dağıtmaktır.
S5: Daha küçük projeler veya kişisel web siteleri için de mantıklı mı?
C5: Başlangıçta öğrenme eğrisi ve kurulum için harcanan zaman göz önüne alındığında, çok küçük ve nadiren güncellenen projeler için aşırıya kaçabilir. Ancak, düzenli olarak içerik yayınlıyorsanız veya gelecekte ölçeklenmeyi planlıyorsanız, uzun vadede içerik yayınlama sürecini basitleştirerek ve verimlilik sağlayarak kesinlikle mantıklı hale gelir. Özellikle geliştiriciler için, bu aynı zamanda değerli bir öğrenme deneyimidir.

#Teknoloji #WebGeliştirme #Otomasyon #CI/CD #BlogYayınlama #DevOps

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.