OCSP (Online Certificate Status Protocol) lets a client ask the certificate authority whether a certificate has been revoked. With OCSP stapling, the web server fetches that signed answer from the CA itself and attaches ("staples") it to the TLS handshake, so visitors do not have to contact the CA, which is faster and does not leak their browsing to it. In this tutorial you will check whether your certificate supports OCSP at all, enable stapling in Nginx and Apache on Ubuntu 24.04, and verify that the server sends a valid response.
Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS, such as a CubePath VPS, with a non-root user that has
sudoprivileges. - Nginx or Apache already serving your site over HTTPS for
your_domain. - Outbound HTTP (port 80) from the server to the Internet, because OCSP responders are usually plain HTTP.
- A certificate from a CA that still operates OCSP. Read the next section before going further.
Does your certificate still use OCSP?
OCSP is being phased out for public TLS certificates. The CA/Browser Forum made it optional in favor of certificate revocation lists (CRLs), and Let's Encrypt shut down its OCSP service in 2025: its certificates no longer contain an OCSP URL, so there is nothing to staple. Browsers now check revocation through their own CRL-based systems (such as Firefox's CRLite and Chrome's CRLSets), which do not depend on stapling. Many commercial CAs still run OCSP responders, so stapling remains useful for their certificates.
Check your certificate. On Ubuntu with Certbot the path is /etc/letsencrypt/live/your_domain/cert.pem; for a commercial certificate, use the file you configured in the web server:
openssl x509 -in /path/to/your_domain.crt -noout -ocsp_uri
A certificate that supports OCSP prints a URL:
http://ocsp.example-ca.com
If the command prints nothing, the certificate has no OCSP responder and stapling cannot work. Nginx will log "ssl_stapling" ignored, no OCSP responder URL in the certificate if you enable it anyway. In that case you can stop here: there is nothing to configure, and revocation is handled by the browsers' CRL mechanisms. Also remove any must-staple option from your Certbot configuration, because Let's Encrypt no longer issues certificates with that extension.
Continue only if the command printed a URL.
Step 1 - Preparing the issuer chain
The server needs the certificate of the CA that issued yours (the intermediate) to build and verify the OCSP request. Most CAs deliver it as a "CA bundle" or "chain" file. Check that your chain file contains the intermediate and ends in the root:
grep -c 'BEGIN CERTIFICATE' /path/to/chain.pem
openssl crl2pkcs7 -nocrl -certfile /path/to/chain.pem | openssl pkcs7 -print_certs -noout | grep subject
2
subject=C = US, O = Example CA, CN = Example CA RSA Intermediate
subject=C = US, O = Example CA, CN = Example CA Root
Copy it to a stable path such as /etc/ssl/certs/your_domain-chain.pem. Then confirm the CA answers for your certificate by querying the responder manually:
openssl ocsp -issuer /etc/ssl/certs/your_domain-chain.pem \
-cert /path/to/your_domain.crt \
-url "$(openssl x509 -in /path/to/your_domain.crt -noout -ocsp_uri)" \
-CAfile /etc/ssl/certs/your_domain-chain.pem
Response verify OK
/path/to/your_domain.crt: good
This Update: Sep 25 08:00:00 2026 GMT
Next Update: Oct 2 08:00:00 2026 GMT
good means the certificate is not revoked and the responder is reachable. If this fails, the web server will fail too; see the Troubleshooting section.
Step 2 - Enabling OCSP stapling in Nginx
Open the server block that serves your HTTPS site:
sudo nano /etc/nginx/sites-available/your_domain
Add the stapling directives inside the server block that listens on 443:
server {
listen 443 ssl http2;
server_name your_domain;
ssl_certificate /etc/ssl/certs/your_domain-fullchain.pem;
ssl_certificate_key /etc/ssl/private/your_domain.key;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/your_domain-chain.pem;
resolver 127.0.0.53 valid=300s;
resolver_timeout 5s;
# ... the rest of your configuration
}
What each line does:
ssl_stapling onmakes Nginx fetch and cache OCSP responses.ssl_stapling_verify onchecks the CA's signature on each response before stapling it, so Nginx never sends a forged or broken answer.ssl_trusted_certificatepoints to the intermediate and root, which Nginx needs for that verification. It is not sent to clients.resolvertells Nginx which DNS server to use to resolve the OCSP responder's hostname.127.0.0.53is the systemd-resolved stub that Ubuntu runs by default.
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Nginx fetches the OCSP response lazily, per worker process, after the first TLS connections arrive. The first handshakes after a reload may therefore go out without a staple; that is expected.
Step 3 - Enabling OCSP stapling in Apache
Apache needs mod_ssl and the shared memory cache module that stores responses:
sudo a2enmod ssl socache_shmcb
The stapling cache must be defined outside any <VirtualHost>. Create a small configuration file for it:
sudo nano /etc/apache2/conf-available/ocsp-stapling.conf
SSLStaplingCache "shmcb:${APACHE_RUN_DIR}/ssl_stapling(128000)"
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingReturnResponderErrors off stops Apache from stapling error responses from the CA, which some clients treat as a hard failure. Enable the file:
sudo a2enconf ocsp-stapling
Then turn stapling on in your HTTPS virtual host:
sudo nano /etc/apache2/sites-available/your_domain-ssl.conf
<VirtualHost *:443>
ServerName your_domain
SSLEngine on
SSLCertificateFile /etc/ssl/certs/your_domain-fullchain.pem
SSLCertificateKeyFile /etc/ssl/private/your_domain.key
SSLUseStapling on
# ... the rest of your configuration
</VirtualHost>
Apache builds the chain from the file in SSLCertificateFile, so it must contain your certificate followed by the intermediate. Check the syntax and reload:
sudo apache2ctl configtest
sudo systemctl reload apache2
Syntax OK
Step 4 - Verifying the stapled response
Use openssl s_client with -status, which asks the server for a stapled OCSP response. Run it twice, because the first connection after a reload can arrive before the response is cached:
openssl s_client -connect your_domain:443 -servername your_domain -status </dev/null 2>/dev/null \
| grep -A 12 'OCSP response:'
A working setup shows a successful response with the status good:
OCSP response:
======================================
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: C = US, O = Example CA, CN = Example CA OCSP Responder
Produced At: Sep 25 08:00:00 2026 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 5A4C1D...
Issuer Key Hash: 8B7E2C...
Look further down the same output for Cert Status: good. If you see this instead, no staple was sent:
OCSP response: no response sent
Repeat the command after a few seconds. If it still says no response sent, check the logs as described below.
Troubleshooting
Nginx logs "ssl_stapling" ignored, no OCSP responder URL in the certificate. The certificate has no OCSP URL (every current Let's Encrypt certificate is in this situation). Stapling cannot work; remove the directives or leave them, they are harmless.
Nginx logs "ssl_stapling" ignored, issuer certificate not found. Nginx cannot find the intermediate. Make sure ssl_certificate contains the full chain, or that ssl_trusted_certificate contains the intermediate.
OCSP_basic_verify() failed in the Nginx error log. ssl_stapling_verify could not validate the response. Add the root certificate to the file in ssl_trusted_certificate, then reload.
Apache logs stapling_renew_response: responder error or OCSP timeouts. The server cannot reach the responder. Test from the server with curl -sI "$(openssl x509 -in /path/to/your_domain.crt -noout -ocsp_uri)" and check outbound firewall rules and DNS.
Where to look. Nginx logs to /var/log/nginx/error.log and Apache to /var/log/apache2/error.log. Follow them while you run the s_client test:
sudo tail -f /var/log/nginx/error.log
Conclusion
You checked whether your certificate still carries an OCSP responder, enabled OCSP stapling with response verification in Nginx and Apache on Ubuntu 24.04, and confirmed the stapled response with openssl s_client -status. If you use Let's Encrypt, the right configuration is simply no stapling, since revocation now travels through CRLs. As next steps, review your TLS protocol and cipher settings and add an external check that alerts you before any certificate expires.
