SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-03

Ubuntu 24.04 자체 서명 TLS 인증서 올바르게 생성하기

Ubuntu 24.04에서 Chrome이 신뢰하는 자체 서명 TLS 인증서 생성법을 다룹니다. SAN 설정부터 nginx 적용, 시스템 신뢰 등록까지 curl -k 없이 안전하게 연결하는 실무 가이드를 제공합니다.

구축할 내용

최신 브라우저와 클라이언트가 실제로 수락하는 자체 서명 TLS 인증서, 올바른 subjectAltName, 적절한 키 권한, nginx 또는 Apache에 연결하는 방법, 그리고 거의 모든 가이드에서 생략하는 핵심 내용인 클라이언트가 경고를 무시하고 클릭하거나 스크립트에 curl -k를 영원히 하드코딩하는 대신 인증서를 올바르게 신뢰하도록 만드는 방법을 다룹니다. 마지막에는 내부 서비스가 6개 이상으로 늘어날 때를 대비한 5개 명령어 기반의 사설 CA 구축법을 포함합니다.

먼저 결정을 내려야 합니다. 자체 서명 인증서는 사용되는 빈도보다 실제로 적합한 도구인 경우가 훨씬 적기 때문입니다. 만약 서비스가 실제 DNS 도메인 이름을 통해 공용 인터넷에서 접근 가능하다면, 이 글을 읽는 것을 멈추고 nginx에서 certbot을 사용한 무료 Let's Encrypt 인증서 또는 Apache용 대응 가이드를 확인하십시오. 비용이 들지 않고 자동으로 갱신되며, 전 세계 모든 브라우저가 이미 신뢰합니다. 공용 사이트에 자체 서명 인증서를 사용하면 사용자가 보안 경고를 무시하고 클릭하도록 유도하게 되는데, 이는 일반 HTTP보다 더 나쁜 습관입니다.

자체 서명 인증서가 적합한 경우는 공용 인터넷이 관여하지 않을 때입니다. 예를 들어 VPS의 WireGuard 터널 주소에 바인딩된 관리자 패널, 사설 네트워크의 스테이징 서버, 백엔드 간의 서비스 통신, 홈랩 장비, 또는 Webmin이 10000번 포트에서 자체 생성하는 기본 인증서를 대체하는 경우입니다. 어차피 Let's Encrypt는 10.8.0.1이나 git.internal.lan에 대해 인증서를 발급할 수 없으며, 어떤 공용 CA도 사설 IP나 임의로 만든 TLD를 인증서에 포함해주지 않습니다. 이러한 이름의 경우, 귀하가 곧 CA가 되어야 합니다.

아래의 모든 과정은 OpenSSL 3.0.x(확인을 위해 openssl version 사용)가 탑재된 최신 Ubuntu 24.04 환경에서 진행됩니다. 이 과정은 인터넷 연결이 필요 없으며, 외부와 완전히 차단된(air-gapped) 환경에서도 작동합니다.

이전의 한 줄짜리 명령어가 Chrome에서 거부되는 인증서를 생성하는 이유

2017년 이전의 모든 튜토리얼에서 제공하는 명령어는 다음과 같습니다.

# Do not run this — shown so you recognise it in old guides
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout selfsigned.key -out selfsigned.crt

이 명령어는 일련의 대화형 질문을 던지고, Common Name 필드에 호스트 이름을 넣으며, subjectAltName 확장이 없는 인증서를 생성합니다. 해당 인증서는 생성 즉시 사용할 수 없는 상태가 됩니다. Chrome은 2017년 4월 버전 58부터 Common Name을 읽지 않게 되었으며, RFC 2818은 이미 2000년에 CN 매칭을 폐기했습니다. Firefox, Safari, curl, Python도 동일하게 동작합니다. 인증서는 SAN 확장을 통해서만 서버를 식별하며, 그렇지 않으면 식별이 불가능합니다. 브라우저는 정확히 다음과 같은 문구로 이 사실을 알립니다.

