Teknoloji

Django ve Flask Uygulamaları İçin VPS Hosting Rehberi: Gunicorn/Uvicorn, Nginx ve SSL

Django veya Flask ile geliştirdiğiniz bir projeyi gerçek kullanıcıların göreceği üretim ortamına taşırken, en çok takılan noktalardan biri genelde şurası oluyor: “Bu uygulamayı VPS’e nasıl düzgünce kurarım, Nginx, Gunicorn/Uvicorn ve SSL ayarlarını nereden tutmaya başlarım?” Özellikle geliştirme ortamında python manage.py runserver ya da flask run ile her şey yolunda giderken, üretim tarafında performans, güvenlik ve ölçeklenebilirlik bir anda masaya geliyor. DCHost ekibi olarak hem kendi altyapımızda hem de müşterilerimizin yüzlerce Python tabanlı projesinde bu soruları tekrar tekrar çözüyoruz. Bu yazıda, Django ve Flask uygulamalarınızı VPS üzerinde modern ve üretim‑hazır bir mimariyle (Gunicorn/Uvicorn + Nginx + SSL) nasıl ayağa kaldırabileceğinizi, adım adım ve gerçekçi ayarlarla anlatacağız. Hedefimiz; elinizdeki kodu, bakımı kolay, logları okunabilir, güvenli ve gerektiğinde rahatça ölçeklenebilir bir üretim ortamına dönüştürmeniz.

Django ve Flask İçin Neden VPS Tercih Etmelisiniz?

Paylaşımlı hosting, basit PHP tabanlı siteler için hâlâ mantıklı bir seçenek olabilir; ancak Django ve Flask gibi framework’ler söz konusu olduğunda çoğu zaman hızla duvara toslarsınız. Uzun süren arka plan işler, WebSocket bağlantıları, özel kütüphaneler, sistem paketleri veya Python versiyonu gibi konularda kontrol ihtiyacı ortaya çıkar. VPS (Sanal Özel Sunucu) tam burada devreye girer; root yetkisi, istediğiniz Linux dağıtımı, özgürce paket kurabilme ve servisleri dilediğiniz gibi yönetebilme imkânı verir.

VPS ile:

  • İstediğiniz Python sürümünü ve sanal ortam (virtualenv/venv) yapısını kullanabilirsiniz.
  • Gunicorn veya Uvicorn işçi (worker) sayısını projeye göre ayarlayarak CPU kullanımını optimize edersiniz.
  • Nginx üzerinde cache, rate limiting, IP kısıtlama gibi gelişmiş ayarlar yapabilirsiniz.
  • Firewall, fail2ban gibi güvenlik katmanlarını kendiniz tasarlarsınız.

VPS’in temel avantajlarını ve paylaşımlı hosting’den geçiş süreçlerini merak ediyorsanız, detaylı olarak anlattığımız paylaşımlı hosting’den VPS’e geçiş rehberi yazımıza da göz atabilirsiniz.

Mimarinin Büyük Resmi: Django/Flask + Gunicorn/Uvicorn + Nginx

Sağlam bir kurulumun ilk adımı, bileşenlerin görevlerini netleştirmektir. Django veya Flask uygulamanız doğrudan dış dünyaya açılmaz; araya bir uygulama sunucusu (Gunicorn veya Uvicorn) ve bir reverse proxy (Nginx) koyarız.

  • Django/Flask: İş kurallarınız, view/route’lar, ORM, template’ler.
  • Gunicorn: WSGI uygulama sunucusu; gelen HTTP isteklerini Django/Flask’a iletir. Klasik senaryo: Django ve Flask projeleri.
  • Uvicorn: ASGI sunucusu; async/await tabanlı, WebSocket ve yüksek eşzamanlılık için ideal. Django (ASGI), Starlette, FastAPI gibi framework’lerle öne çıkar.
  • Nginx: Reverse proxy ve statik dosya sunucusu. HTTP/HTTPS terminasyonu, SSL, gzip/Brotli sıkıştırma, HTTP/2/3 ve güvenlik başlıklarının evidir.

Tipik bir production mimarisi şöyle görünür:

  1. Kullanıcı https://örnek.com adresine istek gönderir.
  2. İstek 443 portundan Nginx’e gelir, SSL burada sonlanır.
  3. Nginx, HTTP ya da Unix socket üzerinden Gunicorn/Uvicorn’a proxy yapar.
  4. Gunicorn/Uvicorn worker’ları uygulama kodunuzu çalıştırır, sonucu Nginx’e döner.
  5. Nginx yanıtı kullanıcıya iletir; statik dosyaları mümkün olduğunca doğrudan kendisi servis eder.

