SSD Nodes Learn Hosting plans →
गाइड Matt Connorलेखक: Matt Connor · अपडेट किया गया: 2026-08-07

Ubuntu 24.04 पर self-signed TLS certificate कैसे बनाएं

Ubuntu 24.04 पर Chrome द्वारा स्वीकार्य self-signed TLS certificate बनाने का सही तरीका जानें। SAN के साथ openssl कमांड, nginx कॉन्फ़िगरेशन और बिना -k के ट्रस्ट सेटअप करें।

आप क्या बना रहे हैं

एक self-signed TLS certificate जिसे आधुनिक browsers और clients वास्तव में स्वीकार करते हैं, सही subjectAltName, उचित key permissions, जिसे nginx या Apache में एकीकृत किया गया है, और वह हिस्सा जिसे लगभग हर guide छोड़ देती है: अपने clients को इसे सही ढंग से trust करना सिखाना, बजाय इसके कि आप warnings को ignore करें और scripts में हमेशा के लिए curl -k को hard-code करें। अंत में, जब एक internal service छह बन जाए, तो उसके लिए पांच-command वाली एक private CA।

सबसे पहले, निर्णय लें, क्योंकि self-signed certificate का उपयोग उतनी बार नहीं किया जाना चाहिए जितनी बार किया जाता है। यदि service एक वास्तविक DNS name के तहत public internet से पहुंच योग्य है, तो इसे पढ़ना बंद करें और इसके बजाय nginx पर certbot के साथ एक मुफ्त Let's Encrypt certificate या Apache के लिए समकक्ष प्राप्त करें। यह मुफ्त है, खुद renew होता है, और दुनिया का हर browser पहले से ही इस पर भरोसा करता है। एक public site पर self-signed certificate का उपयोग आपके users को security warnings को ignore करने के लिए प्रशिक्षित करता है, जो plain HTTP से भी बुरी आदत है।

Self-signed तब सही विकल्प है जब public internet का कोई उपयोग न हो: जैसे आपके VPS पर WireGuard tunnel address से जुड़ा admin panel, private network पर एक staging box, backends के बीच service-to-service traffic, एक home-lab appliance, या उस placeholder certificate को बदलना जिसे Webmin port 10000 पर खुद generate करता है। Let's Encrypt वैसे भी 10.8.0.1 या git.internal.lan के लिए certificate जारी नहीं कर सकता, कोई भी public CA certificate में private IP या मनगढ़ंत TLD नहीं डालेगा। उन नामों के लिए, आप ही CA हैं।

नीचे दी गई हर चीज़ एक नए Ubuntu 24.04 box पर चलती है, जिसमें OpenSSL 3.0.x (पुष्टि करने के लिए openssl version) शामिल है। यहाँ किसी भी चीज़ के लिए internet access की आवश्यकता नहीं है; यह सब air-gapped वातावरण में काम करता है।

पुराना one-liner ऐसे certs क्यों बनाता है जिन्हें 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

यह आपसे कई इंटरैक्टिव प्रश्न पूछती है, आपके hostname को Common Name फ़ील्ड में डालती है, और एक ऐसा सर्टिफिकेट बनाती है जिसमें कोई subjectAltName एक्सटेंशन नहीं होता। वह सर्टिफिकेट पूरी तरह से बेकार है। Chrome ने वर्ज़न 58 में, अप्रैल 2017 में 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 नहीं है (या गलत है) और आपको एक नया सर्टिफिकेट बनाना होगा। सौभाग्य से, इसका समाधान केवल एक कमांड है।

ऐसा सर्टिफिकेट बनाएँ जिसे ब्राउज़र स्वीकार करें: एक कमांड

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 साइनिंग रिक्वेस्ट के बजाय सीधे एक सेल्फ-साइन्ड सर्टिफिकेट जारी करता है।
  • -newkey rsa:4096 उसी चरण में एक नई की (key) बनाता है। RSA 4096 किसी भी पुराने क्लाइंट को प्रभावित नहीं करता; यदि कनेक्ट होने वाले सभी क्लाइंट आधुनिक हैं, तो -newkey ec -pkeyopt ec_paramgen_curve:P-256 छोटा और तेज़ है।
  • -noenc पुराने -nodes का OpenSSL 3.x संस्करण है: की (key) पर कोई पासफ़्रेज़ नहीं। दोनों स्पेलिंग काम करती हैं। पासफ़्रेज़ वाली की का मतलब है कि Nginx हर बूट पर इनपुट के लिए इंतज़ार करेगा, इसलिए सर्वर की के लिए आपको इसकी आवश्यकता है।
  • -days 730, दो वर्ष; उस संख्या के बारे में अधिक जानकारी समाप्ति अनुभाग में दी गई है।
  • -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 नहीं है और ब्राउज़र इसे अस्वीकार कर देंगे, आगे बढ़ने के बजाय इसे फिर से बनाएँ।

