Deploying to Microsoft Azure

Information

PSPDFKit Server has been deprecated and replaced by PSPDFKit Document Engine. All PSPDFKit Server and PSPDFKit for Web Server-Backed licenses will work as before and be supported until 15 May 2024 (we will contact you about license migration). To start using Document Engine, refer to the migration guide. With Document Engine, you’ll have access to robust new capabilities (read the blog for more information).

This guide will walk you through the steps for deploying PSPDFKit Server to the Microsoft Azure Container Service with Kubernetes.

Setting Up Azure CLI

To be able to deploy PSPDFKit Server to the Microsoft Azure Container Service with Kubernetes, you have to set up the Azure CLI utility to manage your Kubernetes cluster in the command line.

To install Azure CLI, follow the installation instructions from the Azure CLI installation guide.

After you’ve installed Azure CLI, run the following command to log in to Microsoft Azure:

az login

This command will print the URL https://microsoft.com/devicelogin and the code for signing in. Open the URL in your browser and enter the code to sign in to your Microsoft Azure account.

Sign in Page

Creating a Resource Group

To create a resource group, run the following:

az group create -l eastus -n pspdfkitresourcegroup

In this example, we created the resource group in the eastus region with the name pspdfkitresourcegroup. An overview of available regions can be found on Microsoft’s Azure Regions page.

Creating a Kubernetes Cluster

To be able to manage your Kubernetes cluster from the command line, you have to install kubectl:

az aks install-cli

To create a Kubernetes cluster with the name pspdfkitAKScluster, run the following:

az aks create -g pspdfkitresourcegroup --name pspdfkitAKScluster --generate-ssh-keys

To connect kubectl with your cluster, execute:

az aks get-credentials -g pspdfkitresourcegroup -n pspdfkitAKScluster

Creating a ConfigMap

ConfigMaps allow you to decouple configuration artifacts from image content. To create the pspdfkit-config ConfigMap, run the following command:

kubectl create configmap pspdfkit-config

After the ConfigMap is created, you can edit it with the following:

kubectl edit configmap pspdfkit-config

This should open the created ConfigMap in your editor. Edit the file to match the following file and replace activation_key with your activation key:

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving,
# this file will be reopened with the relevant failures.
#
apiVersion: v1
data:
  activation_key: YOUR_ACTIVATION_KEY_GOES_HERE
  api_auth_token: secret
  dashboard_password: secret
  dashboard_username: dashboard
  jwt_algorithm: RS256
  jwt_public_key: |
    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2gzhmJ9TDanEzWdP1WG+
    0Ecwbe7f3bv6e5UUpvcT5q68IQJKP47AQdBAnSlFVi4X9SaurbWoXdS6jpmPpk24
    QvitzLNFphHdwjFBelTAOa6taZrSusoFvrtK9x5xsW4zzt/bkpUraNx82Z8MwLwr
    t6HlY7dgO9+xBAabj4t1d2t+0HS8O/ed3CB6T2lj6S8AbLDSEFc9ScO6Uc1XJlSo
    rgyJJSPCpNhSq3AubEZ1wMS1iEtgAzTPRDsQv50qWIbn634HLWxTP/UH6YNJBwzt
    3O6q29kTtjXlMGXCvin37PyX4Jy1IiPFwJm45aWJGKSfVGMDojTJbuUtM+8P9Rrn
    AwIDAQAB
    -----END PUBLIC KEY-----
  pgdata: /var/lib/postgresql/data/pgdata
  pgdatabase: pspdfkit
  pghost: pspdfkitdb
  pgpassword: examplepassword
  pgport: "5432"
  pguser: pspdfkit
  secret_key_base: secret-key-base
kind: ConfigMap

Don’t change anything that comes after the kind: ConfigMap line, because that part is autogenerated.

Creating an Azure Disk Volume

To create the Azure Disk Volume where the database saves the data, run:

az group list --output table

This will print a list of resource groups. Copy the name of the resource group that starts with MC — for example, MC_pspdfkitresourcegroup_pspdfkitAKScluster_eastus — and insert it into the following command after --resource-group:

az disk create \
  --resource-group MC_pspdfkitresourcegroup_pspdfkitAKScluster_eastus \
  --name postgres-disk\
  --size-gb 50 \
  --query id --output tsv

