Django uygulamasını yayına almak için Türkçe dökümantasyon
YouTube kanalımdaki Django Uygulamasını Yayına Alma adlı video ders serisi için dökümantasyon.
Kullanılan teknolojiler : Ubuntu 16.04, Nginx, Gunicorn, PostgreSQL
Dersler YouTube'da ücretsiz olarak yayımlanmaktadır.
İçindekiler
Django Yayın Ortamı Yapılandırması
adduser kullanici_adi # adduser baris
usermod -aG sudo kullanici_adi # usermod -aG sudo baris
ssh-keygen
cat ~/.ssh/id_rsa.pub
su - kullanici_adi # su - baris
.ssh
klasörünün oluşturulması ve klasöre kısıtlı izin verilmesi: mkdir ~/.ssh
chmod 700 ~/.ssh
.ssh
klasöründe authorized_keys
dosyasını oluşturma ve açma: nano ~/.ssh/authorized_keys
# Yerel bilgisayardan kopyalanan public key yapıştırılarak CTRL + X kombinasyonunun ardından 'y' tuşuna basılıp, 'Enter' tuşlanarak dosya kaydedilir.
.ssh
klasörünün yazma iznini kısıtlamak: chmod 600 ~/.ssh/authorized_keys
sudo nano /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
# CTRL + X kombinasyonunun ardından 'y' tuşuna basılıp, 'Enter' tuşlanarak dosya kaydedilir.
sudo systemctl reload sshd
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
sudo apt-get update
sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx
sudo -u postgres psql
CREATE DATABASE proje_adi;
CREATE USER kullanici_adi WITH PASSWORD 'parola123';
ALTER ROLE kullanici_adi SET client_encoding TO 'utf8';
ALTER ROLE kullanici_adi SET default_transaction_isolation TO 'read committed';
ALTER ROLE kullanici_adi SET timezone TO 'Europe/Istanbul';
GRANT ALL PRIVILEGES ON DATABASE proje_adi TO kullanici_adi;
\q
virtualenv
paketinin kurulması sudo -H pip3 install --upgrade pip
sudo -H pip3 install virtualenv
Not: "locale.Error: unsupported locale setting" hatası için çözüm:
export LC_ALL="en_US.UTF-8"
git clone https://github.com/barissaslan/eventhub.git
venv
adlı Sanal Python Ortamının oluşturulması cd eventhub
virtualenv venv
source venv/bin/activate
pip install -r requirements.txt
pip install gunicorn psycopg2
Not: Projenin settings.py dosyasının dizin hiyerarşisi aşağıdaki gibidir:
/home/baris/eventhub/
/accounts/
/event/
/eventhub/
/__init__.py
/settings.py
/urls.py
/wsgi.py
/notification/
/static/
/templates/
. . .
setting.py
Dosyasındaki Ayarlarsetting.py
dosyasındaki DEBUG ifadesinin False
olarak ayarlanması. DEBUG = False # Production ortamında DEBUG kesinlikle kapatılmalıdır ki saldırganlar site hakkında detaylı hata raporlarına ulaşamasınlar.
setting.py
dosyasındaki ALLOWED_HOSTS (İzin verilmiş sunucular) ataması ALLOWED_HOSTS = ['alan_adiniz_veya_IP_adresiniz', 'ikinci_alan_adiniz_veya_IP_adresiniz', . . .]
# Örnek:
ALLOWED_HOSTS = ['alanadi.com', '192.168.1.10'] # IP adresi örnek amaçlı yazılmış olup private adrestir.
Django projesinin veritabanı ayarlarını SQLite'dan PostgreSQL'e çevirme.
Not: Aşağıdaki 'NAME'
, 'USER'
, 'PASSWORD'
alanları değişken olup, atanan değerler yukarıda ki PostgreSQL Yapılandırması'nda verilen takma adlardan alınmıştır.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'proje_adi',
'USER': 'kullanici_adi',
'PASSWORD': 'parola123',
'HOST': 'localhost',
'PORT': '',
}
}
STATICFILES_DIR Değişkeninin Kaldırılması ve STATIS_ROOT değişkeninin düzenlenmesi
Not: Yayın Ortamında static dosyalar STATIC_ROOT değişkeninin gösterdiği klasör referans alınarak servis edileceği için STATICFILES_DIR'ın bir anlamı olmadığından yorum satırı haline getiriyoruz veya siliyoruz. Projemizde STATIC_ROOT değişkeni "static" klasörünü göstermelidir.
# STATICFILES_DIRS = [
# os.path.join(BASE_DIR, "static"),
# ]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
python manage.py makemigrations
python manage.py migrate
python manage.py collectstatic
sudo ufw allow 8000
python manage.py runserver 0.0.0.0:8000
# 0.0.0.0 -> sunucunun IP adresi. (sunucu kendi IP adresini bildiğinden 0.0.0.0 yazılabilir)
http://alan_adi_veya_IP:8000
# Sanal ortam aktif olmalı ve manage.py dizininde çalıştırılmalı. (eventhub.wsgi -> proje_adı.wsgi)
gunicorn --bind 0.0.0.0:8000 eventhub.wsgi
Tarayıcıdan test etme: http://alan_adi_veya_IP:8000
Gunicorn sunucusunu durduma: CTRL + C
systemd
Servis Dosyası Oluşturma # Sanal ortamdan çıkılmalı
deactivate
# Servis dosyası oluşturma
sudo nano /etc/systemd/system/gunicorn.service
gunicorn.service dosya içeriği şu şekilde olmalıdır:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=baris
Group=www-data
WorkingDirectory=/home/baris/eventhub
ExecStart=/home/baris/eventhub/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/baris/eventhub/eventhub.sock eventhub.wsgi:application
[Install]
WantedBy=multi-user.target
Not: Sanal ortamın adı venv
, projenin adı eventhub
, kullanıcı adı baris
olarak varsayılmıştır.
Not 2: Dosyayı kaydetmek için CTRL + X
yaptıktan sonra y
harfine basıp, enter
tuşuna basılmalı.
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl status gunicorn
# Yeşil renkte "active (running)" yazıyorsa başarılı bir şekilde çalışıyor demektir.
ls /home/baris/eventhub
# ls çıktısında "proje_adı.sock" adlı (.sock) uzantılı bir soket dosyası görülüyorsa gunicorn başarılı bir şekilde yapılandırılmıştır.
sudo nano /etc/nginx/sites-available/eventhub
Dosyanın içinde bulunması gerekenler:
server {
listen 80;
server_name alan_adi_veya_IP;
root /home/baris/eventhub; # Projenin kök dizini
location /static/ {
}
location /media/ {
}
location / {
include proxy_params;
proxy_pass http://unix:/home/baris/eventhub/eventhub.sock; # Projenin kök dizinindeki 'proje_adı.sock' dosyası
}
}
Not: Dosyayı kaydetmek için CTRL + X
yaptıktan sonra y
harfine basıp, enter
tuşuna basılmalı.
sites-enabled
dizinine link olarak verme sudo ln -s /etc/nginx/sites-available/eventhub /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx
sudo ufw delete allow 8000
sudo ufw allow 'Nginx Full'
settings.py
dosyasının bulunduğu dizinde (/home/baris/eventhub/eventhub
klasörü içinde ) settings adında bir Python Paketi (içinde __init__.py dosyası bulunan bir klasör) oluşturulur.
settings.py dosyası yeni oluşturulan pakete taşınır ve adı base.py
olarak değiştirilir.
settings paketinin içinde development.py
ve production.py
dosyaları oluşturulur. Her iki dosyanın en başında base.py dosyası import edilir (from eventhub.settings.base import *
).
base.py
dosyasının proje dizinini yanlış hesaplamaması için BASE_DIR
ifadesi şu şekilde değiştirilir:
# Önce
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Sonra
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
base.py
'de ki ortama bağlı ifadeler çıkarılarak ilgili ortamların settings dosyalarında ayrı ayrı değerler olarak yazılır.
İlgili settings dosyalarının sanal ortam tarafından bulunması için her iki ortamın activate
dosyasının (venv/bin/activate
) sonuna şu ifadeler eklenir.
# Geliştirme ortamındaki venv/bin/activate dosyası açılarak sonuna şu ifadeler eklenir:
DJANGO_SETTINGS_MODULE="eventhub.settings.development"
export DJANGO_SETTINGS_MODULE
# Yayın ortamındaki venv/bin/activate dosyası açılarak sonuna şu ifadeler eklenir:
DJANGO_SETTINGS_MODULE="eventhub.settings.production"
export DJANGO_SETTINGS_MODULE
wsgi.py
dosyasında settings konumu olarak production dosyası verilir (eventhub.settings.production
).
Projenin dizin hiyerarşisi:
/home/baris/eventhub/
/accounts/
/event/
/eventhub/
/__init__.py
/settings/
/__init__.py
/base.py
/development.py
/production.py
/urls.py
/wsgi.py
/notification/
/static/
/templates/
. . .
sudo add-apt-repository ppa:certbot/certbot # Onaylamak için ENTER'a basılmalı.
sudo apt-get update # Ubuntu paket listesini güncelleme.
sudo apt-get install python-certbot-nginx # Certbox'un Nginx paketinin yüklenmesi.
sudo certbot --nginx -d alan_adı -d www.alan_adı
Not: 2. Adımdaki komut hata verirse 3. adımdaki komut denenmelidir. Hatanın sebebi bir güvenlik açığının tespiti sebebiyle Let's Encrypt, Certbot servisini geçici süreyle kapalı tutmaktadır. Aşağıdaki alternatif denenmelidir.
sudo certbot --authenticator standalone --installer nginx --pre-hook "service nginx stop" --post-hook "service nginx start"
sudo nano /etc/nginx/sites-available/eventhub
server {
listen 80;
server_name alan_adınız www.alan_adınız; # server_name aslanbaris.com www.aslanbaris.com
location / {
return 302 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name www.alan_adınız; # www tercihe bağlıdır.
ssl_certificate /etc/letsencrypt/live/www.alan_adınız/fullchain.pem; # Certbot yazılımından seçilen domain adı yazılmalıdır.
ssl_certificate_key /etc/letsencrypt/live/www.alan_adınız/privkey.pem; # Certbot yazılımından seçilen domain adı yazılmalıdır.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 5M;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /.well-known {
alias /var/www/cert/.well-known;
}
root /home/kullanıcı_adı/proje_adı; # root /home/baris/eventhub
location /static/ {
}
location /media/ {
}
location / {
include proxy_params;
proxy_pass http://unix:/home/kullanıcı_adı/proje_adı/proje_adı.sock; # proxy_pass http://unix:/home/baris/eventhub/eventhub.sock;
}
}
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
sudo systemctl restart nginx
Kaynaklar:
[1] https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04