SSD Nodes Learn Hosting plans →
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-08-03

Jinsi ya Kutengeneza Cheti Self-Signed Ubuntu 24.04

Tengeneza cheti cha TLS self-signed kinachokubaliwa na Chrome kwenye Ubuntu 24.04, ukiwa na SAN, nginx au Apache, na uaminifu bila kutumia curl -k.

Unachojenga

Cheti cha TLS kilichojisainia chenyewe ambacho browsers na clients za kisasa hukikubali, subjectAltName sahihi, ruhusa salama za key, kimeunganishwa na nginx au Apache, pamoja na sehemu ambayo karibu kila mwongozo huiacha: kufanya clients zako zikiamini cheti hicho ipasavyo, badala ya kupita warnings kwa kubofya na kuweka curl -k moja kwa moja kwenye scripts milele. Mwishoni, kuna CA binafsi ya commands tano kwa wakati huduma moja ya ndani inapokuwa sita.

Kwanza, uamuzi, kwa sababu cheti kilichojisainia chenyewe si chaguo sahihi mara nyingi kama kinavyotumiwa. Ikiwa huduma inafikiwa kutoka public internet kwa kutumia jina halisi la DNS, acha kusoma na upate cheti cha bure cha Let's Encrypt kwa certbot kwenye nginx au sawa na hicho kwa Apache. Hakigharimu chochote, hujirenew yenyewe, na kila browser duniani tayari inakiamini. Cheti kilichojisainia chenyewe kwenye tovuti ya umma huwazoesha watumiaji wako kupita security warnings kwa kubofya, jambo ambalo ni tabia mbaya zaidi kuliko kutumia HTTP tupu.

Self-signed ndiyo chaguo sahihi wakati public internet haihusiki: admin panel iliyofungwa kwenye anwani ya WireGuard tunnel kwenye VPS yako, staging box kwenye private network, traffic ya service-to-service kati ya backends, home-lab appliance, au kubadilisha placeholder certificate ambayo Webmin hujitengenezea kwenye port 10000. Let's Encrypt haiwezi kutoa vyeti vya 10.8.0.1 au git.internal.lan hata hivyo; hakuna public CA itakayoweka private IP au TLD ya kutungwa kwenye cheti. Kwa majina hayo, wewe ndiye CA.

Kila kitu hapa kinaendeshwa kwenye fresh Ubuntu 24.04, ambayo husafirisha OpenSSL 3.0.x (openssl version ya kuthibitisha). Hakuna kinachohitaji internet access; kila kitu hufanya kazi kwenye mazingira yaliyotengwa na mtandao.

Kwa nini one-liner ya zamani huzalisha certificates ambazo Chrome hukataa

Command ambayo kila tutorial ya kabla ya 2017 hukupa huwa hivi:

# 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

Inauliza mfululizo wa maswali ya kuingiza majibu, inaweka hostname yako kwenye sehemu ya Common Name, na huzalisha certificate bila extension ya subjectAltName. Certificate hiyo haiwezi kutumiwa. Chrome iliacha kusoma Common Name katika version 58, mwezi wa Aprili 2017. RFC 2818 ilikuwa tayari imeacha kupendekeza ulinganishaji wa CN mwaka wa 2000. Firefox, Safari, curl na Python hufanya vivyo hivyo. Certificate humtambua server wake kupitia extension ya SAN; bila hiyo haitambui server. Browser hukuonyesha ujumbe huu halisi:

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.

Hakuna kiasi cha kubadili trust store kinachoweza kurekebisha error hiyo, kwa sababu certificate hiyo kwa kweli haitaji hostname yoyote. Ukiona NET::ERR_CERT_COMMON_NAME_INVALID sasa, certificate yako haina SAN au ina SAN isiyo sahihi. Unahitaji kutengeneza certificate mpya. Kwa bahati nzuri, marekebisho hayo yanahitaji command moja.

Tengeneza certificate inayokubaliwa na browsers: command moja

OpenSSL iliongeza flag ya -addext katika 1.1.1. Hivyo, huhitaji tena mbinu changamano za config file zilizotumiwa na miongozo ya zamani kuingiza SAN. Kwenye 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"

