Deploying on Kubernetes with Helm

This guide describes a generic way to install Document Engine from the command line on any Kubernetes platform using Helm.

We have an example of how this can be orchestrated with Terraform in any Kubernetes environment, along with another example that also provisions an AWS EKS cluster and a managed database.

Prerequisites

This guide assumes you have kubectl and Helm installed, that you have a configured context, and that you’re going to install into a namespace named document-engine.

If necessary, create the namespace:

kubectl create namespace document-engine

If you want, you can make it the default namespace in the current context:

kubectl config set-context --current --namespace=pspdfkit

If you do that, you won’t have to add -n document-engine to the commands below.

Let Helm know about Document Engine charts:

helm repo add pspdfkit https://pspdfkit.github.io/helm-charts
helm repo update

Preparing the Helm Values File

Start with the values.simple.yaml deployment configuration file from the Helm chart:

curl -o document-engine.values.yaml \
    https://raw.githubusercontent.com/PSPDFKit/helm-charts/master/charts/document-engine/values.simple.yaml

This configuration will set up Document Engine with a PostgreSQL database and a nameless Ingress resource. The PostgreSQL database it creates will make use of ephemeral storage, so any data stored in it while using the Document Engine instance won’t be persisted. If you want to set up the database yourself, refer to the corresponding section.

You can also begin with the full set of parameters by getting the values.yaml file:

curl -o document-engine.values.yaml \
    https://raw.githubusercontent.com/PSPDFKit/helm-charts/master/charts/document-engine/values.yaml

In both cases, you can alter the document-engine.values.yaml file, as well as use additional files or override values directly within the Helm command.

Setting Up the License

If you have a license, create a secret for the activation key:

kubectl -n document-engine \
  create secret generic document-engine-license \
  --from-literal=DOCUMENT_ENGINE_ACTIVATION_KEY=<YOUR ACTIVATION KEY>

Then refer to it in the document-engine.values.yaml file. To do that, find the documentEngineLicense.externalSecret section and set the name and key values there:

documentEngineLicense:
  externalSecret:
    name: document-engine-license
    key: DOCUMENT_ENGINE_ACTIVATION_KEY

See more about license configuration in our product activation guide.

Database Configuration

If you already have a PostgreSQL database, you need to configure it.

To disable installation of the external PostgreSQL Helm chart, make the following change in document-engine.values.yaml:

postgresql:
  enabled: false

Create secrets with the parameters of your database:

kubectl -n document-engine \
  create secret generic de-db-secret \
    --from-literal=PGHOST='<database host>' \
    --from-literal=PGPORT='<database port>' \
    --from-literal=PGSSL='<true or false>' \
    --from-literal=PGDATABASE='<database name>' \
    --from-literal=PGUSER='<username>' \
    --from-literal=PGPASSWORD='<password>'

kubectl -n document-engine \
  create secret generic de-db-admin-secret \
    --from-literal=PG_ADMIN_USER='<username>' \
    --from-literal=PG_ADMIN_PASSWORD='<password>'

If migration jobs are disabled, set the same PG_ADMIN_USER as PGUSER and the same PG_ADMIN_PASSWORD as PGPASSWORD. You can read more about Document Engine configuration in the corresponding guide.

Finally, refer Document Engine to your database using the following settings in document-engine.values.yaml:

assetStorage:
  enableMigrationJobs: false
  databaseEngine: postgresql
  postgres:
    enabled: true
    auth:
      createSecret: false
      # ...or use external secrets:
      # `PGUSER`, `PGPASSWORD`, `PGDATABASE`, `PGHOST`, `PGPORT`, `PGSSL`
      externalSecretName: de-db-secret
      # `PG_ADMIN_USER` and `PG_ADMIN_PASSWORD`
      externalAdminSecretName: de-db-admin-secret

Object Storage

To set S3-compatible asset storage instead of the database, update document-engine.values.yaml in the following way:

assetStorage:
  s3:
    bucket: "<your bucket name>"
    region: "<bucket region>"
    # host: "os.local"
    port: 443
      scheme: "https://"
Information

You only need to set /pspdfkit/storage/s3/host if you’re using S3-compatible storage with a custom URL.

If you aren’t providing access to your bucket using an underlying instance profile, IAM role for a service account, pod-level IAM role association, or any other authorization propagation, you might need to set up credentials.

To do that, create a secret:

kubectl -n document-engine \
  create secret generic de-s3-secret \
    --from-literal=AWS_ACCESS_KEY_ID='<AWS access key>' \
    --from-literal=AWS_SECRET_ACCESS_KEY='<AWS secret key>'

Then, configure Document Engine to use it:

assetStorage:
  s3:
    auth:
      externalSecretName: de-s3-secret

Installing the Helm Chart

To install the Helm chart with your deployment configuration into the previously created document-engine namespace, use the following command:

helm upgrade --install -n document-engine \
  document-engine pspdfkit/document-engine \
  -f document-engine.values.yaml

You can also override specific parameters. This isn’t recommended in production, but it’s useful for testing purposes.

Here’s how to scale up the deployment to two nodes (for more information, refer to the dedicated guide on horizontal scaling):

helm upgrade --install -n document-engine \
  document-engine pspdfkit/document-engine \
  -f document-engine.values.yaml \
  --set replicaCount=2
Information

The command above installs the chart if it hasn’t yet been installed; otherwise, it updates it. Such an update operation will ensure that the state of the deployed components corresponds to the command-line parameters, changes in the values file, and new versions of the chart.

Accessing the Document Engine Service inside the Cluster

Once the Helm chart is installed, your application can access the service from within the Kubernetes cluster.

Service names in Kubernetes are defined as <service name>.<namespace>.svc.cluster.local. In this scenario, the name would be document-engine.document-engine.svc.cluster.local.

To reach the Document Engine API and dashboard from outside the cluster, configure an Ingress resource.

Logging and Monitoring

Kubernetes allows different ways to retrieve logs, traces, and metrics from the workload. Document Engine writes logs to the standard output and supports OpenTelemetry traces.

Migrating from Docker Compose

If you’ve previously used Docker Compose, it’s still recommended to use our Helm values structure. However, since most of the values map to configuration options defined as environment variables, it’s also possible to use an extraEnvs value:

extraEnvs:
  - name: JWT_ALGORITHM
    value: RS512
  - name: DASHBOARD_USERNAME
    value: testUser
  - name: DASHBOARD_PASSWORD
    value: testPassword
  - name: MAX_UPLOAD_SIZE_BYTES
    value: "12345678"
  - name: ASSET_STORAGE_CACHE_SIZE
    value: "987654321"
  - name: LOG_LEVEL
    value: debug
Information

This approach is the quickest path from docker-compose.yml to values.yaml, but it has limitations and isn’t recommended for use in production.