Using a Cloud HSM key to serve Apache traffic

Stay organized with collections Save and categorize content based on your preferences.

This guide provides instructions for setting up an Apache server to use a Cloud HSM key for TLS signing on Debian 11 (Bullseye). These instructions generally apply even if you're using another OS or environment, but there may be slight differences.


As a prerequisite, complete the configuration documented in OpenSSL Setup.

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

sudo apt-get update
sudo apt-get install apache2


Creating a Cloud KMS-hosted signing key

Create a Cloud KMS EC-P256-SHA256 signing key in your Google Cloud project, in the key ring that you previously configured for OpenSSL:

# Create a new HSM-backed EC-P256-SHA256 signing key
gcloud kms keys create "KEY_NAME" --keyring "KEY_RING" \
  --project "PROJECT" --location "LOCATION" \
  --purpose "asymmetric-signing" --default-algorithm "ec-sign-p256-sha256" \
  --protection-level "hsm"

Creating a self-signed certificate with OpenSSL

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

openssl req -new -x509 -days 3650 -subj '/CN=test/' -sha256 -engine pkcs11 \
  -keyform engine -key pkcs11:object=KEY_NAME > ca.cert

If this command fails, PKCS11_MODULE_PATH may have been set incorrectly, or you might not have the right permissions to use the Cloud KMS signing key. You should now have a certificate that looks like this:


Setting up the Apache server

First, create a directory in /etc/apache2 to store your self-signed certificate in:

sudo mkdir /etc/apache2/ssl
sudo mv ca.cert /etc/apache2/ssl

Now, edit the 000-default.conf virtual host configuration files located in /etc/apache2/sites-available to provide the certificate file path and ensure that the SSLEngine is on.

Sample configuration, listening on port 443:

  <VirtualHost *:443>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/ca.cert
        SSLCertificateKeyFile "pkcs11:object=KEY_NAME"

Ensure Apache exports the environment variables correctly by adding them to the /etc/apache2/envvars file:

sudo vi /etc/apache2/envvars

# Add the following lines:
export PKCS11_MODULE_PATH="/path/to/"
export KMS_PKCS11_CONFIG="/path/to/pkcs11-config.yaml"

GRPC_ENABLE_FORK_SUPPORT is needed for gRPC to include fork support and correctly run the Cloud KMS PKCS #11 library as part of the Apache server.

If you want to authenticate using a service account key, you must also set a value for the GOOGLE_APPLICATION_CREDENTIALS environment variable.

Running your server

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

sudo a2enmod ssl
sudo a2ensite 000-default.conf
echo '<!doctype html><html><body><h1>Hello World!</h1></body></html>' | \
  sudo tee /var/www/html/index.html

Restart your Apache server and test with curl that the configuration works as expected. The --insecure flag is needed to ignore self-signed certificate checks.

sudo systemctl restart apache2
curl -v --insecure

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

gcloud auth application-default login

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