Despliega tu propio servidor PrivateBin colaborativo y seguro en Kubernetes
¿Te gustaría ofrecer a tus usuarios un servicio de notas colaborativas instantáneas, totalmente privado, sin depender de plataformas externas como Pastebin o Google Docs rápidos? Hoy desplegamos PrivateBin en Kubernetes: una app de moda para compartir texto colaborativamente en tiempo real, con cifrado extremo a extremo. Además, añadiremos autenticación opcional, almacenamiento persistente y HTTPS con Cert-Manager. ¡Nivel intermedio-avanzado y utilidad real para equipos y comunidades!
¿Qué es PrivateBin y por qué lo usarías?
- Plataforma de pegado (“pastebin”) privado: Los mensajes se cifran en el navegador antes de subirlos al servidor; el administrador jamás ve los textos “en claro”.
- Ideal para equipos, bug reporting, entornos DevSecOps: Comparte logs, credenciales temporales o código sensible sin escapar de tu propia infraestructura.
- Apoyado por la comunidad de ciberseguridad: Es el sustituto recomendado de pads inseguros para compartir secreto entre equipos.
Hoy lo montamos con:
- Autenticación básica (evitando abusos públicos)
- HTTPS automático con Cert-Manager
- Almacenamiento persistente en un PVC (para adjuntos o logs)
- Despliegue escalable (replicas controladas por Deployment)
Arquitectura Kubernetes
Nuestro stack será sencillo pero robusto:
- 1 Service de tipo ClusterIP
- 1 Deployment (PrivateBin con sidecar nginx para autenticación básica)
- 1 Ingress con anotaciones para Cert-Manager e integración HTTPS automática
- 1 PersistentVolumeClaim (almacenamiento de archivos o logs, configurable)
¿No tienes Cert-Manager? Puedes saltarte las anotaciones del Ingress y usar un Ingress Controller con TLS manual.
Ficheros YAML completos del despliegue
ConfigMap: configuración personalizada de PrivateBin
apiVersion: v1
kind: ConfigMap
metadata:
name: privatebin-config
data:
conf.php: |
<?php
return [
"expire" => "1d",
"fileupload" => true,
"sizelimit" => 10485760,
"opendiscussion" => true,
"password" => true,
"burnafterreading" => true,
"formatter" => "markdown",
];
?>
PVC: almacenamiento persistente
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: privatebin-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Deployment: PrivateBin + Nginx con autenticación básica
apiVersion: apps/v1
kind: Deployment
metadata:
name: privatebin
spec:
replicas: 2
selector:
matchLabels:
app: privatebin
template:
metadata:
labels:
app: privatebin
spec:
containers:
- name: privatebin
image: privatebin/nginx-fpm-alpine:1.6.0
ports:
- containerPort: 8080
volumeMounts:
- name: config
mountPath: /srv/cfg/
- name: storage
mountPath: /srv/data
- name: nginx-auth
image: docker.io/nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: htpasswd
mountPath: /etc/nginx/conf.d/
env:
- name: PRIVATEBIN_UPSTREAM
value: "localhost:8080"
volumes:
- name: config
configMap:
name: privatebin-config
items:
- key: conf.php
path: conf.php
- name: storage
persistentVolumeClaim:
claimName: privatebin-pvc
- name: htpasswd
secret:
secretName: privatebin-htpasswd
Secret: usuario y password (htpasswd)
apiVersion: v1
kind: Secret
metadata:
name: privatebin-htpasswd
data:
htpasswd: |
dXNlciRhcHI6JDEkNkhHT0o1eTh6TXhOZ0ZUZ3U5WUV0cG9OeUrgZW54LnJMejRLRytlR2JMSTZlQzEyVWNNUldEOGVDRG4wOQ==
La línea anterior es un htpasswd
base64 con usuario “user☁️” y contraseña “changeme”. Genera el tuyo localmente en producción.
Service
apiVersion: v1
kind: Service
metadata:
name: privatebin
spec:
selector:
app: privatebin
ports:
- port: 8080
targetPort: 8080
name: http
Ingress (cert-manager, HTTPS y path personalizado)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: privatebin-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
rules:
- host: "paste.tudominio.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: privatebin
port:
number: 8080
tls:
- hosts:
- "paste.tudominio.com"
secretName: privatebin-tls
Recuerda sustituir paste.tudominio.com
por el dominio que quieras usar; tendrás que crear el registro DNS adecuado.
¿Cómo lo despliego?
- Guarda cada bloque YAML en ficheros como
configmap-privatebin.yaml
,deployment.yaml
… - Lanza
kubectl apply -f
en tu clúster, uno a uno. - Comprueba que los pods y servicios levantan correctamente. Usa
kubectl get pods,svc,ingress
. - ¡Accede al dominio configurado! Prueba a loguearte con el usuario y pass… y comparte tu paste seguro.
Consejos extra y troubleshooting
-
Error 502 Gateway: Comprueba que tanto PrivateBin como nginx sidecar están levantados. Loguéate a ambos contenedores usando
kubectl exec -it
para ver logs. - Problemas con volúmenes persistentes: Si el storage da error, prueba a borrar y recrear el PVC (ojo, perderás almacenado).
-
Personaliza el
htpasswd
: Usahtpasswd -nb user password | base64
y reemplaza en el Secret. - Para aumentar la seguridad: Activa firewall de red en el Ingress (NetworkPolicy), limita el acceso por IP, y activa alertas si detectas movimientos extraños.
Si quieres que tus pastes se autodestruyan, simplemente configura la opción burnafterreading
como true
en el configMap.