Skip to main content

Kubernetes Quickstart

This quick-start will show you how to deploy Pomerium with Kubernetes.

Prerequisites

  • Install kubectl.
  • A Kubernetes provider.
    • A cluster, with your local kubectl authorized to interact with it.
  • A configured identity provider.
  • A domain space. The steps below use *.localhost.pomerium.io as a placeholder value. We have set DNS records for this domain space to point to 127.0.0.1 (localhost), so you can use this domain space when testing Pomerium locally.
  • TLS certificates. If you don't yet have a production environment with trusted certificates, this page will cover using mkcert to create locally trusted certificates.

Certificates

This setup uses mkcert to generate certificates that are trusted by your local web browser for testing. If you already have a certificate solution, you can skip the steps below and move on to the next stage.

Install mkcert

  1. After installing mkcert, confirm the presence and names of your local CA files:

    mkcert -install
    The local CA is already installed in the system trust store! 👍
    The local CA is already installed in the Firefox and/or Chrome/Chromium trust store! 👍

    ls "$(mkcert -CAROOT)"
    rootCA-key.pem rootCA.pem

    The output of mkcert -install may vary depending on your operating system.

  2. Generate a wildcard certificate and key for Pomerium to use:

mkcert "*.localhost.pomerium.io"

Install Pomerium

  1. Install Pomerium to your cluster:
kubectl apply -k github.com/pomerium/ingress-controller/config/default\?ref=v0.20.0

This will create all the components of Pomerium in the pomerium namespace, as well as a bootstrap secret:

namespace/pomerium created
customresourcedefinition.apiextensions.k8s.io/pomerium.ingress.pomerium.io created
serviceaccount/pomerium-controller created
serviceaccount/pomerium-gen-secrets created
clusterrole.rbac.authorization.k8s.io/pomerium-controller created
clusterrole.rbac.authorization.k8s.io/pomerium-gen-secrets created
clusterrolebinding.rbac.authorization.k8s.io/pomerium-controller created
clusterrolebinding.rbac.authorization.k8s.io/pomerium-gen-secrets created
service/pomerium-metrics created
service/pomerium-proxy created
deployment.apps/pomerium created
job.batch/pomerium-gen-secrets created
ingressclass.networking.k8s.io/pomerium created
  1. Add the certificate created earlier and key to the cluster as a Secret:
kubectl create secret tls pomerium-wildcard-tls --namespace=pomerium \
--cert=./_wildcard.localhost.pomerium.io.pem --key=./_wildcard.localhost.pomerium.io-key.pem
  1. Define a Kubernetes secret to hold identity provider (IdP) credentials:
idp-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: idp
namespace: pomerium
type: Opaque
stringData:
client_id: ${IDP_PROVIDED_CLIENT_ID}
client_secret: ${IDP_PROVIDED_CLIENT_SECRET}

The data required in this secret will depend on your identity provider. See the Kubernetes Reference page for all available keys, and cross-reference it with the requirements of your IdP.

  1. Provide this secret to the cluster:
kubectl apply -f idp-secret.yaml

You can confirm with kubectl get secrets --namespace pomerium:

NAME                               TYPE                                  DATA   AGE
bootstrap Opaque 3 99m
default-token-whpnw kubernetes.io/service-account-token 3 149m
idp Opaque 2 5s
pomerium-controller-token-cckv5 kubernetes.io/service-account-token 3 99m
pomerium-gen-secrets-token-4pdkd kubernetes.io/service-account-token 3 99m
  1. Define the global Pomerium settings:
pomerium.yaml
apiVersion: ingress.pomerium.io/v1
kind: Pomerium
metadata:
name: global
spec:
secrets: pomerium/bootstrap
authenticate:
url: https://authenticate.localhost.pomerium.io
identityProvider:
provider: ${YOUR_IdP}
secret: pomerium/idp
certificates:
- pomerium/pomerium-wildcard-tls
  1. Apply the global settings:
kubectl apply -f pomerium.yaml

The Pomerium Proxy service should now be running in your cluster:

kubectl describe pomerium
Name: global
Namespace:
Labels: <none>
Annotations: <none>
API Version: ingress.pomerium.io/v1
Kind: Pomerium
Metadata:
...

You should now be able to access https://authenticate.localhost.pomerium.io/ which, after signing in with your IdP, should redirect you to the .pomerium endpoint.

Test Service

  1. Define a test service. We'll use the Pomerium Verify app:
verify-service.yaml
apiVersion: v1
kind: Service
metadata:
name: verify
labels:
app: verify
service: verify
spec:
ports:
- port: 8000
targetPort: 8000
name: http
selector:
app: pomerium-verify
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: verify
spec:
replicas: 1
selector:
matchLabels:
app: pomerium-verify
template:
metadata:
labels:
app: pomerium-verify
spec:
containers:
- image: docker.io/pomerium/verify
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 8000
protocol: TCP
name: http

Deploy it with kubectl apply -f verify-service.yaml

  1. Define an Ingress for the new service:
verify-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: verify
annotations:
ingress.pomerium.io/allowed_domains: |
- example.com
ingress.pomerium.io/pass_identity_headers: 'true'
spec:
ingressClassName: pomerium
rules:
- host: 'verify.localhost.pomerium.io'
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: verify
port:
number: 8000

Note that we include the annotation ingress.pomerium.io/pass_identity_headers, which provides a JWT to the Verify service.

Deploy the service with kubectl apply -f verify-ingress.yaml, and visit the path in your browser:

The top of the Pomerium Verify page

tip

Identity verification fails because we're using an untrusted test certificate. Updating your deployment with a trusted certificate solution like Let's Encrypt through cert-manager will resolve this error.

Next steps

Once Pomerium is configured, you should configure persistence. This prevents the loss of user sessions if containers are restarted, and supports deployments with multiple replicas. See our Kubernetes Reference page for more information on configuring Databroker storage.

Troubleshooting

Pomerium posts events to the Ingress and Pomerium objects, which may be inspected with the kubectl describe command:

kubectl describe pomerium

The Spec section provides details on the Pomerium configuration:

Spec:
Authenticate:
URL: https://authenticate.localhost.pomerium.io
Certificates: pomerium/pomerium-wildcard-tls
Identity Provider:
Provider: github
Secret: pomerium/idp
Secrets: pomerium/bootstrap

The Status section details what Ingresses are configured:

Status:
Ingress:
pomerium/verify:
Last Reconciled: 2022-07-13T16:38:39Z
Reconciled: true

And the Events section will provide useful debug information about recent updates to the configuration:

Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Updated 3m28s pomerium Pomerium configuration updated
Normal Updated 42s pomerium pomerium/verify: Pomerium configuration updated