NET::ERR_CERT_COMMON_NAME_INVALID

This server could not prove that it is git.internal.lan; its security
certificate does not specify Subject Alternative Names.

인증서가 실제로 아무런 이름도 지정하지 않기 때문에 신뢰 저장소(trust-store)를 아무리 수정해도 이 오류는 해결되지 않습니다. 현재 NET::ERR_CERT_COMMON_NAME_INVALID 오류를 보고 있다면, 인증서에 SAN이 없거나 잘못된 SAN이 포함된 것이므로 새로 발급해야 합니다. 다행히 해결 방법은 한 줄의 명령어로 충분합니다.

브라우저가 신뢰하는 인증서 발급: 단일 명령어

OpenSSL은 1.1.1 버전부터 -addext 플래그를 도입했습니다. 따라서 과거 가이드에서 SAN을 삽입하기 위해 사용하던 복잡한 설정 파일 작업이 더 이상 필요하지 않습니다. Ubuntu 24.04 환경에서는 다음과 같이 실행합니다.

sudo openssl req -x509 -newkey rsa:4096 -sha256 -days 730 -noenc \
  -keyout /etc/ssl/private/git.internal.key \
  -out /etc/ssl/certs/git.internal.crt \
  -subj "/CN=git.internal.lan" \
  -addext "subjectAltName=DNS:git.internal.lan,IP:10.8.0.1"

각 플래그의 역할은 다음과 같습니다.

  • -x509: 서명 요청(CSR) 대신 자체 서명된 인증서를 즉시 생성합니다.
  • -newkey rsa:4096: 동일한 단계에서 새로운 키를 생성합니다. RSA 4096은 구형 클라이언트와 호환성 문제가 없으며, 연결되는 모든 환경이 최신이라면 -newkey ec -pkeyopt ec_paramgen_curve:P-256을 사용하는 것이 더 작고 빠릅니다.
  • -noenc: 기존 -nodes의 OpenSSL 3.x 버전 표기법으로, 키에 암호를 설정하지 않습니다. 두 표기법 모두 작동합니다. 키에 암호가 설정되어 있으면 부팅할 때마다 nginx가 입력을 대기하며 멈추게 되므로, 서버용 키에는 이 옵션이 필수입니다.
  • -days 730: 유효 기간을 2년으로 설정합니다. 이 수치에 관한 자세한 내용은 만료 섹션을 참조하십시오.
  • -subj: 대화형 질문에 대한 답변을 명령줄에서 바로 입력합니다. CN은 현재 장식적인 용도에 불과하지만, 일부 도구에서 표시하므로 기본 도메인 이름을 설정하는 것이 좋습니다.
  • -addext "subjectAltName=...": 핵심적인 역할을 하는 플래그입니다. 클라이언트가 입력할 모든 이름과 모든 IP를 나열하십시오. 호스트 이름은 DNS: 항목(DNS:*.internal.lan와 같은 와일드카드 사용 가능), 주소는 IP: 항목을 사용합니다. 누군가 https://10.8.0.1로 접속할 예정이라면 IP:10.8.0.1 항목이 반드시 포함되어야 합니다. DNS 전용 SAN만 설정하면 다시 NET::ERR_CERT_COMMON_NAME_INVALID 오류가 발생합니다.

설정을 적용하기 전에 SAN이 제대로 포함되었는지 확인하십시오.

openssl x509 -in /etc/ssl/certs/git.internal.crt -noout -ext subjectAltName

올바른 출력 결과:

X509v3 Subject Alternative Name:
    DNS:git.internal.lan, IP Address:10.8.0.1

만약 결과에 No extensions in certificate이 출력된다면, 인증서에 SAN이 없는 상태입니다. 브라우저가 이를 거부하므로, 그대로 진행하지 말고 다시 생성하십시오.

키 보안 설정