Key को सुरक्षित करें

यदि सर्वर पर मौजूद कोई भी user private key को पढ़ सकता है, तो वह private key नहीं है। 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 दोनों ही privileges छोड़ने से पहले root के रूप में certificates को पढ़ते हैं, इसलिए उनके लिए root:root mode 600 काम करता है। यदि key किसी ऐसी service के लिए है जो अपने स्वयं के user के रूप में चलती है और key को स्वयं लोड करती है, जैसे कि Node app, Gitea, या Python daemon, तो इसके बजाय इसे उस service user को chown करें, और mode 600 ही रखें। जो आपको कभी नहीं करना चाहिए: mode 644 का उपयोग, git repository में copy रखना, या /tmp में copy रखना।

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 को reload करने से पहले syntax is ok और test is successful प्रिंट करना चाहिए। यदि इसके बजाय SSL_CTX_use_PrivateKey_file() failed ... key values mismatch प्रिंट होता है, तो इसका मतलब है कि certificate और key दो अलग-अलग generation runs से हैं, इसके लिए failure-modes सेक्शन देखें।

इसे Apache के साथ जोड़ें

sudo a2enmod ssl proxy proxy_http

यहाँ केवल ssl पर्याप्त नहीं है: नीचे दिया गया vhost ProxyPass का उपयोग करता है, और mod_proxy तथा mod_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

configtest को Syntax 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 का ओवरहेड तो बनाए रखते हैं लेकिन वह ऑथेंटिकेशन खो देते हैं जो इसका मुख्य उद्देश्य था। इससे भी बुरा यह है कि ये फ्लैग्स फैलते जाते हैं: एक cron job में पेस्ट किए गए, फिर एक deploy स्क्रिप्ट में, फिर प्रोडक्शन कोड में, जब तक कि किसी को याद न रहे कि कौन से कनेक्शन अस्थायी होने चाहिए थे। यदि कोई 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 का अपना स्टोर है: Settings → Privacy & Security → Certificates → Import, या about:config में security.enterprise_roots.enabled को true पर सेट करें ताकि यह सिस्टम स्टोर को पढ़ सके।
  • 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 पर डबल-क्लिक करें और इसे Trusted Root Certification Authorities में इंस्टॉल करें; macOS पर, इसे Keychain Access में System कीचेन में जोड़ें और इसे Always Trust के रूप में मार्क करें।

कई सेवाओं के लिए एक root: एक छोटा private CA

प्रति-प्रमाणपत्र (per-certificate) विश्वास का मॉडल तुरंत ही बड़े पैमाने पर विफल हो जाता है: छह सेवाएँ और चार client मशीनें होने पर चौबीस बार trust install करना पड़ता है, और हर नई सेवा के साथ यह संख्या बढ़ती जाती है। इसका समाधान एक private CA है, जहाँ client केवल एक root पर भरोसा करते हैं, और आप प्रत्येक सेवा के प्रमाणपत्र को उसी से sign करते हैं।

सबसे सरल विकल्प mkcert है, जो Ubuntu 24.04 के repos में उपलब्ध है और उन NSS stores (Chrome, Firefox) को भी संभालता है जिन्हें update-ca-certificates छोड़ देता है:

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

mkcert -install एक root बनाता है और उसे उस मशीन के हर trust store में पंजीकृत करता है; तीसरा कमांड git.internal.lan+2.pem और git.internal.lan+2-key.pem जारी करता है, जो ऊपर दिए गए nginx या Apache snippets में उपयोग के लिए तैयार होते हैं। इसका डिज़ाइन एक development मशीन के लिए है, जहाँ root key उसी बॉक्स पर रहती है जिसने -install चलाया था, इसलिए यह dev laptop के लिए तो सही है लेकिन सर्वर फ्लीट के लिए उपयुक्त नहीं है।

सर्वर के लिए, सामान्य OpenSSL पाँच कमांड में पूरा 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 से सभी extensions हटा देता है, जिसमें आपके द्वारा सावधानीपूर्वक जोड़ा गया SAN भी शामिल है। -copy_extensions copy (एक OpenSSL 3.x विकल्प, जो 24.04 पर काम करता है) उन्हें बरकरार रखता है; यदि आप इसे छोड़ देते हैं, तो signed प्रमाणपत्र में कोई SAN नहीं होगा, और Chrome आपको फिर से NET::ERR_CERT_COMMON_NAME_INVALID दिखाएगा। पहले की तरह ही openssl x509 -noout -ext subjectAltName चेक के साथ इसकी पुष्टि करें।

