Musa Yılmaz
·5 dk okuma

AWS Lightsail'de Django Deploy: Sıfırdan Yayına

awsdjangodevopsdeploy

AWS'nin tam kapsamlı EC2 kurulumu güçlüdür ama küçük ve orta ölçekli projeler için gereğinden karmaşıktır: VPC, security group, elastic IP, EBS derken basit bir siteyi yayına almak yarım güne yayılır. Lightsail aynı altyapının sadeleştirilmiş halidir — sabit aylık fiyat, önceden tanımlı ağ ayarları ve tek ekranda yönetim.

Bu yazıda bir Django uygulamasını sıfırdan Lightsail'de yayına almayı anlatıyorum.

Sunucu seçimi

Lightsail planları sabit fiyatlıdır ve bant genişliği dahildir. Django + PostgreSQL + Next.js gibi çoklu servis çalıştıracaksanız — bu kurulum için Next.js ve Django'yu Docker Compose ile tek origin'de çalıştırma yazısına bakabilirsiniz — en az 2 GB RAM alın. 1 GB planında Docker build sırasında bellek yetmeyebilir.

İşletim sistemi olarak "OS Only → Ubuntu LTS" seçin. Hazır uygulama imajları (bitnami vb.) sizin kurulumunuzla çakışabilecek yapılandırmalar getirir.

Bölge seçiminde kullanıcılarınıza yakın olanı tercih edin — Türkiye'den erişim için Frankfurt tipik olarak en düşük gecikmeyi verir.

İlk bağlantı ve temel sertleştirme

Lightsail size bir SSH anahtarı verir. İlk iş sunucuyu güncellemek:

sudo apt update && sudo apt upgrade -y

Ardından root olmayan bir kullanıcı oluşturun:

sudo adduser deploy
sudo usermod -aG sudo deploy
sudo rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy

SSH yapılandırmasında iki ayarı değiştirin:

sudo nano /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
sudo systemctl restart ssh

Parola ile girişi kapatmak, sunucunuza yönelik otomatik brute-force denemelerinin tamamını etkisiz kılar. Bunu yapmadan önce anahtarla giriş yapabildiğinizden emin olun — aksi halde sunucudan kilitlenirsiniz. Yeni bir terminal açıp test edin, mevcut oturumu kapatmayın.

Güvenlik duvarı

Lightsail'in kendi ağ güvenlik duvarı vardır (konsol → Networking sekmesi). Sadece şu portları açık bırakın:

PortAmaç
22SSH
80HTTP (HTTPS yönlendirmesi ve sertifika doğrulaması için)
443HTTPS

Veritabanı portunu (5432) asla dışarıya açmayın. Uygulama aynı sunucudaysa buna gerek yoktur; Docker'ın iç ağı üzerinden bağlanır.

SSH portunu kendi IP'nize kısıtlayabiliyorsanız yapın, ama dinamik IP kullanıyorsanız bu erişiminizi kesebilir.

Docker kurulumu

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker deploy

Grup değişikliğinin geçerli olması için oturumu kapatıp açın. Doğrulama:

docker run --rm hello-world

Uygulamayı sunucuya almak

Deploy anahtarı ile depoyu klonlamak, sunucuya parola girmeden erişim sağlar:

ssh-keygen -t ed25519 -C "lightsail-deploy" -f ~/.ssh/deploy_key
cat ~/.ssh/deploy_key.pub

Bu anahtarı GitHub'da depo ayarlarındaki Deploy keys bölümüne ekleyin ve yazma iznini vermeyin. Sunucunun sadece kodu çekmesi yeterlidir; oraya kod göndermesi gerekmez.

git clone git@github.com:kullanici/depo.git app
cd app

Ortam değişkenlerini oluşturun:

cp .env.example .env
nano .env
chmod 600 .env

Django SECRET_KEY için güvenli bir değer üretin:

python3 -c "import secrets; print(secrets.token_urlsafe(50))"

Ayağa kaldırma

docker compose up -d --build
docker compose run --rm backend python manage.py migrate
docker compose run --rm backend python manage.py collectstatic --noinput
docker compose run --rm backend python manage.py createsuperuser

Durumu kontrol edin:

docker compose ps
docker compose logs -f --tail=50

Domain bağlama

