diff --git a/deploy/tls/Caddyfile b/deploy/tls/Caddyfile new file mode 100644 index 0000000..c89d0f2 --- /dev/null +++ b/deploy/tls/Caddyfile @@ -0,0 +1,10 @@ +auth.example.test { + tls /etc/tls/tls.crt /etc/tls/tls.key + + reverse_proxy keycloak:8080 { + header_up Host {host} + header_up X-Forwarded-Host {host} + header_up X-Forwarded-Port 443 + header_up X-Forwarded-Proto https + } +} diff --git a/deploy/tls/nginx.conf b/deploy/tls/nginx.conf new file mode 100644 index 0000000..586f8d4 --- /dev/null +++ b/deploy/tls/nginx.conf @@ -0,0 +1,21 @@ +events {} + +http { + server { + listen 443 ssl; + server_name auth.example.test; + + ssl_certificate /etc/tls/tls.crt; + ssl_certificate_key /etc/tls/tls.key; + ssl_protocols TLSv1.2 TLSv1.3; + + location / { + proxy_pass http://keycloak:8080; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port 443; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + } +} diff --git a/docs/https-termination.md b/docs/https-termination.md new file mode 100644 index 0000000..794acc1 --- /dev/null +++ b/docs/https-termination.md @@ -0,0 +1,20 @@ +# HTTPS termination: nginx or Caddy + +두 예제 모두 public `443`에서 TLS를 종료하고 private Docker network의 +`keycloak:8080`으로 전달한다. Keycloak 쪽 설정은 +`deploy/reverse-proxy/keycloak.env.example`의 hostname/proxy contract를 +같이 사용한다. + +- nginx: 인증서 배포·갱신을 운영자가 담당할 때 적합하다. +- Caddy: ACME를 통한 인증서 수명주기를 proxy가 담당하게 할 때 간단하다. +- 둘을 동시에 production entry point로 띄우지 않는다. +- 인증서와 private key는 repository 또는 image에 포함하지 않는다. +- HTTP challenge/redirect 및 방화벽의 80/443 허용은 배포 환경에서 별도로 + 결정한다. + +검증 스크립트는 임시 자체 서명 인증서를 만들고 두 vendor image에서 설정을 +각각 validate한 뒤 임시 파일을 제거한다. + +```sh +./scripts/verify-https-termination-config.sh +``` diff --git a/scripts/verify-https-termination-config.sh b/scripts/verify-https-termination-config.sh new file mode 100755 index 0000000..3870506 --- /dev/null +++ b/scripts/verify-https-termination-config.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env sh +set -eu + +test_dir="$(mktemp -d)" +cleanup() { + rm -rf "$test_dir" +} +trap cleanup EXIT + +openssl req -x509 -newkey rsa:2048 -nodes -days 1 \ + -subj "/CN=auth.example.test" \ + -keyout "$test_dir/tls.key" \ + -out "$test_dir/tls.crt" >/dev/null 2>&1 + +docker run --rm \ + --add-host keycloak:127.0.0.1 \ + -v "$PWD/deploy/tls/nginx.conf:/etc/nginx/nginx.conf:ro" \ + -v "$test_dir:/etc/tls:ro" \ + nginx:1.29-alpine nginx -t + +docker run --rm \ + --add-host keycloak:127.0.0.1 \ + -v "$PWD/deploy/tls/Caddyfile:/etc/caddy/Caddyfile:ro" \ + -v "$test_dir:/etc/tls:ro" \ + caddy:2.10.2-alpine caddy validate --config /etc/caddy/Caddyfile + +echo "nginx and Caddy HTTPS termination configurations verified"