시스템의 모든 사용자가 읽을 수 있는 개인 키는 더 이상 개인 키가 아닙니다. Ubuntu에서 /etc/ssl/private은 이미 710 root:ssl-cert로 설정되어 있어 일반적인 접근을 차단하지만, 파일 자체의 권한을 명시적으로 설정해야 합니다.

sudo chown root:root /etc/ssl/private/git.internal.key
sudo chmod 600 /etc/ssl/private/git.internal.key

nginx와 Apache는 권한을 낮추기 전에 root 권한으로 인증서를 읽으므로, root:root 모드 600 설정으로 충분합니다. 만약 Node 앱, Gitea, Python 데몬과 같이 별도의 사용자 권한으로 실행되면서 직접 키를 로드하는 서비스라면, chown를 사용하여 해당 서비스 사용자로 소유권을 변경하십시오. 이때도 권한은 600으로 유지해야 합니다. 절대 하지 말아야 할 행동은 다음과 같습니다: 644 모드 설정, git 저장소에 복사본 저장, /tmp에 복사본 보관.

Nginx에 연결하기

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name git.internal.lan;

    ssl_certificate     /etc/ssl/certs/git.internal.crt;
    ssl_certificate_key /etc/ssl/private/git.internal.key;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}
sudo nginx -t && sudo systemctl reload nginx

nginx -t은 리로드를 수행하기 전에 반드시 syntax is oktest is successful을 출력해야 합니다. 만약 SSL_CTX_use_PrivateKey_file() failed ... key values mismatch가 출력된다면, 인증서와 키가 서로 다른 생성 과정에서 만들어진 것이므로 실패 유형(failure-modes) 섹션을 확인하십시오.

Apache에 연결하기

sudo a2enmod ssl proxy proxy_http

ssl만으로는 충분하지 않습니다. 아래의 vhost는 ProxyPass을 사용하며, mod_proxymod_proxy_http이 없으면 설정 테스트가 Invalid command 'ProxyPass', perhaps misspelled or defined by a module not included in the server configuration 오류와 함께 실패합니다. vhost를 /etc/apache2/sites-available/git-internal.conf로 저장하십시오:

<VirtualHost *:443>
    ServerName git.internal.lan
    SSLEngine on
    SSLCertificateFile      /etc/ssl/certs/git.internal.crt
    SSLCertificateKeyFile   /etc/ssl/private/git.internal.key

    ProxyPass        / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/
</VirtualHost>
sudo a2ensite git-internal
sudo apache2ctl configtest && sudo systemctl reload apache2

configtestSyntax OK로 응답해야 합니다. 이제 클라이언트 머신에서 테스트하십시오:

curl -v https://git.internal.lan/

그러면 다음과 같은 오류가 발생합니다:

curl: (60) SSL certificate problem: self-signed certificate

이는 버그가 아닙니다. TLS가 정상적으로 작동하고 있는 것입니다. curl은 귀하의 인증서에 대해 알지 못하며, 인증할 수 없는 서버와 통신하기를 거부합니다. 다음 섹션에서 올바른 해결 방법을 다룹니다. 이는 현재 인터넷상의 절반이 수행하는 방식과는 다른 방법입니다.

클라이언트가 인증서를 신뢰하도록 설정하기 및 피해야 할 안티패턴

잘못된 해결책부터 언급하겠습니다. 스크립트에 포함된 curl -k(또는 --insecure), Python requests의 verify=False, Node의 NODE_TLS_REJECT_UNAUTHORIZED=0 등은 인증서를 신뢰하게 만들지 않습니다. 이러한 설정은 인증서 검증 기능을 비활성화하며, 이는 클라이언트가 공격자가 중간에 배치한 인증서를 포함하여 어떤 서버가 제시하는 어떤 인증서와도 통신하게 만듭니다. TLS의 오버헤드는 그대로 유지하면서 정작 TLS의 목적인 인증 기능은 상실하게 됩니다. 더 나쁜 점은 이러한 플래그가 확산된다는 것입니다. 크론 작업에 붙여넣고, 배포 스크립트에 넣고, 운영 코드에까지 포함되어 결국 어떤 연결이 일시적인 것이었는지 아무도 기억하지 못하게 됩니다. 디버깅 세션이 끝난 후에도 verify=False가 남아 있다면, 이는 설계가 잘못된 것입니다.

