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