Kazi ya kila flag:

  • -x509 hutengeneza certificate ya self-signed moja kwa moja badala ya signing request.
  • -newkey rsa:4096 hutengeneza key mpya katika hatua hiyo hiyo. RSA 4096 haileti tatizo kwa client ya zamani; ikiwa kila kinachounganisha ni cha kisasa, -newkey ec -pkeyopt ec_paramgen_curve:P-256 ni ndogo na ya haraka zaidi.
  • -noenc ni uandishi wa OpenSSL 3.x wa -nodes ya zamani: hakuweki passphrase kwenye key. Miandiko yote miwili hufanya kazi. Key yenye passphrase husababisha nginx kusubiri input kila boot. Kwa hiyo, kwa server key, tumia hii.
  • -days 730, miaka miwili; tutaeleza zaidi kuhusu nambari hiyo katika sehemu ya expiry.
  • -subj hujibu maswali ya mwingiliano ndani ya command. CN sasa ni ya mapambo, lakini iweke kuwa jina kuu hata hivyo; baadhi ya tools huionyesha.
  • -addext "subjectAltName=..." ndiyo flag muhimu. Orodhesha kila jina na kila IP ambayo clients wataandika: entries za DNS: kwa hostnames (wildcards kama DNS:*.internal.lan zinaruhusiwa), na entries za IP: kwa addresses. Ikiwa mtu atafungua https://10.8.0.1, entry ya IP:10.8.0.1 lazima iwepo. SAN ya DNS pekee itasababisha NET::ERR_CERT_COMMON_NAME_INVALID hiyo hiyo tena.

Thibitisha kuwa SAN iliingizwa kwa kweli kabla ya kuunganisha kitu chochote:

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

Output sahihi:

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

Ikiwa badala yake itaonyesha No extensions in certificate, certificate haina SAN na browsers zitaikataa. Itengeneze upya badala ya kuendelea.

Funga ufunguo

Private key inayoweza kusomwa na kila mtumiaji kwenye seva si private key. Kwenye Ubuntu, /etc/ssl/private tayari ni 710 root:ssl-cert, jambo linalozuia watumiaji wengine kuisoma kwa urahisi, lakini weka ruhusa za faili lenyewe wazi:

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

nginx na Apache zote husoma certificates zikiwa root kabla ya kushusha privileges, kwa hiyo mode 600 ya root:root inazifaa. Ikiwa key ni ya huduma inayoendesha kwa user wake yenyewe na inasoma key yenyewe, kama Node app, Gitea au Python daemon, chown kwa user huyo wa huduma badala yake, huku ukiendelea kutumia mode 600. Usifanye kamwe yafuatayo: kutumia mode 644, kuweka nakala kwenye git repository, au kuweka nakala kwenye /tmp.

Iunganishe kwenye 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 lazima ichapishe syntax is ok na test is successful kabla reload haijafanya chochote. Ikiwa badala yake itachapisha SSL_CTX_use_PrivateKey_file() failed ... key values mismatch, certificate na key zilitokana na utekelezaji wa vizazi viwili tofauti; tazama sehemu ya failure-modes.

Iunganishe kwenye Apache

sudo a2enmod ssl proxy proxy_http

ssl pekee haitoshi hapa: vhost iliyo hapa chini inatumia ProxyPass, na bila mod_proxy pamoja na mod_proxy_http, jaribio la usanidi litashindwa kwa Invalid command 'ProxyPass', perhaps misspelled or defined by a module not included in the server configuration. Hifadhi vhost kama /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 inapaswa kujibu Syntax OK. Sasa fanya jaribio kutoka kwenye mashine ya mteja:

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

na utapata hitilafu:

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

Hilo si hitilafu ya programu. Hiyo ndiyo TLS inavyofanya kazi: curl haijawahi kusikia kuhusu certificate yako na inakataa kuwasiliana na server ambayo haiwezi kuthibitisha. Sehemu inayofuata ndiyo suluhisho halisi, na si mbinu ambayo nusu ya Internet inatumia kwa sasa.

Wafanye wateja waiamini, na mifumo ya usanidi ya kukataa