올바른 해결책은 각 클라이언트 OS에 이 인증서가 신뢰할 수 있는 루트 인증서임을 알리는 것입니다. Ubuntu 및 Debian 클라이언트에서는 다음과 같이 합니다.

sudo cp git.internal.crt /usr/local/share/ca-certificates/git.internal.crt
sudo update-ca-certificates

출력 내용 중 중요한 줄은 다음과 같습니다(Running hooks in /etc/ca-certificates/update.d... 블록이 뒤따릅니다).

Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.

이 과정에는 두 가지 주의사항이 있습니다. 파일은 반드시 .crt로 끝나야 합니다. .pem 확장자를 사용하면 무시되며 오류 메시지 없이 0 added이 발생합니다. 또한 내용은 PEM 형식이어야 하며 파일은 -----BEGIN CERTIFICATE-----로 시작해야 합니다. DER 바이너리 형식이라면 먼저 openssl x509 -inform der -in file.der -out file.crt을 사용하여 변환하십시오. 자체 서명된 인증서 자체를 루트로 추가하는 것은 자체 서명된 인증서가 자신의 루트이기 때문에 정상적으로 작동합니다.

그 후에는 curl, wget, git, apt 및 시스템 번들을 사용하는 OpenSSL 기반의 모든 도구가 별도의 플래그 없이 서버를 신뢰하게 됩니다. 자체적인 신뢰 저장소를 사용하는 일부 클라이언트는 개별적인 처리가 필요합니다.

  • Linux의 Chrome/Chromium: 시스템 저장소가 아닌 NSS 데이터베이스를 읽습니다. sudo apt install libnss3-tools을 사용하거나 사용자별로 certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "git.internal" -i git.internal.crt를 수행하십시오.
  • Firefox: 자체 저장소를 사용합니다. 설정 → 개인정보 및 보안 → 인증서 → 불러오기를 수행하거나, about:config에서 security.enterprise_roots.enabledtrue으로 변경하여 시스템 저장소를 읽도록 설정하십시오.
  • Python requests: 자체 CA 번들(certifi)을 포함하고 있으며 시스템 저장소를 무시합니다. verify="/usr/local/share/ca-certificates/git.internal.crt"을 전달하거나 REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt를 내보내십시오.
  • Node.js: NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/git.internal.crt을 내보내십시오.

Windows 클라이언트에서는 .crt을 더블 클릭하여 신뢰할 수 있는 루트 인증 기관에 설치하십시오. macOS에서는 키체인 접근(Keychain Access)의 시스템 키체인에 추가하고 항상 신뢰(Always Trust)로 표시하십시오.

여러 서비스를 위한 하나의 루트: 소규모 사설 CA

인증서별로 신뢰를 설정하는 방식은 즉시 확장성이 떨어집니다. 6개의 서비스와 4대의 클라이언트 머신이 있다면 24번의 신뢰 설정이 필요하며, 서비스가 추가될 때마다 작업은 늘어납니다. 해결책은 사설 CA를 구축하는 것입니다. 클라이언트는 하나의 루트 인증서만 신뢰하고, 각 서비스의 인증서는 이 루트로 서명합니다.

사용하기 쉬운 옵션은 mkcert입니다. 이는 Ubuntu 24.04 저장소에 포함되어 있으며, update-ca-certificates이 놓치는 NSS 저장소(Chrome, Firefox)까지 처리합니다.

sudo apt install -y mkcert libnss3-tools
mkcert -install
mkcert git.internal.lan "*.internal.lan" 10.8.0.1