lab-ca.crt को ऊपर बताए गए trust-store चरणों के माध्यम से client मशीनों पर वितरित करें, यह काम हर मशीन पर केवल एक बार करना है। lab-ca.key की सुरक्षा वैसे ही करें जैसे आप सबसे कीमती चीज़ की करते हैं: mode 600 रखें, और आदर्श रूप से इसे उस बॉक्स पर रखें जो उन सर्वरों में से नहीं है जिनके लिए यह sign करता है, क्योंकि जिसके पास यह key है, वह किसी भी नाम के लिए प्रमाणपत्र बना सकता है जिस पर आपके client भरोसा करेंगे।

समाप्ति और रोटेशन

Public CA certificate की वैधता अवधि कम होती जा रही है। CA/Browser Forum ने मार्च 2026 में नए जारी किए गए publicly trusted certificates की सीमा 200 दिन (398 दिन से कम) तय की है, जो 2027 में 100 दिन और मार्च 2029 तक 47 दिन हो जाएगी। हालाँकि, ये नियम केवल publicly trusted CAs पर लागू होते हैं। आपका private CA इन नियमों से बंधा नहीं है और browsers manually installed roots के लिए इन्हें लागू नहीं करते हैं। एक वास्तविक सीमा जरूर लागू होती है: Apple platforms किसी भी ऐसे TLS server certificate को अस्वीकार कर देते हैं जो 825 दिनों से अधिक वैध हो, चाहे उसे किसी ने भी जारी किया हो। इसलिए, यदि iPhones या Macs कनेक्ट होंगे, तो leaf certificates को दो साल या उससे कम पर रखें। -days 730 हर जगह इस सीमा को पूरा करता है; दस साल का root और दो साल के leaves एक सुविधाजनक आंतरिक संरचना है।

लंबे समय तक चलने वाले certificates केवल एक ही तरीके से विफल होते हैं: चुपचाप, एक साथ, उस तारीख पर जिसे चुनना किसी को याद नहीं रहता। जाँचें कि आपके पास क्या है:

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

नवीनीकरण (renewal) को वास्तविक कैलेंडर में दर्ज करें, या cron से 30 दिन पहले सूचना प्राप्त करें। यदि समाप्ति की अवधि निर्धारित सेकंड के भीतर हो, तो openssl x509 -checkend 2592000 -in cert.crt non-zero exit code देता है। यदि आप पहले से ही status monitoring के लिए Uptime Kuma चला रहे हैं, तो इसके HTTPS monitors बिना किसी अतिरिक्त शुल्क के certificate की समाप्ति तिथि निकट आने पर चेतावनी दे देते हैं।

Private CA के साथ रोटेशन काफी सरल प्रक्रिया है: CSR-and-sign commands को फिर से चलाएं, फाइलों को बदलें और web server को reload करें। Root में कोई बदलाव नहीं हुआ है, इसलिए किसी भी client को इसका पता नहीं चलता है।

विफलता के प्रकार और दिखाई देने वाले संदेश

NET::ERR_CERT_AUTHORITY_INVALID, यह trust स्थापित करने से पहले की अपेक्षित स्थिति है, न कि certificate में कोई दोष। यदि यह root install करने के बाद भी बना रहता है, तो इसके कारण ये हो सकते हैं: Linux पर Chrome सिस्टम स्टोर के बजाय NSS को पढ़ता है (certutil चरण देखें); या कॉपी की गई फ़ाइल .crt पर समाप्त नहीं हुई और update-ca-certificates ने 0 added दिखाया; या सर्वर उस certificate के बजाय कोई अन्य certificate प्रस्तुत कर रहा है जिस पर आपने भरोसा किया है, तो openssl s_client -connect git.internal.lan:443 </dev/null 2>/dev/null | openssl x509 -noout -fingerprint -sha256 के साथ fingerprints की तुलना करें।

NET::ERR_CERT_COMMON_NAME_INVALID, certificate में कोई SAN नहीं है, या SAN एड्रेस बार में दिए गए नाम को कवर नहीं करता है। सामान्य स्थिति: SAN में DNS:git.internal.lan सूचीबद्ध है लेकिन उपयोगकर्ता https://10.8.0.1 पर गया है। Trust-store में बदलाव इसे ठीक नहीं कर सकते; छूटे हुए entry के साथ इसे पुनः जारी (reissue) करें।

curl: (60) SSL certificate problem: self-signed certificate, curl certificate पर भरोसा नहीं करता है। variant self-signed certificate in certificate chain का अर्थ आपके private CA द्वारा हस्ताक्षरित certificate के लिए भी यही है। एक बार का समाधान: curl --cacert lab-ca.crt https://...; स्थायी समाधान: trust store। -k का उपयोग न करें।

