기록 84편을 계약 에이전트로 다시 썼다. 기존 71편(kss 25 · virt 46)과, 계약에만 있고 안 쓰여 있던 새 글감 13편이다. 원장 84개를 열어 단계마다 스킬 영수증과 관문 종료 코드를 적었고 verify-pipeline-run.py 가 error 0 으로 닫는다. SSOT 결함 둘을 고쳤다. - kss 의 `약 58일` 이 반입 중 `약 59일` 로 바뀌어 있었다. 원 증거 파일이 「남은 일수: 88일 … 실제 갱신까지 약 58일」로 산수를 직접 적는다. D-4a 쪽 `약 59일` 은 강제 갱신 뒤(`VALID: 89 days`)라 맞는 값이라 그대로 뒀다. - virt §198 의 `11.6GB` 는 §178 의 원 측정 `Mem: 11648`(MiB)과 어긋나는데 원 가이드의 표기 그대로라 고치지 않고 쓰이는 자리에 대조를 적었다. 기록의 수치 오류 셋을 고쳤다 — CASE 요약의 「게스트 셋에 8240MB」(5120+3120 은 둘이다), k3s 편이 같은 것을 여섯·일곱·여덟로 세던 것, no-docker 편의 「셋을 더 든다」(§281 의 표는 네 행이고 디스크 행이 빠져 있었다). 계약을 셋 고쳤다. - kss 의 sourceRepository 리비전이 cdac9b8 이었는데 그 커밋에는 docs/guides/** 28개가 아예 없다. 9465582b 로 바꾸고, 반입한 바이트가 어느 커밋과도 같지 않다는 것을 측정값과 함께 적었다 — 반입은 커밋이 아니라 그 시점의 작업 트리에서 떠 온 것이다(kss 297/306 · virt 12/14 가 작업 트리와 같고, 200 커밋을 거슬러 전수 대조했을 때 가장 가까운 커밋도 28개가 어긋났다). - virt 계약이 「2026-09-11 재배분」이라고 적는데 SSOT 는 재배분 날짜를 적지 않고 재배분 뒤 값은 이미 2026-09-10 측정에 찍혀 있다. - kss 후보 대장이 지나친 절 아홉에 처분을 적었다(warn 9 → 0). 새 글감은 0건이고 넷은 앵커가 h3 슬러그의 접두가 아니라 중간 토막이라 검사기가 못 본 것이었다. style_profile.mjs 의 결함 둘을 고쳤다 — frontmatter 가 문장으로 세어져 (실측 398자짜리 「문장」 하나) 평균 길이를 기준 안으로 밀어 올리고 있었고, engPerSent 의 분자는 목록을 포함한 글에서, 분모는 목록을 걷어낸 글에서 세고 있었다(Question 기록에서 11.94 → 3.86). verify-pipeline.py 전 항목 PASS · error 0 · unittest 334건 OK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.9 KiB
kind, slug, title, topic, topicName, project, status, questionStatus, sourceRevision, source
| kind | slug | title | topic | topicName | project | status | questionStatus | sourceRevision | source | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| QUESTION | is-this-lab-issuing-certificates-with-http-01-or-dns-01 | 이 실험대의 certbot 은 HTTP-01 로 받고 있는가 DNS-01 로 받고 있는가 | lab-environment-build | 실험대 환경 구성 | virtualization | 게시 전 | OPEN | 9465582b5d1630eb4ae7c4e078021486919bf6b6 |
|
이 실험대의 certbot 은 HTTP-01 로 받고 있는가 DNS-01 로 받고 있는가
어느 방식으로 받고 있는지 아직 읽지 못했다. §266 의 결론과 §190 은 DNS-01 을 가리키는데 원본 가이드 04 는 HTTP-01 로 적혀 있다. authenticator 한 값이면 갈리지만 호스트의 sudo 가 비밀번호를 요구해 비대화식으로 못 읽었다.
관계
- 인증서는 DNS-01 로 받는다 — 실험대 주소가 공개 인터넷에 없어 HTTP-01 이 성립하지 않는다 그 결정이 적은 것이 의도인지 이 호스트의 실제 설정인지를 이 물음이 가른다.
- DNS-01 으로 와일드카드 인증서를 받고 갱신이 서빙까지 닿게 한다
그 절차가
--dns-cloudflare로 받는 길을 적는다. 이 호스트가 그 길로 받았는지는 확인하지 않았다. - 실험대를 철거하고 무엇이 남는지 확인한다 그 절차의 「인증서를 지우지 않는다」가 이 물음의 답에 걸려 있다.
- 갱신은 매번 SUCCESS 였고 옛 인증서가 계속 나갔다 — 2305초와 1~2초 갱신은 됐는데 서빙까지 안 간 사건이다. 이 물음이 캐는 것은 갱신 자체가 도는지다.
- 공개 터널을 쓰지 않고 tailnet 직결로 둔다 — 홉이 하나 늘면 재려던 계약이 오염된다 공개 인터넷에서 이 호스트에 닿을 길을 두지 않기로 한 결정이고, HTTP-01 이 성립하지 않는 조건을 그 결정이 만든다.
- 가이드대로 다시 쳐서 이 실험대가 같은 상태로 서는가 그 물음이 재는 7단계 가운데 04 의 통과 조건이 이 답으로 확정된다.
사실
§266 이 문서 둘이 어긋나 있다고 직접 적었다. 그 절의 결론과 §190 은 DNS-01 을 가리킨다.
원본 가이드 docs/guides/04-tls/README.md 는 certbot certonly --webroot 로 적혀 있다. 전제도 공개 DNS 에 이름 셋이 이 호스트를 가리켜야 한다는 것이다.
dig +short auth.hyeonworks.com 이 100.83.212.4 를 낸다.
100.64.0.0/10 은 CGNAT(Carrier-Grade NAT, 통신사 공용 주소 변환)용 예약 대역이라 공개 인터넷에서 라우팅 자체가 안 된다. 방화벽을 여는 문제가 아니라 그 주소가 인터넷에 존재하지 않는다. 이것은 규격이고 이 실험대가 잰 값이 아니다.
certbot plugins 를 돌린 실측이 dns-cloudflare · standalone · webroot 세 줄을 냈으니 플러그인은 깔려 있다.
§190 이 적은 발급 대상은 -d hyeonworks.com -d '*.hyeonworks.com' 이고 lineage 디렉터리는 /etc/letsencrypt/live/hyeonworks.com/ 이다. 자격증명 파일은 /etc/letsencrypt/cloudflare.ini 이고 권한이 600 이다.
ACME 명세가 와일드카드를 DNS-01 로만 허용한다. 호스트 한 대에 파일을 놓는 것은 그 이름 하나를 통제한다는 증명이고, DNS 존의 TXT 레코드를 고칠 수 있다는 것은 도메인 전체를 통제한다는 증명이라 증명의 급이 다르다.
§204 가 이 항목을 「미측정」으로 적었다. 호스트의 sudo 가 비밀번호를 요구해 비대화식으로 읽지 못했다.
가정
지금 서빙되는 인증서가 와일드카드라면 발급은 DNS-01 로 이뤄졌을 수밖에 없다. 다만 그 인증서가 실제로 와일드카드인지는 이 저장소에 출력으로 남아 있지 않다.
플러그인이 보인다는 것과 그것으로 받았다는 것을 같게 읽지 않는다. certbot plugins 는 설치된 것을 세지 무엇으로 발급했는지를 세지 않는다.
갱신이 돌고 있다는 것도 아직 확인이 아니다. §218 의 구축 완료 판정 기준이 systemctl is-active nginx certbot-renew.timer 에 active active 를 요구하지만, §190 은 systemctl list-timers certbot-renew.timer 의 실제 출력이 남아 있지 않다고 적는다.
갱신 설정이 발급 시점의 방식을 그대로 물려받았다고 전제한다. 발급 뒤에 누가 renewal/*.conf 를 손으로 고쳤다면 그 전제가 깨진다.
미지수
/etc/letsencrypt/renewal/*.conf 의 authenticator 가 무엇인가.
그 값이 webroot 나 standalone 이면 지금 갱신이 실제로 돌고 있는가. 검증이 성립하지 않는 주소에 HTTP-01 로 설정돼 있다면 갱신은 조용히 실패한다.
그 값이 dns-cloudflare 라면 /etc/letsencrypt/cloudflare.ini 에 든 토큰의 권한이 존 하나 + DNS:Edit 으로 좁혀져 있는가. §266 이 그 범위를 값으로 치르는 것이라고 적었는데, 이 호스트의 토큰이 실제로 그 범위인지는 SSOT 에 없다.
지금 서빙되는 인증서가 와일드카드인가, 그리고 lineage 이름이 무엇인가.
제약
호스트의 sudo 가 비밀번호를 요구해서 비대화식으로는 읽을 수 없고, 콘솔에서 쳐야 한다. 이것이 §204 가 미측정으로 남긴 까닭이다.
비밀 값을 옮기지 않는다. cloudflare.ini 의 토큰은 길이와 존재 여부까지만 적고 값을 찍는 명령을 남기지 않는다.
Let's Encrypt 를 tailnet 에 초대할 방법이 없다. 검증 방식을 바꿔 가며 돌려 보는 실험으로 답을 대신할 수 없다.
발급 한도가 같은 이름 조합에 주당 중복 5장이다. 시험은 --dry-run 으로 먼저 한다.
선택지
1. 갱신 설정 파일을 콘솔에서 직접 읽는다
authenticator 한 값이 이 물음을 통째로 닫는다. 같은 콘솔 세션에서 쓸 수 있는 방식과 갱신 예행연습과 이름이 가리키는 주소까지 한 번에 찍어 같은 시각의 출력으로 묶는다. 값을 읽을 수 없는 경우는 파일이 없을 때뿐이고, 그때는 이 호스트가 인증서를 받은 적이 없다는 다른 답이 된다.
2. 지금 서빙되는 인증서가 와일드카드인지부터 본다
sudo 없이도 밖에서 TLS 핸드셰이크만으로 도메인 목록을 볼 수 있다. 와일드카드로 나오면 발급이 DNS-01 이었다는 쪽으로 정황이 좁혀진다. 다만 좁혀질 뿐 authenticator 를 대신하지는 못한다. 발급은 와일드카드로 받고 갱신 설정만 다른 경우를 이 방법으로는 가르지 못한다.
3. 인증서를 지우고 다시 받아 본다 — 제외
다시 받아 보면 어느 방식이 성립하는지 바로 드러나지만, §204 가 「어느 쪽인지 모르는 채로는 지우지 않는다」로 그 순서를 막아 두었다. HTTP-01 로 설정돼 있으면 재발급이 안 되고, 그러면 재구축을 시작하자마자 검증 방식부터 손봐야 한다. 답을 얻으려고 답이 필요한 상태를 만드는 순서다.
다음 검증
§204 와 §266 이 적은 네 줄을 호스트 콘솔에서 그대로 친다.
sudo grep -H authenticator /etc/letsencrypt/renewal/*.conf으로 검증 방식을 읽는다.certbot plugins를 돌려 앞에*가 붙은 줄을 적는다.sudo certbot renew --dry-run으로 갱신이 실제로 되는지 본다.dig +short auth.hyeonworks.com으로 Let's Encrypt 가 올 수 있는 주소인지를 같은 시각에 함께 남긴다.- 지금 서빙되는 인증서가 와일드카드인지와 lineage 이름이 무엇인지를
certbot certificates의 도메인 목록으로 적는다. - 출력 원문을
final/evidence/raw/에 남기고meta/에 명령과 cwd 와 실행 시각과 종료 코드를 적는다.cloudflare.ini의 토큰 값은 찍지 않는다.
닫는 조건 : authenticator 한 값과 --dry-run 결과가 나오면 닫는다.
dns-cloudflare 면 「인증서는 DNS-01 로 받는다」가 이 호스트의 현재 상태를 적은 것으로 확인되고, 철거 절차의 「인증서를 지우지 않는다」가 정책에서 선택으로 바뀐다. §204 가 적은 대로 그때는 백업이 헛수고이므로 지워도 되고 재구축 절차가 한 단계 짧아진다.
webroot 나 standalone 이면 그 결정이 적은 것은 의도이고 실제 설정은 다른 것이므로, §190 과 가이드 04 가운데 어느 쪽이 실재인지를 먼저 고친 뒤 그 기록을 다시 판정한다.
--dry-run 이 실패하면 갱신이 이미 멈춰 있다는 뜻이라 그 자체가 새 Case 다. 「갱신은 매번 SUCCESS 였고 옛 인증서가 계속 나갔다」가 갱신은 되는데 서빙까지 안 간 것을 다뤘다면, 이번 것은 갱신 자체가 안 되는 쪽이고 증상이 또 조용하다.