Anza na marekebisho yasiyofaa, ukiyataja kulingana na yalivyo. curl -k (au --insecure) iliyowekwa moja kwa moja kwenye script, verify=False katika Python requests, na NODE_TLS_REJECT_UNAUTHORIZED=0 katika Node; hakuna kati ya hivi kinachofanya certificate yako iaminike. Huzima uthibitishaji wa certificate, jambo linalomaanisha kuwa client itawasiliana kwa urahisi na server yoyote inayowasilisha certificate yoyote, hata certificate iliyowekwa na mshambuliaji kwenye njia ya mawasiliano. Unabaki na gharama ya TLS na kupoteza authentication ambayo ndiyo sababu ya kuitumia. Mbaya zaidi, flags hizi huenea: mtu huzibandika kwenye cron job moja, kisha deploy script, halafu production code, hadi hakuna anayekumbuka ni miunganisho ipi iliyokusudiwa kuwa ya muda. Ikiwa verify=False itabaki baada ya kipindi cha debugging kilichoifanya iongezwe, muundo huo si sahihi.

Marekebisho sahihi ni kuifundisha OS ya kila client kuwa certificate hii ni root inayoaminika. Kwenye clients za Ubuntu na Debian:

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

Mstari muhimu kwenye output (block ya Running hooks in /etc/ca-certificates/update.d... hufuata):

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

Kuna mambo mawili ya kuzingatia kwenye mistari hiyo. Faili lazima iishie kwa .crt; extension ya .pem hupuuzwa kimya na unapata 0 added bila ujumbe wa error. Pia, yaliyomo lazima yawe PEM; faili huanza kwa -----BEGIN CERTIFICATE-----. Kwanza badilisha binary ya DER kwa kutumia openssl x509 -inform der -in file.der -out file.crt. Kuongeza certificate iliyojisainisha yenyewe kama root hufanya kazi kwa sababu certificate iliyojisainisha yenyewe ndiyo root yake.

Baada ya hapo, curl, wget, git, apt, na kitu kingine chochote kinachotumia OpenSSL dhidi ya system bundle kitaamini server bila flags yoyote. Baadhi ya clients zina trust store zao na zinahitaji usanidi wa kila moja:

  • Chrome/Chromium kwenye Linux husoma database ya NSS, si system store: sudo apt install libnss3-tools, kisha certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "git.internal" -i git.internal.crt kwa kila user.
  • Firefox ina store yake: Settings → Privacy & Security → Certificates → Import, au badilisha security.enterprise_roots.enabled kuwa true katika about:config ili isome system store.
  • Python requests huja na CA bundle yake (certifi) na hupuuza system store: pitisha verify="/usr/local/share/ca-certificates/git.internal.crt" au export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt.
  • Node.js: export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/git.internal.crt.

Kwenye clients za Windows, bofya mara mbili .crt na uisakinishe kwenye Trusted Root Certification Authorities; kwenye macOS, iongeze kwenye System keychain kupitia Keychain Access na uiweke kuwa Always Trust.

Root moja kwa huduma nyingi: CA ndogo ya faragha

Uaminifu wa kila certificate kivyake hauwezi kuendelea kuongezeka kwa urahisi: huduma sita mara mashine nne za wateja ni usakinishaji 24 wa trust, na kila huduma mpya huongeza usakinishaji mwingine. Suluhisho ni CA ya faragha. Wateja huiamini root moja, kisha unasaini certificate ya kila huduma kwa kuitumia.

Chaguo rahisi ni mkcert, ambayo inapatikana kwenye repos za Ubuntu 24.04 na hushughulikia NSS stores za Chrome na Firefox ambazo update-ca-certificates huzikosa:

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

mkcert -install huunda root na kuisajili katika kila trust store kwenye mashine hiyo. Command ya tatu hutoa git.internal.lan+2.pem na git.internal.lan+2-key.pem, ambazo ziko tayari kuwekwa kwenye snippets za nginx au Apache hapo juu. Muundo wake unalenga mashine ya development. Root key huhifadhiwa kwenye box iliyotumia -install. Kwa hiyo inafaa sana kwa laptop ya development, lakini si muundo unaofaa kwa kundi la servers.

Kwa servers, OpenSSL ya kawaida hukamilisha CA nzima kwa commands tano:

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

Tatizo liko kwenye command ya mwisho: openssl x509 -req huondoa extensions zote kwenye CSR kwa chaguo-msingi, pamoja na SAN uliyoiongeza kwa uangalifu. -copy_extensions copy ni option ya OpenSSL 3.x, kwa hiyo inafanya kazi kwenye 24.04, na huhamisha extensions hizo. Ukiiacha, certificate iliyosainiwa haitakuwa na SAN, na Chrome itakuonyesha NET::ERR_CERT_COMMON_NAME_INVALID tena. Thibitisha kwa check ileile ya openssl x509 -noout -ext subjectAltName kama hapo awali.