Nginx’in reverse proxy ve basit load balancer olarak kullanımını daha derinlemesine anlamak istiyorsanız, küçük projeler için hazırladığımız Nginx reverse proxy kurulum rehberi ile bu yazıyı birlikte okumanızı öneririz.

Doğru VPS Kaynaklarını ve Linux Dağıtımını Seçmek

Altyapı kararlarını sonradan değiştirmek mümkündür ama zahmetlidir. DCHost tarafında Django/Flask projeleri için en sık karşılaştığımız soru, “Kaç vCPU, ne kadar RAM almalıyım?” oluyor. Çok kabaca:

  • Küçük projeler / dahili paneller: 1–2 vCPU, 2–4 GB RAM.
  • Orta trafik (günde birkaç on bin istek): 2–4 vCPU, 4–8 GB RAM.
  • Yüksek trafik, API veya gerçek zamanlı bildirimler: 4+ vCPU, 8+ GB RAM, tercihen NVMe disk.

Disk tarafında, rastgele okuma/yazma performansı Django/Flask projelerinde veritabanı ve loglar nedeniyle önemlidir. Bu nedenle DCHost üzerindeki NVMe VPS paketlerimizde, klasik SATA SSD’ye göre çok daha düşük I/O gecikmesi ile daha yüksek TPS (transaction per second) elde edersiniz.

Linux dağıtımı seçimi de işin omurgasıdır. Ubuntu, Debian ve AlmaLinux üçlüsü Python projelerinde sık kullanılan, paket ekosistemi zengin seçeneklerdir. Hangi dağıtımın sizin senaryonuza uygun olduğunu merak ediyorsanız, artı ve eksileri detaylı karşılaştırdığımız Ubuntu mu Debian mı AlmaLinux mu? VPS üzerinde doğru seçim rehberi yazısını okumanızı tavsiye ederiz.

Django/Flask Uygulamasını VPS’te Çalıştırmak: Gunicorn ve Uvicorn

Örnek Django + Gunicorn Kurulumu

Senaryomuz şu olsun: Debian/Ubuntu tabanlı bir DCHost VPS’iniz var, Django projeniz /srv/myproject dizininde duruyor ve sanal ortam kullanmak istiyorsunuz.

sudo apt update && sudo apt install -y python3-venv python3-pip

sudo mkdir -p /srv/myproject
sudo chown $USER:$USER /srv/myproject
cd /srv/myproject

python3 -m venv venv
source venv/bin/activate

pip install --upgrade pip
pip install django gunicorn

# Projeniz yoksa örnek proje
django-admin startproject config .

Gunicorn’u elle test edelim:

source /srv/myproject/venv/bin/activate
gunicorn config.wsgi:application --bind 127.0.0.1:8000

Tarayıcıdan http://sunucu-ip-adresi:8000 ile test edebilir veya sunucu üzerinde curl ile yanıt alıp almadığınızı kontrol edebilirsiniz. Her şey yolundaysa, bir sonraki adım Gunicorn’u systemd servisi haline getirmek.

sudo nano /etc/systemd/system/gunicorn-myproject.service
[Unit]
Description=Gunicorn for Django project myproject
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/srv/myproject
Environment="PATH=/srv/myproject/venv/bin"
ExecStart=/srv/myproject/venv/bin/gunicorn 
  --workers 3 
  --bind unix:/run/gunicorn-myproject.sock 
  config.wsgi:application

[Install]
WantedBy=multi-user.target

Dikkat edilmesi gerekenler:

  • User ve Group için genelde www-data (Debian/Ubuntu) veya benzeri web kullanıcısı tercih edilir.
  • TCP port yerine Unix socket kullanıyoruz: /run/gunicorn-myproject.sock. Nginx bu sokete bağlanacak.
  • --workers 3 değeri, CPU çekirdeği sayısı ve uygulamanızın IO/CPU ağırlığına göre ayarlanmalı.

Servisi etkinleştirelim:

sudo systemctl daemon-reload
sudo systemctl enable gunicorn-myproject
sudo systemctl start gunicorn-myproject
sudo systemctl status gunicorn-myproject

Flask İçin Gunicorn Kullanımı

