---
title: SoftHSMv2
description: Learn how to use Keyless SSL with SoftHSMv2.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ssl/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# SoftHSMv2

Important

SoftHSMv2 should not be considered any more secure than storing private keys directly on disk. No attempt is made below to secure this installation; it is provided simply for demonstration purposes.

---

## 1\. Install and configure SoftHSMv2

First, we install SoftHSMv2 and configure it to store tokens in the default location `/var/lib/softhsm/tokens`. We also need to give the `softhsm` group permission to this directory as this is how the `keyless` user will access this directory.

Terminal window

```
sudo apt-get install -y softhsm2 opensc
#...
cat <<EOF | sudo tee /etc/softhsm/softhsm2.confdirectories.tokendir = /var/lib/softhsm/tokensobjectstore.backend = filelog.level = DEBUGslots.removable = falseEOF
sudo mkdir /var/lib/softhsm/tokenssudo chown root:softhsm $_sudo chmod 0770 /var/lib/softhsm/tokenssudo usermod -G softhsm keylesssudo usermod -G softhsm $(whoami)
echo 'export SOFTHSM2_CONF=/etc/softhsm/softhsm2.conf' | tee -a ~/.profilesource ~/.profile
```

---

## 2\. Create a token and private keys, and generate CSRs

Next, we create a token in slot 0 called `test-token` and secure it with a PIN of `1234`. In this slot we’ll store the RSA keys for our SSL certificates for `keyless-softhsm.example.com`.

Terminal window

```
sudo -u keyless softhsm2-util --init-token --slot 0 --label test-token --pin 1234 --so-pin 4321
```

```
The token has been initialized.
```

Using cfssl, we generate the [private keys and Certificate Signing Requests (CSRs) ↗](https://github.com/cloudflare/cfssl), the latter of which will be sent to a Certificate Authority (CA) for signing.

Terminal window

```
cat <<EOF | tee csr.json{    "hosts": [        "keyless-softhsm.example.com"    ],    "CN": "keyless-softhsm.example.com",    "key": {        "algo": "rsa",        "size": 2048    },    "names": [{        "C": "US",        "L": "San Francisco",        "O": "TLS Fun",        "OU": "Technical Operations",        "ST": "California"    }]}EOF
cfssl genkey csr.json | cfssljson -bare certificate
```

```
2018/08/12 00:52:22 [INFO] generate received request2018/08/12 00:52:22 [INFO] received CSR2018/08/12 00:52:22 [INFO] generating key: rsa-20482018/08/12 00:52:22 [INFO] encoded CSR
```

---

## 3\. Convert and import the key

Now that the key has been generated, it’s time to load it into the slot we created. Before doing so, we need to convert from PKCS#1 to PKCS#8 format. During import, we specify the token and PIN from token initialization and provide a unique hexadecimal ID and label to the key.

Terminal window

```
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in certificate-key.pem -out certificate-key.p8sudo chown keyless certificate-key.p8
sudo -u keyless softhsm2-util --pin 1234 --import ./certificate-key.p8 --token test-token --id a000 --label rsa-privkey
```

```
Found slot 915669571 with matching token label.The key pair has been imported.
```

After importing we ask `pkcs11-tool` to confirm the objects have been successfully stored in the token.

Terminal window

```
sudo -u keyless pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -l -p 1234 --token test-token --list-objects
```

```
Public Key Object; RSA 2048 bits  label:      rsa-privkey  ID:         a000  Usage:      verifyPrivate Key Object; RSA  label:      rsa-privkey  ID:         a000  Usage:      sign
```

---

## 4\. Modify your gokeyless config file and restart the service

With the keys in place, it’s time to build the configuration file that the key server will read on startup. The `id` refers to the hexadecimal ID you provided to the `softhsm2-util` import statement; we used `a000` so it is encoded as `%a0%00`. The `module-path` will vary slightly based on the Linux distribution you are using. On Debian it should be `/usr/lib/softhsm/libsofthsm2.so`.

Open up `/etc/keyless/gokeyless.yaml` and immediately after

YAML

```
private_key_stores:  - dir: /etc/keyless/keys
```

add

YAML

```
- uri: pkcs11:token=test-token;id=%a0%00?module-path=/usr/lib/softhsm/libsofthsm2.so&pin-value=1234&max-sessions=1
```

Save the config file, restart `gokeyless`, and verify it started successfully.

Terminal window

```
sudo systemctl restart gokeyless.servicesudo systemctl status gokeyless.service -l
```

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/softhsmv2/#page","headline":"SoftHSMv2 · Cloudflare SSL/TLS docs","description":"Learn how to use Keyless SSL with SoftHSMv2.","url":"https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/softhsmv2/","inLanguage":"en","image":"https://developers.cloudflare.com/core-services-preview.png","dateModified":"2026-05-05","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/softhsmv2/","name":"SoftHSMv2"}}]}
```