unable to load certificate ... Expecting: TRUSTED CERTIFICATE (या Expecting: CERTIFICATE REQUEST, या no start line), PEM भ्रम। आपने OpenSSL को गलत प्रकार की फ़ाइल दी है: एक key या CSR जहाँ certificate की अपेक्षा थी, या DER बाइनरी जहाँ PEM की अपेक्षा थी। head -1 filename आपको बताता है कि आपके पास वास्तव में क्या है, एक certificate -----BEGIN CERTIFICATE----- से शुरू होता है। DER के लिए, openssl x509 -inform der -in file.der -out file.crt के साथ convert करें।

nginx: [emerg] SSL_CTX_use_PrivateKey_file(...) failed (SSL: error ... key values mismatch), certificate और key एक-दूसरे से संबंधित नहीं हैं, आमतौर पर ऐसा तब होता है जब generation command दो बार चलाई गई हो और फ़ाइलें आपस में मिल गई हों। openssl x509 -in git.internal.crt -noout -pubkey | sha256sum बनाम openssl pkey -in git.internal.key -pubout | sha256sum के साथ पुष्टि करें; मेल खाते hashes का मतलब है कि वे एक सही जोड़ी हैं। यदि वे भिन्न हैं, तो दोनों को एक साथ पुनः उत्पन्न (regenerate) करें।

FAQ

self-signed certificate बनाने के बाद भी Chrome "Not secure" क्यों दिखाता है?

यदि error NET::ERR_CERT_AUTHORITY_INVALID है, तो certificate सही है, Chrome के पास अभी उस पर भरोसा करने का कोई कारण नहीं है। इसे (या अपने private CA root को) client के trust store में install करें। याद रखें कि Linux पर Chrome system store के बजाय certutil के माध्यम से NSS database का उपयोग करता है। यदि error NET::ERR_CERT_COMMON_NAME_INVALID है, तो certificate में URL से मेल खाने वाला Subject Alternative Name नहीं है। इसे -addext "subjectAltName=..." के साथ फिर से जारी (reissue) करना होगा।

मैं -k के बिना curl को self-signed certificate पर भरोसा करने के लिए कैसे कहूँ?

Certificate (PEM format, .crt extension) को /usr/local/share/ca-certificates/ में copy करें और sudo update-ca-certificates चलाएं। output में 1 added दिखना चाहिए। इसके बाद curl इसे किसी भी public certificate की तरह verify करेगा। system को प्रभावित किए बिना एक बार के request के लिए, curl --cacert /path/to/cert.crt केवल उस file के आधार पर verification करता है। -k verification को पूरी तरह से disable कर देता है और इसे किसी की भी scripts में इस्तेमाल नहीं करना चाहिए।

एक self-signed certificate कितने समय तक valid रह सकता है?

तकनीकी रूप से आप जितना चाहें उतना समय रख सकते हैं। CA/Browser Forum की सीमाएं (अब 200 दिन, 2029 तक 47 दिन) केवल publicly trusted CA पर लागू होती हैं, private trust पर नहीं। व्यावहारिक रूप से, server certificates को 825 दिनों तक ही सीमित रखें, क्योंकि Apple devices issuer की परवाह किए बिना इससे अधिक अवधि वाले किसी भी certificate को reject कर देते हैं। दो साल (-days 730) के leaf certificates के साथ दस साल का private root एक उचित default है। बस renewal के लिए calendar में reminder लगा लें, क्योंकि expired internal cert किसी भी ऐसी तारीख पर सब कुछ चुपचाप बंद कर सकता है जिसे कोई याद नहीं रखता।

मुझे self-signed certificate का उपयोग करना चाहिए या Let's Encrypt का?

यदि service का public DNS name है और वह internet से reachable है, तो हमेशा Let's Encrypt का उपयोग करें। यह मुफ्त है, स्वचालित है, और हर client द्वारा पहले से ही trusted है। Self-signed (या private CA) उन चीजों के लिए है जिन्हें Let's Encrypt जारी नहीं कर सकता: private IP, केवल internal उपयोग वाले hostnames जैसे .lan, air-gapped networks, और जानबूझकर VPN के पीछे छिपी services। यह निर्णय reachability और naming के बारे में है, security strength के बारे में नहीं; cryptography दोनों में समान है।

/usr/local/share/ca-certificates में जोड़ने के बाद भी मेरा certificate क्यों reject हो जाता है?

तीन चीजों की जाँच करें। File का अंत .crt पर होना चाहिए; .pem extension को चुपचाप छोड़ दिया जाता है और update-ca-certificates पर 0 added report होता है। सामग्री PEM text होनी चाहिए जो -----BEGIN CERTIFICATE----- से शुरू हो, न कि DER binary। और application को वास्तव में system store का उपयोग करना चाहिए। Linux पर Chrome, Firefox, Python requests, Node.js, और Java प्रत्येक अपना एक private trust store रखते हैं और उनमें certificate को अलग से जोड़ने की आवश्यकता होती है।