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

# Prepare cryptographic material for Access Server

> This step prepares the keys and certificates used by Access Server and securely stores them in the CryptoHub. You generate the CA, server, and client certificates using PKCS

<Warning>
  **Important**

  If you are using an external CA, this tutorial does not cover how to configure or apply Access Server's required `v3 extensions` during the certificate signing. Follow your CA's documentation for extension handling.
</Warning>

<Note>
  VPN clients rely on the CA certificate to validate the server. If the CA certificate expires, client connections will fail until it is replaced.
</Note>

<Warning>
  **Important**

  Futurex can't provide support for issues arising from the use of an external CA; refer to your CA's documentation for guidance on extension handling and certificate issuance.
</Warning>

## Set FXPKCS11 environment variables

<Steps>
  <Step>
    Export the PKCS #11 module path:

    ```shell expandable lines wrap title="Shell" theme={null}
    export FXPKCS11_MODULE=/usr/local/lib/fxpkcs11/libfxpkcs11.so
    ```
  </Step>
</Steps>

## Configure Access Server for external PKI

<Steps>
  <Step>
    Connect to the Access Server console and get root privileges.
  </Step>

  <Step>
    Edit the `as.conf` for external PKI usage:

    ```shell expandable lines wrap title="Shell" theme={null}
    nano /usr/local/openvpn_as/etc/as.conf
    ```

    Comment out `certs_db`:

    ```ini expandable lines wrap title="Configuration" theme={null}
    # certificates database
    # certs_db=sqlite:///~/db/certs.db
    ```

    Save and exit the file — Ctrl-X, Y, then Enter.

    * Access Server no longer uses the certificate database. Instead, an external system must handle this.
  </Step>
</Steps>

### Generate the CA key on CryptoHub

<Tip>
  We use OpenSSL to generate the files. Skip this section if you're using an external CA.
</Tip>

<Note>
  We're storing the files in the `root` directory.
</Note>

<Steps>
  <Step>
    Generate the private key:

    ```shell expandable lines wrap title="Shell" theme={null}
    pkcs11-tool --module $FXPKCS11_MODULE --login --key-type rsa:2048 --pin "$(cat /root/pkcs11-pin.txt)" --label "OpenVPN-CA-Key" --id 01 --keypairgen --usage-sign
    ```
  </Step>

  <Step>
    Generate the PKCS #11 URI reference file for the CA key:

    * For **Ubuntu/Debian:**

    ```shell expandable lines wrap title="Shell" theme={null}
    python3 ~/src/pkcs11-provider/tools/uri2pem.py "pkcs11:token=Futurex;object=OpenVPN-CA-Key;type=private" > /root/ca.key
    ```

    * For **RHEL:**

    ```shell expandable lines wrap title="Shell" theme={null}
    python3 /usr/local/src/pkcs11-provider/tools/uri2pem.py "pkcs11:token=Futurex;object=OpenVPN-CA-Key;type=private" > /root/ca.key
    ```
  </Step>

  <Step>
    Generate the CA certificate:

    ```shell expandable lines wrap title="Shell" theme={null}
    openssl req -new -x509 -provider pkcs11 -provider-path $FXPKCS11_MODULE -key ca.key -out ca.crt -days 3650 -subj "/CN=OpenVPN_CA"
    ```

    From the above commands, you get two files:

    * CA key (`ca.key`)
    * CA certificate (`ca.crt`)
  </Step>
</Steps>

### Create OpenSSL configuration for the server certificate

<Warning>
  **Important**

  This tutorial assumes `openssl.cnf` is located in `/usr/lib/ssl/`. Update the path in the following commands accordingly.
</Warning>

<Steps>
  <Step>
    Copy the default OpenSSL configuration file to a new file named `openssl-server.cnf`:

    ```shell expandable lines wrap title="Shell" theme={null}
    OUT="/usr/lib/ssl/openssl-server.cnf"
    cp /usr/lib/ssl/openssl.cnf "$OUT"
    ```
  </Step>

  <Step>
    Update the `[ req ]` section:

    ```shell expandable lines wrap title="Shell" theme={null}
    sed -i '/^[ req ]/,/^[/{/req_extensions/ d}' "$OUT"
    sed -i '/^[ req ]/,/^[/{/x509_extensions/ a\
    req_extensions = v3_req
    }' "$OUT"
    ```
  </Step>

  <Step>
    Update the `[ v3_req ]` section:

    ```shell expandable lines wrap title="Shell" theme={null}
    sed -i '/^[ v3_req ]/,/^[/{s/basicConstraints.*/basicConstraints = critical, CA:FALSE/}' "$OUT"
    sed -i '/^[ v3_req ]/,/^[/{s/keyUsage.*/keyUsage = critical, digitalSignature, keyEncipherment/}' "$OUT"
    sed -i '/^[ v3_req ]/,/^[/{/extendedKeyUsage/ d}' "$OUT"
    sed -i '/keyUsage = critical, digitalSignature, keyEncipherment/ a\
    extendedKeyUsage = serverAuth
    ' "$OUT"
    ```
  </Step>
</Steps>

### Create OpenSSL configuration for the client certificate

<Warning>
  **Important**

  This tutorial assumes `openssl.cnf` is located in `/usr/lib/ssl/`. Update the path in the following commands accordingly.
</Warning>

