Use a Cloud HSM key to serve Apache traffic

This guide provides instructions for setting up an Apache server to use aCloud HSM key for TLS signing on Debian 11 (Bullseye). You might need tomodify these commands to work with your OS or Linux distribution.

Note: TLS termination with Apache is only supported for Elliptic CurveDigital Signature Algorithm (ECDSA) keys.

You can find a Terraform-based blueprint version of this tutorial in thekms-solutions GitHub repository.

Before you begin

As a prerequisite, complete the configuration documented inOpenSSL Setup.

Once OpenSSL setup is complete, ensure that a recent version of Apache isinstalled:

sudo apt-get updatesudo apt-get install apache2
Note:PKCS #11 URIs are only available inapache2-2.4.42 andlater. If you are using an earlier version, you must upgrade theapache2package with the command above, or install from non-stable sources.
For Debian Buster:sudo apt install -t buster-backports apache2

Configuration

Create a Cloud KMS-hosted signing key

Create a Cloud KMSEC-P256-SHA256 signing key in yourGoogle Cloud project, in the key ring that you previously configuredfor OpenSSL:

gcloud kms keys create "KEY_NAME" --keyring "KEY_RING" \  --project "PROJECT_ID" --location "LOCATION" \  --purpose "asymmetric-signing" --default-algorithm "ec-sign-p256-sha256" \  --protection-level "hsm"
Note: Make sure that your Compute Engine service account has the rightIdentity and Access Management (IAM) permissions on the key ring to be able to use it.

Create a self-signed certificate with OpenSSL

Generate a self-signed certificate with the Cloud KMS-hostedsigning key. You can use OpenSSL to use a PKCS #11 URI instead of a file pathand identify the key by its label. In the Cloud KMS PKCS #11library, the key label is the CryptoKey name.

openssl req -new -x509 -days 3650 -subj '/CN=CERTIFICATE_NAME/' \DIGEST_FLAG -engine pkcs11 -keyform engine \  -keyPKCS_KEY_TYPE=KEY_IDENTIFIER >PATH_TO_CERTIFICATE

Replace the following:

  • CERTIFICATE_NAME: a name for the certificate.
  • DIGEST_FLAG: the digest algorithm used by the asymmetric signingkey. Use-sha256,-sha384, or-sha512 depending on the key.
  • PKCS_KEY_TYPE: the type of identifier used to identify the key.To use the latest key version, usepkcs11:object with the key's name. Touse a specific key version, usepkcs11:id with the full resource ID of thekey version.
  • KEY_IDENTIFIER: an identifier for the key. If you're usingpkcs11:object, use the key's name—for example,KEY_NAME.If you're usingpkcs11:id, use the full resource ID of the key or keyversion—for example,projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions/KEY_VERSION.
  • PATH_TO_CERTIFICATE: the path where you want to save the certificatefile.

If this command fails,PKCS11_MODULE_PATH might have been set incorrectly, oryou might not have the right permissions to use the Cloud KMSsigning key.

You should now have a certificate that looks like this:

-----BEGIN CERTIFICATE-----.........-----END CERTIFICATE-----

Set up the Apache server

  1. Create a directory in/etc/apache2 to store your self-signedcertificate in:

    sudo mkdir /etc/apache2/sslsudo mv ca.cert /etc/apache2/ssl
  2. Edit the000-default.conf virtual host configuration files located in/etc/apache2/sites-available to provide the certificate file path andensure that the SSLEngine is on.

    Here is a sample configuration listening on port 443:

    <VirtualHost*:443>ServerAdminwebmaster@localhostDocumentRoot/var/www/htmlErrorLog${APACHE_LOG_DIR}/error.logCustomLog${APACHE_LOG_DIR}/access.logcombinedSSLEngineonSSLCertificateFile/etc/apache2/ssl/ca.certSSLCertificateKeyFile"PKCS_KEY_TYPE=KEY_IDENTIFIER"</VirtualHost>
  3. Ensure Apache exports the environment variables correctly by adding them tothe/etc/apache2/envvars file using your text editor of choice. You mightneed to edit the file as root usingsudo. Add the following lines to theend of the file:

    exportPKCS11_MODULE_PATH="<var>PATH_TO_LIBKMSP11</var>"exportKMS_PKCS11_CONFIG="<var>PATH_TO_PKCS11_CONFIG</var>"exportGRPC_ENABLE_FORK_SUPPORT=1

    Replace the following:

    • PATH_TO_LIBKMSP11: the path tolibkmsp11.so.
    • PATH_TO_PKCS11_CONFIG: the path topkcs11-config.yaml.

    GRPC_ENABLE_FORK_SUPPORT is needed for gRPC to include fork support andcorrectly run the Cloud KMS PKCS #11 library as part of the Apacheserver.

    If you want to authenticate using a service account key, you must alsoexport a value for theGOOGLE_APPLICATION_CREDENTIALS environmentvariable.

Run your server

Enable the Apache SSL module, enable the virtualhost configuration, and add atest web page in your DocumentRoot folder:

sudoa2enmodsslsudoa2ensite000-default.confecho'<!doctype html><html><body><h1>Hello World!</h1></body></html>'|\sudotee/var/www/html/index.html

Restart your Apache server and test withcurl that the configuration works asexpected. The--insecure flag is needed to ignore self-signed certificatechecks.

sudo systemctl restart apache2curl -v --insecure https://127.0.0.1

If you encounter any errors, the Apache error log is a good starting place tosee what went wrong. Authentication issues are a common source of errors. If youseePERMISSION_DENIED errors, make sure that you are fully authenticated andthat the credentials file has the right permissions. To make sure you are fullyauthenticated, run the following command:

gcloudauthapplication-defaultlogin

To confirm that authentication was successful, the output should include thelineCredentials saved to file: [/path/to/credentials.json].

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2026-02-19 UTC.