Skip to content

Installer PrivateBin en conteneur LXC sur Proxmox

Guide d'installation manuelle, étape par étape, de PrivateBin (partage de texte chiffré côté client) en conteneur LXC Proxmox, via Nginx + PHP-FPM.


Prérequis

  • Un hôte Proxmox VE avec accès pct
  • Un pool de stockage local-lvm (ou adapter les commandes à votre pool)
  • Accès internet depuis l'hôte (téléchargement du template Debian et de l'archive PrivateBin)

Valeurs d'exemple utilisées dans ce guide :

Paramètre Valeur d'exemple
ID du conteneur 201
IP fixe 192.168.1.201/24 (ou dhcp)
Version PrivateBin 1.7.4
Port interne 8080
Port externe (NAT) 9160

1⃣ Création du conteneur LXC

pveam update
pveam available | grep debian-12-standard
pveam download local debian-12-standard_12.7-1_amd64.tar.zst

pct create 201 local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst \
    --hostname privatebin.votre-domaine.tld \
    --memory 512 \
    --swap 256 \
    --cores 1 \
    --rootfs local-lvm:8 \
    --net0 name=eth0,bridge=vmbr0,ip=192.168.1.201/24,gw=192.168.1.1 \
    --unprivileged 1 \
    --onboot 1

pct start 201

2⃣ Installation des paquets

pct exec 201 -- apt update
pct exec 201 -- apt install -y nginx php8.2-fpm php8.2-sqlite3 php8.2-gd php8.2-opcache wget unzip curl

3⃣ Téléchargement de PrivateBin

pct exec 201 -- bash -c "
    cd /var/www &&
    wget -q https://github.com/PrivateBin/PrivateBin/archive/refs/tags/1.7.4.tar.gz &&
    tar xzf 1.7.4.tar.gz &&
    mv PrivateBin-1.7.4 privatebin &&
    rm 1.7.4.tar.gz
"

4⃣ Configuration Nginx

Créer le virtual host /etc/nginx/sites-available/privatebin :

pct exec 201 -- bash -c "cat > /etc/nginx/sites-available/privatebin" << 'EOF'
server {
    listen 8080;
    server_name _;
    root /var/www/privatebin;
    index index.php;

    client_max_body_size 10M;

    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /data { deny all; }
    location ~ /cfg  { deny all; }
    location ~ /\.ht { deny all; }

    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}
EOF

pct exec 201 -- ln -sf /etc/nginx/sites-available/privatebin /etc/nginx/sites-enabled/privatebin
pct exec 201 -- rm -f /etc/nginx/sites-enabled/default
pct exec 201 -- nginx -t

5⃣ Configuration PHP

pct exec 201 -- bash -c "cat > /etc/php/8.2/fpm/conf.d/99-privatebin.ini" << 'EOF'
[PHP]
upload_max_filesize = 10M
post_max_size = 10M
memory_limit = 128M
max_execution_time = 60

session.cookie_httponly = 1
session.use_strict_mode = 1

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,show_source
expose_php = Off
allow_url_fopen = Off

upload_tmp_dir = /tmp
EOF

6⃣ Configuration applicative de PrivateBin

Créer /var/www/privatebin/cfg/conf.php :

pct exec 201 -- bash -c "cat > /var/www/privatebin/cfg/conf.php" << 'EOF'
;<?php http_response_code(403); /*

[main]
name = "PrivateBin"
discussion = true
opendiscussion = false
password = true
fileupload = false
sizelimit = 10485760
template = "bootstrap"
languageselection = false
qrcode = true

[expire]
default = "1week"

[expire_options]
5min = 300
10min = 600
1hour = 3600
1day = 86400
1week = 604800
1month = 2592000
1year = 31536000
never = 0

[formatter_options]
plaintext = "Plain Text"
syntaxhighlighting = "Source Code"
markdown = "Markdown"

[traffic]
limit = 10
header = "X_FORWARDED_FOR"

[model]
class = Filesystem

[model_options]
dir = PATH "data"
EOF

La première ligne (;<?php http_response_code(403); /*) empêche l'exécution du fichier comme script PHP s'il est accédé directement via le navigateur — c'est une convention PrivateBin, à ne pas retirer.


7⃣ Permissions et démarrage

pct exec 201 -- mkdir -p /var/www/privatebin/data /var/www/privatebin/tmp
pct exec 201 -- chown -R www-data:www-data /var/www/privatebin
pct exec 201 -- chmod -R 755 /var/www/privatebin
pct exec 201 -- chmod 640 /var/www/privatebin/cfg/conf.php /var/www/privatebin/cfg/conf.sample.php

pct exec 201 -- systemctl restart php8.2-fpm nginx

8⃣ Redirection du port externe (NAT)

CT_IP=192.168.1.201
iptables -t nat -A PREROUTING -p tcp --dport 9160 -j DNAT --to-destination $CT_IP:8080
iptables -I FORWARD -p tcp -d $CT_IP --dport 8080 -j ACCEPT
iptables-save > /etc/iptables.rules

Accès : http://<IP_HÔTE>:9160 (ou en interne directement http://192.168.1.201:8080).


⚙️ Points d'administration importants

  • Le chiffrement est côté client : le serveur ne stocke que des données déjà chiffrées dans /var/www/privatebin/data/, sans la clé (transmise uniquement dans le fragment d'URL, jamais envoyée au serveur). Une sauvegarde de ce dossier ne compromet donc pas la confidentialité des pâtes, mais leur perte est définitive sans clé.
  • Sauvegarde : sauvegarder /var/www/privatebin/data/ (contenu chiffré) et /var/www/privatebin/cfg/conf.php (configuration). Une simple archive tar suffit.
  • Restreindre les fonctions PHP dangereuses (disable_functions dans le .ini ci-dessus) limite la surface d'attaque en cas de faille dans PrivateBin ou ses dépendances — à conserver même après mise à jour.
  • Mettre à jour PrivateBin : télécharger la nouvelle archive sur GitHub, en conservant cfg/conf.php et le dossier data/. Toujours lire le changelog avant une mise à jour majeure.
  • Exposer en HTTPS uniquement (via un reverse proxy comme Caddy) : sans TLS, le contenu chiffré transite en clair entre le client et le serveur au moment du chargement de la page (même si le texte du paste reste chiffré côté navigateur).
  • Limiter la taille des pâtes (sizelimit dans conf.php) selon votre cas d'usage, pour éviter qu'un disque ne se remplisse via des envois abusifs.
  • Purge des pâtes expirées : PrivateBin ne purge pas automatiquement les pâtes dont l'expiration est passée (elles deviennent juste inaccessibles). Ajouter un cron appelant cronjob.php à la racine de l'installation :
    pct exec 201 -- bash -c 'echo "0 3 * * * www-data php /var/www/privatebin/cronjob.php" > /etc/cron.d/privatebin-purge'
    

Conclusion

PrivateBin en LXC dédié fournit un service de partage de texte chiffré rapide à mettre en place, avec une configuration entièrement déclarative (conf.php) et peu de surface d'administration au quotidien.