Flask uygulamasında da mantık aynıdır. Uygulamanız app.py içinde app isimli bir Flask instance’ı tanımlıyorsa, Gunicorn komutu şöyle olur:

gunicorn "app:app" --bind unix:/run/gunicorn-flask.sock --workers 3

Systemd servis dosyasında sadece ExecStart satırını Flask’a göre değiştirirsiniz. Örneğin:

ExecStart=/srv/flaskapp/venv/bin/gunicorn 
  --workers 3 
  --bind unix:/run/gunicorn-flask.sock 
  app:app

Django ASGI veya Async Uygulamalar İçin Uvicorn/Gunicorn Kombinasyonu

Django Channels, WebSocket veya yoğun async IO kullanıyorsanız, ASGI tarafına geçmek mantıklıdır. En yaygın üretim deseni, gunicorn + uvicorn.workers.UvicornWorker kombinasyonudur:

pip install uvicorn[standard]

# ASGI entry point genelde config.asgi:application olur
gunicorn config.asgi:application 
  -k uvicorn.workers.UvicornWorker 
  --workers 4 
  --bind unix:/run/uvicorn-myproject.sock

Systemd dosyası da benzer şekilde güncellenir. Burada -k ile worker sınıfını Uvicorn olarak belirtiyorsunuz. Daha fazla eşzamanlı bağlantı, WebSocket ve async işlemler için bu yapı önemli fark yaratır.

Nginx Reverse Proxy ve Statik/Media Dosyaları

Gunicorn/Uvicorn doğrudan internete açılmaz; bunun yerine Nginx üzerinden proxy yapılır. Aynı zamanda /static/ ve /media/ altındaki dosyaları Nginx doğrudan servis eder; böylece Python proseslerine gereksiz yük binmez.

Basit bir Nginx server bloğu şöyle olabilir:

server {
    listen 80;
    server_name ornek.com www.ornek.com;

    # HTTP'den HTTPS'ye yönlendirme (SSL kurduktan sonra)
    # return 301 https://$host$request_uri;

    location /static/ {
        alias /srv/myproject/static/;
    }

    location /media/ {
        alias /srv/myproject/media/;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn-myproject.sock;
    }
}

Dikkat edilmesi gerekenler:

  • alias yolunun collectstatic veya kullandığınız build sürecine göre doğru dizini göstermesi gerekir.
  • proxy_params dosyasında X-Forwarded-* başlıklarının doğru ayarlı olduğundan emin olun.
  • Unix socket yolunun, systemd servis dosyasındaki yol ile birebir aynı olması gerekir.

Nginx tarafında cache, rate limiting ve daha gelişmiş proxy senaryolarına ihtiyacınız varsa, Nginx reverse proxy ve load balancer rehberimizde daha kapsamlı örnekler ve mimari desenler bulabilirsiniz.

SSL, HTTPS ve Güvenlik Başlıkları

Modern bir Django/Flask uygulamasının HTTP üzerinde kalması artık gerçekçi değil. Kullanıcı oturum çerezleri, giriş formları, API istekleri ve SEO açısından HTTPS zorunlu hale geldi. DCHost üzerinde barındırdığınız VPS için Let’s Encrypt veya ücretli bir SSL sertifikası kullanabilirsiniz; kurulum mantığı benzer.

Let’s Encrypt ile Temel SSL Kurulumu

Örnek olarak Debian/Ubuntu üzerinde certbot kullanalım:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d ornek.com -d www.ornek.com

Certbot, Nginx konfigürasyonunuzu tarar, uygun server bloklarını bulur ve gerekli ssl_certificate, ssl_certificate_key satırlarını ekler. Ardından otomatik yenileme için cron/systemd timer kurar.

El ile Nginx içine eklemek isterseniz, SSL’li bir blok aşağı yukarı şöyle görünür:

server {
    listen 443 ssl http2;
    server_name ornek.com www.ornek.com;

    ssl_certificate /etc/letsencrypt/live/ornek.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ornek.com/privkey.pem;

    # Güvenlik başlıkları (örnek)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    location /static/ {
        alias /srv/myproject/static/;
    }

    location /media/ {
        alias /srv/myproject/media/;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn-myproject.sock;
    }
}

HTTP’den HTTPS’ye Yönlendirme ve Güvenlik Başlıkları

SSL kurduktan sonra, 80 portundaki tüm trafiği 443’e yönlendirmek gerekir:

server {
    listen 80;
    server_name ornek.com www.ornek.com;
    return 301 https://$host$request_uri;
}

HSTS, CSP, X-Frame-Options gibi HTTP güvenlik başlıkları hem tarayıcı güvenliği hem de uyumluluk açısından önemlidir. Bu başlıkları detaylı açıklamalar, örnek Nginx/Apache konfigürasyonları ve hangi senaryoda hangisini nasıl ayarlamanız gerektiğiyle birlikte görmek için HTTP güvenlik başlıkları rehberimizi mutlaka incelemenizi öneririz.

Güvenlik, Loglama ve Otomatik Deploy: Üretim İpuçları

VPS Güvenlik Sertleştirme

Uygulamanız ne kadar güzel olursa olsun, SSH portu açık, root şifresi tahmin edilebilir ve firewall kapalı bir VPS uzun süre ayakta kalmaz. DCHost tarafında yeni bir Python projesi için VPS hazırlarken genelde şu adımları atıyoruz:

  • SSH için parola girişini kapatıp sadece anahtar ile erişimi zorunlu kılmak.
  • ufw veya firewalld ile sadece gerekli portları (22, 80, 443 vb.) açmak.
  • fail2ban ile SSH ve Nginx brute-force denemelerini kısıtlamak.
  • Root kullanıcı ile doğrudan giriş yerine sudo yetkili ayrı bir kullanıcı kullanmak.

Bu başlıkları tek tek uygulamak için hazır bir kontrol listesine ihtiyacınız varsa, adım adım örneklerle anlattığımız VPS güvenlik sertleştirme rehberimizi referans alabilirsiniz.

Loglama, logrotate ve İzlenebilirlik

Django/Flask + Gunicorn/Uvicorn + Nginx üçlüsünde tipik log kaynakları:

  • Nginx erişim ve hata logları (/var/log/nginx/access.log, error.log).
  • Gunicorn/Uvicorn stdout/stderr logları (systemd journal veya ayrı dosyalar).
  • Uygulama seviyesinde Django/Flask log’ları (örn. dosyaya veya syslog’a).

Logların disk doldurmaması için logrotate yapılandırması kritik. Özellikle DEBUG seviyesinde log yazan projelerde NVMe diskinizi gereksiz yere tüketmemek için rotasyon, sıkıştırma ve saklama sürelerini planlayın. DCHost üzerindeki izleme ve yedek altyapılarıyla log stratejinizi birleştirerek hem KVKK/GDPR uyumluluğunu hem de performansı dengeleyebilirsiniz.

CI/CD ile Otomatik Deploy

Production ortamında SSH ile sunucuya girip manuel git pull komutları çalıştırmak hem hata riski yüksek hem de sürdürülebilir değil. Django/Flask projelerinizde tipik bir pratik, GitHub Actions veya benzeri CI/CD araçları ile:

  • Testleri koşturmak,
  • Build adımlarını (ör. frontend, collectstatic) çalıştırmak,
  • VPS’e SSH veya rsync ile dağıtım yapmak,
  • Son aşamada systemctl restart gunicorn-myproject gibi bir komutla yeni sürümü devreye almak.

GitHub Actions ile VPS’e güvenli ve sıfıra yakın kesintiyle deploy örneklerini adım adım görmek isterseniz, hazır YAML örnekleri ve systemd tabanlı sürümleme stratejileri paylaştığımız GitHub Actions ile VPS’e otomatik deploy rehberimize göz atabilirsiniz.

Sonuç ve DCHost Üzerinde Yol Haritanız

Django ve Flask uygulamalarını üretim ortamına taşırken asıl zorluk genelde framework’te değil, etrafındaki ekosistemi doğru kurmakta ortaya çıkıyor. Bir yanda Gunicorn veya Uvicorn worker sayıları, diğer yanda Nginx reverse proxy, SSL, HTTP/2, güvenlik başlıkları, firewall, loglama ve yedek stratejileri… DCHost olarak günlük operasyonlarımızda şunu görüyoruz: Temel mimariyi baştan doğru kuran ekipler, ileride ölçekleme ve güvenlik tarafında çok daha az sürpriz yaşıyor.

Bu rehberde, tek bir DCHost VPS üzerinde Django/Flask + Gunicorn/Uvicorn + Nginx + SSL kombinasyonuyla:

  • Doğru kaynak planlaması ve Linux dağıtımı seçimini,
  • Gunicorn/Uvicorn için systemd servisleri üzerinden kalıcı servis yönetimini,
  • Nginx ile reverse proxy, statik/media servis ve HTTPS terminasyonunu,
  • Güvenlik sertleştirme, loglama ve otomatik deploy pratiklerini