This will print the disk ID of the created disk. For example:

/subscriptions/12345abc-def1-2345-6789-abcdef123456/resourceGroups/MC_pspdfkitresourcegroup_pspdfkitAKScluster_eastus/providers/Microsoft.Compute/disks/postgres-disk

Creating Services and Deployments

Kubernetes Services and Deployments can be configured in a file. To run PSPDFKit Server, you have to define a Service and a Deployment for the database and a Service and a Deployment for PSPDFKit Server. First, create the file that configures the database Service and Deployment. To do this, create the pspdfkitdb.yml file in the current directory:

apiVersion: v1
kind: Service
metadata:
  name: pspdfkitdb
spec:
  ports:
    - port: 5432
  selector:
    app: pspdfkitdb
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pspdfkitdb
spec:
  selector:
    matchLabels:
      app: pspdfkitdb
  template:
    metadata:
      labels:
        app: pspdfkitdb
    spec:
      containers:
        - image: "postgres:15"
          name: pspdfkitdb
          env:
            - name: POSTGRES_USER
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pguser
            - name: POSTGRES_PASSWORD
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgpassword
            - name: PGDATA
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgdata
          ports:
            - containerPort: 5432
              name: pspdfkitdb
          volumeMounts:
            - name: postgres-storage
              mountPath: /var/lib/postgresql/data
      volumes:
        - name: postgres-storage
          azureDisk:
            kind: Managed
            diskName: postgres-disk
            diskURI: /subscriptions/12345abc-def1-2345-6789-abcdef123456/resourceGroups/MC_pspdfkitresourcegroup_pspdfkitAKScluster_eastus/providers/Microsoft.Compute/disks/postgres-disk

Make sure to replace diskURI in the last line with the disk ID you got from the command before.

After you’ve created the configuration file for the database, create the configuration for PSPDFKit Server (pspdfkit.yml) and ensure that the pspdfkit/pspdfkit image tag corresponds to the latest PSPDFKit Server version:

apiVersion: v1
kind: Service
metadata:
  name: pspdfkit
spec:
  ports:
    - protocol: TCP
      port: 5000
      targetPort: 5000
  selector:
    app: pspdfkit
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pspdfkit
spec:
  selector:
    matchLabels:
      app: pspdfkit
  template:
    metadata:
      labels:
        app: pspdfkit
    spec:
      containers:
        - image: "pspdfkit/pspdfkit:2024.2.0"
          name: pspdfkit
          env:
            - name: PGUSER
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pguser
            - name: PGPASSWORD
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgpassword
            - name: PGDATABASE
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgdatabase
            - name: PGHOST
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pghost
            - name: PGPORT
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgport
            - name: ACTIVATION_KEY
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: activation_key
            - name: API_AUTH_TOKEN
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: api_auth_token
            - name: SECRET_KEY_BASE
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: secret_key_base
            - name: JWT_ALGORITHM
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: jwt_algorithm
            - name: JWT_PUBLIC_KEY
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: jwt_public_key
            - name: DASHBOARD_USERNAME
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: dashboard_username
            - name: DASHBOARD_PASSWORD
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: dashboard_password
          ports:
            - containerPort: 5000
              name: pspdfkit

To create all Services and Deployments needed to run PSPDFKit Server, execute:

kubectl create -f ./pspdfkitdb.yml
kubectl create -f ./pspdfkit.yml

Viewing the Dashboard

To be able to access the server, you have to get the external IP address that was assigned to the server. Run the following command to view all the Services in your cluster, along with their assigned external IP addresses:

kubectl get services

This will show something like the following:

NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)          AGE
kubernetes   ClusterIP      10.15.240.1     <none>           443/TCP          54m
pspdfkit     LoadBalancer   10.15.247.197   12.345.678.910   5000:32393/TCP   1m
pspdfkitdb   ClusterIP      10.15.244.127   <none>           5432/TCP         4m

Copy the EXTERNAL-IP address from the pspdfkit column and access the dashboard with the port 5000 and the /dashboard path in your web browser. In this example, you would access the dashboard with http://12.345.678.910:5000/dashboard.

Limitations

Be aware that this is just an example setup, and we recommend looking deeper into the Microsoft Azure Container Service for a production-ready setup.