# Python Uygulama Barındırma

WHost, Django, Flask ve FastAPI gibi Python web uygulamalarını Gunicorn/Uvicorn uygulama sunucuları ve Nginx reverse proxy ile barındırmanızı sağlar.

Python barındırma ücretsiz **Python Hosting** eklentisidir: **Ayarlar → Eklentiler** altında bir kez etkinleştirin. Eklenti etkin değilken **Python Uygulamaları** menü girdisi iki panelde de gizlenir ve her Python uygulaması endpoint'i `503 PLUGIN_DISABLED` döner.

---

## Desteklenen Yapı

| Bileşen | Seçenekler |
|---------|-----------|
| Framework | Django, Flask, FastAPI, Custom |
| Uygulama Sunucusu | Gunicorn (WSGI; Uvicorn worker sınıfıyla ASGI), Uvicorn (ASGI) |
| Python Sürümleri | 3.10 – 3.13 arasından sunucuda kurulu olanlar (`/usr/bin/python3.X`) |
| Web Sunucu | Nginx reverse proxy, otomatik yazılır — sunucunun web sunucusu kurulumunda Nginx bulunmalıdır (Nginx veya Nginx + Apache) |
| Süreç Yönetimi | systemd (otomatik yeniden başlatma, hesabın cgroup slice'ı) |

---

## Yönetici Paneli

### Uygulama Oluşturma

**Araçlar → Python Uygulamaları → Yeni Python Uygulaması** bir seçim ekranı açar:

- **Akıllı Deploy** (önerilen) — bir arşiv yükleyin ya da sunucudaki bir yolu gösterin; proje tek seferde analiz edilip deploy edilir. Bkz. [Akıllı Deploy](#ak-ll-deploy).
- **Boş Uygulama Oluştur** — yalnızca runtime iskeletini aşağıdaki formla kurar; kodu siz ekler, kurulum adımlarını siz çalıştırırsınız.

| Alan | Açıklama | Örnek |
|------|----------|-------|
| Hesap | Uygulamanın ait olacağı hesap | `siteowner` |
| Uygulama Adı | Benzersiz tanımlayıcı: küçük harfle başlar, ardından küçük harf, rakam, `_` veya `-` (2–31 karakter) | `turkuaz` |
| Görünen Ad | Görünen ad | `Turkuaz Site Yönetimi` |
| Alan Adı | Hesabın bir alan adı — birincil alan adı, bir ek alan adı veya bir alt alan adı (hesap seçilince birincil alan adı doldurulur) | `turkuaz.example.com` |
| Python Sürümü | Sunucudaki kurulu sürümlerden biri | `3.12` |
| Framework | Uygulama tipi | `Django` |
| Uygulama Sunucusu | Gunicorn (WSGI) veya Uvicorn (ASGI) | `Gunicorn (WSGI)` |
| Giriş Noktası | WSGI/ASGI giriş noktası (`module.path:callable`) | `turkuaz.wsgi:application` |
| Worker Sayısı | İşçi sayısı (1–16 ve hesabın Python Worker / Uygulama limitinden fazla değil) | `2` |
| Worker Sınıfı | Sync, Threaded (gthread) veya Uvicorn Worker (ASGI) — Gunicorn kullanır | `Sync` |
| WebSocket Desteği | ASGI uygulamalar için aktifleştir | Kapalı |
| Otomatik Yeniden Başlatma | Çökme durumunda otomatik yeniden başlat | Açık |

Oluşturma işlemi sırasında sistem otomatik olarak:
- `/home/{kullanıcı}/{uygulama}/` uygulama dizinini ve bir virtualenv'i oluşturur
- Gunicorn kurar (Uvicorn uygulamalarında `uvicorn[standard]` ve Gunicorn)
- systemd servisi ve logrotate kuralı tanımlar
- Nginx reverse proxy yapılandırır
- Servisi başlatır — kod yerine konana kadar servis açılamaz (bkz. [Tipik Kurulum Adımları](#tipik-kurulum-ad-mlar))

### Uygulama Yönetimi

Tablo satırındaki `⋮` menüsünden veya uygulama adına tıklayarak açılan detay ekranından:

**Satır menüsü:**
- Uygulamayı Düzenle (görünen ad, alan adı, giriş noktası, worker sayısı, worker sınıfı, WebSocket desteği, otomatik yeniden başlatma)
- Paketler / Ortam Değişkenleri / Günlükler / manage.py — detay ekranını o sekmede açar
- Başlat (çalışmıyorken) / Durdur (çalışırken) / Yeniden Başlat
- Uygulamayı Sil (onay gerektirir) — servisi, Nginx yapılandırmasını, virtualenv'i, kodla birlikte `/home/{kullanıcı}/{uygulama}/` uygulama dizinini ve uygulamanın log dosyalarını siler

**Detay Ekranı (5 Sekme):**

| Sekme | İçerik |
|-------|--------|
| Genel Bakış | Tüm yapılandırma bilgileri ve durum |
| Paketler | Kurulu pip paketleri (ad, sürüm) — yönetici panelinde salt okunur; kurma, kaldırma ve requirements.txt müşteri panelinde ve API'dedir |
| Ortam Değişkenleri | Ortam değişkenleri düzenleme (KEY=VALUE) |
| Günlükler | Hata ve erişim loglarını görüntüleme |
| manage.py | Django komutları çalıştırma |

### Tüm Uygulamalar Görünümü

Yönetici panelindeki Python Uygulamaları sayfası tüm hesaplardaki uygulamaları tek tabloda gösterir. Arama (uygulama adı, görünen ad, hesap, alan adı), durum filtresi (Çalışıyor / Durduruldu / Başarısız) ve Python sürümü filtresi (uygulamalar birden fazla sürüm kullanıyorsa görünür) ile daraltılabilir.

---

## Müşteri Paneli

### Uygulama Oluşturma

**Araçlar → Python Uygulamaları → Uygulama Oluştur** aynı seçim ekranını açar (**Akıllı Deploy** veya **Boş Uygulama Oluştur**). Boş uygulama formu yönetici formuyla aynıdır; yalnız Hesap seçimi yoktur — uygulama giriş yapan kullanıcının hesabına oluşturulur — ve Worker Sınıfı alanı yoktur (sonradan Uygulamayı Düzenle ile değiştirilir).

### Uygulama Yönetimi

Müşteri panelinde aynı satır menüsü ve aynı beş detay sekmesi bulunur. Yönetici panelinden farkları:

- **Paketler** sekmesi paket kurup kaldırabilir ve `requirements.txt` kurabilir (bkz. [Pip Paket Yönetimi](#pip-paket-y-netimi)).
- **manage.py** listesi `createsuperuser` ve `shell` komutlarını da gösterir (bkz. [Django Komutları](#django-komutlar-manage-py)).
- Listede arama kutusu (uygulama adı, görünen ad, alan adı) vardır, durum ve sürüm filtresi yoktur.

---

## Akıllı Deploy

Seçim ekranından iki panelde de kullanılabilir:

1. **Kaynak** — **Arşiv Yükle** (`.zip` / `.tar.gz`, en fazla 250 MB) veya **Sunucu Yolu** (hesabın ev dizini içindeki bir klasör ya da arşiv; daha büyük projeler için SSH/SFTP ile yükleyip bu modu kullanın).
2. **Analiz Et** — framework'ü, uygulama sunucusunu, Python sürümünü, giriş noktasını, statik yolları ve kodun okuduğu ortam değişkenlerini tespit eder, eksik sistem kütüphanelerini bildirir.
3. **Deploy Et** — tespit edilen değerleri ve seçenekleri (**Mevcudun Üzerine Yaz**, **.env Dosyalarını Dahil Et**, **migrate Çalıştır**, **collectstatic Çalıştır**) gözden geçirip deploy edin. Süreç dosyaları `/home/{kullanıcı}/{uygulama}/` dizinine kopyalar, uygulamayı oluşturur, `requirements.txt`'yi kurar, seçildiyse Django için `migrate` ve `collectstatic` çalıştırır ve uygulamayı başlatır; diyalog günlüğü canlı akıtır.

`DB_NAME`, `DB_USER` ve `DB_PASSWORD` boş bırakılırsa (bu değişkenleri okuyan bir projede) deploy sırasında bir MySQL veritabanı ve kullanıcısı oluşturulur ve kimlik bilgileri uygulamaya verilir. Yüklenen projenin içindeki veritabanı dökümü veya media klasörü iki panelde de tespit edilir; ayrı bir SQL dökümü ya da media arşivi yüklemek yalnız yönetici panelinde çalışır.

---

## Pip Paket Yönetimi

Detay ekranı → **Paketler** sekmesi. Yönetici paneli kurulu paketleri listeler; kurma ve kaldırma müşteri panelinden (veya API üzerinden) yapılır.

| İşlem | Açıklama |
|-------|----------|
| Paket kur | Paket adını yazıp **Kur**'a tıkla (birden fazla: boşlukla ayır) |
| requirements.txt | **requirements.txt'den kur** `/home/{kullanıcı}/{uygulama}/requirements.txt` dosyasını kurar |
| Paket kaldır | Satır sonundaki çöp kutusu ikonu (**Kaldır**) |

Paket adı formatı: `django`, `django==6.0.1`, `gunicorn>=22.0`, `uvicorn[standard]`

---

## Ortam Değişkenleri

Detay ekranı → **Ortam Değişkenleri** sekmesi

| İşlem | Açıklama |
|-------|----------|
| Ekle | Anahtar ve Değer gir, **Değişken Ekle**'ye tıkla |
| Düzenle | Mevcut değeri satır üzerinde değiştir |
| Sil | Satır sonundaki × ikonu |
| Kaydet | **Değişkenleri Kaydet** — ekleme, düzenleme ve silmeler ancak kaydedilince geçerli olur |

Anahtarlar harf, rakam ve `_` içerir ve rakamla başlamaz; değerler tek satırdır, en fazla 16.384 karakter. Kaydetme sonrası uygulama çalışıyorsa otomatik yeniden başlatılır.

Değişkenler `/home/{kullanıcı}/{uygulama}/.env` dosyasına (0600) yazılır ve uygulamanın servisine verilir; değeri boş olan değişken dosyaya yazılmaz. `manage.py` komutları — sekmeden, API'den ya da Akıllı Deploy'dan — bu servisin dışında çalışır ve bu değişkenleri ancak proje `.env` dosyasını kendisi okuyorsa görür (örneğin python-decouple veya django-environ ile).

**Yaygın değişkenler:**

```
DJANGO_SETTINGS_MODULE = myapp.settings.production
SECRET_KEY             = güvenli-rastgele-anahtar
DATABASE_URL           = mysql://user:pass@localhost/dbname
DEBUG                  = false
ALLOWED_HOSTS          = example.com
```

---

## Log Görüntüleme

Detay ekranı → **Günlükler** sekmesi

- **Hata Günlüğü:** Uygulama hataları ve traceback'ler
- **Erişim Günlüğü:** HTTP istekleri (IP, yol, durum kodu)
- Dropdown ile log tipi seçilir, **Yenile** ile güncellenir. Sekme son 200 satırı gösterir.

Log dosyaları: `/home/{kullanıcı}/logs/{uygulama}-error.log` ve `{uygulama}-access.log`

---

## Django Komutları (manage.py)

Detay ekranı → **manage.py** sekmesi (Django projeleri — uygulama dizininde `manage.py` bulunmalıdır)

Dropdown'dan komut seçip **Çalıştır** ile çalıştırılır. Komut, uygulama dizininde hesabın kullanıcısıyla ve 5 dakikalık sınırla çalışır; çıkış kodu, çıktı ve hatalar ekranda gösterilir.

| Komut | Açıklama |
|-------|----------|
| `migrate` | Veritabanı migration'larını uygular (`--noinput` ile çalışır) |
| `collectstatic` | Static dosyaları toplar (`--noinput` ile çalışır) |
| `showmigrations` | Migration durumunu gösterir |
| `check` | Proje hatalarını kontrol eder |

Müşteri panelinin listesi `createsuperuser` ve `shell` komutlarını da gösterir, API de ikisini kabul eder; ancak ikisi de panelin ya da API'nin sağlamadığı etkileşimli bir terminal ister. Django yönetici kullanıcısını bunun yerine, hesabın shell erişimi varsa SSH üzerinden oluşturun: `cd ~/{uygulama} && ~/venvs/{uygulama}/bin/python manage.py createsuperuser`.

---

## Tipik Kurulum Adımları

Yeni bir Django uygulamasını boş uygulama olarak barındırmak için (**Akıllı Deploy** 4–9. adımları tek seferde yapar):

1. **Hesap oluştur** — Hesaplar → Hesap Oluştur
2. **Alan adı ekle** (yalnız uygulama hesabın birincil alan adından farklı bir alan adı kullanacaksa) — Alan Adları → Ek Alan Adı Ekle veya Alt Alan Adı Ekle
3. **Veritabanı oluştur** — Veritabanları → Veritabanı Oluştur
4. **Python uygulaması oluştur** — Python Uygulamaları → Yeni Python Uygulaması → Boş Uygulama Oluştur
5. **Uygulama kodunu yükle** — FTP, Dosya Yöneticisi veya SSH/SFTP ile `/home/{kullanıcı}/{uygulama}/` dizinine
6. **Bağımlılıkları kur** — Paketler → requirements.txt'den kur (müşteri paneli ya da API üzerinden `POST …/pip/requirements`)
7. **Ortam değişkenlerini ayarla** — Ortam Değişkenleri → DATABASE_URL, SECRET_KEY vb.
8. **Migration çalıştır** — manage.py → migrate
9. **Static dosyaları topla** — manage.py → collectstatic
10. **Yönetici kullanıcı oluştur** — SSH üzerinden `manage.py createsuperuser` (etkileşimli terminal ister)

Servis, uygulama oluşturulduğunda başlatılmıştır ve kod yerine konana kadar açılamaz. Otomatik Yeniden Başlatma açıksa systemd servisi 5 saniyede bir yeniden dener; kod, paketler ve değişkenler hazır olduğunda servis açılır ve uygulama alan adı üzerinden erişilebilir olur. Kapalıysa `⋮` menüsünden başlatın.

---

## Kod Güncelleme Adımları

Mevcut bir uygulamayı güncellemek için:

1. Yeni kodu yükle (FTP / Dosya Yöneticisi / SSH)
2. Yeni bağımlılıklar varsa → Paketler → requirements.txt'den kur (müşteri paneli veya API)
3. Migration varsa → manage.py → migrate
4. Static dosyalar değiştiyse → manage.py → collectstatic
5. Yeniden Başlat

---

## Paket Limitleri

Hosting paketlerinde Python uygulamaları için iki limit tanımlanabilir:

| Limit | Açıklama | Varsayılan |
|-------|----------|-----------|
| Maks. Python Uygulaması | Hesap başına maksimum uygulama sayısı | 0 (sınırsız) |
| Python Worker / Uygulama | Tek bir uygulamaya verilebilecek en fazla worker sayısı (0 = sınırsız) | 4 |

Bu limitler Planlar → Planı Düzenle → Paket Limitleri bölümünden ayarlanır; hesap oluşturma ve düzenleme sayfalarında da aynı alanlar bulunur. Kontrol hesabın kendi değerlerini okur; bu yüzden bir plan değişikliği mevcut bir hesaba paket değişimiyle ya da hesabın düzenleme sayfasından ulaşır. Limit aşımı `403 PYTHON_APP_LIMIT` veya `403 PYTHON_WORKER_LIMIT` ile reddedilir.

---

## Dosya Yapısı

Bir Python uygulaması oluşturulduğunda sunucuda şu yapı oluşur:

```
/home/{kullanıcı}/
├── {uygulama}/                  ← Uygulama kodu
│   ├── manage.py
│   ├── gunicorn.conf.py         ← Otomatik üretilir
│   ├── .env                     ← Ortam değişkenleri (0600)
│   └── ...
├── venvs/{uygulama}/            ← Virtualenv
│   ├── bin/python
│   ├── bin/pip
│   └── bin/gunicorn             ← Uvicorn uygulamalarında bin/uvicorn da
└── logs/
    ├── {uygulama}-error.log
    └── {uygulama}-access.log

/etc/systemd/system/
└── whost-pyapp-{kullanıcı}-{uygulama}.service

/etc/nginx/sites-available/      ← AlmaLinux, Rocky Linux, CentOS Stream'de /etc/nginx/conf.d/
└── {domain}-pyapp-{uygulama}.conf

/etc/logrotate.d/
└── whost-pyapp-{kullanıcı}-{uygulama}   ← log döndürme, 14 sıkıştırılmış kopya tutulur

/run/whost/{kullanıcı}/
└── {uygulama}.sock              ← Unix socket
```

---

## API Referansı

Tüm endpoint'ler `/api/v1/` prefix'i altındadır.

### Yönetici Endpoint'leri

| Metot | Yol | Açıklama |
|-------|-----|----------|
| GET | `/accounts/{user}/python-apps` | Uygulamaları listele |
| POST | `/accounts/{user}/python-apps` | Uygulama oluştur |
| GET | `/accounts/{user}/python-apps/{app}` | Detay |
| PUT | `/accounts/{user}/python-apps/{app}` | Güncelle |
| DELETE | `/accounts/{user}/python-apps/{app}` | Sil |
| POST | `/accounts/{user}/python-apps/{app}/start` | Başlat |
| POST | `/accounts/{user}/python-apps/{app}/stop` | Durdur |
| POST | `/accounts/{user}/python-apps/{app}/restart` | Yeniden başlat |
| GET | `/accounts/{user}/python-apps/{app}/status` | Durum |
| GET | `/accounts/{user}/python-apps/{app}/pip` | Paket listesi |
| POST | `/accounts/{user}/python-apps/{app}/pip/install` | Paket kur |
| POST | `/accounts/{user}/python-apps/{app}/pip/uninstall` | Paket kaldır |
| POST | `/accounts/{user}/python-apps/{app}/pip/requirements` | requirements.txt kur |
| GET | `/accounts/{user}/python-apps/{app}/env` | Env vars getir |
| PUT | `/accounts/{user}/python-apps/{app}/env` | Env vars ayarla |
| GET | `/accounts/{user}/python-apps/{app}/logs` | Log getir |
| POST | `/accounts/{user}/python-apps/{app}/manage` | manage.py çalıştır |
| POST | `/accounts/{user}/python-apps/analyze` | Akıllı Deploy: yüklenen bir `archive`'ı (multipart, en fazla 250 MB) ya da bir `server_path`'i analiz et |
| POST | `/accounts/{user}/python-apps/migration/upload` | Akıllı Deploy: sonraki deploy için SQL dökümü ve/veya media arşivi hazırla |
| POST | `/accounts/{user}/python-apps/deploy` | Akıllı Deploy: süreci başlat; bir `task_id` döner |
| GET | `/accounts/{user}/python-apps/deploy/{task_id}` | Deploy görevinin durumu ve olayları |
| GET | `/accounts/{user}/python-apps/deploy/{task_id}/events` | Canlı deploy günlüğü (Server-Sent Events) |
| GET | `/system/python/versions` | Kurulu Python sürümleri |
| GET | `/system/python/apps` | Tüm uygulamalar |

### Müşteri Endpoint'leri

Müşteri endpoint'leri `/client/python-apps/` prefix'i altındadır ve hesabın oturum çereziyle (veya hesaba bağlı bir API anahtarıyla) doğrulanır. Hesap adı belirtilmez — bu kimlikten alınır.

| Metot | Yol | Açıklama |
|-------|-----|----------|
| GET | `/client/python-apps` | Uygulamalarım |
| POST | `/client/python-apps` | Uygulama oluştur |
| GET | `/client/python-apps/{app}` | Detay |
| PUT | `/client/python-apps/{app}` | Güncelle |
| DELETE | `/client/python-apps/{app}` | Sil |
| POST | `/client/python-apps/{app}/start` | Başlat |
| POST | `/client/python-apps/{app}/stop` | Durdur |
| POST | `/client/python-apps/{app}/restart` | Yeniden başlat |
| GET | `/client/python-apps/{app}/status` | Durum |
| GET | `/client/python-apps/{app}/pip` | Paket listesi |
| POST | `/client/python-apps/{app}/pip/install` | Paket kur |
| POST | `/client/python-apps/{app}/pip/uninstall` | Paket kaldır |
| POST | `/client/python-apps/{app}/pip/requirements` | requirements.txt kur |
| GET | `/client/python-apps/{app}/env` | Env vars getir |
| PUT | `/client/python-apps/{app}/env` | Env vars ayarla |
| GET | `/client/python-apps/{app}/logs` | Log getir |
| POST | `/client/python-apps/{app}/manage` | manage.py çalıştır |
| POST | `/client/python-apps/analyze` | Akıllı Deploy: yüklenen bir `archive`'ı (multipart, en fazla 250 MB) ya da bir `server_path`'i analiz et |
| POST | `/client/python-apps/deploy` | Akıllı Deploy: süreci başlat; bir `task_id` döner |
| GET | `/client/python-apps/deploy/{task_id}` | Deploy görevinin durumu ve olayları |
| GET | `/client/python-apps/deploy/{task_id}/events` | Canlı deploy günlüğü (Server-Sent Events) |
| GET | `/client/python-apps/versions` | Kurulu Python sürümleri |
