# πŸ” HTTPS μ‚¬μ΄νŠΈ λΈ”λ‘μ˜ μ£Όμ†Œκ°€ 곡개 이름이면 `tls` μ§€μ‹œμ–΄ 없이도 HTTPSκ°€ λ©λ‹ˆλ‹€. PingclairλŠ” ACME둜 Let's Encrypt에 μΈμ¦μ„œλ₯Ό μš”μ²­ν•˜κ³ , 80 ν¬νŠΈμ—μ„œ HTTP-01 μ±Œλ¦°μ§€μ— μ‘λ‹΅ν•˜κ³ , κ²°κ³Όλ₯Ό μ €μž₯ν•˜κ³ , λ°±κ·ΈλΌμš΄λ“œμ—μ„œ κ°±μ‹ ν•©λ‹ˆλ‹€. λ‚˜λ¨Έμ§€ μ„Έ κ°€μ§€ 방법 β€” DNS-01, 둜컬 인증 κΈ°κ΄€, 직접 μ€€λΉ„ν•œ 파일 β€” 은 각각 무엇이 ν•„μš”ν•œμ§€μ™€ v0.2.0-rc.3μ—μ„œ μ‹€μ œλ‘œ μ–΄λ–»κ²Œ λ™μž‘ν•˜λŠ”μ§€λ₯Ό μ•„λž˜μ— μ μ—ˆμŠ΅λ‹ˆλ‹€. ## 🧾 μ‹œμž‘ν•˜κΈ° 전에 - 이 호슀트둜 ν•΄μ„λ˜λŠ” 이름. μ„œλ²„λ₯Ό μ˜μ‹¬ν•˜κΈ° 전에 ν™•μΈν•˜μ‹­μ‹œμ˜€: `dig +short A example.com`. - μΈν„°λ„·μ—μ„œ 도달 κ°€λŠ₯ν•œ 80κ³Ό 443 포트. HTTP-01 μ±Œλ¦°μ§€λŠ” 80μ—μ„œ μ‘λ‹΅ν•˜κ³ , μΈμ¦μ„œλŠ” 443μ—μ„œ μ“°μž…λ‹ˆλ‹€. - ACME κ³„μ •μš© 이메일 μ£Όμ†Œ. μ‹€μ œ μ‚¬μ„œν•¨μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€. Let's EncryptλŠ” μ˜ˆμ•½λœ example 도메인을 κ±°λΆ€ν•˜λ©° λ°œκΈ‰μ€ `contact email has forbidden domain "example.com"`둜 μ‹€νŒ¨ν•©λ‹ˆλ‹€. μ•„λž˜ 섀정은 μ„œλΉ„μŠ€κ°€ μ‹€ν–‰ν•˜λŠ” `/etc/Pingclair/Pingclairfile`을 κ΅μ²΄ν•©λ‹ˆλ‹€. λ‹€μ‹œ 읽기 전에 κ²€μ¦ν•˜μ‹­μ‹œμ˜€. κ·Έ 흐름은 [ν€΅μŠ€νƒ€νŠΈ](/ko/start/quickstart/)에, 재적용의 μ˜λ―ΈλŠ” [μ„œλΉ„μŠ€λ‘œ μ‹€ν–‰](/ko/start/service/)에 μžˆμŠ΅λ‹ˆλ‹€. ## 🌐 Let's Encrypt μΈμ¦μ„œ ```caddyfile { email pingclair@pingclair.com } example.com { file_server /var/lib/pingclair/html } ``` μ„€μ •ν•  것은 μ΄κ²ƒλΏμž…λ‹ˆλ‹€. μ‹œμž‘ν•  λ•Œ μ„œλ²„κ°€ 호슀트 이름을 ν—ˆκ°€ν•˜κ³ , ACME 흐름을 μ‹œμž‘ν•˜κ³ , μ±Œλ¦°μ§€μ— μ‘λ‹΅ν•©λ‹ˆλ‹€. ```text 🌐 Automatic public certificates authorised for 1 hostname(s) πŸš€ Eager issuance for 1 hostname(s) πŸ” Starting ACME flow for domains: ["example.com"] πŸ” Serving ACME challenge for token: Ix9X74-tENLdJY0F6f7kUe3TXkoXOxOyTb8iHcnv9Z4 βœ… Certificate stored successfully: example.com πŸŽ‰ Certificate issuance complete for example.com ``` μ•‘μ„ΈμŠ€ λ‘œκ·Έμ— λ‚¨λŠ” μ±Œλ¦°μ§€ μš”μ²­μ€ λΈŒλΌμš°μ €κ°€ μ•„λ‹ˆλΌ 인증 κΈ°κ΄€μ—μ„œ μ˜΅λ‹ˆλ‹€. ```text πŸ“ Access ... path="/.well-known/acme-challenge/Ix9X74-..." status=200 user_agent="Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)" ``` λ‹€λ₯Έ λ¨Έμ‹ μ—μ„œ μ‹€μ œλ‘œ 무엇이 μ œκ³΅λ˜λŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€. ```bash curl -I https://example.com/ ``` ```text HTTP/2 200 content-type: text/html; charset=utf-8 etag: "493b-6ab1f452" server: Pingclair ``` ```bash echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \ | openssl x509 -noout -subject -issuer -dates ``` ```text subject=CN=example.com issuer=C=US, O=Let's Encrypt, CN=YE2 notBefore=Sep 22 02:35:03 2026 GMT notAfter=Dec 21 02:35:02 2026 GMT ``` μΈμ¦μ„œ μ‹€μ²΄λŠ” μ„œλΉ„μŠ€ κ³„μ •μ˜ 데이터 디렉터리, `/var/lib/pingclair/.local/share/pingclair`에 λ³΄κ΄€λ©λ‹ˆλ‹€β€”β€”κ·Έ κ³„μ •μ˜ ν™ˆμ—μ„œ λ°”μ΄λ„ˆλ¦¬κ°€ ν’€μ–΄λ‚΄λŠ” 경둜이고, λ‹€λ₯Έ μ‚¬μš©μžλ‘œ λͺ…령을 돌릴 λ•Œ `PINGCLAIR_TLS_STORE`κ°€ κ°€λ¦¬ν‚€λŠ” κ²½λ‘œμ΄κΈ°λ„ ν•©λ‹ˆλ‹€. ## πŸ“‘ DNS-01κ³Ό μ™€μΌλ“œμΉ΄λ“œ DNS-01은 80 ν¬νŠΈμ—μ„œ μ‘λ‹΅ν•˜λŠ” λŒ€μ‹  TXT λ ˆμ½”λ“œλ₯Ό κ²Œμ‹œν•΄ 이름에 λŒ€ν•œ μ§€λ°°λ₯Ό 증λͺ…ν•©λ‹ˆλ‹€. μ™€μΌλ“œμΉ΄λ“œ μΈμ¦μ„œμ—λŠ” 이 방법이 ν•„μš”ν•©λ‹ˆλ‹€. μ„€μ •μ—λŠ” κ³΅κΈ‰μž 블둝이 ν•„μš”ν•©λ‹ˆλ‹€. ```caddyfile { email pingclair@pingclair.com } *.example.com { tls { auto dns cloudflare resolvers 1.1.1.1 propagation_delay 10s } file_server /var/lib/pingclair/html } ``` λ†“μΉ˜κΈ° μ‰¬μš΄ 점이 두 κ°€μ§€ μžˆμŠ΅λ‹ˆλ‹€. 블둝 μ•ˆμ˜ `auto` 쀄이 이름을 λ°œκΈ‰ λŒ€μƒ λͺ©λ‘μ— μ˜¬λ¦½λ‹ˆλ‹€. 이것이 μ—†μœΌλ©΄ μ„œλ²„λŠ” `authorised for 0 hostname(s)`λ₯Ό κΈ°λ‘ν•˜κ³  μΈμ¦μ„œλ₯Ό μ „ν˜€ μš”μ²­ν•˜μ§€ μ•Šμ•„, λͺ¨λ“  ν•Έλ“œμ…°μ΄ν¬κ°€ `NO_CERTIFICATE_SET`으둜 μ‹€νŒ¨ν•©λ‹ˆλ‹€. λ˜ν•œ 토큰은 κ·Έ 이름을 담은 쑴에 λŒ€ν•œ `Zone:DNS:Edit` κΆŒν•œμ΄ μžˆλŠ” Cloudflare API ν† ν°μž…λ‹ˆλ‹€. ⚠️ **v0.2.0-rc.3μ—μ„œλŠ” DNS-01 λ°œκΈ‰μ΄ λλ‚˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.** μ±Œλ¦°μ§€ μžμ²΄λŠ” λ™μž‘ν•©λ‹ˆλ‹€. λ ˆμ½”λ“œκ°€ κ²Œμ‹œλ˜κ³ , 섀정에 적은 λ¦¬μ‘Έλ²„λ‘œ μ „νŒŒκ°€ ν™•μΈλ˜κ³ , 인증 기관에 검증이 μš”μ²­λ©λ‹ˆλ‹€. κ·Έ 직후 μ‹œλ„ν•œ λͺ¨λ“  μ΄λ¦„μ—μ„œ 주문이 1초 μ•ˆμ— invalidκ°€ 되고 μΈμ¦μ„œλŠ” μ €μž₯λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ```text πŸ“‘ Published the DNS-01 record for _acme-challenge.example.com via cloudflare πŸ‘ DNS-01 record for _acme-challenge.example.com is visible πŸš€ Verification triggered for example.com ⏳ Polling order status... ⚠️ Eager issuance failed for example.com: Order ended in state: Invalid ``` 고쳐질 λ•ŒκΉŒμ§€ 곡개 μ΄λ¦„μ—λŠ” HTTP-01을 μ‚¬μš©ν•˜μ‹­μ‹œμ˜€. λ”°λΌμ„œ μ™€μΌλ“œμΉ΄λ“œ 이름은 아직 μΈμ¦μ„œμ™€ ν•¨κ»˜ μ œκ³΅ν•  수 μ—†μŠ΅λ‹ˆλ‹€. λŒ€μ‹  μ΄λ¦„λ§ˆλ‹€ μΈμ¦μ„œλ₯Ό ν•˜λ‚˜μ”© λ°›κ±°λ‚˜, λ‹€λ₯Έ κ³³μ—μ„œ λ°œκΈ‰ν•œ μΈμ¦μ„œλ₯Ό 파일둜 λ„˜κΈ°μ‹­μ‹œμ˜€. ## πŸ›οΈ λ‚΄λΆ€ 인증 κΈ°κ΄€μ˜ μΈμ¦μ„œ 사섀 μ˜€λ¦¬μ§„ β€” 터널, λ‚΄λΆ€ 호슀트 이름, μ‹€ν—˜μš© λ¨Έμ‹  β€” μ—λŠ” Pingclair 자체λ₯Ό 인증 κΈ°κ΄€μœΌλ‘œ μ“Έ 수 μžˆμŠ΅λ‹ˆλ‹€. ```caddyfile https://internal.test { tls internal file_server /var/lib/pingclair/html } ``` μ‚¬μ΄νŠΈλŠ” `CN=Pingclair Local Authority`κ°€ 10λ…„ 유효둜 λ°œκΈ‰ν•œ μΈμ¦μ„œλ‘œ μ‘λ‹΅ν•˜κ³ , λ£¨νŠΈλŠ” μ €μž₯μ†Œμ— κ²Œμ‹œλ©λ‹ˆλ‹€. ```bash sudo ls -l /var/lib/pingclair/.local/share/pingclair/internal/ ``` ```text -rw------- 1 pingclair pingclair 652 Sep 22 03:40 root.crt ``` ν΄λΌμ΄μ–ΈνŠΈλŠ” 아직 μ‹ λ’°ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ `-k` μ—†λŠ” μš”μ²­μ€ μ‹€νŒ¨ν•©λ‹ˆλ‹€. 루트λ₯Ό μ‹œμŠ€ν…œ μ‹ λ’° μ €μž₯μ†Œμ— λ„£μŠ΅λ‹ˆλ‹€. ```bash sudo PINGCLAIR_TLS_STORE=/var/lib/pingclair/.local/share/pingclair pingclair trust ``` ```text βœ… Internal CA root installed into the system trust store ``` `PINGCLAIR_TLS_STORE` 접두사가 μ€‘μš”ν•©λ‹ˆλ‹€. `pingclair trust`λŠ” μ‹€ν–‰ν•œ μ‚¬μš©μžμ˜ μ €μž₯μ†Œ(root라면 `/root/.local/share/pingclair`)λ₯Ό λ³΄μ§€λ§Œ μ„œλΉ„μŠ€λŠ” `/var/lib/pingclair/.local/share/pingclair`λ₯Ό μ”λ‹ˆλ‹€. 접두사가 μ—†μœΌλ©΄ `No internal CA root at /root/.local/share/pingclair/internal/root.crt`라고 λ‹΅ν•©λ‹ˆλ‹€. 루트λ₯Ό μ‹ λ’°ν•œ λ’€μ—λŠ” 같은 μš”μ²­μ΄ `-k` 없이 μ„±κ³΅ν•©λ‹ˆλ‹€. ```bash curl -s -o /dev/null -w '%{http_code}\n' https://internal.test/ ``` ```text 200 ``` `pingclair untrust`λŠ” 같은 μ €μž₯μ†Œ μ ‘λ‘μ‚¬λ‘œ λ‹€μ‹œ μ œκ±°ν•©λ‹ˆλ‹€. ## πŸ“œ 직접 μ€€λΉ„ν•œ μΈμ¦μ„œ λ‹€λ₯Έ μ‹œμŠ€ν…œμ΄ μΈμ¦μ„œλ₯Ό λ°œκΈ‰ν•œλ‹€λ©΄ `tls`λ₯Ό 파일둜 ν–₯ν•˜κ²Œ ν•©λ‹ˆλ‹€. ```caddyfile https://byo.test { tls { cert /etc/pingclair/certs/byo.crt key /etc/pingclair/certs/byo.key } file_server /var/lib/pingclair/html } ``` μ„œλΉ„μŠ€λŠ” `pingclair` μ‚¬μš©μžλ‘œ μ‹€ν–‰λ˜λ―€λ‘œ κ·Έ μ‚¬μš©μžκ°€ νŒŒμΌμ„ 읽을 수 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. `validate`λŠ” μ—†λŠ” 경둜λ₯Ό 첫 ν•Έλ“œμ…°μ΄ν¬μ—μ„œ μ‹€νŒ¨μ‹œν‚€λŠ” λŒ€μ‹  κ±°λΆ€ν•©λ‹ˆλ‹€. ```text ❌ TLS certificate file does not exist: /etc/pingclair/certs/missing.crt ``` ## ⚠️ HTTPSκ°€ λœ¨μ§€ μ•Šμ„ λ•Œ - **`contact email has forbidden domain "example.com"`.** Let's EncryptλŠ” μ˜ˆμ•½λœ example 도메인을 계정 μ—°λ½μ²˜λ‘œ κ±°λΆ€ν•©λ‹ˆλ‹€. `email` μ˜΅μ…˜μ— μ‹€μ œ μ‚¬μ„œν•¨μ„ λ„£μœΌμ‹­μ‹œμ˜€. - **둜그의 `NO_CERTIFICATE_SET`.** μ„œλ²„μ— μΈμ¦μ„œκ°€ μ—†λŠ” μ΄λ¦„μœΌλ‘œ ν•Έλ“œμ…°μ΄ν¬κ°€ λ“€μ–΄μ™”μŠ΅λ‹ˆλ‹€. λ°”λ‘œ μœ„ 둜그λ₯Ό μ½μœΌμ‹­μ‹œμ˜€. `auto`κ°€ μ—†λŠ” `tls` 블둝은 λ°œκΈ‰μ„ μ‹œμž‘ν•˜μ§€ μ•Šκ³ , DNS-01은 이 λ¦΄λ¦¬μŠ€μ—μ„œ λλ‚˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. - **μ±Œλ¦°μ§€κ°€ μ œκ³΅λ˜μ§€ μ•ŠμŒ.** 80 ν¬νŠΈκ°€ 방화벽에 λ§‰ν˜”κ±°λ‚˜ λ‹€λ₯Έ ν”„λ‘œκ·Έλž¨μ΄ 작고 μžˆμŠ΅λ‹ˆλ‹€. 인증 기관이 μΈν„°λ„·μ—μ„œ `http://your-name/.well-known/acme-challenge/`에 도달할 수 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. - **이름이 이 호슀트둜 ν•΄μ„λ˜μ§€ μ•ŠμŒ.** `dig +short A your-name`은 인증 기관이 접속할 λŒ€μƒμ„ 보여 μ€λ‹ˆλ‹€. 졜근 λ³€κ²½ ν›„μ—λŠ” κΈ°λŒ€μ™€ λ‹€λ₯Έ κ²½μš°κ°€ λ§ŽμŠ΅λ‹ˆλ‹€. - **λ°˜λ³΅λ˜λŠ” μ‹€νŒ¨.** Let's EncryptλŠ” μ΄λ¦„λ§ˆλ‹€ 검증 μ‹€νŒ¨λ₯Ό μ œν•œν•©λ‹ˆλ‹€. 원인을 고친 λ’€ μž¬μ‹œλ„ν•˜μ‹­μ‹œμ˜€. κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ μž¬μ‹œλ„ μžμ²΄κ°€ 였λ₯˜κ°€ λ©λ‹ˆλ‹€. ## 🧭 λ‹€μŒ 단계 - [μ„œλΉ„μŠ€λ‘œ μ‹€ν–‰](/ko/start/service/): μœ λ‹›, 재적용의 의미, 둜그. - [`tls`](/ko/reference/directives/#tls): μ§€μ‹œμ–΄μ˜ λͺ¨λ“  λͺ¨λ“œμ™€ μ˜΅μ…˜. - [Pingclairfile](/ko/reference/pingclairfile/): μ£Όμ†Œ, 맀처, μ»΄νŒŒμΌλŸ¬κ°€ λ°›μ•„λ“€μ΄λŠ” 것.