
지난 내용 요약
지난 NCP 서버 배포기 (2)에서,
Docker로Django프로젝트를 이미지화하여NCP서버로 끌어와 컨테이너 형태로 작동하게 하였다. 현재Django프로젝트는NCP내의 8000번 포트에서 안정적으로 runserver되고 있다.
현재 상태에서는 로컬에서 백엔드 레포지토리를 일일이 클론하지 않고도 해당 서버주소로 접속하여 프로젝트의 여러 api를 사용하고 테스트해볼 수 있는 환경이 있다.
하지만 개발을 하다보면https설정이 필요한 경우(아래와 같은 경우)가 자주 발생한다. 결국엔 개발환경에서도https를 적용해놓는 것이 아무래도 차후에 문제 방지를 위해 필요하다.
Secure속성을 사용한 쿠키, 즉 보안 쿠키(Secure cookie)를 사용하려할 때- Mixed content 이슈를 디버깅해야 할 때
- HTTP/2 이상의 프로토콜을 사용하고자 할 때
- HTTPS가 요구되는 라이브러리, API 등을 사용할 때
- 호스트네임을 커스터마이즈했을 때
이번 게시글의 목표
위에서 언급한 문제를 해결하기 위해 이번 포스트에서는 서버의
Nginx설정을 마친 후,Let's encrypt인증서를 이용해Nginx SSL설정까지 해볼 예정이다.
먼저 NCP 서버 내에 Nginx를 설치한다.
# NCP termial에서..
sudo apt-get install nginx
# NCP terminal에서..
sudo nano /etc/nginx/nginx.conf
.conf는 config(구성)파일의 확장명 중 하나이다. 이 파일에서 우리는 Nginx 여러 영역에서 매개 변수, 기본 설정, 대체 옵션을 결정할 수 있다. 다음과 같은 창이 띄워지면 해당 파일에 다음과 같이 기입한다.
프로젝트의 구성은 프로젝트의 규모에 따라 달라질 수 있다. 우리의 경우, 백엔드 서버 하나 내부에서 모든 백엔드 상호작용이 일어나는 것으로 설정하여, 다음과 같이 설정하였다.
# /nginx.conf에서..
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
# terminal에서..
sudo service nginx restart
# 상태확인을 위해..
sudo service nginx status
status가 running이 아니라면, 오류 log를 확인하여 문제를 해결하자.현재 nginx.conf 파일의
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
부분을 보면 알 수 있듯이, 가상 호스트에 대한 설정은 위 두가지 경로에서 모두 가져오는 것으로 되어있다. 초기 설정 시, conf.d 폴더에는 아무것도 없었고, sites-enabled 폴더에는 default 파일이 하나 있었다.
sites-enabled 디렉토리의 default 파일을 지웠고 프로젝트명.conf를 생성하여 구성을 새로 정의하였다.
# /etc/nginx/sites-enabled/ 디렉토리에서
rm default
sudo nano '프로젝트명'.conf
# '프로젝트명'.conf
upstream app {
server 127.0.0.1:8000;
}
server {
server_name www.project.site project.site;
client_max_body_size 20M;
location /api/ {
proxy_pass http://localhost:8000;
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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization';
}
location /admin/ {
proxy_pass http://localhost:8000;
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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /media/ {
alias /home/back/media/;
}
location /static/ {
alias /home/back/static/;
}
location / {
proxy_pass http://app;
proxy_buffering off;
}
}
upstream app:
upstream app 섹션은 백엔드 서버에 대한 연결 풀을 정의한다. 여기서 server 127.0.0.1:8000;은 로컬호스트의 8000 포트로 실행되는 서버를 지정한다. 이 설정을 통해 proxy_pass http://app; 지시문을 사용하여 트래픽을 이 서버로 라우팅할 수 있다.server:
server_name www.project.site project.site;는 Nginx가 처리할 도메인 이름을 지정한다.client_max_body_size 20M;는 클라이언트가 보낼 수 있는 요청 본문의 최대 크기를 20MB로 제한한다.location /api/:
proxy_pass http://localhost:8000;는 해당 요청을 localhost의 8000 포트로 전달한다.proxy_set_header 지시문은 프록시 요청에 헤더를 추가하거나 수정한다.add_header를 통해 CORS 관련 헤더를 설정하여 다른 도메인에서도 이 API에 접근할 수 있게 한다.location /admin/:
/api/ 경로와 유사하게 백엔드로 요청을 전달합니다. CORS 설정은 제외된다.location /media/와 /static/:
/home/back/media/와 /home/back/static/ 디렉터리의 정적 파일을 제공한다. alias 지시문은 요청된 URL의 일부를 파일 시스템의 경로로 매핑한다.location /:
upstream app에 정의된 서버로 전달한다.proxy_buffering off;는 프록시 서버에서 응답을 버퍼링하지 않도록 설정한다.# terminal에서..
sudo service nginx restart
# 상태확인을 위해..
sudo service nginx status
status가 running이 아니라면, 오류 log를 확인하여 문제를 해결하자.# terminal에서..
apt-get update
sudo apt-get install certbot
apt-get install python3-certbot-nginx
위의 프로젝트 관련 Nginx 설정에서 이미 하여서 건너뛰었다.
Nginx 플러그인은 Nginx certbot를 재구성하고 필요할 때마다 해당 구성을 다시 로드한다.
Nginx 플러그인으로 인증서를 생성한다.sudo certbot --nginx -d project.com -d www.project.com
certbot이메일 주소를 입력하고 Let’s Encrypt 서비스 약관에 동의하는 것을 포함하여 Https 설정을 구성 하라는 메시지에 응답한다.인증서 생성이 완료되면 Nginx가 새 설정으로 다시 로드된다. certbot인증서 생성에 성공했으며 서버에서 인증서 위치를 지정하는 메시지를 생성한다.
Congratulations! You have successfully enabled https://project.com and https://www.project.com
-------------------------------------------------------------------------------------
IMPORTANT NOTES:
Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/project.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/project.com//privkey.pem
Your cert will expire on 2024-07-14.
참고 : Let’s Encrypt 인증서는 90일 후에 만료된다.
'프로젝트명'.conf 를 보면 다음과 같이 수정 되었음을 알 수 있다.
# /'프로젝트명'.conf
root@project:/etc/nginx/sites-enabled# cat project.conf
upstream app {
server 127.0.0.1:8000;
}
server {
server_name www.project.site project.site;
client_max_body_size 20M;
location /api/ {
proxy_pass http://localhost:8000;
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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization';
}
location /admin/ {
proxy_pass http://localhost:8000;
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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /media/ {
alias /home/back/media/;
}
location /static/ {
alias /home/back/static/;
}
location / {
proxy_pass http://app;
proxy_buffering off;
# root /2023-MY-AWARDS-FRONT/dist; # 프론트 인스턴스 내의 정적 파일 경로 (index.html 이 존재하는 경로)
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/project.site/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/project.site/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 {
if ($host = www.project.site) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = project.site) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name www.project.site project.site;
return 404; # managed by Certbot
}
Let’s Encrypt 인증서는 90일 후에 만료된다. 인증서를 자동으로 갱신하는 것이 좋다. 여기에서 이를 cron수행하기 위해 기존 crontab 파일에 작업을 추가한다.
# terminal에서..
crontab -e
certbot 매일 실행할 명령을 추가한다 . 이 예에서는 매일 정오에 명령을 실행한다. 이 명령은 서버의 인증서가 다음 30일 이내에 만료되는지 확인하고 만료되면 갱신한다. --quiet지시문은 출력 certbot을 생성하지 않도록 지시한다.# crontab에서
0 12 * * * /usr/bin/certbot renew --quiet
등록된 도메인 이름에 대한 SSL/TLS 인증서를 생성하기 위해 Let’s Encrypt 에이전트를 설치했다. 인증서를 사용하고 자동 인증서 갱신을 설정하도록 Nginx를 구성했다. Nginx 및 Nginx Plus용 Let’s Encrypt 인증서를 사용하면 몇 분 안에 간단하고 안전한 웹사이트를 구축하고 실행할 수 있다.