özetlemeye çalıştık. Eğer halen mimarinizden veya VPS seçiminizden emin değilseniz, DCHost üzerinde sunduğumuz VPS, dedicated sunucu ve colocation altyapılarıyla Python projelerinizi birlikte planlayabiliriz. İster ilk Django projenizi canlıya alıyor olun, ister mevcut bir Flask API’yi daha performanslı ve güvenli bir ortama taşımak isteyin; bu yazıdaki adımları uygulayarak sağlam bir temel oluşturabilir, detaylı optimizasyon için de blogumuzdaki diğer VPS, güvenlik ve SSL rehberleriyle mimarinizi adım adım olgunlaştırabilirsiniz.

Sıkça Sorulan Sorular

Tam cevap, kodunuzun ne yaptığına ve beklenen trafiğe bağlıdır; ama sahada gördüğümüz bazı pratik aralıklar var. İç kullanım amaçlı yönetim panelleri, CRM benzeri düşük trafikli uygulamalar için genelde 1–2 vCPU ve 2–4 GB RAM rahatlıkla yetiyor. Günde birkaç on bin HTTP isteği alan tipik kurumsal siteler ve API’ler için 2–4 vCPU ve 4–8 GB RAM daha güvenli bir başlangıç. Daha yoğun trafik, raporlama ve ağır sorgular içeren projelerde ise 4+ vCPU ve 8+ GB RAM, NVMe disk ile birlikte öneriyoruz. Önemli olan, CPU/RAM kullanımını izleyip gerektiğinde DCHost üzerinde kaynakları yukarı yönlü ölçekleyebilmek.

Klasik Django ve Flask projeleri için, özellikle tamamen senkron çalışan uygulamalarda Gunicorn tek başına fazlasıyla yeterli ve olgun bir çözüm. Uvicorn ise ASGI tabanlı, async/await ile yoğun IO bekleyen, WebSocket kullanan veya çok sayıda eşzamanlı bağlantıyı verimli yönetmek isteyen projeler için öne çıkıyor. Django’da Channels ya da ASGI giriş noktasını kullanıyorsanız, genelde "gunicorn + uvicorn.workers.UvicornWorker" kombinasyonu tercih ediliyor. Flask tarafında ise çoğu senaryoda düz Gunicorn işinizi görür. Özetle: tamamen senkron Django/Flask için Gunicorn, async ihtiyacı olan Django/ASGI projeleri için Uvicorn worker’lı bir kurulum daha doğru seçim.

Debian/Ubuntu gibi yaygın dağıtımlarda certbot kullanıyorsanız, paketle birlikte gelen systemd timer veya cron job genelde otomatik yenilemeyi sizin için halleder. Örneğin certbot --nginx -d alanadiniz.com çalıştırdığınızda, sertifika 90 günde bir yenilenecek şekilde bir zamanlayıcı oluşturulur. sudo systemctl list-timers | grep certbot ile bu zamanlayıcıyı görebilir, sudo certbot renew --dry-run ile test yenilemesi yapabilirsiniz. Önemli nokta, HTTP-01 doğrulaması için 80 portunun açık ve Nginx’in doğru ayarlı olmasıdır. Daha gelişmiş, wildcard veya çok alan adlı senaryolarda ise DNS-01 ve ACME otomasyon stratejilerini kullanmak gerekir.

Evet, doğru izole edildiği sürece aynı VPS üzerinde birden fazla Django/Flask projesini barındırmak oldukça yaygın bir pratik. Her proje için ayrı bir Linux kullanıcısı, ayrı bir sanal ortam (venv), ayrı bir Gunicorn/Uvicorn systemd servisi ve Nginx’te ayrı bir server bloğu tanımlayabilirsiniz. Böylece bağımlılık çakışmalarını önler, log ve hata ayıklama sürecini sadeleştirirsiniz. Güvenlik tarafında ise kullanıcı ve izin yapısına dikkat etmek, SSH erişimini kısıtlamak ve firewall kurallarıyla yüzeye açık portları minimumda tutmak önemli. DCHost üzerinde doğru boyutlandırılmış bir VPS ile, bu çoklu proje mimarisini yıllarca stabil şekilde kullanmak mümkün.