In diesem Abschnitt wird die Ausstellung eines TLS-Serverzertifikats durch die interne Intermediate-CA sowie dessen Einbindung in einen Apache-Webserver beschrieben.
Ziel ist der Aufbau einer funktionsfähigen HTTPS-Verbindung auf Basis der zuvor erstellten internen PKI. Dabei wird ein Serverzertifikat mit Subject Alternative Names (SANs) erzeugt, durch die Intermediate-CA signiert und anschließend im Apache-Webserver verwendet.
Der Abschnitt behandelt insbesondere:
- Erstellung eines privaten Server-Schlüssels
- Erstellung eines Certificate Signing Requests (CSR) mit SANs
- Signierung des CSRs durch die Intermediate-CA
- Einbindung von Serverzertifikat, privatem Schlüssel und Zertifikatskette in Apache
- Validierung der TLS-Verbindung
- Import der Root-CA in Client-Vertrauensspeicher
Die Root-CA bleibt während dieses Vorgangs offline. Die Ausstellung des Serverzertifikats erfolgt ausschließlich über die operative Intermediate-CA.
Ausgangssituation und Voraussetzungen
Für die folgenden Schritte wird vorausgesetzt, dass die zuvor beschriebenen Komponenten bereits vorhanden und funktionsfähig eingerichtet wurden:
- Eine Offline-Root-CA auf Basis von OpenSSL
- Eine operative Intermediate-CA
- Eine gültige Zertifikatskette (Root-CA + Intermediate-CA)
- Ein Linux-System mit installiertem Apache-Webserver
- Funktionierende DNS-Auflösung oder entsprechende Hosts-Dateien für die Testdomäne
Im Beispiel wird folgende Testumgebung verwendet:
| Komponente | Funktion |
|---|---|
| Root-CA | Offline Root Certification Authority |
| Intermediate-CA | Operative Intermediate-CA |
| pki-webserver-test | Apache-Testserver |
| testpki.local | Testdomäne |
| www.testpki.local | Zusätzlicher DNS-Alias |
Erstellung der TLS-Verzeichnisstruktur auf dem Webserver
Zur sauberen Trennung der TLS- und PKI-Komponenten wird auf dem Webserver eine eigene Verzeichnisstruktur unterhalb von /etc/ssl angelegt. Die systemseitigen OpenSSL-Verzeichnisse des Betriebssystems bleiben dabei unverändert.
Verzeichnisstruktur erstellen:
$ sudo mkdir -p /etc/ssl/testpki/{private,csr,certs,chain}
Zugriffsrechte für private Schlüssel setzen:
$ sudo chmod 700 /etc/ssl/testpki/private
Verzeichnisstruktur prüfen:
$ pronto@pki-webserver-test:/etc/ssl$ sudo tree -L 1 testpki/
testpki/
├── certs
├── chain
├── csr
└── private
5 directories, 0 file
Zweck der einzelnen Verzeichnisse:
certs: Speicherung ausgestellter Serverzertifikatechain: Speicherung von Zertifikatsketten und CA-Chain-Dateiencsr: Speicherung von Certificate Signing Requestsprivate: Speicherung privater Schlüssel
Erstellung des privaten Server-Schlüssels (Webserver)
Der Apache-Webserver benötigt einen privaten Schlüssel zur späteren TLS-Kommunikation.
Im Gegensatz zu CA-Schlüsseln wird der private Schlüssel eines Webservers üblicherweise nicht zusätzlich mit einer Passphrase geschützt, da der Webserver beim Systemstart automatisiert auf den Schlüssel zugreifen können muss.
Generierung des privaten Schlüssels:
$ sudo openssl genrsa \
-out /etc/ssl/testpki/private/testpki.local.key.pem \
4096
Zugriffsrechte setzen:
$ sudo chmod 600 /etc/ssl/testpki/private/testpki.local.key.pem
Eigenschaften des Schlüssels:
Der erzeugte Schlüssel besitzt folgende Eigenschaften:
- RSA-Schlüssel mit 4096 Bit
- Unverschlüsselte Speicherung (Keine Passphrase)
- Ausschließlicher Zugriff für
root - Verwendung für TLS-Serverauthentifizierung
Erstellung eines Certificate Signing Requests (CSR) mit Subject Alternative Names (Webserver)
Für die Ausstellung eines TLS-Serverzertifikats wird ein Certificate Signing Request (CSR) erzeugt. Moderne TLS-Clients validieren Servernamen primär über sogenannte Subject Alternative Names (SANs). Der Common Name (CN) allein ist für aktuelle Browser und TLS-Implementierungen nicht mehr ausreichend.
Die gewünschten DNS-Namen müssen daher explizit innerhalb des CSRs definiert werden.
Erstellung einer OpenSSL-Konfigurationsdatei für den CSR:
$ sudo vi /etc/ssl/testpki/csr/testpki.local.cnf
[ req ]
default_bits = 4096
prompt = no
default_md = sha512
req_extensions = req_ext
distinguished_name = dn
[ dn ]
C = DE
O = Prontosystems
OU = Webserver
CN = testpki.local
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = testpki.local
DNS.2 = www.testpki.local
Erstellung des CSRs:
$ sudo openssl req \
-new \
-key /etc/ssl/testpki/private/testpki.local.key.pem \
-out /etc/ssl/testpki/csr/testpki.local.csr.pem \
-config /etc/ssl/testpki/csr/testpki.local.cnf
CSR prüfen:
$ sudo openssl req \
-in /etc/ssl/testpki/csr/testpki.local.csr.pem \
-noout -text
Wichtiger Abschnitt der Ausgabe:
X509v3 Subject Alternative Name:
DNS:testpki.local, DNS:www.testpki.local
Übertragung des CSRs zur Intermediate-CA
Speicherort des CSRs auf dem Webserver:
/etc/ssl/testpki/csr/testpki.local.csr.pem
Beispielhafte Übertragung mittels SCP:
$ scp /etc/ssl/testpki/csr/testpki.local.csr.pem \
pki@intermediateca:/home/pki/intermediate-ca/csr/
Signierung des Serverzertifikats durch die Intermediate-CA
Die eigentliche Ausstellung des TLS-Serverzertifikats erfolgt auf der operativen Intermediate-CA. Hierbei wird der zuvor erzeugte CSR geprüft und anschließend durch die Intermediate-CA signiert.
Signierung des Serverzertifikats:
$ openssl ca \
-config ~/intermediate-ca/openssl.cnf \
-extensions server_cert \
-days 1 \
-notext \
-md sha512 \
-in ~/intermediate-ca/csr/testpki.local.csr.pem \
-out ~/intermediate-ca/issued/testpki.local.cert.pem
Bedeutung der verwendeten Parameter:
-extensions server_cert: Verwendung des Server-Zertifikatprofils-days 1: Laufzeit des Zertifikats-md sha512: Verwendung von SHA-512-notext: Kompaktere Zertifikatsausgabe
Eigenschaften des Server-Zertifikatprofils:
Das in der Intermediate-CA definierte Profil server_cert enthält unter anderem:
CA:FALSEserverAuthDigital SignatureKey Encipherment
Dadurch wird sichergestellt, dass das Zertifikat ausschließlich für TLS-Serverauthentifizierung verwendet werden kann.
Beispielhafte Bestätigungsabfragen:
- Passphrase des Intermediate-CA-Schlüssels
- Bestätigung der Zertifikatsausstellung
- Aktualisierung der CA-Datenbank
Übertragung des ausgestellten Serverzertifikats auf den Webserver
Nach erfolgreicher Signierung wird das ausgestellte Serverzertifikat zurück auf den Apache-Webserver übertragen.
Zusätzlich wird die CA-Chain-Datei benötigt, damit TLS-Clients die vollständige Zertifikatskette validieren können.
Verwendete Dateien:
testpki.local.cert.pem: Ausgestelltes Serverzertifikatca-chain.cert.pem: Zertifikatskette aus Intermediate- und Root-CA
Speicherorte auf der Intermediate-CA:
~/intermediate-ca/issued/testpki.local.cert.pem~/intermediate-ca/chain/ca-chain.cert.pem
Zielverzeichnisse auf dem Webserver:
/etc/ssl/testpki/certs//etc/ssl/testpki/chain/
Einbindung des Serverzertifikats in Apache
Für die Nutzung von HTTPS muss zunächst das Apache-SSL-Modul aktiviert werden.
Aktivierung des SSL-Moduls:
$ sudo a2enmod ssl
Beispielhafte TLS-Konfiguration innerhalb eines HTTPS-VirtualHosts:
Die allgemeine Apache- und VirtualHost-Konfiguration wird hierbei als bereits vorhanden vorausgesetzt.
<VirtualHost *:443>
ServerName testpki.local
ServerAlias www.testpki.local
SSLEngine on
SSLCertificateFile /etc/ssl/testpki/certs/testpki.local.cert.pem
SSLCertificateKeyFile /etc/ssl/testpki/private/testpki.local.key.pem
SSLCertificateChainFile /etc/ssl/testpki/chain/ca-chain.cert.pem
</VirtualHost>
Bedeutung der TLS-Direktiven:
SSLEngine on: Aktivierung von TLSSSLCertificateFile: ServerzertifikatSSLCertificateKeyFile: Privater SchlüsselSSLCertificateChainFile: Zertifikatskette
HTTPS-Verbindung testen:
$ openssl s_client \
-connect testpki.local:443 \
-servername testpki.local \
-showcerts
Wichtige Teile der Ausgabe:
---snip---
Server certificate
subject=C=DE, O=Prontosystems, OU=Webserver, CN=testpki.local
issuer=C=DE, O=Prontosystems, CN=Prontosystems Intermediate CA 01
---snap---
Die Ausgabe bestätigt:
- erfolgreiche TLS-Kommunikation
- korrekte Zertifikatskette
- erfolgreiche Auslieferung des Serverzertifikats
- funktionierende Server-Authentifizierung
Import der Root-CA in Client-Vertrauensspeicher
Damit Clients dem ausgestellten Serverzertifikat vertrauen können, muss das Root-Zertifikat der internen PKI als vertrauenswürdige Stammzertifizierungsstelle installiert werden. Die Intermediate-CA wird hierbei nicht manuell importiert. Sie wird später automatisch über die Zertifikatskette validiert.
Verwendetes Root-Zertifikat: root-ca.cert.pem
Ubuntu Linux
Unter Ubuntu kann das Root-Zertifikat systemweit in den lokalen Trust Store eingebunden werden. Wichtig ist hierbei die Dateiendung .crt, da Ubuntu ausschließlich Zertifikate mit dieser Endung automatisch verarbeitet.
$ sudo cp root-ca.cert.pem \
/usr/local/share/ca-certificates/prontosystems-root-ca.crt
Zertifikatsspeicher aktualisieren:
$ sudo update-ca-certificates
---snip---
1 added, 0 removed; done.
---snap---
HTTPS-Verbindung testen:
$ curl -Iv https://testpki.local
* Host testpki.local:443 was resolved.
* IPv6: (none)
* IPv4: 172.16.23.167
* Trying 172.16.23.167:443...
* Connected to testpki.local (172.16.23.167) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / RSASSA-PSS
* ALPN: server accepted http/1.1
* Server certificate:
* subject: C=DE; O=Prontosystems; OU=Webserver; CN=testpki.local
* start date: May 15 12:50:23 2026 GMT
* expire date: May 16 12:50:23 2026 GMT
* subjectAltName: host "testpki.local" matched cert's "testpki.local"
* issuer: C=DE; O=Prontosystems; CN=Prontosystems Intermediate CA 01
* SSL certificate verify ok.
---snip---
Wichtige Bestandteile der Ausgabe:
subjectAltName: host "testpki.local" matched cert's "testpki.local"SSL certificate verify ok.
Damit wird bestätigt, dass:
- das Root-Zertifikat erfolgreich importiert wurde
- die Zertifikatskette korrekt validiert wird
- die HTTPS-Verbindung als vertrauenswürdig eingestuft wird
- die SAN-Einträge korrekt verarbeitet werden
Hinweis zu Mozilla Firefox unter Linux:
Während viele Linux-Anwendungen sowie Chromium-basierte Browser den systemweiten Zertifikatsspeicher verwenden, nutzt Mozilla Firefox unter Linux häufig weiterhin einen eigenen Zertifikatsspeicher auf Basis von NSS (Network Security Services). Dadurch kann es vorkommen, dass HTTPS-Verbindungen trotz erfolgreich importierter Root-CA weiterhin als nicht vertrauenswürdig angezeigt werden.
In diesem Fall muss das Root-Zertifikat zusätzlich innerhalb von Firefox importiert werden:

Microsoft Windows
Unter Windows wird das Root-Zertifikat in den Zertifikatsspeicher für vertrauenswürdige Stammzertifizierungsstellen importiert. Moderne Browser wie Microsoft Edge und Google Chrome verwenden anschließend automatisch den zentralen Windows-Zertifikatsspeicher.
Das Root-Zertifikat kann beispielsweise als prontosystems-root-ca.cer gespeichert werden. Das Zertifikat enthält ausschließlich den öffentlichen Teil der Root-CA und darf innerhalb der Infrastruktur verteilt werden.
Zertifikat importieren:
Dazu den Zertifikatsspeicher des lokalen Computerkontos öffnen (Konsolenstamm → Zertifikate (Lokaler Computer) → Vertrauenswürdige Stammzertifikate → Zertifikate) und über das Kontextmenü das Root-Zertifikat importieren:

Hinweise zu Mozilla Firefox unter Windows:
Aktuelle Firefox-Versionen können zusätzlich den Windows-Zertifikatsspeicher verwenden.
Hierfür muss folgende Einstellung aktiviert sein: security.enterprise_roots.enabled = true
Dadurch übernimmt Firefox automatisch die Vertrauensstellung des Windows-Truststores.
Zusammenfassung
Nach Abschluss der beschriebenen Schritte steht eine vollständig funktionsfähige interne HTTPS-PKI zur Verfügung. Der Apache-Webserver verwendet ein durch die interne Intermediate-CA ausgestelltes TLS-Serverzertifikat. Clientsysteme können die HTTPS-Verbindung nach Import des Root-Zertifikats erfolgreich validieren. Die eigentliche Root-CA verbleibt weiterhin offline. Die operative Zertifikatsausstellung erfolgt ausschließlich über die Intermediate-CA.
![]()