Django서버에 간단한 HTTPS Let's Encrypt 적용하기
서론
웹 서비스에 기본적으로 들어가는 https는 nginx 설정, ssl 발급, 키파일 적용까지
필자에게는 너무 복잡하고 어려운 일이었다.
그러나 아래 레퍼런스의 튜토리얼을 보고 간단하게 ssl 적용하는 내용을 기억할 겸 다시 적어보는 내용이다.
그리고 튜토리얼 답게 정말 간단하게 사용이 가능하다.
글로만 설명 해보면
1. docker-compose로 nginx-proxy, acme-companion(let's encrypt) 연결
2. 환경변수를 통한 도메인 ssl 적용
그리고 인증서의 만료는 3개월이나
자동으로 인증서를 체킹 하여, 갱신해준다 (필자가 직접 3개월 동안 뒀더니 자동으로 갱신되었다.)
주의사항
- docker container를 사용하여 무료 ssl인 let's encrypt를 적용하는 내용입니다.
- 레퍼런스 그대로 따라가면서 최신 docker image를 사용한 내용이라 레퍼런스와 조금 다를 수 있습니다
본론
해야 할 내용
1. docker-compose로 nginx-proxy와 acme-companion(let's encrypt) 연결
nginx-proxy와 acme-companion(let's encrypt)를 볼륨으로 연결
2. 도메인 준비
당연하지만 ssl을 적용하려면 도메인이 필요하다.
도메인은 환경변수에 적용하면 됩니다.
3. 환경변수
let's encrypt에 적용될 도메인 host와
nginx에 적용될 port 정보가 필요하므로 env 파일을 만들어 적용한다.
이하 파일의 환경변수는 필자의 프로젝트에 썼던 파일들입니다.
docker-compose.prod.yml
certs, vhost, html, docker.sock을 volume으로 nginx와 let's encrypt 연결
version: '3.8'
services:
###########################
web:
container_name: web
build:
context: ./company_review
dockerfile: Dockerfile/Dockerfile.prod
command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
ports:
- 8000
env_file:
- ./.env/.env.prod
volumes:
- static:/usr/src/company_review/static
- media:/usr/src/company_review/media
###########################
redis:
image: redis:6.2.6-alpine
ports:
- 6379:6379
volumes:
- redis_data:/etc/redis_data/data
depends_on:
- web
###########################
nginx-proxy:
container_name: nginx-proxy
restart: always
build:
context: nginx
ports:
- 80:80
- 443:443
volumes:
- certs:/etc/nginx/certs
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
- static:/usr/src/company_review/static
- media:/usr/src/company_review/media
depends_on:
- web
###########################
nginx-proxy-acme:
container_name: nginx-proxy-acme
image: nginxproxy/acme-companion
volumes:
- certs:/etc/nginx/certs
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- /var/run/docker.sock:/var/run/docker.sock:ro
- acme:/etc/acme.sh
env_file:
- ./.env/.env.prod.nginx_acme
depends_on:
- nginx-proxy
###########################
volumes:
redis_data:
certs:
vhost:
html:
acme:
static:
media:
.env.prod
VIRTUAL_HOST와 VIRTUAL_PORT로 nginx에 적용할 호스트를 적고,
LETSENCRYPT_HOST로 let's encrypt에 적용할 도메인을 정의해준다.
다른 env는 django에 사용되는 env이므로 설정하지 않아도 된다.
DEBUG=False
STAGE=PROD
DJANGO_SETTINGS_MODULE=config.settings.prod
VIRTUAL_HOST=mixedprogramming.net
VIRTUAL_PORT=8000
LETSENCRYPT_HOST=mixedprogramming.net
.env.prod.nginx_acme
nginx-proxy와 acme-companion(let's encrypt) 연결을 위한 컨테이너 명 지정
email은 ssl 적용 후 만료 알람 등 이메일 보내는 용도
DEFAULT_EMAIL=skarndrkd1@naver.com
NGINX_PROXY_CONTAINER=nginx-proxy
let's encrypt 인증에는 시간당 횟수 제한이 있으므로 테스트 환경에서는 아래의 staging letsencrypt를 추가하여 사용하도록 하자
ACME_CA_URI=https://acme-staging-v02.api.letsencrypt.org/directory
이후 적용된 nginx / default.conf
아래 코드를 보면 단순 env 설정만으로 도메인, 포트 연결이 된 걸 알 수 있다.
당연하겠지만 ssl도 적용이 완료되었다.
#default.conf
...
# 생략
# mixedprogramming.net
upstream mixedprogramming.net {
## Can be connected with "job-search-and-company-review_default" network
# web
server 172.18.0.3:8000;
}
server {
server_name mixedprogramming.net;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
auth_basic off;
auth_request off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name mixedprogramming.net;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/mixedprogramming.net.crt;
ssl_certificate_key /etc/nginx/certs/mixedprogramming.net.key;
ssl_dhparam /etc/nginx/certs/mixedprogramming.net.dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/mixedprogramming.net.chain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
include /etc/nginx/vhost.d/default;
location / {
proxy_pass http://mixedprogramming.net;
}
}
Reference
Django on Docker Series:
Dockerizing Django with Postgres, Gunicorn, and Nginx
Dockerizing Django with Postgres, Gunicorn, and Nginx
This tutorial details how to configure Django to run on Docker along with Postgres, Nginx, and Gunicorn.
testdriven.io
Securing a Containerized Django Application with Let's Encrypt
Securing a Containerized Django Application with Let's Encrypt
In this tutorial, we'll look at how to secure a containerized Django app running behind an HTTPS Nginx proxy with Let's Encrypt SSL certificates.
testdriven.io
Deploying Django to AWS with Docker and Let's Encrypt
Deploying Django to AWS with Docker and Let's Encrypt
In this tutorial, we'll deploy a Django app to AWS EC2 with Docker and Let's Encrypt.
testdriven.io