Deploy OSS on Kubernetes

Deploy open source Password Pusher on Kubernetes with Helm, raw manifests, or Kustomize.

This article applies to: OSS Self-Hosted

Deploy OSS Password Pusher on Kubernetes

This guide covers running open source Password Pusher on Kubernetes. The public image is pglombardo/pwpush on Docker Hub. The app listens on HTTP port 5100. Terminate TLS at Ingress (or your load balancer); do not set TLS_DOMAIN inside the container when Kubernetes already handles HTTPS.

For most teams, Docker Compose on a single VM is simpler. Use Kubernetes when you already operate a cluster and want GitOps, Ingress, and cluster-native secrets.

Looking for Pro Self-Hosted? Use the official Pro Helm chart instead. It is a different chart, private images, and a license.


Which method should I use?

Method Best for Persistence Source
Helm (recommended) Most Kubernetes teams You add Postgres and/or a PVC Official starter chart in the OSS repo
Raw manifests Simple clusters with nginx Ingress + cert-manager Ephemeral, or sidecar Postgres + hostPath Official examples in the OSS repo
Kustomize GitOps overlays, patches, AWS ALB Community example is ephemeral; wrap official files for your own storage Official files + community Kustomize repo

All three use the same image and the same PWP__... environment variables. See Configuration and Database URL.


Prerequisites

  • Kubernetes 1.24 or later
  • kubectl
  • For Helm: Helm 3.x
  • For Kustomize: kubectl with -k (built in) or the kustomize CLI
  • An Ingress controller if you want a public hostname (nginx, AWS ALB, Traefik, etc.)

Pin an image tag. Prefer stable or a version tag such as v2.x.x over an untagged latest.


The official chart lives at containers/helm. It deploys a Deployment, Service (port 5100), and optional Ingress. It does not bundle PostgreSQL. Treat it as a starting point and add your own database, secrets, and storage.

Install

git clone https://github.com/pglombardo/PasswordPusher.git
cd PasswordPusher/containers/helm

helm install my-passwordpusher . \
  --create-namespace \
  --namespace pwpush

Port-forward to confirm the app is up:

kubectl port-forward --namespace pwpush svc/my-passwordpusher 5555:5100

Then open http://localhost:5555.

Secrets

Create a Kubernetes Secret for encryption and session keys, then point the chart at it. The chart reads encKeys.existingSecret (pwpush-keys by default) via envFrom.

kubectl create namespace pwpush

kubectl create secret generic pwpush-keys \
  --namespace pwpush \
  --from-literal=PWPUSH_MASTER_KEY='your-master-key' \
  --from-literal=SECRET_KEY_BASE='your-secret-key-base'

Generate keys with the guidance in Application encryption. Keep these values. Losing PWPUSH_MASTER_KEY means existing push payloads cannot be decrypted.

Example values

Create values.yaml:

image:
  repository: docker.io/pglombardo/pwpush
  tag: "stable"
  pullPolicy: IfNotPresent

replicaCount: 1

encKeys:
  existingSecret: pwpush-keys

env:
  PWP__ALLOW_ANONYMOUS: "true"
  PWP__LOG_TO_STDOUT: "true"
  # DATABASE_URL: postgres://user:pass@postgres:5432/pwpush

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: pwpush.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: pwpush-tls
      hosts:
        - pwpush.example.com

Install or upgrade with that file:

helm upgrade --install my-passwordpusher . \
  --namespace pwpush \
  --create-namespace \
  -f values.yaml

Useful chart knobs: env (any PWP__... or DATABASE_URL), ingress.*, resources, volumes / volumeMounts for file storage, replicaCount.

The default probes hit /. The application also exposes /up as a health endpoint; you can point probes there if you prefer.

Uninstall

helm uninstall my-passwordpusher --namespace pwpush

Secrets and PVCs are not removed automatically. Delete them yourself if you intend to wipe the install.


Raw Kubernetes manifests

Example manifests are in containers/kubernetes. They assume:

  • An nginx Ingress controller
  • cert-manager with a ClusterIssuer named letsencrypt-prod
  • Hostname pwpush.domain.tld (change this before apply)

They create namespace pwpush, a Deployment, Service pwpush-http on port 5100, and an Ingress.

Update the Ingress API before you apply. The bundled ingress.yaml still uses extensions/v1beta1, which modern clusters reject. Convert it to networking.k8s.io/v1 (service name pwpush-http, port 5100) to match your Ingress controller.

