Skip to content

Instantly share code, notes, and snippets.

@kenjiakito
Last active December 15, 2022 19:53
Show Gist options
  • Save kenjiakito/97d1f241ae7c838ef5bf5d0af5f811e3 to your computer and use it in GitHub Desktop.
Save kenjiakito/97d1f241ae7c838ef5bf5d0af5f811e3 to your computer and use it in GitHub Desktop.
deploy_django_nginx

Bước 1: SSH vào server của bạn

ssh -i ./key_rsa server@domain.com

hoặc

ssh -i ./ssh.key server@domain.com

Bước 2: Kéo code về từ github (gitlab), sử dụng phương thức HTTPS

git clone https://username@github.com/yourproject.git

Sau đó nhập mật khẩu của tài khoản username

Bước 3: Cài đặt package

source venv/bin/activate

pip install -r requirement.txt

Bước 4: Cấu hình local_settings.py, bao gồm:

# local_setting.py
import os

DEBUG = False
DEBUG_TOOLBAR = False  # django-debug-toolbar

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  • DATABASES
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'project_db',
        'USER': 'project_user',
        'PASSWORD': 'project_password',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}
  • Một số thông tin cần có
SITE_DOMAIN = 'project.com'

CORS_ORIGIN_WHITELIST = (
    'http://project.com',
)
CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True

CSRF_TRUSTED_ORIGINS = ['project.com']
ALLOWED_HOSTS = ['project.com']

DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'

ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'http'
  • STATIC_URL: Đường dẫn trỏ đến thư mục static

  • STATIC_ROOT: Thư mục static chứa data sau khi gõ lệnh python manage.py collectstatic

STATIC_URL = 'https://static.project.com/'
STATIC_ROOT = '/home/linuxuser/webapps/project.com/static'
  • Tương tự với MEDIA_URL và MEDIA_ROOT
MEDIA_URL = 'https://media.project.com/'
MEDIA_ROOT = '/home/linuxuser/webapps/project.com/media'
  • Tạo file ghi log
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
            'datefmt': "%d/%b/%Y %H:%M:%S"
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'handlers': {
        'file': {
            'level': 'ERROR',
            'class': 'logging.FileHandler',
            'filename': '/home/linuxuser/webapps/project.com/django.log',
            'formatter': 'verbose'
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'propagate': True,
            'level': 'ERROR',
        },
        'MYAPP': {
            'handlers': ['file'],
            'level': 'ERROR',
        },
    }
}

Bước 5: Migrate dữ liệu, tạo superuser, chạy collectstatic (trong môi trường venv)

# Đảm bảo đã makenigrations trước đó
python manage.py migrate

# Tạo tài khoản bảo mật cao
python manage.py createsuperuser

# Khởi tạo 2 thư mục `static` và `media` khớp với STATIC_ROOT và MEDIA_ROOT trước khi chạy lệnh này
python manage.py collectstatic

Bước 6: Chạy thử project với Gunicorn

# Lưu ý: Cần cd vào trong projectname và đang ở trong venv mới có thể chạy
/home/linuxuser/webapps/project.com/venv/bin/gunicorn projectname.wsgi -b localhost:9987 -w 4

Sau đó truy cập vào project.com của bạn, nếu project khởi chạy thành công (chưa có css) là ổn.

Bước 7: Cấu hình Nginx server Dir: /home/linuxuser/nginx-sites/project.com.conf