Sambaza lab-ca.crt kwa wateja kwa kutumia hatua za trust-store zilizo hapo juu, mara moja kwa kila mashine. Linda lab-ca.key kwa uangalifu mkubwa: tumia mode 600, na ikiwezekana ihifadhiwe kwenye box ambayo si mojawapo ya servers inazozisainia certificates. Mtu yeyote aliye nayo anaweza kuunda certificate ya jina lolote ambalo wateja wako watalikubali.

Muda wa kuisha na mzunguko

Muda wa uhalali wa certificates za CA za umma unapungua. CA/Browser Forum iliweka kikomo cha certificates mpya zinazoaminika hadharani kuwa siku 200 mwezi Machi 2026, kutoka siku 398. Kikomo hicho kitapungua hadi siku 100 mwaka 2027 na siku 47 kufikia Machi 2029. Hata hivyo, sheria hizo zinawahusu publicly trusted CAs. Private CA yako haiongozwi na sheria hizo, na browsers hazilazimishi kwa roots zilizosakinishwa manually. Sharti moja la vitendo linatumika: platforms za Apple hukataa TLS server certificate yenye uhalali unaozidi siku 825, bila kujali aliyeitoa. Kwa hiyo, ikiwa iPhones au Macs zitaunganishwa, weka leaf certificates katika muda wa miaka miwili au chini. -days 730 inatimiza sharti hilo kila mahali. Root ya miaka kumi yenye leaves za miaka miwili ni muundo unaofaa kwa matumizi ya ndani.

Certificates zenye muda mrefu wa uhalali hushindwa kwa njia moja tu: zote huisha kimya kimya kwa wakati mmoja, katika tarehe ambayo hakuna anayekumbuka kuichagua. Kagua ulivyo navyo:

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

Weka renewal kwenye kalenda halisi, au tumia cron ikutaarifu siku 30 kabla. openssl x509 -checkend 2592000 -in cert.crt hutoka kwa hali isiyo ya sifuri pindi muda wa kuisha unapokaribia ndani ya idadi hiyo ya sekunde. Ikiwa tayari unaendesha Uptime Kuma kwa ufuatiliaji wa hali, HTTPS monitors zake huonyesha bila malipo kwamba certificate inakaribia kuisha.

Mzunguko wa certificates kwa private CA ni rahisi: endesha tena commands za CSR-and-sign, badilisha files, kisha reload web server. Root haijabadilika, kwa hiyo hakuna client inayogundua mabadiliko.

Aina za kushindwa, pamoja na mifuatano utakayoiona

NET::ERR_CERT_AUTHORITY_INVALID, ni hali inayotarajiwa kabla ya kusakinisha trust; si kasoro kwenye certificate. Ikiendelea baada ya kusakinisha root: kwenye Linux, Chrome husoma NSS badala ya system store (tazama hatua ya certutil); au faili lililonakiliwa halikuishia kwenye .crt na update-ca-certificates ilisema 0 added; au server inawasilisha certificate tofauti na uliyoiamini. Linganisha fingerprints kwa openssl s_client -connect git.internal.lan:443 </dev/null 2>/dev/null | openssl x509 -noout -fingerprint -sha256.

NET::ERR_CERT_COMMON_NAME_INVALID, certificate haina SAN, au SAN haihusishi jina lililo kwenye address bar. Hali ya kawaida ni hii: SAN inaorodhesha DNS:git.internal.lan lakini mtumiaji amefungua https://10.8.0.1. Mabadiliko ya trust store hayawezi kurekebisha tatizo hili; toa certificate mpya yenye entry iliyokosekana.

curl: (60) SSL certificate problem: self-signed certificate, curl haiamini certificate. Toleo la self-signed certificate in certificate chain lina maana hiyo hiyo kwa certificate iliyotiwa saini na private CA yako. Marekebisho ya mara moja: curl --cacert lab-ca.crt https://...; marekebisho ya kudumu: trust store. Usitumie -k.

unable to load certificate ... Expecting: TRUSTED CERTIFICATE (au Expecting: CERTIFICATE REQUEST, au no start line), kuna mkanganyiko wa PEM. Uliipa OpenSSL aina isiyo sahihi ya faili: key au CSR mahali ilipotarajia certificate, au binary ya DER mahali ilipotarajia PEM. head -1 filename hukuonyesha ulicho nacho; certificate huanza na -----BEGIN CERTIFICATE-----. Kwa DER, badilisha kwa openssl x509 -inform der -in file.der -out file.crt.

