태그 보관물: selinux

Let’s Encrypt 인증서 생성 실패

개요

certbot을 사용해 Let’s Encrypt 인증서 생성 실패가 발생하는 원인은 다양하지만, RHEL/Rocky Linux 계열의 서버에서는 SELinux가 certbot의 HTTP 인증 프로세스를 차단하여 실패하는 경우가 있습니다. Apache가 설치된 환경에서는 Apache 자체는 SELinux 정책에 자동 등록되지만, certbot이 도메인 검증 시 사용하는 80/443 포트 바인딩용 독립 프로세스는 SELinux 정책에 등록되지 않아 차단됩니다. 이 글에서는 오류 내용과 SELinux 비활성화를 통한 해결 방법을 정리합니다.

증상 — certbot 실행 오류

certbot으로 인증서 발급을 시도하면 webroot 플러그인 관련 오류가 발생하며 인증서 발급이 완료되지 않습니다.

@:~# sudo certbot certonly --cert-name  -d www.
...
certbot.errors.PluginError: Every requested domain must have a webroot when using the webroot plugin.
2025-01-01 01:13:52,404:ERROR:certbot._internal.log:Every requested domain must have a webroot when using the webroot plugin.

원인 분석 — SELinux 정책 미등록

SELinux가 enforcing 모드로 활성화된 경우, Apache처럼 사전에 SELinux 정책이 등록된 서비스는 정상 동작하지만, certbot이 도메인 인증 시 새로 바인딩하는 포트(80, 443)용 프로세스는 정책이 없어 차단됩니다. 이 때문에 certbot이 ACME challenge 응답을 처리하지 못하고 실패합니다.

# SELinux 현재 상태 확인
@:~# sestatus
SELinuxfs mount:                /sys/fs/selinux
SELinuxfs status:                 enabled
SELinux mount directory:         /etc/selinux
Loaded policy name:              targeted
Current mode:                    enforcing

해결 방법 — SELinux 비활성화

SELinux 정책을 개별 추가하는 방법도 있으나, 서버 환경에서 SELinux 제어가 불필요한 경우 비활성화 처리가 가장 빠른 해결책입니다. /etc/sysconfig/selinux 파일에서 SELINUX=disabled로 변경한 뒤 재부팅합니다.

@:~# vi /etc/sysconfig/selinux
SELINUX=disabled

@:~# init 6

# 재기동 이후 SELinux 상태 확인
@:~# sestatus -v
SELinux status:                 disabled

SELinux 영구 비활성화 vs 임시 비활성화

/etc/sysconfig/selinux를 수정하고 재부팅하는 방식은 영구 비활성화입니다. 재부팅 없이 즉시 permissive 모드(정책 위반은 로깅만 하고 차단하지 않음)로 전환하려면 setenforce 0을 사용합니다. Permissive 모드는 SELinux 정책 개발이나 문제 진단 시 유용하며, 재부팅하면 /etc/sysconfig/selinux에 설정된 모드로 복귀합니다.

# 현재 세션에서만 permissive로 전환 (재부팅 후 원복)
setenforce 0

# 다시 enforcing으로 전환
setenforce 1

# 현재 상태 확인
getenforce

SELinux를 완전히 비활성화하는 대신 certbot에 대한 SELinux 정책만 추가하는 방법도 있습니다. audit.log에서 certbot 관련 AVC 거부 메시지를 확인하고 audit2allow 도구로 커스텀 정책 모듈을 생성할 수 있습니다. 그러나 프로덕션 서버에서 SELinux가 필수가 아닌 환경이라면 비활성화가 더 단순하고 확실한 해결책입니다.

결과 확인 — 인증서 재발급

SELinux 비활성화 후 certbot을 재실행하면 인증서가 정상 발급됩니다. 인증서 경로와 만료일을 확인합니다.

@:~# sudo certbot certonly --cert-name  -d www.
...
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live//fullchain.pem
Key is saved at:         /etc/letsencrypt/live//privkey.pem
This certificate expires on 2025-03-31.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

자동 갱신 확인

certbot은 인증서 발급 완료 시 --standalone 또는 --webroot 플러그인에 따라 systemd timer 또는 cron 기반 자동 갱신 태스크를 등록합니다. 자동 갱신이 정상 동작하려면 서버가 재부팅된 후에도 SELinux 상태가 disabled인지 확인해야 합니다. SELinux를 재활성화한 경우 certbot 갱신 시 다시 차단될 수 있습니다.

# systemd timer 확인 (RHEL 8+)
systemctl status certbot-renew.timer

# 갱신 dry-run 테스트
certbot renew --dry-run

# 인증서 만료일 확인
certbot certificates

참고

관련 포스트:

참고 문서: certbot standalone 플러그인 공식 문서 · RHEL SELinux 상태 변경 공식 문서