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 -f https://raw.githubusercontent.com/pomerium/ingress-controller/main/deployment.yaml

    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
  2. 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
  3. 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.

  4. 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
  5. 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
  6. 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

  2. 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