Deploying PrivateBin on K3s
Continuing my line of posts about services that I run in K8s, I wanted to blog about my deployment of PrivateBin. PrivateBin is described as:
A minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bits AES.
I decided to deploy PrivateBin as an alternative to texting secrets or sharing them directly from a password manager with my family. This service doesn’t get used that often, but it’s light weight and there when we need it. PrivateBin publishes a container to DockerHub, so it was straightforward to setup with a small PVC backend for storage.
Deploying PrivateBin in K3s
I run K3s in my home lab and leverage most of the built in utilities that come with it, such as Traefik ingress. I also have Longhorn installed for block storage provisioning.
Persistent Volume Claim
The only contents shared over PrivateBin are small secrets, so a 2GB
PVC is well more than this service needs for sharing small secrets for a short amount of time. The following pvc.yml
file defines the PVC.
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: privatebin-pvc
namespace: privatebin
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 2Gi
Service
The PrivateBin container exposes its interface over port 8080, so service.yml
exposes the same port.
---
apiVersion: v1
kind: Service
metadata:
name: privatebin-service
namespace: privatebin
spec:
ports:
- name: web
port: 8080
targetPort: 8080
selector:
app: privatebin
Ingress
The ingress.yml
file implements Traefik annotations to expose HTTP and HTTPS ports. I also have a middleware defined in the default namespace that redirects HTTP traffic to HTTPS. Lastly, I used a certmanager annotation to issue an TLS certificate that Traefik will use for TLS termination.
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: privatebin-ingress
namespace: privatebin
annotations:
traefik.ingress.kubernetes.io/router.middlewares: default-redirect@kubernetescrd
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
cert-manager.io/cluster-issuer: letsencrypt-aws
spec:
rules:
- host: privatebin.domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: privatebin-service
port:
number: 8080
tls:
- secretName: ssl-cert
hosts:
- privatebin.domain
Deployment
Lastly, deployment.yml
implements the deployment. The PVC is mounted to the pod at /srv/data
, which is the container’s default storage location. The important configuration is the securityContext
which defines the user and group that the pod will run as. If you do not set these values, then PrivateBin will present an error when attempting to save secrets due to an inability to write to the file system.
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: privatebin
name: privatebin-deployment
namespace: privatebin
spec:
replicas: 1
selector:
matchLabels:
app: privatebin
template:
metadata:
labels:
app: privatebin
spec:
securityContext:
runAsUser: 65534
runAsGroup: 82
fsGroup: 82
terminationGracePeriodSeconds: 40
containers:
- name: privatebin
image: privatebin/nginx-fpm-alpine:stable
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
protocol: TCP
env:
- name: TZ
value: America/New_York
- name: PHP_TZ
value: America/New_York
livenessProbe:
httpGet:
path: /
port: 8080
readinessProbe:
httpGet:
path: /
port: 8080
volumeMounts:
- name: privatebin-volume
mountPath: /srv/data
readOnly: false
volumes:
- name: privatebin-volume
persistentVolumeClaim:
claimName: privatebin-pvc
Applying the Configuration
Now, just apply all of the files to your cluster. PrivateBin should be running in your cluster once the services start and the TLS certificate is issued.
kubectl apply -f .