upstream truyenhub_upstream  {
    server localhost:9999;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen       80; 
    server_name  project.com;

    root   /home/linuxuser/webapps/project.com;
    index  index.html index.htm;

    recursive_error_pages   on;
    server_tokens off;
    client_max_body_size 30M;
    
    gzip on;
    gzip_min_length  1100;
    gzip_buffers  4 32k;
    gzip_types    text/plain application/x-javascript text/xml text/css;
    gzip_vary on;

    location / {
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_redirect off;
        proxy_buffering off;
        proxy_set_header 		X-Forwarded-Host $http_host;
        proxy_set_header 		X-Forwarded-Proto $scheme; 
        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 60s;
		proxy_send_timeout 180s;
		proxy_http_version 1.1; 
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
		proxy_pass  http://project_upstream;
    }
	location ~ /.well-known {
	   allow all;
    }
    location /robots.txt {
        alias /home/linuxuser/webapps/project.com/robots.txt;
        expires 30d;
        access_log off;
    }
    location ~ \.(txt) {
        root /home/linuxuser/webapps/project.com;
        expires 30d;
        access_log off;
    }
    location ~*  \.(jpg|jpeg|png|gif|ico|css|js|svg|json|wav|mp3|ogg)$ {
        expires 30d;
        add_header Vary Accept-Encoding;
        access_log off;
    }
    location ~* \.(eot|otf|ttf|woff|woff2)$ {
	    expires 30d;
        add_header Access-Control-Allow-Origin *;
        access_log off;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/project.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/project.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
	listen 		80;
    server_name  	static.project.com;

    root   /home/linuxuser/webapps/project.com/static;
    index  index.html index.htm;
    
    
    pagespeed off;
    access_log off;
    error_log off;

    recursive_error_pages   on;
    server_tokens 			off;
    client_max_body_size 	40M;
    sendfile        		on;
    
    include       mime.types;
	default_type  application/octet-stream;
    
	gzip_disable "msie6";
	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 6;
	gzip_buffers 16 8k;
	gzip_http_version 1.1;
	gzip_min_length 256;
	gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon application/octet-stream;
	gzip on;
    
    location ~ /.well-known {
	   allow all;
    }
    
    location ~*  \.(jpg|jpeg|png|gif|ico|css|js|svg|mp3|ogg|wav|json|webp)$ {
        expires 30d;
        add_header Vary Accept-Encoding;
        access_log off;
        
        if ($request_method = 'OPTIONS') {

        add_header 'Access-Control-Allow-Origin' '*';
        
        #
        # Om nom nom cookies
        #

        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #

        add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        
        #
        # Tell client that this pre-flight info is valid for 20 days
        #

        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;

        return 204;
     }

     if ($request_method = 'POST') {

        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

     }

     if ($request_method = 'GET') {

        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

     }
    }
    
    location ~* \.(eot|otf|ttf|woff|woff2)$ {
	    expires 30d;
        add_header Access-Control-Allow-Origin *;
        access_log off;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/project.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/project.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
	listen 		80;
    server_name  	media.project.com;

    root   /home/linuxuser/webapps/project.com/media;
    index  index.html index.htm;
    
    
    pagespeed off;
    access_log off;
    error_log off;

    recursive_error_pages   on;
    server_tokens 			off;
    client_max_body_size 	40M;
    sendfile        		on;
    
    include       mime.types;
	default_type  application/octet-stream;
    
	gzip_disable "msie6";
	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 6;
	gzip_buffers 16 8k;
	gzip_http_version 1.1;
	gzip_min_length 256;
	gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon application/octet-stream;
	gzip on;
    
    location ~ /.well-known {
	   allow all;
    }
    
    location ~*  \.(jpg|jpeg|png|gif|ico|css|js|svg|mp3|ogg|wav|json|webp)$ {
        expires 30d;
        add_header Vary Accept-Encoding;
        access_log off;
        
        if ($request_method = 'OPTIONS') {

        add_header 'Access-Control-Allow-Origin' '*';
        
        #
        # Om nom nom cookies
        #

        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #

        add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        
        #
        # Tell client that this pre-flight info is valid for 20 days
        #

        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;

        return 204;
     }

     if ($request_method = 'POST') {

        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

     }

     if ($request_method = 'GET') {

        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

     }
    }
    
    location ~* \.(eot|otf|ttf|woff|woff2)$ {
	    expires 30d;
        add_header Access-Control-Allow-Origin *;
        access_log off;
    }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/project.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/project.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

Sau đó reload lại nginx: service nginx reload (tham khảo docs của Nginx: Tại đây)

Bước 8: Cấu hình supervisor để khởi chạy dự án.

project.com
├── projectname
│   ├── projectname
│   ├── manage.py
│   ├── static
│   ├── templates
│   └── requirements.txt
├── ctrl.sh
├── manage.sh
├── supervisord.ini
├── run_supervisord.sh
└── venv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment