docker + Nginx Reverse-proxy + Wildcard SSL

2021. 6. 20. 00:02개발노트

Wildcard SSL이란?

  • 도메인 뿐만이 아니라 서브 도메인 모두 인증지원하는 인증서
    예를 들어 도메인이 devgno.me 일 때 이 인증서를 발급, 적용하면
    site1.devgno.me, site2.devgno.me ....
    모든 서브 도메인도 ssl인증이 적용된다.

도메인 준비

ssl인증서 발급을 위해 도메인을 구한다.

이 글에서는 무료 도메인인 freenom을 사용

인증서 발급

  • certbot 설치
    sudo apt install certbot
  • Wildcard ssl 발급
    sudo certbot certonly --manual --preferred-challenges=dns --email \ jinho021712@gmail.com --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d devgno.me -d \*.devgno.me
  • 발급 받을 서버에 위 명령어를 입력한다. 이메일과 도메인 입력에 주의
  • IP주소 수집, 로그로 기록됨을 동의
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for hiseon.me

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
  • 도메인 인증
    인증이 된 후 엔터를 치고 넘어가야한다.
    도메인 인증을 위해 위 값을 freenom DNS Management에서 아래와 같이 등록
  • 인증 확인
    watch dig -t txt \_acme-challenge.devgno.me +short도메인 인증에 시간이 걸릴 수 있으므로 위 명령어로 도메인 인증되었는지 모니터링

docker-compose.yml

version: '3'

services:

  reverse-proxy:
    image: nginx:1.17.10
    container_name: reverse_proxy_demo
    depends_on:
        - ex-page1
        - ex-page2

    volumes:
      - ./reverse_proxy/conf.d:/etc/nginx/conf.d
      - ./reverse_proxy/nginx.conf:/etc/nginx/nginx.conf
      - /etc/letsencrypt:/etc/letsencrypt
      - /etc/ssl/certs/dhparam.pem:/etc/ssl/certs/dhparam.pem

    ports:
      - 80:80
      - 443:443

  ex-page1:
    image: ex-page1
    container_name: ex-page1
    build: 
      context: ./ex-page1
    ports:
      - 5001:5001
    restart: on-failure

  ex-page2:
    image: ex-page2
    container_name: ex-page2
    build: 
      context: ./ex-page2
    ports:
      - 5001:5002
    restart: on-failure

기존에 docker-compose를 사용하고 있었다면 port에 443포트만 매핑시켜주고

ssh인증서 폴더 "/etc/letsencrypt"를 volumes에 매핑한다. (개별 파일을 매핑하면 링크파일로 매핑 될 수 있다. 폴더를 매핑시켜주자)

nginx.conf

user nginx;
worker_processes auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    server_names_hash_bucket_size 64;
    server_names_hash_max_size 8192;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;

    server_tokens off; # 응답 헤더에서 서버 버전 숨기기

    keepalive_timeout  65;

    include /etc/nginx/conf.d/*.conf;

}

conf.d 폴더의 conf확장자 파일을 모두 include하도록 한다.

Nginx conf 작성 참고

[

NGINX Docs | Creating NGINX Plus and NGINX Configuration Files

Understand the basic elements in an NGINX or NGINX Plus configuration file, including directives and contexts.

docs.nginx.com

](https://docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files/)

conf.d > default.conf

conf.d폴더 안에 페이지별 conf 파일을 작성한다.

return을 줘서 http로 연결하면 https로 연결을 유도한다.

https를 사용하기 위해 인증서 위치를 적어준다.

# ex-page1

server {
        listen 80;
        server_name ex-page1.devgno.ga www.ex-page1.devgno.ga;
        charset utf-8;

    # https로 연결
        location / {
        return 307 https://ex-page1.devgno.ga$request_uri;
        }

}

server {
        listen 443;
        listen [::]:443;
        ssl on;
        server_name ex-page1.devgno.ga www.ex-page1.devgno.ga;

        # ssl인증서 위치
        ssl_certificate /etc/letsencrypt/live/devgno.ga/fullchain.pem; 
        ssl_certificate_key /etc/letsencrypt/live/devgno.ga/privkey.pem; 
        ssl_dhparam /etc/ssl/certs/dhparam.pem;

        location / {
                # include proxy_params;
                proxy_pass http://172.17.0.1:5001;
        }

}