mkcert -install는 루트 인증서를 생성하고 해당 머신의 모든 신뢰 저장소에 등록합니다. 세 번째 명령은 nginx나 Apache 스니펫에 바로 사용할 수 있는 git.internal.lan+2.pemgit.internal.lan+2-key.pem을 생성합니다. 이 도구는 개발 머신을 전제로 설계되었습니다. 루트 키는 -install을 실행한 장비에 저장되므로, 개발용 노트북에는 적합하지만 서버 군을 관리하기에는 적절하지 않습니다.

서버의 경우, 일반 OpenSSL을 사용하여 5개의 명령어로 CA 전체를 구축할 수 있습니다.

openssl genrsa -out lab-ca.key 4096
openssl req -x509 -new -key lab-ca.key -sha256 -days 3650 \
  -out lab-ca.crt -subj "/CN=Lab Internal CA" \
  -addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
  -addext "keyUsage=critical,keyCertSign,cRLSign"
openssl genrsa -out git.key 2048
openssl req -new -key git.key -out git.csr -subj "/CN=git.internal.lan" \
  -addext "subjectAltName=DNS:git.internal.lan,IP:10.8.0.1"
openssl x509 -req -in git.csr -CA lab-ca.crt -CAkey lab-ca.key \
  -CAcreateserial -days 730 -sha256 -copy_extensions copy -out git.crt

마지막 명령에 함정이 있습니다. openssl x509 -req은 기본적으로 CSR에서 모든 확장을 제거하며, 여기에는 신중하게 추가한 SAN도 포함됩니다. -copy_extensions copy(OpenSSL 3.x 옵션이므로 24.04에서 작동)를 사용하면 확장을 유지할 수 있습니다. 이 옵션을 생략하면 서명된 인증서에 SAN이 포함되지 않으며, Chrome은 다시 NET::ERR_CERT_COMMON_NAME_INVALID 오류를 표시합니다. 이전과 동일한 openssl x509 -noout -ext subjectAltName 명령으로 확인하십시오.

lab-ca.crt를 클라이언트의 신뢰 저장소에 배포하십시오. 이 작업은 각 머신당 한 번만 수행하면 됩니다. lab-ca.key은 이제 왕실의 보물처럼 보호해야 합니다. 권한을 600으로 설정하고, 가급적 서명 대상 서버가 아닌 별도의 장비에 보관하십시오. 이 키를 가진 사람은 클라이언트가 신뢰하는 어떤 도메인으로든 인증서를 위조할 수 있기 때문입니다.

만료 및 갱신

공용 CA 인증서의 유효 기간은 점차 짧아지고 있습니다. CA/Browser Forum은 2026년 3월부터 신규 발행되는 공용 신뢰 인증서의 최대 유효 기간을 200일(기존 398일)로 제한했으며, 2027년에는 100일, 2029년 3월까지는 47일로 단축할 예정입니다. 하지만 이러한 규칙은 공용 신뢰 CA에만 적용됩니다. 사설 CA는 해당 규정의 적용을 받지 않으며, 브라우저 역시 수동으로 설치된 루트 인증서에 대해서는 이를 강제하지 않습니다. 다만 실제 환경에서 적용되는 제약 사항이 하나 있습니다. Apple 플랫폼은 발행 주체와 관계없이 유효 기간이 825일을 초과하는 모든 TLS 서버 인증서를 거부합니다. 따라서 iPhone이나 Mac이 연결되는 환경이라면 리프 인증서의 유효 기간을 2년 이하로 유지해야 합니다. -days 730는 모든 환경에서 이 기준을 충족하며, 10년 유효 기간의 루트 인증서와 2년 유효 기간의 리프 인증서를 조합하는 것이 내부 운영상 적절한 형태입니다.

수명이 긴 인증서는 단 한 가지 방식으로 실패합니다. 아무도 기억하지 못하는 특정 날짜에, 아무런 예고 없이 한꺼번에 만료됩니다. 현재 보유한 인증서를 확인하십시오:

openssl x509 -in /etc/ssl/certs/git.internal.crt -noout -enddate

갱신 일정을 실제 달력에 기록하거나, cron을 사용하여 30일 전부터 알림을 받도록 설정하십시오. openssl x509 -checkend 2592000 -in cert.crt는 만료 시점이 지정된 초 단위 이내로 다가오면 0이 아닌 값을 반환하며 종료됩니다. 이미 상태 모니터링을 위한 Uptime Kuma를 운영 중이라면, 해당 도구의 HTTPS 모니터 기능을 통해 인증서 만료 임박 알림을 무료로 받을 수 있습니다.

사설 CA를 이용한 인증서 교체는 매우 단순한 작업입니다. CSR 생성 및 서명 명령을 다시 실행하고, 파일을 교체한 뒤 웹 서버를 리로드하면 됩니다. 루트 인증서는 변경되지 않았으므로 클라이언트는 아무런 변화를 감지하지 못합니다.

실패 유형 및 표시되는 문자열

NET::ERR_CERT_AUTHORITY_INVALID, 신뢰를 설정하기 전의 예상되는 상태이며, 인증서 자체의 결함은 아닙니다. 루트 인증서를 설치한 에도 이 문제가 지속된다면 다음을 확인하십시오. Linux에서 Chrome은 시스템 저장소가 아닌 NSS를 참조합니다(certutil 단계 참조). 또는 복사한 파일이 .crt로 끝나지 않았고 update-ca-certificates0 added을 반환했을 수 있습니다. 혹은 서버가 신뢰한 인증서와 다른 인증서를 제공하고 있을 수 있으므로 openssl s_client -connect git.internal.lan:443 </dev/null 2>/dev/null | openssl x509 -noout -fingerprint -sha256을 사용하여 지문을 비교하십시오.

NET::ERR_CERT_COMMON_NAME_INVALID, 인증서에 SAN이 없거나, 주소 표시줄의 도메인 이름이 SAN에 포함되지 않은 경우입니다. 흔한 사례로, SAN에는 DNS:git.internal.lan이 나열되어 있으나 사용자가 https://10.8.0.1로 접속한 경우입니다. 신뢰 저장소 변경으로는 이 문제를 해결할 수 없으며, 누락된 항목을 포함하여 인증서를 재발급해야 합니다.

curl: (60) SSL certificate problem: self-signed certificate, curl이 인증서를 신뢰하지 않는 상태입니다. 변형인 self-signed certificate in certificate chain은 사설 CA에서 서명한 인증서에 대해 동일한 의미를 갖습니다. 일회성 해결책은 curl --cacert lab-ca.crt https://...이며, 영구적인 해결책은 신뢰 저장소에 등록하는 것입니다. -k을 사용하지 마십시오.

unable to load certificate ... Expecting: TRUSTED CERTIFICATE(또는 Expecting: CERTIFICATE REQUEST, no start line), PEM 형식 혼동입니다. OpenSSL에 인증서가 필요한 곳에 키나 CSR을 입력했거나, PEM이 필요한 곳에 DER 바이너리를 입력한 경우입니다. head -1 filename를 사용하면 현재 파일의 실제 형식을 확인할 수 있으며, 인증서는 -----BEGIN CERTIFICATE-----으로 시작합니다. DER 형식인 경우 openssl x509 -inform der -in file.der -out file.crt를 사용하여 변환하십시오.

nginx: [emerg] SSL_CTX_use_PrivateKey_file(...) failed (SSL: error ... key values mismatch), 인증서와 키가 서로 일치하지 않는 경우입니다. 보통 생성 명령을 두 번 실행하여 파일이 뒤섞였을 때 발생합니다. openssl x509 -in git.internal.crt -noout -pubkey | sha256sumopenssl pkey -in git.internal.key -pubout | sha256sum을 비교하여 확인하십시오. 해시 값이 일치하면 올바른 쌍입니다. 값이 다르면 둘 다 새로 생성하십시오.