<Steps>
  <Step>
    Copy the default OpenSSL configuration file to a new file named `openssl-client.cnf`:

    ```shell expandable lines wrap title="Shell" theme={null}
    OUT="/usr/lib/ssl/openssl-client.cnf"
    cp /usr/lib/ssl/openssl.cnf "$OUT"
    ```
  </Step>

  <Step>
    Update the `[ req ]` section:

    ```shell expandable lines wrap title="Shell" theme={null}
    sed -i '/^[ req ]/,/^[/{/req_extensions/ d}' "$OUT"
    sed -i '/^[ req ]/,/^[/{/x509_extensions/ a\
    req_extensions = v3_req
    }' "$OUT"
    ```
  </Step>

  <Step>
    Update the `[ v3_req ]` section:

    ```shell expandable lines wrap title="Shell" theme={null}
    sed -i '/^[ v3_req ]/,/^[/{s/basicConstraints.*/basicConstraints = critical, CA:FALSE/}' "$OUT"
    sed -i '/^[ v3_req ]/,/^[/{s/keyUsage.*/keyUsage = critical, digitalSignature/}' "$OUT"
    sed -i '/^[ v3_req ]/,/^[/{/extendedKeyUsage/ d}' "$OUT"
    sed -i '/^[ v3_req ]/,/^[/{/nsCertType/ d}' "$OUT"
    sed -i '/keyUsage = critical, digitalSignature/ a\
    extendedKeyUsage = clientAuth
    ' "$OUT"
    sed -i '/extendedKeyUsage = clientAuth/ a\
    nsCertType = client
    ' "$OUT"
    ```
  </Step>
</Steps>

### Generate the server key and certificate

<Tip>
  We're storing the files in the `root` directory.
</Tip>

<Warning>
  **Important**

  This tutorial assumes `openssl.cnf` is located in `/usr/lib/ssl/`. Update the path in the following commands accordingly.
</Warning>

<Steps>
  <Step>
    Generate the server private key on CryptoHub:

    ```shell expandable lines wrap title="Shell" theme={null}
    pkcs11-tool --module $FXPKCS11_MODULE --login --key-type rsa:2048 --pin "$(cat /root/pkcs11-pin.txt)" --label "OpenVPN-Server-Key" --id 02 --keypairgen --usage-sign
    ```
  </Step>

  <Step>
    Generate the PKCS #11 URI reference file for the server key:

    * For **Ubuntu/Debian:**

    ```shell expandable lines wrap title="Shell" theme={null}
    python3 ~/src/pkcs11-provider/tools/uri2pem.py "pkcs11:token=Futurex;object=OpenVPN-Server-Key;type=private" > server.key
    ```

    * For **RHEL:**

    ```shell expandable lines wrap title="Shell" theme={null}
    python3 /usr/local/src/pkcs11-provider/tools/uri2pem.py "pkcs11:token=Futurex;object=OpenVPN-Server-Key;type=private" > server.key
    ```
  </Step>

  <Step>
    Generate the server CSR:

    ```shell expandable lines wrap title="Shell" theme={null}
    openssl req -new -key server.key -out server.csr -subj "/CN=OpenVPN Server" -config /usr/lib/ssl/openssl-server.cnf
    ```
  </Step>

  <Step>
    Sign the server certificate:

    ```shell expandable lines wrap title="Shell" theme={null}
    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -extfile /usr/lib/ssl/openssl-server.cnf -extensions v3_req
    ```

    From the above commands, you get three files:

    * Server key (`server.key`)
    * Server certificate (`server.crt`)
    * Server CSR (`server.csr`)
  </Step>
</Steps>

### Generate the client certificate and package

<Tip>
  We're storing the files in the `root` directory.
</Tip>

<Warning>
  **Important**

  This tutorial assumes `openssl.cnf` is located in `/usr/lib/ssl/`. Update the path in the following commands accordingly.
</Warning>

<Steps>
  <Step>
    Generate the client private key:

    ```shell expandable lines wrap title="Shell" theme={null}
    openssl genpkey -algorithm RSA -out client.key -pkeyopt rsa_keygen_bits:2048
    ```
  </Step>

  <Step>
    Generate the client CSR:

    <Warning>
      The **Common Name** you define while generating the client CSR must match the name of the user you create in the OpenVPN Access Server admin portal.

      For example, in the command above, we set `/CN=etest` in the `-subj` flag. So the user name would need to be "etest".
    </Warning>

    ```shell expandable lines wrap title="Shell" theme={null}
    openssl req -new -key client.key -out client.csr -subj "/CN=etest" -config /usr/lib/ssl/openssl-client.cnf
    ```

    (Optional) Generate the client CSR compatible with auto-login:

    ```shell expandable lines wrap title="Shell" theme={null}
    openssl req -new -key client.key -out client.csr -subj "/role=AUTOLOGIN/CN=etest" -config /usr/lib/ssl/openssl-client.cnf
    ```
  </Step>

  <Step>
    Sign the client certificate:

    ```shell expandable lines wrap title="Shell" theme={null}
    openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -extfile /usr/lib/ssl/openssl-client.cnf -extensions v3_req
    ```
  </Step>

  <Step>
    Create the P12 bundle:

    ```shell expandable lines wrap title="Shell" theme={null}
    openssl pkcs12 -export -inkey client.key -in client.crt -certfile ca.crt -out etest.p12 -name "etest"
    ```
  </Step>

  <Step>
    Enter the P12 password when prompted.

    * From the above commands, you get four files:
    * Client key (`client.key`)
    * Client certificate (`client.crt`)
    * Client CSR (`client.csr`)
    * Client P12 file (`etest.p12`)
  </Step>
</Steps>
