--- kind: QUESTION slug: does-the-renewal-timer-actually-renew title: 갱신 타이머가 실제 갱신에서도 도는가 topic: operations-that-report-success topicName: 운영 절차의 완료 판정 — 백업 · 판올림 · Secret · 인증서 갱신 project: keycloak-session-store status: 게시 전 questionStatus: OPEN sourceRevision: cdac9b8178391311d8eca1ebc6cac15bb62d79af source: - final/document.md#얻은-것-잃은-것-적용하지-않을-때-재보지-않은-것 - final/document.md#선택이-코드와-흐름에-반영되는-방식-d4a evidence: - ../../../final/evidence/raw/d4-certificate-renewal__07-renewal-hook-missing.txt - ../../../final/evidence/raw/d4-certificate-renewal__12-certbot-state.txt - ../../../final/evidence/raw/d4-certificate-renewal__13-verdict.txt - ../../../final/evidence/raw/d4a-deploy-hook__01-hook-verified.txt - ../../../final/evidence/raw/d4a-deploy-hook__03-after-state.txt --- # 갱신 타이머가 실제 갱신에서도 도는가 deploy 훅은 강제 갱신으로만 검증했고, 타이머가 스스로 갱신하는 날도 그 훅이 도는지는 재지 않았다. 만료 30일 전에야 조건이 성립해 약 59일 뒤에나 시험할 수 있다. 그때까지 타이머는 매번 SUCCESS 를 찍는다. ## 관계 - **새 인증서가 디스크에 있고 38분 25초 동안 옛 인증서가 나갔다** 이 질문이 나온 결함이다. reload 를 부르는 경로가 셋 다 비어 있었다. - **deploy 훅 하나가 그 공백을 1~2초로 줄였다** 그 훅을 강제 갱신으로만 시험했고, 타이머 경로는 남겨 두었다. ## 사실 - certbot-renew.timer 는 하루 두 번 도는 일정으로 잡혀 있다. RandomizedDelaySec : 12h Persistent : true - 2026-09-04 에 그 타이머가 두 번 돌았고 둘 다 status=0/SUCCESS 로 끝났다. - 같은 날 서빙 인증서는 만료까지 88일 남아 있었다. 두 번의 SUCCESS 는 갱신을 하지 않은 채 끝난 것이다. - certbot 의 인증서 상태 출력이 남은 일수를 VALID: 89 days 로 찍었다. 89일은 만료까지 남은 일수다. 다만 그 출력은 D-4 의 강제 갱신이 만든 인증서를 본 것이고, D-4a 가 다시 받은 인증서에 대해서는 같은 출력이 증거에 없다. 두 장은 만료 시각이 다르다. certbot 은 30일 남았을 때 갱신하므로 갱신 조건은 약 59일 뒤에 성립한다. - D-4 에서 새 인증서가 디스크에 기록된 시각과 실제 서빙이 바뀐 시각 사이가 2305초, 38분 25초 비었다. 그 사이 428회 관측했다. - 그때 reload 를 건 것은 사람이었다. certbot-renew.service 에 ExecStartPost 가 없었고 renewal-hooks 의 deploy · post · pre 세 디렉터리가 다 비어 있었으며 certbot 의 nginx 플러그인도 없었다. - D-4a 에서 deploy 훅 하나를 넣고 강제 갱신하자 갱신에서 서빙까지가 1~2초로 줄었다. - 누가 reload 를 걸었는지는 워커 프로세스 번호(PID)로 갈린다. 사람이 걸었을 때 28829, 훅이 걸었을 때 37252 였고 마스터 585 는 그대로였다. - 훅이 돌 때 certbot 은 Hook 'deploy-hook' ran with error output 을 찍었다. 실패는 아니었고 nginx 의 types_hash 경고가 stderr 로 나간 것이며 내용은 test is successful · signal process started 였다. ## 가정 - 타이머가 스스로 갱신하는 경로도 같은 certbot renew 를 부르고 같은 deploy/ 훅을 실행한다. 이 실험대의 기록이 그렇게 판단했고, 그 판단대로라면 남은 미지수는 타이머가 뜨는가 하나이며 그것은 D-4 에서 확인됐다. 훅 실행까지 같다는 부분은 실행으로 확인하지 않았다. - 갱신일까지 아무도 이 호스트의 타이머 유닛과 훅 파일을 건드리지 않는다. ## 미지수 - 타이머가 실제 갱신을 수행하는 날에도 deploy/ 훅이 도는가. 이 실험대가 훅을 확인한 경로는 --force-renewal 하나뿐이다. - --dry-run 에서 Running deploy-hook command 줄이 나오는가. 강제 갱신으로 바로 검증하는 바람에 dry-run 경로 자체를 거치지 않았다. - 훅이 실제로 실패하면 certbot 이 무엇을 찍는가. 성공한 훅의 출력만 봤다. - 훅이 /tmp 에 로그를 남기도록 만들면 타이머가 돌렸을 때 그 파일을 밖에서 찾을 수 있는가. certbot-renew.service 는 PrivateTmp=true 이고, 이 실험은 훅에 로그를 넣지 않았다. ## 제약 - 만료 30일 전에야 갱신 조건이 성립하므로 실제 갱신은 약 59일 뒤다. 다만 기다리는 것 말고도 이 실험대가 적어 둔 길이 하나 있다 — certbot renew --dry-run 은 인증서를 발급하지 않고 발급 한도도 깎지 않으면서 훅이 호출되는지까지는 보여 준다. - 강제 갱신으로는 이 질문에 답할 수 없다. 그 경로는 D-4a 에서 이미 검증했고, 지금 묻는 것은 타이머가 스스로 도는 경로다. - deploy 훅 파일은 지우지 않고 남긴다. 지우면 D-4 의 상태로 돌아간다. - 발급 한도가 있다. 강제 갱신을 쓸 때는 이번 주에 몇 장 발급했는지 센다. ## 선택지 갱신일이 와야 끝까지 시험할 수 있지만 그 전에 고를 수 있는 것이 하나 있다. certbot renew --dry-run 을 먼저 돌려 훅이 호출되는지만 본다 : 발급도 한도 소모도 없다. 다만 실제 갱신에서 훅이 무엇을 받는지까지는 답하지 않는다. 이 실험대는 이 줄을 미검증으로 표시했고 돌리지 않았다. 약 59일을 기다렸다가 실제 갱신을 본다 : 이 질문에 온전히 답하는 유일한 경로다. ## 다음 검증 약 59일 뒤, 만료 30일 전 조건이 성립해 타이머가 갱신을 수행한 날에 두 가지를 읽는다. 1. nginx 워커의 lstart 를 읽어 갱신 시각 근처인지 본다. 마스터는 그대로이고 워커만 새것이어야 한다. 2. 서빙 인증서의 serial 과 notAfter 를 읽어 notAfter 가 밀렸는지 본다. 판정은 이 둘로 한다. certbot 이 찍는 문구로는 갈리지 않는다 — D-4a 에서 ran with error output 은 실패가 아니었다. 닫는 조건 : 워커 PID 가 바뀌고 서빙 일련번호가 새 인증서와 같으면 닫는다. 그렇지 않으면 훅이 강제 갱신에서만 도는 것이므로 타이머 유닛 쪽에 훅을 다시 건다.