FAQ

자체 서명 인증서를 생성했는데도 Chrome에서 왜 계속 "주의 요함"이라고 표시하나요?

오류가 NET::ERR_CERT_AUTHORITY_INVALID이라면 인증서 자체는 정상이나 Chrome이 아직 신뢰할 근거가 없는 상태입니다. 인증서(또는 사설 CA 루트)를 클라이언트의 신뢰 저장소에 설치하십시오. Linux 환경의 Chrome은 시스템 저장소가 아닌 certutil를 통해 NSS 데이터베이스를 사용한다는 점을 기억해야 합니다. 오류가 NET::ERR_CERT_COMMON_NAME_INVALID이라면 인증서에 URL과 일치하는 Subject Alternative Name이 없는 것이므로 -addext "subjectAltName=..."을 사용하여 다시 발급해야 합니다.

-k 옵션 없이 curl이 자체 서명 인증서를 신뢰하게 하려면 어떻게 해야 하나요?

인증서(PEM 형식, .crt 확장자)를 /usr/local/share/ca-certificates/에 복사한 뒤 sudo update-ca-certificates를 실행하십시오. 출력 결과에 1 added가 포함되어야 합니다. 이후부터는 curl이 공인 인증서와 동일하게 해당 인증서를 검증합니다. 시스템 설정을 변경하지 않고 일회성으로 요청하려면 curl --cacert /path/to/cert.crt을 사용하여 해당 파일로만 검증하십시오. -k은 검증을 완전히 비활성화하므로 스크립트에는 사용하지 마십시오.

자체 서명 인증서는 얼마나 오래 유효할 수 있나요?

기술적으로는 원하는 만큼 길게 설정할 수 있습니다. CA/Browser Forum의 제한(현재 200일, 2029년에는 47일)은 공개적으로 신뢰받는 CA에만 적용되며 사설 신뢰에는 적용되지 않습니다. 실제 운영 시에는 Apple 기기가 발행 기관과 관계없이 그 이상의 기간을 거부하므로 서버 인증서의 유효 기간을 825일로 제한하십시오. 10년 유효한 사설 루트와 2년(-days 730) 유효한 리프 인증서를 사용하는 것이 합리적인 기본값입니다. 만료된 내부 인증서는 아무도 기억하지 못하는 날짜에 모든 서비스를 조용히 중단시키므로 갱신 일정을 반드시 기록해 두십시오.

자체 서명 인증서와 Let's Encrypt 중 무엇을 사용해야 하나요?

서비스에 공인 DNS 이름이 있고 인터넷에서 접근 가능하다면 항상 Let's Encrypt를 사용하십시오. 무료이며 자동화되어 있고 모든 클라이언트가 이미 신뢰합니다. 자체 서명(또는 사설 CA)은 Let's Encrypt가 발급할 수 없는 경우, 즉 사설 IP, .lan와 같은 내부 전용 호스트 이름, 외부와 차단된 네트워크, VPN 뒤에 의도적으로 숨겨진 서비스에 적합합니다. 이 결정은 보안 강도가 아닌 접근성과 이름 지정 방식에 따른 것이며, 암호화 기술 자체는 동일합니다.

/usr/local/share/ca-certificates에 추가했는데도 왜 인증서가 거부되나요?

세 가지를 확인하십시오. 파일은 반드시 .crt으로 끝나야 합니다. .pem 확장자는 무시되며 update-ca-certificates0 added을 보고합니다. 파일 내용은 DER 바이너리가 아닌 -----BEGIN CERTIFICATE-----로 시작하는 PEM 텍스트여야 합니다. 또한 애플리케이션이 실제로 시스템 저장소를 사용하는지 확인하십시오. Linux의 Chrome, Firefox, Python requests, Node.js, Java는 각각 별도의 신뢰 저장소를 유지하므로 인증서를 개별적으로 추가해야 합니다.