# 플랫폼 도메인 와일드카드 인증서 (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장 절차나 위 방법으로 받아 두면 다음 기동 때 자동 적용된다.