nginx: [emerg] SSL_CTX_use_PrivateKey_file(...) failed (SSL: error ... key values mismatch), certificate na key si za jozi moja, kwa kawaida kwa sababu command ya kuzitengeneza iliendeshwa mara mbili na mafaili yakachanganywa. Thibitisha kwa kulinganisha openssl x509 -in git.internal.crt -noout -pubkey | sha256sum na openssl pkey -in git.internal.key -pubout | sha256sum; hashes zinazolingana zinaonyesha jozi inayolingana. Zikitofautiana, tengeneza zote mbili upya pamoja.

FAQ

Kwa nini Chrome bado inaonyesha "Not secure" baada ya kuunda certificate ya self-signed?

Ikiwa kosa ni NET::ERR_CERT_AUTHORITY_INVALID, certificate iko sawa; Chrome haina sababu ya kuiamini bado. Isakinishe, au sakinisha root ya private CA, kwenye trust store ya client. Kumbuka kuwa kwenye Linux, Chrome hutumia database ya NSS kupitia certutil, si system store. Ikiwa kosa ni NET::ERR_CERT_COMMON_NAME_INVALID, certificate haina Subject Alternative Name inayolingana na URL na lazima itolewe upya kwa kutumia -addext "subjectAltName=...".

Ninawezaje kufanya curl iamini certificate ya self-signed bila kutumia -k?

Nakili certificate katika umbizo la PEM, yenye extension ya .crt, hadi /usr/local/share/ca-certificates/, kisha endesha sudo update-ca-certificates. Output lazima iseme 1 added. Kuanzia hapo, curl itaithibitisha kama certificate yoyote ya umma. Kwa ombi la mara moja bila kubadili mfumo, curl --cacert /path/to/cert.crt huthibitisha kwa kutumia faili hiyo pekee. -k huzima uthibitishaji kabisa na haipaswi kuwekwa kwenye scripts za mtu yeyote.

Certificate ya self-signed inaweza kuwa halali kwa muda gani?

Kitaalamu, inaweza kuwa halali kwa muda wowote unaotaka. Vizuizi vya CA/Browser Forum, yaani siku 200 kwa sasa na siku 47 kufikia 2029, vinawahusu CAs zinazoaminika hadharani, si trust ya ndani. Kwa matumizi ya kawaida, zuia certificates za seva zisitumike zaidi ya siku 825, kwa sababu vifaa vya Apple hukataa certificate ndefu zaidi bila kujali issuer. Root ya private ya miaka 10 pamoja na leaf certificates za miaka 2 (-days 730) ni chaguo linalofaa. Weka tarehe ya renewal kwenye kalenda, kwa sababu certificate ya ndani ikiisha muda inaweza kusababisha kila kitu kisifanye kazi bila taarifa kwenye tarehe ambayo hakuna anayokumbuka.

Je, nitumie certificate ya self-signed au Let's Encrypt?

Ikiwa huduma ina public DNS name na inaweza kufikiwa kutoka Internet, tumia Let's Encrypt kila wakati. Ni ya bure, ina automation, na tayari inaaminika na kila client. Certificate ya self-signed, au private CA, ni ya hali ambazo Let's Encrypt haiwezi kutoa certificate: private IPs, hostnames za ndani pekee kama .lan, mitandao isiyounganishwa na nje, na huduma zilizofichwa kwa makusudi nyuma ya VPN. Uamuzi unategemea reachability na naming, si nguvu ya usalama. Cryptography ni ileile.

Kwa nini certificate yangu inakataliwa hata baada ya kuiongeza kwenye /usr/local/share/ca-certificates?

Kagua mambo matatu. Jina la faili lazima liishie kwa .crt. Extension ya .pem hurukwa kimya kimya, na update-ca-certificates huripoti 0 added. Maudhui lazima yawe maandishi ya PEM yanayoanza na -----BEGIN CERTIFICATE-----, si binary ya DER. Pia, application lazima itumie system store. Chrome kwenye Linux, Firefox, Python requests, Node.js na Java kila moja huhifadhi trust store yake binafsi, hivyo certificate lazima iongezwe kando kwenye kila moja.