#!/bin/sh # ========================================== # nginx 템플릿(nginx.conf)에 넣을 값을 만든다 — nginx 이미지의 docker-entrypoint 가 envsubst 전에 source 한다 # (Dockerfile 이 /docker-entrypoint.d/16-nginx-env.envsh 로 넣는다. 실행 권한이 있어야 읽힌다) # # 본문 한도는 백엔드 한도와 같은 루트 env 에서 만든다 → 루트 env 한 곳만 고치면 백엔드와 nginx 가 함께 바뀐다. # compose 는 정의되지 않은 변수를 빈 문자열로 넣으므로 빈 값은 백엔드 기본값으로 대신한다. # 값이 잘못됐으면 기본값으로 조용히 넘어가지 않고 컨테이너 기동을 멈춘다 (fail-fast — .claude/rules/env-structure.md). # # ⚠️ source 되는 파일이라 entrypoint 셸과 이름·옵션을 함께 쓴다 — set -e/-u 를 걸지 않고, 이름은 nginx_env_ 로 시작한다. # exit 하면 entrypoint 가 끝나 컨테이너가 뜨지 않는다 (그게 의도다). # ========================================== nginx_env_fail() { echo "nginx-env.envsh: $1" >&2 exit 1 } # $1(변수 이름)의 값이 양의 십진 정수면 그 값, 비어 있으면 $2(기본값). 그 밖은 기동 중단. # 앞자리 0 은 받지 않는다 — 셸 산술이 8진수로 읽어(010 → 8) 백엔드와 한도가 어긋나거나 08 에서 오류가 난다. # 6자리(999999MB)를 넘는 값도 받지 않는다 — 실수로 넣은 값이 산술에서 넘치지 않게. nginx_env_positive_int() { eval "nginx_env_value=\${$1:-}" if [ -z "$nginx_env_value" ]; then echo "$2" return fi case "$nginx_env_value" in 0* | *[!0-9]*) nginx_env_fail "$1 는 0 으로 시작하지 않는 양의 정수(MB)여야 합니다 (현재: \"$nginx_env_value\")." ;; esac if [ "${#nginx_env_value}" -gt 6 ]; then nginx_env_fail "$1 가 너무 큽니다 (현재: \"$nginx_env_value\", 최대 999999)." fi echo "$nginx_env_value" } # 멀티파트 경계·헤더 몫의 여유 (MB) — 백엔드 한도에 딱 맞는 파일도 nginx 에서 막히지 않게 nginx_body_margin_mb=1 # 백엔드 기본값과 같다: MAIL_ATTACHMENT_MAX_SIZE_MB=20 (modules/mail/mail.settings.ts) · UPLOAD_MAX_SIZE_MB=5 # (명령 치환 안에서 실패하면 그 서브셸만 끝나므로, 값을 먼저 받아 실패를 여기서 확인한다) nginx_env_mail_mb="$(nginx_env_positive_int MAIL_ATTACHMENT_MAX_SIZE_MB 20)" || exit 1 nginx_env_upload_mb="$(nginx_env_positive_int UPLOAD_MAX_SIZE_MB 5)" || exit 1 NGINX_MAIL_ATTACHMENT_BODY_LIMIT="$((nginx_env_mail_mb + nginx_body_margin_mb))m" NGINX_UPLOAD_BODY_LIMIT="$((nginx_env_upload_mb + nginx_body_margin_mb))m" # 백엔드 주소 — compose 가 http://-backend: 를 준다. # 서비스 이름(backend)은 쓰지 않는다: proxy 네트워크를 다른 프로젝트와 함께 쓰면 그쪽 backend 로 풀릴 수 있다. if [ -z "${NGINX_BACKEND_UPSTREAM:-}" ]; then [ -n "${PROJECT_NAME:-}" ] || nginx_env_fail "NGINX_BACKEND_UPSTREAM(예: http://-backend:3000) 또는 PROJECT_NAME 이 필요합니다." NGINX_BACKEND_UPSTREAM="http://${PROJECT_NAME}-backend:3000" fi # http://호스트[:포트] 만 받는다. 경로(끝의 / 포함)가 붙으면 proxy_pass 가 모든 /api 요청을 그 경로 하나로 보내고, # 공백·; 등은 설정 문법을 깨거나 지시어를 끼워 넣을 수 있다. nginx_env_upstream_host="${NGINX_BACKEND_UPSTREAM#http://}" if [ "$nginx_env_upstream_host" = "$NGINX_BACKEND_UPSTREAM" ] || [ -z "$nginx_env_upstream_host" ]; then nginx_env_fail "NGINX_BACKEND_UPSTREAM 은 http://호스트[:포트] 형식이어야 합니다 (현재: \"$NGINX_BACKEND_UPSTREAM\")." fi case "$nginx_env_upstream_host" in *[!A-Za-z0-9.:_-]*) nginx_env_fail "NGINX_BACKEND_UPSTREAM 에는 경로·쿼리·공백을 넣지 않습니다 — http://호스트[:포트] 만 (현재: \"$NGINX_BACKEND_UPSTREAM\")." ;; :* | *:*:* | *:*[!0-9]* | *:) nginx_env_fail "NGINX_BACKEND_UPSTREAM 의 호스트·포트가 올바르지 않습니다 (현재: \"$NGINX_BACKEND_UPSTREAM\")." ;; esac # 도커 내장 DNS — 15-local-resolvers.envsh 가 /etc/resolv.conf 에서 읽어 둔다 (Dockerfile 의 NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1) NGINX_LOCAL_RESOLVERS="${NGINX_LOCAL_RESOLVERS:-127.0.0.11}" export NGINX_MAIL_ATTACHMENT_BODY_LIMIT NGINX_UPLOAD_BODY_LIMIT NGINX_BACKEND_UPSTREAM NGINX_LOCAL_RESOLVERS