Set your hostname:

sed -i 's|pwpush.domain.tld|pwpush.your.domain.here|g' containers/kubernetes/ingress.yaml

Ephemeral

SQLite lives in the container. A pod restart wipes all pushes. Fine for demos, not for production.

kubectl apply -f containers/kubernetes/namespace.yaml
kubectl apply -f containers/kubernetes/ephemeral_deploy.yaml
kubectl apply -f containers/kubernetes/service.yaml
kubectl apply -f containers/kubernetes/ingress.yaml

Persistent (example)

The persistent example runs Postgres in the same pod and mounts a hostPath volume defaulting to /nfs/k8s/services/pwpush/data. Change that path, or replace pv.yaml with storage that matches your cluster (CSI, EBS, Azure Disk, NFS, etc.).

sed -i 's|/nfs/k8s/services/pwpush/data|/your/path/here|g' containers/kubernetes/pv.yaml

kubectl apply -f containers/kubernetes/namespace.yaml
kubectl apply -f containers/kubernetes/pv.yaml
kubectl apply -f containers/kubernetes/pvc.yaml
kubectl apply -f containers/kubernetes/persistent_deploy.yaml
kubectl apply -f containers/kubernetes/service.yaml
kubectl apply -f containers/kubernetes/ingress.yaml

For production, prefer an external PostgreSQL (managed or in-cluster operator) via DATABASE_URL, not a sidecar in the app pod. See Database URL.


Kustomize

The OSS repo does not ship a kustomization.yaml. You can wrap the official manifests (or Helm output) in your own overlay, or start from the community project below.

Community: weyderfs/pwpush-k8s

weyderfs/pwpush-k8s is a community Kustomize layout (see GitHub discussion #2364 and issue #2370).

It deploys a single replica, a Service on port 5100, and an AWS ALB Ingress scheme. It is ephemeral: if the pod is replaced, in-flight pushes are lost. Customize the YAMLs, then:

git clone https://github.com/weyderfs/pwpush-k8s.git
cd pwpush-k8s
kubectl apply -k .

Tear down with kubectl delete -k ..

This is not an Apnotic-maintained chart. Review it like any third-party manifest (image tag, Ingress class, secrets, storage) before you use it in production.

Your own overlay

A typical GitOps layout:

overlays/prod/
  kustomization.yaml
  ingress-patch.yaml
  secret-generator.yaml   # or ExternalSecret

kustomization.yaml example:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: pwpush
resources:
  - github.com/pglombardo/PasswordPusher/containers/kubernetes?ref=master
patches:
  - path: ingress-patch.yaml
images:
  - name: docker.io/pglombardo/pwpush
    newTag: stable

The containers/kubernetes folder is a set of example YAMLs, not a ready-made Kustomize base (no kustomization.yaml, mixed ephemeral/persistent files). Copy the files you need into your base, or list explicit remote URLs, rather than pointing Kustomize at the whole directory.

You can also render Helm and patch with Kustomize:

helm template my-passwordpusher ./containers/helm -f values.yaml > /tmp/pwpush.yaml
# add /tmp/pwpush.yaml as a resource in kustomization.yaml, then:
kubectl apply -k overlays/prod

Production notes

  • One replica with SQLite. Do not scale replicaCount above 1 unless you use PostgreSQL (or another shared DATABASE_URL).
  • Persist encryption keys. Store PWPUSH_MASTER_KEY and SECRET_KEY_BASE in a Secret (or an external secret store). Backup those values with the database.
  • External database. Sidecar Postgres is only an example. Use a managed or operator-managed database and set DATABASE_URL.
  • TLS at Ingress. Forward HTTP to port 5100. The app honors X-Forwarded-Proto when your Ingress sets it.
  • File pushes. If you enable local file storage, mount a PVC at the storage path. Object storage (s3 / gcs / azure) is usually easier in Kubernetes. See file storage.
  • Public Gateway. To expose only push retrieval, run pglombardo/pwpush-public-gateway as a separate Deployment/Service with a tighter Ingress.
  • Config. Same env vars as Docker Compose. See docker-compose.yml and Configuration strategies.

Topic Doc
Docker Compose install OSS Installation
Env vars and settings Configuration
DATABASE_URL Database URL
Encryption keys Application encryption
Helm chart source containers/helm
Example manifests containers/kubernetes
Community Kustomize weyderfs/pwpush-k8s
Pro on Kubernetes Deploy Pro on Kubernetes