From 7b3378bc45fc1819ece9db9164a77aaf2b8dad03 Mon Sep 17 00:00:00 2001 From: Macbook Date: Sun, 12 Jul 2026 19:10:16 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A0=91=EC=86=8D=20dns=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.yml | 2 +- deploy_server_guide.md | 47 ++++++++++++++++++---- docker-compose.yml | 2 +- scripts/caddy-bizcare.Caddyfile | 25 ++++++++---- scripts/deploy.sh | 2 +- scripts/issue-bizcare-cert.sh | 44 ++++++++++++++++++++ 6 files changed, 104 insertions(+), 18 deletions(-) create mode 100755 scripts/issue-bizcare-cert.sh diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 44319f4..2e3d6ac 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -26,5 +26,5 @@ app: secret: ${APP_JWT_SECRET:bizcare-homes-secret-key-must-be-long-enough-256bits} expiration-ms: ${APP_JWT_EXPIRATION_MS:86400000} cors: - origins: ${APP_CORS_ORIGINS:http://localhost:5174,http://localhost:82,http://127.0.0.1:82,http://localhost:1420,https://bizcare.exdev.co.kr,tauri://localhost,https://tauri.localhost,http://tauri.localhost} + origins: ${APP_CORS_ORIGINS:http://localhost:5174,http://localhost:82,http://127.0.0.1:82,http://localhost:1420,https://bizcare.exdev.co.kr,https://billcare.exdev.co.kr,tauri://localhost,https://tauri.localhost,http://tauri.localhost} upload-dir: ${APP_UPLOAD_DIR:./storage/uploads} diff --git a/deploy_server_guide.md b/deploy_server_guide.md index 7cd654b..d8b9ce6 100644 --- a/deploy_server_guide.md +++ b/deploy_server_guide.md @@ -11,11 +11,12 @@ | 항목 | 경로 | |------|------| -| bare repo | `/Volumes/ADATA/git/BizCare.git` | -| work-tree | `/Users/aidev/apps/BizCare` | +| bare repo | `/Volumes/ADATA/git/BizCare.git` (또는 기존 `BillCare.git`) | +| work-tree | `/Users/aidev/apps/BizCare` (또는 기존 `BillCare`) | | 배포 스크립트 | `/Volumes/ADATA/git/deploy-bizcare.sh` | | 로그 | `/Volumes/ADATA/logs/deploy/bizcare-deploy.log` | -| HTTPS | https://bizcare.exdev.co.kr | +| HTTPS (정본) | https://bizcare.exdev.co.kr | +| HTTPS (구) | https://billcare.exdev.co.kr → bizcare 로 301 | ## 호스트 포트 @@ -32,16 +33,46 @@ cd /Users/macbook/dev/billCare git push origin main ``` -## HTTPS / TLS +## HTTPS / TLS — bizcare.exdev.co.kr 활성화 + +### 1) DNS +`bizcare.exdev.co.kr` A(또는 CNAME) 레코드를 `billcare.exdev.co.kr` 과 **동일 서버 IP**로 추가합니다. + +### 2) 인증서 발급 +```bash +# 서버에서 (HTTP-01 webroot 준비된 상태) +chmod +x /Users/aidev/apps/BizCare/scripts/issue-bizcare-cert.sh +# 또는 work-tree 경로에 맞게 +BIZCARE_DOMAIN=bizcare.exdev.co.kr \ +ACME_WEBROOT=/var/www/certbot \ +CERT_OUT=/Users/aidev/dev/exAIChatbot2.0/docker/nginx/certs/bizcare \ + ./scripts/issue-bizcare-cert.sh +``` | 항목 | 값 | |------|-----| | URL | https://bizcare.exdev.co.kr | | Caddy | `ex-chatbot-caddy` → host `:83` | -| 인증서 | LE 전용 (`bizcare.exdev.co.kr`) | | cert 경로 | `.../nginx/certs/bizcare/{fullchain,privkey}.pem` | -| 발급 | `acme.sh` + HTTP-01 (`gc-frontend` `/var/www/certbot`) | -| 갱신 reload | `docker exec ex-chatbot-caddy caddy reload --config /etc/caddy/Caddyfile` | +| 구 도메인 cert | `.../nginx/certs/billcare/` (리다이렉트용) | -공유 인증서(`stock`/`chatbot`) SAN에 bizcare가 없어 별도 발급했습니다. +### 3) Caddy 스니펫 적용 +`scripts/caddy-bizcare.Caddyfile` 내용을 `ex-chatbot` Caddyfile 에 import/반영합니다. + +- `bizcare.exdev.co.kr` → reverse_proxy `host.docker.internal:83` +- `billcare.exdev.co.kr` → `https://bizcare.exdev.co.kr` 영구 리다이렉트 + +```bash +docker exec ex-chatbot-caddy caddy reload --config /etc/caddy/Caddyfile +``` + +### 4) CORS +배포 스크립트/`APP_CORS_ORIGINS`에 `https://bizcare.exdev.co.kr` 와 `https://billcare.exdev.co.kr` 가 모두 포함되어 있습니다. 컨테이너 재기동 후 반영됩니다. + +```bash +cd /Users/aidev/apps/BizCare # work-tree +docker compose up -d --force-recreate backend +``` + +공유 인증서(`stock`/`chatbot`) SAN에 bizcare가 없어 **별도 발급**이 필요합니다. `gc-frontend`에 acme-webroot가 마운트되어 있어야 갱신이 됩니다. diff --git a/docker-compose.yml b/docker-compose.yml index 47aa12d..e8d48dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,7 +33,7 @@ services: SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/bizcare?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8 SPRING_DATASOURCE_USERNAME: bizcare SPRING_DATASOURCE_PASSWORD: bizcare - APP_CORS_ORIGINS: ${APP_CORS_ORIGINS:-http://localhost:82,http://127.0.0.1:82,http://localhost:5174,http://localhost:1420,https://bizcare.exdev.co.kr,tauri://localhost,https://tauri.localhost,http://tauri.localhost} + APP_CORS_ORIGINS: ${APP_CORS_ORIGINS:-http://localhost:82,http://127.0.0.1:82,http://localhost:5174,http://localhost:1420,https://bizcare.exdev.co.kr,https://billcare.exdev.co.kr,tauri://localhost,https://tauri.localhost,http://tauri.localhost} APP_UPLOAD_DIR: /app/storage/uploads volumes: - bizcare_uploads:/app/storage/uploads diff --git a/scripts/caddy-bizcare.Caddyfile b/scripts/caddy-bizcare.Caddyfile index 9c45315..d90e9f3 100644 --- a/scripts/caddy-bizcare.Caddyfile +++ b/scripts/caddy-bizcare.Caddyfile @@ -1,14 +1,19 @@ # BizCare — exdev Caddy 서브도메인 스니펫 -# host 포트 83 → bizcare-frontend -# 인증서: acme.sh 로 발급한 bizcare 전용 LE cert -# /Users/aidev/dev/exAIChatbot2.0/docker/nginx/certs/bizcare/{fullchain,privkey}.pem -# (Caddy 컨테이너 마운트: /etc/caddy/certs/bizcare/) +# host 포트 83 → bizcare-frontend (구 billcare-frontend) +# +# 인증서: +# bizcare: .../certs/bizcare/{fullchain,privkey}.pem +# billcare: .../certs/billcare/{fullchain,privkey}.pem (구 도메인 → 리다이렉트용) +# Caddy 컨테이너 마운트 예: /etc/caddy/certs/{bizcare,billcare}/ +# +# 설치: 이 스니펫을 ex-chatbot Caddyfile 에 import 한 뒤 +# docker exec ex-chatbot-caddy caddy reload --config /etc/caddy/Caddyfile -# BizCare -https://{$BILLCARE_DOMAIN:bizcare.exdev.co.kr} { +# 신규 도메인 (정본) +https://{$BIZCARE_DOMAIN:bizcare.exdev.co.kr} { tls /etc/caddy/certs/bizcare/fullchain.pem /etc/caddy/certs/bizcare/privkey.pem handle { - reverse_proxy host.docker.internal:{$BILLCARE_HOST_PORT:83} { + reverse_proxy host.docker.internal:{$BIZCARE_HOST_PORT:83} { flush_interval -1 transport http { read_timeout 120s @@ -22,3 +27,9 @@ https://{$BILLCARE_DOMAIN:bizcare.exdev.co.kr} { } } } + +# 구 도메인 → 신규로 영구 리다이렉트 (인증서 있을 때만 동작) +https://{$BILLCARE_LEGACY_DOMAIN:billcare.exdev.co.kr} { + tls /etc/caddy/certs/billcare/fullchain.pem /etc/caddy/certs/billcare/privkey.pem + redir https://{$BIZCARE_DOMAIN:bizcare.exdev.co.kr}{uri} permanent +} diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 4e974e8..7961e90 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -22,7 +22,7 @@ export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:${PATH:-/usr/bi export FRONTEND_PORT="${FRONTEND_PORT:-83}" export BACKEND_PORT="${BACKEND_PORT:-18082}" export MYSQL_PORT="${MYSQL_PORT:-3308}" -export APP_CORS_ORIGINS="${APP_CORS_ORIGINS:-https://bizcare.exdev.co.kr,http://bizcare.exdev.co.kr,http://localhost:83,http://127.0.0.1:83}" +export APP_CORS_ORIGINS="${APP_CORS_ORIGINS:-https://bizcare.exdev.co.kr,https://billcare.exdev.co.kr,http://bizcare.exdev.co.kr,http://billcare.exdev.co.kr,http://localhost:83,http://127.0.0.1:83}" mkdir -p "$(dirname "$DEPLOY_LOG")" exec >> "$DEPLOY_LOG" 2>&1 diff --git a/scripts/issue-bizcare-cert.sh b/scripts/issue-bizcare-cert.sh new file mode 100755 index 0000000..29dc7bb --- /dev/null +++ b/scripts/issue-bizcare-cert.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# BizCare 도메인(bizcare.exdev.co.kr) LE 인증서 발급 도우미 +# 전제: DNS A/CNAME 이 서버를 가리키고, HTTP-01 용 webroot 가 열려 있어야 함. +set -euo pipefail + +DOMAIN="${BIZCARE_DOMAIN:-bizcare.exdev.co.kr}" +WEBROOT="${ACME_WEBROOT:-/var/www/certbot}" +CERT_OUT="${CERT_OUT:-/Users/aidev/dev/exAIChatbot2.0/docker/nginx/certs/bizcare}" +EMAIL="${ACME_EMAIL:-admin@exdev.co.kr}" + +echo "==> domain : $DOMAIN" +echo "==> webroot: $WEBROOT" +echo "==> out : $CERT_OUT" + +mkdir -p "$CERT_OUT" + +if ! command -v acme.sh >/dev/null 2>&1 && [ ! -x "$HOME/.acme.sh/acme.sh" ]; then + echo "acme.sh 가 없습니다. https://github.com/acmesh-official/acme.sh 설치 후 재실행하세요." + exit 1 +fi + +ACME_BIN="${ACME_SH:-$HOME/.acme.sh/acme.sh}" +[ -x "$ACME_BIN" ] || ACME_BIN="$(command -v acme.sh)" + +"$ACME_BIN" --issue -d "$DOMAIN" -w "$WEBROOT" --email "$EMAIL" || true + +# 심볼릭/복사는 환경에 맞게 조정 +LIVE="$HOME/.acme.sh/${DOMAIN}_ecc" +[ -d "$LIVE" ] || LIVE="$HOME/.acme.sh/${DOMAIN}" +if [ ! -d "$LIVE" ]; then + echo "발급 디렉터리를 찾지 못했습니다: $HOME/.acme.sh/${DOMAIN}[_ecc]" + exit 1 +fi + +cp -f "$LIVE/fullchain.cer" "$CERT_OUT/fullchain.pem" +cp -f "$LIVE/${DOMAIN}.key" "$CERT_OUT/privkey.pem" 2>/dev/null \ + || cp -f "$LIVE/private.key" "$CERT_OUT/privkey.pem" + +chmod 644 "$CERT_OUT/fullchain.pem" +chmod 600 "$CERT_OUT/privkey.pem" + +echo "==> 인증서 저장 완료: $CERT_OUT" +echo "==> Caddy reload:" +echo " docker exec ex-chatbot-caddy caddy reload --config /etc/caddy/Caddyfile"