Setting up VM Infrastructure


Required Infrastructure to Support Run Anywhere

The Run Anywhere on-premise PKI solution itself runs on a customer-managed Kubernetes cluster. However, the total scope of this project requires the following list of technologies:

DNS Solution

You will need to set up an Alias record (*.<base_project_domain>) directing traffic to an IP address sitting in front of Run Anywhere.

Network Load Balancer (or Reverse Proxy with Run Anywhere exposed as NodePort)

Will bind to a single IP address on the cluster and connect to a pod which serves as an internal router to all run anywhere services.

PostgreSQL Database

Backend storage for Run Anywhere

Minimum Specifications

Postgres 11+

Recommended Specifications

Postgres 13+

Redis Instance

Ephemeral data and Pub/Sub, used by the web app

Minimum Specifications

Redis 4+

Recommended Specifications

Redis 5+

Kubernetes Cluster

Compute resources for the Run Anywhere software stack

Minimum Specifications

  • 1 Master Node
  • 2 Worker Nodes
  • 24 GB of Memory
  • 8 GB of RAM
  • 2 CPUs

Recommended Specifications

  • 3 Master Nodes
  • 6 Worker Nodes (2 nodes each to provide a failover)
  • 100 GB of Memory
  • 16 GB of RAM
  • 4 CPUs

Key Management Solution

Can be HSM or KMS - will be used to store the encryption key to your Root Certificate Authority.


Install Embedded Cluster on VMs

curl | sudo bash -s ha


Smallstep services currently use Linkerd for some internal load balancing needs. Install it manually with a long-lived certificate. Linkerd comes with a default certificate with a lifetime of 1 year; we don’t want our CA to become useless in 1 year, so this step is necessary. However, we may eventually remove the dependency on Linkerd.

First, create a root CA cert and key:

step certificate create root.linkerd.cluster.local ca.crt ca.key \
  --profile root-ca --no-password --insecure --not-after=87600h

Use the CA to issue an identity certificate for Linkerd:

step certificate create identity.linkerd.cluster.local issuer.crt issuer.key \
  --profile intermediate-ca --not-after 87600h --no-password --insecure \
  --ca ca.crt --ca-key ca.key

Install Linkerd, providing the files from the previous commands:

kubectl config use-context <your context>

linkerd install \
  --identity-trust-anchors-file ca.crt \
  --identity-issuer-certificate-file issuer.crt \
  --identity-issuer-key-file issuer.key \
  | kubectl apply -f -

Shred the key material:

shred -uv ca.key issuer.key


This project uses Kubernetes secrets internal to the Kubernetes cluster to manage the passwords for Run Anywhere. Generate and add them to the cluster using the following commands.

kubectl create secret -n smallstep generic postgresql --from-literal=password=<pg-pass>

kubectl create secret -n smallstep generic smtp --from-literal=password=<smtp-pass>

# generate random
cat /dev/urandom | head -c 32 | step base64 -u -r | xargs -r echo -n 2> /dev/null

kubectl create secret -n smallstep generic auth --from-literal=secret=<random-string>

# generate random
cat /dev/urandom | head -c 32 | step base64 -u -r | xargs -r echo -n 2> /dev/null

kubectl create secret -n smallstep generic majordomo-provisioner-password --from-literal=password=<random-string>

# generate JWK keys
echo -n "{\"keys\": [$(step crypto jwk create /dev/null /dev/stdout --kty RSA --force --no-password --insecure 2> /dev/null &)]}"

kubectl create secret -n smallstep generic oidc --from-literal=jwks=<json-output>

kubectl create secret -n smallstep generic scim-server-secrets --from-literal=credentials.json=""

Next Steps

Now that your cloud infrastructure is in place, the K8s cluster is running, and in a good state, DNS has propagated, and your cluster keys have been rotated out:

Continue to SSH Professional Setup


Continue to Certificate Manager Setup