Alan adınızın DNS ayarlarında bir A kaydı oluşturun ve Lightsail'in statik IP'sine yönlendirin.

Statik IP atamayı unutmayın (konsol → Networking → Create static IP). Varsayılan IP kalıcı değildir; sunucu yeniden başlatıldığında değişebilir ve siteniz erişilemez hale gelir. Lightsail'de statik IP, sunucuya bağlı olduğu sürece ücretsizdir.

HTTPS sertifikası

Let's Encrypt ücretsiz ve otomatik yenilenen sertifika sağlar:

sudo apt install -y certbot
docker compose stop nginx
sudo certbot certonly --standalone -d example.com -d www.example.com
docker compose start nginx

Sertifikaları nginx konteynerine bağlayın:

nginx:
  volumes:
    - /etc/letsencrypt:/etc/letsencrypt:ro
    - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro

nginx yapılandırmasına HTTPS bloğunu ekleyin:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
 
server {
    listen 443 ssl;
    server_name example.com www.example.com;
 
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 
    location / {
        proxy_pass http://frontend:3000;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Otomatik yenileme için bir cron girdisi:

sudo crontab -e
0 3 * * * certbot renew --quiet --deploy-hook "cd /home/deploy/app && docker compose restart nginx"

--deploy-hook yalnızca sertifika gerçekten yenilendiğinde çalışır; her gece gereksiz yere nginx'i yeniden başlatmaz.

Django production ayarları

Yayına almadan önce şunları doğrulayın:

DEBUG = False
ALLOWED_HOSTS = ["example.com", "www.example.com"]
 
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF_TRUSTED_ORIGINS = ["https://example.com"]

DEBUG = True ile yayına çıkmak, hata sayfalarında ortam değişkenlerinizi ve kod yapınızı ziyaretçilere gösterir. Django'nun kendi kontrol komutu bu tür sorunları yakalar:

docker compose run --rm backend python manage.py check --deploy

Yedekleme

Lightsail'in otomatik anlık görüntü (snapshot) özelliği konsoldan tek tıkla açılır ve tüm diski günlük yedekler. Bu iyi bir temeldir ama veritabanı için ek olarak mantıksal yedek almak daha esnektir:

#!/bin/bash
# ~/backup.sh
set -euo pipefail
 
BACKUP_DIR="/home/deploy/backups"
mkdir -p "$BACKUP_DIR"
 
docker compose -f /home/deploy/app/docker-compose.yml exec -T postgres \
  pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" | gzip > "$BACKUP_DIR/db-$(date +%F).sql.gz"
 
# 14 günden eski yedekleri sil
find "$BACKUP_DIR" -name "db-*.sql.gz" -mtime +14 -delete
chmod +x ~/backup.sh
crontab -e
30 2 * * * /home/deploy/backup.sh

Yedeklerin başka bir yerde de kopyası olmalı — sunucu tamamen kaybolursa üzerindeki yedekler de gider. Bir S3 kovasına veya başka bir sunucuya kopyalayan bir satır ekleyin.

Ve en önemlisi: yedeği geri yükleyebildiğinizi test edin. Test edilmemiş yedek, yedek sayılmaz.

Güncelleme akışı

Kod değişikliği sonrası:

cd ~/app
git pull
docker compose up -d --build
docker compose run --rm backend python manage.py migrate

Kullanılmayan imajlar zamanla diski doldurur; ara sıra temizleyin:

docker image prune -f

Uygulamanın arka plan görevlerine ihtiyacı varsa (e-posta, zamanlanmış raporlar, yeniden deneme) ayrı bir sunucu yerine aynı compose dosyasına bir worker konteyneri ekleyin; production için hazır bir kurulum için Django + Celery + Redis: Arka Plan Görevlerini Doğru Yapmak yazısına bakın.

Lightsail ne zaman yetmez

Lightsail sabit kaynaklı tek bir sunucudur. Şu durumlarda EC2 veya yönetilen servislere geçmek gerekir:

  • Trafik arttıkça otomatik ölçeklenme gerekiyorsa
  • Yüksek erişilebilirlik (birden fazla sunucu, yük dengeleyici) şartsa
  • Veritabanının yönetilen bir servis olmasını istiyorsanız

Ama tek sunucunun yettiği projelerde Lightsail, öngörülebilir maliyeti ve sade yönetimiyle uzun süre iş görür.