Files
AriWeb-Suite/modules/webmaker/docs/SSL-WILDCARD.md

77 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 플랫폼 도메인 와일드카드 인증서 (Let's Encrypt)
AI Webmaker v1.4.14 · 2026-10-10 · 대상: 운영자
## 1. 두 종류의 인증서
| 대상 | 인증서 | 발급 방법 | 누가·언제 |
|---|---|---|---|
| 서브 도메인 사이트 `이름.ibit.kr` (플랫폼 도메인 아래 한 단계) | **와일드카드** `*.ibit.kr` — 이름 `wh-wild-ibit.kr`, 하나로 전체 | DNS 인증(TXT `_acme-challenge.ibit.kr`) | 운영자가 관리자 콘솔에서 한 번 (갱신 60~90일마다) |
| 고객 도메인 `example.com`, `www.example.com` | **사이트별** `wh-<사이트ID>` | HTTP 인증(webroot) | 발행(배포) 때 자동 (DNS 가 이 서버를 가리키는 도메인만) |
- 분리하는 이유: 서브 도메인은 수가 늘어도 인증서 하나(발급 한도 문제 없음), 고객 도메인은 사이트 폐기 때 그 인증서만 지운다.
- nginx 설정은 도메인 묶음마다 server 블록을 만든다. 와일드카드가 없으면 서브 도메인은 HTTP 로 열리고, 와일드카드를 발급하면 배포된 서브 도메인 사이트들의 설정을 **재배포 없이** 다시 써 HTTPS 가 된다.
- `a.b.ibit.kr` 처럼 두 단계 아래 이름과 `ibit.kr` 자신은 와일드카드로 덮이지 않는다(서브 도메인 등록은 한 단계만 허용하므로 해당 없음).
## 2. 조건
| 조건 | 확인 |
|---|---|
| 플랫폼 도메인 | 관리자 콘솔 › 설정 › 도메인 서비스 › 플랫폼 도메인 (webmaker 는 `ibit.kr`) |
| 기본 배포 서버가 서비스 서버 자신(종류 local)·sudo 허용·certbot 설치 | webmaker: "서비스 서버 (bear, webmaker.ibit.kr)" ✅ |
| 원격(ssh) 배포 서버 | 지원하지 않음 — 훅이 그 서버에서 실행되어 이 서비스의 DNS 접속 정보를 쓸 수 없다. 그 서버의 서브 도메인은 사이트별 인증서로 발급된다 |
| 와일드카드 DNS `*.ibit.kr A 121.152.149.45` | 인증서와 별개로 사이트가 열리려면 필요 ([DOMAIN-SETUP.md](DOMAIN-SETUP.md) 5장). 인증서 발급 자체에는 필요 없다 |
| Let's Encrypt 알림 이메일 | 설정 › SSL (비워도 발급됨) |
## 3. 발급 절차
관리자 콘솔 › 설정 › **SSL (Let's Encrypt)** › 플랫폼 도메인 와일드카드 인증서
### DNS 방식이 수동 (ibit.kr — hosting.co.kr DNS, 지금 상태)
1. **와일드카드 인증서 발급·갱신** 을 누른다.
2. 몇 초 뒤 화면에 **DNS 에 넣을 TXT 레코드** 가 뜬다.
| 이름 | 종류 | 값 |
|---|---|---|
| `_acme-challenge.ibit.kr` (hosting.co.kr 화면에서는 호스트 `_acme-challenge`) | TXT | 화면의 값 (43자) |
3. hosting.co.kr 도메인 관리 › ibit.kr › DNS 레코드에 위 TXT 를 추가한다.
4. 서비스가 공용 DNS(1.1.1.1·8.8.8.8)에서 그 값을 확인하면 자동으로 인증이 이어진다(최대 40분 대기, 보통 수 분). 끝나면 상태 줄에 "인증서 있음 — *.ibit.kr, 만료 …" 가 보이고, 서브 도메인 사이트들의 nginx 설정이 HTTPS 로 바뀐다.
5. TXT 는 지워도 된다. **갱신 때(만료 30일 전부터 certbot 이 시도, 화면은 20일 전 경고)** 새 값이 다시 필요하다 — 같은 절차를 반복한다. 갱신 전에는 기존 인증서가 그대로 쓰인다.
### DNS 방식이 자동 (플랫폼 도메인 DNS 를 Openprovider 로 옮긴 뒤)
- 발급·갱신을 누르면 훅이 Openprovider API 로 TXT 를 넣고 인증 뒤 지운다. certbot 타이머의 자동 갱신도 같은 훅으로 사람 손 없이 된다.
- 조건: 설정 › 도메인 서비스 › DNS 방식 "자동(Openprovider)", 외부 연동 접속 정보에 Openprovider 등록.
## 4. 동작 원리 (코드)
- `lib/ssl.js`: 상태(`GET /api/admin/ssl`)·발급 시작(`POST /api/admin/ssl/wildcard`, 비동기)·취소. certbot 을 `--manual --preferred-challenges dns` 와 훅으로 실행한다:
`certbot certonly --manual --manual-auth-hook "node scripts/acme-dns-hook.js auth" --manual-cleanup-hook "… cleanup" --cert-name wh-wild-<도메인> -d "*.<도메인>" --keep-until-expiring --deploy-hook "systemctl reload nginx"`
- `scripts/acme-dns-hook.js`: certbot 이 넘기는 `CERTBOT_DOMAIN`·`CERTBOT_VALIDATION` 으로 TXT 를 넣거나(Openprovider) 대기 파일(`/var/tmp/webmaker-acme/<도메인>.json`)에 적고 공용 DNS 에 보일 때까지 기다린다. 서비스는 그 파일을 읽어 화면에 보인다.
- 발급이 끝나면 `lib/ssl.js reconfigureSites` 가 그 플랫폼의 서브 도메인이 연결된 배포 사이트들의 vhost 를 다시 쓴다(`deploy.configureVhost` — 묶음별 인증서).
- 결과는 `data/ssl-wildcard.json` 에 남고, certbot 로그는 `/var/log/letsencrypt/letsencrypt.log`.
## 5. 자주 나는 메시지
| 메시지 | 원인 | 해결 |
|---|---|---|
| 플랫폼 도메인이 없습니다 | 설정 › 도메인 서비스 › 플랫폼 도메인 비어 있음 | 도메인 입력 (예: ibit.kr) |
| 와일드카드 인증서는 서비스 서버가 배포 서버인 경우(종류 local)에만 발급합니다 | 기본 배포 서버가 원격(ssh) | 서비스 서버를 기본 배포 서버로, 또는 그대로 사이트별 인증서 사용 |
| 40분 안에 TXT 가 보이지 않아 중단합니다 (마지막 발급: 실패) | DNS 에 TXT 를 넣지 않았거나 값이 다름·전파 지연 | TXT 를 확인하고 다시 "발급·갱신" (새 값이 뜬다) |
| too many certificates / rate limit | Let's Encrypt 발급 한도 (같은 이름 주 5회) | 1주일 뒤 다시. 인증서가 이미 있으면 `--keep-until-expiring` 이라 보통 발생하지 않음 |
| 서브 도메인 사이트가 발행 뒤 HTTP 로만 열림 — "운영자가 와일드카드 인증서를 발급하면 HTTPS 로 열립니다" | 와일드카드 인증서 없음 | 위 3장 절차. 발급되면 재배포 없이 HTTPS |
| 인증서 있음인데 특정 서브 도메인 사이트가 HTTP | 그 사이트의 nginx 설정이 와일드카드 전 것 | 그 사이트를 재배포하거나, 관리자 콘솔에서 "발급·갱신"(끝나면 설정을 다시 씀) |
## 6. 서버에 미리 발급해 둔 와일드카드 인증서 (v1.5.17)
서버를 설치할 때 운영자가 이미 `sudo certbot certonly … -d '*.example.com'` 으로 인증서를 받아 두었다면(이름은 무엇이든: `live/example.com`, `live/wild-example` …) 서비스가 그것을 **인지해 서브 도메인 사이트에 자동으로 쓴다**. 별도 설정은 없다.
- 감지: 배포 서버의 `/etc/letsencrypt/live/*/fullchain.pem` 을 sudo 로 훑어 SAN 에 `*.<플랫폼 도메인>` 이 있는 인증서를 고른다(`lib/deploy.js findWildcardCert`). 서비스가 발급한 `wh-wild-<도메인>` 이 있으면 그것, 없으면 만료가 가장 먼 것. 플랫폼 도메인은 설정이 없으면 서비스 공개 주소에서 유도된다(webmaker.example.com → example.com).
- 적용: 새로 발행하는 사이트는 vhost 구성 때 바로, 이미 HTTP 로 배포된 사이트는 **서비스 기동 20초 뒤** `ssl.autoApply` 가 nginx 설정을 다시 써서 HTTPS 가 된다(재배포 없음). 직접 실행: `node scripts/ssl-wildcard.js --apply`.
- 확인: 설치 점검표(초기 설정 페이지·시스템 설정 탭)의 "와일드카드 인증서 (*.도메인)" 항목, `node scripts/ssl-wildcard.js`(설치·갱신 스크립트가 마지막에 출력), 관리자 콘솔 › 설정 › SSL 상태 줄("서버에 미리 발급된 인증서 <이름> 를 씁니다").
- 갱신: 그 인증서를 받은 방법(certbot 타이머·DNS 플러그인 등)대로 이어진다. 관리자 콘솔의 "발급·갱신" 은 미리 발급된 인증서가 유효하면 409 로 거절하고(만료 20일 전부터 허용), 강제 갱신이면 서비스 이름(`wh-wild-<도메인>`)으로 따로 발급한다 — 그 뒤에는 서비스 이름이 우선한다.
- 조건: 배포 서버 종류 local 또는 ssh 모두 감지한다(ssh 는 그 서버에서 sudo 가 되어야 함). 발급(3장)은 local 만.
## 7. letsencrypt 밖의 와일드카드 인증서 (v1.5.27)
감지는 `/etc/letsencrypt/live` 외에 **nginx 설정이 참조하는 `ssl_certificate` 파일**과 **`/etc/ssl/*/*.pem|.crt`**(예: Cloudflare 원본 인증서 `/etc/ssl/cloudflare/example.pem` + `example.key`)의 SAN 도 본다. 키 파일은 같은 폴더의 `<이름>.key` / `privkey.pem` / `<이름>-key.pem` 중 있는 것이며, 키를 못 찾으면 후보에서 뺀다. 사이트 vhost 에는 그 경로가 그대로 들어간다(`ssl_certificate /etc/ssl/cloudflare/example.pem;`).
플랫폼 도메인에 인증서가 하나도 없으면(예: webmaker.ariweb.net 의 `*.ariweb.net`) 서브 도메인은 HTTP 로 열린다 — 3장 절차나 위 방법으로 받아 두면 다음 기동 때 자동 적용된다.