feat(privatebin): añadir stack de pastebin cifrado end-to-end

PrivateBin como pastebin autohospedado con cifrado en el cliente,
protegido con Authentik SSO.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Eduardo David Paredes Vara
2026-05-25 05:49:55 +00:00
parent 66bec9992d
commit f390ac8828
3 changed files with 102 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
services:
privatebin:
image: ${PRIVATEBIN_IMAGE}
container_name: privatebin
restart: unless-stopped
read_only: true
user: "65534:65534"
volumes:
- ${PRIVATEBIN_DATA_PATH}:/srv/data:Z
- ./nginx-site.conf:/etc/nginx/http.d/site.conf:ro,Z
networks:
- proxy
labels:
traefik.enable: "true"
traefik.docker.network: "${TRAEFIK_DOCKER_NETWORK}"
# Router publico — permite abrir enlaces compartidos sin login.
traefik.http.routers.pbin-public.rule: "Host(`${PRIVATEBIN_DOMAIN}`) && (Method(`GET`) || Method(`HEAD`))"
traefik.http.routers.pbin-public.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.pbin-public.tls: "true"
traefik.http.routers.pbin-public.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.pbin-public.middlewares: "crowdsec-bouncer@file"
traefik.http.routers.pbin-public.service: "pbin-svc"
traefik.http.routers.pbin-public.priority: "20"
# Router protegido — crear/borrar requiere login.
traefik.http.routers.pbin.rule: "Host(`${PRIVATEBIN_DOMAIN}`)"
traefik.http.routers.pbin.entrypoints: "${TRAEFIK_ENTRYPOINT_SECURE}"
traefik.http.routers.pbin.tls: "true"
traefik.http.routers.pbin.tls.certresolver: "${TRAEFIK_CERTRESOLVER}"
traefik.http.routers.pbin.middlewares: "crowdsec-bouncer@file,${TRAEFIK_AUTH_MIDDLEWARE}"
traefik.http.routers.pbin.service: "pbin-svc"
traefik.http.routers.pbin.priority: "10"
traefik.http.services.pbin-svc.loadbalancer.server.port: "8080"
homepage.group: "Automatizacion y desarrollo"
homepage.name: "PrivateBin"
homepage.icon: "privatebin.png"
homepage.href: "https://${PRIVATEBIN_DOMAIN}/"
homepage.description: "Pastebin cifrado de extremo a extremo"
homepage.siteMonitor: "https://${PRIVATEBIN_DOMAIN}/"
networks:
proxy:
external: true
+46
View File
@@ -0,0 +1,46 @@
server {
listen 8080 default_server;
listen [::]:8080 default_server;
root /var/www;
index index.php index.html index.htm;
set $privatebin_needs_auth 0;
if ($request_uri = "/") {
set $privatebin_needs_auth "${privatebin_needs_auth}1";
}
if ($http_cookie !~* "privatebin_auth_ready=1") {
set $privatebin_needs_auth "${privatebin_needs_auth}1";
}
if ($privatebin_needs_auth = "011") {
return 302 https://$host/outpost.goauthentik.io/start?rd=/_auth_done;
}
location = /_auth_done {
add_header Set-Cookie "privatebin_auth_ready=1; Path=/; Max-Age=3300; Secure; HttpOnly; SameSite=Lax";
return 302 https://$host/;
}
location / {
add_header Cache-Control "public, max-age=3600, must-revalidate, no-transform";
add_header Cross-Origin-Embedder-Policy require-corp;
add_header Cross-Origin-Resource-Policy same-origin;
add_header Referrer-Policy no-referrer;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options deny;
include /etc/nginx/location.d/*.conf;
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include /etc/nginx/location.d/*.conf;
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param SERVER_SOFTWARE "";
}
include /etc/nginx/server.d/*.conf;
}
+10
View File
@@ -0,0 +1,10 @@
##### PrivateBin #####
PRIVATEBIN_IMAGE=privatebin/nginx-fpm-alpine:latest
PRIVATEBIN_DOMAIN=pastebin.example.com
PRIVATEBIN_DATA_PATH=/opt/privatebin/data
##### Traefik #####
TRAEFIK_DOCKER_NETWORK=proxy
TRAEFIK_ENTRYPOINT_SECURE=websecure
TRAEFIK_CERTRESOLVER=letsencrypt
TRAEFIK_AUTH_MIDDLEWARE=ths-authentik@docker