· 8 min read · by pilippopilippo

CryptPad self-hosted su Proxmox


Contents

CryptPad è una suite di collaborazione (documenti, fogli di calcolo, presentazioni, kanban, moduli).
È un alternativa privata, cifrata e self-hosted a Google Docs.

In questa guida creeremo due VM Debian 13 in Proxmox dentro una DMZ/LAN, una con CryptPad e una con nginx come proxy HTTPS, con certificato Let’s Encrypt ottenuto tramite le API DNS di Cloudflare.

Due varianti:

  • A: tutte le porte disponibili, CryptPad risponde sulla 443.
  • B: solo una porta pubblica alta (negli esempi 49101), come con alcuni provider.

Prima di iniziare

  • Proxmox VE con circa 140 GiB liberi per due VM (compreso il disco dati da 100 GiB).
  • Firewall con una LAN/DMZ e port forward.
  • Dominio con DNS (in questa guida su Cloudflare).
  • IP pubblico raggiungibile sulla 443 o su una porta concessa dal provider.

Architettura

CryptPad richiede due domini diversi: il principale (accessi e chiavi) e il sandbox (interfaccia).
La separazione è un requisito di sicurezza: servono un certificato per entrambi e un proxy che li serva con lo stesso backend.

  • Proxy (10.99.0.251): nginx stabile da nginx.org e acme.sh, termina TLS.
    È l’unica macchina raggiungibile da internet.
  • CryptPad (10.99.0.201): Node.js 24, CryptPad 2026.5.1, editor office.
    Porte 3000 (HTTP) e 3003 (websocket), raggiungibili solo dal proxy.

Percorso: internet → port forward → proxy nginx (HTTPS) → CryptPad (HTTP 3000 e 3003).

Valori da preparare

Sostituisci gli esempi con i tuoi in tutti i comandi e i file.

  • Domini: pad.example.com e sandbox-pad.example.com (basta un altro sottodominio).
  • Porta pubblica: 443 oppure 49101.
  • IP: CryptPad 10.99.0.201, proxy 10.99.0.251, gateway della DMZ 10.99.0.1.
  • Email ACME: admin@example.com, riceve gli avvisi di Let’s Encrypt.
  • Disco dati: /dev/sdb, il disco da 100 GiB senza partizioni (lsblk).
  • Token API Cloudflare (segreto): My Profile → API Tokens → Create Token → modello Edit zone DNS, Zone Resources: Include → Specific zone → il tuo dominio.
    Viene mostrato una sola volta: salvalo nel gestore di password, mai in chat, documenti o cronologia della shell.
  • Zone ID Cloudflare (32 caratteri): dominio → Overview → colonna destra → API → Zone ID.
    Non è l’Account ID, che ha la stessa lunghezza.

Le due varianti

Variante A (443) B (49101)
Porta pubblica 443, più la 80 per il redirect Solo la porta scelta
Origini in config.js Senza porta Con la porta
nginx in ascolto 443 ssl, più il redirect dalla 80 49101 ssl, niente porta 80
Host verso CryptPad $host $http_host
Regole del firewall Port forward Port forward, a volte anche una regola di forward WAN → DMZ

Nella variante B la porta compare ovunque: origini, indirizzo (https://pad.example.com:49101/) e prove.
$http_host inoltra anche la porta, $host la perderebbe.
In entrambe il certificato usa il challenge DNS-01 (la HTTP-01 richiederebbe la porta 80).
Il resto è identico.

Rete, firewall e DNS

Internet → LAN: port forward verso il proxy e relativa regola.

DNS: un record per nome verso l’IP pubblico (A o CNAME).
Con Cloudflare: DNS only, nuvola grigia.
Verifica dal PC:

nslookup pad.example.com 1.1.1.1
nslookup sandbox-pad.example.com 1.1.1.1

VM in Proxmox

Dove: interfaccia web di Proxmox e console delle VM.

Parametro VM CryptPad VM proxy
Nome cryptpad nginx
CPU 2 core, tipo host 1 core, tipo host
RAM 4096 MiB 1024 MiB
Disco di sistema 20-30 GiB 8-10 GiB
Disco dati 100 GiB Nessuno

Per entrambe: controller VirtIO SCSI single, Qemu Agent, Discard (storage thin), rete VirtIO sul bridge della DMZ con il suo VLAN Tag, firewall di Proxmox disattivato, Start at boot.

Installazione di Debian:

  • Lingua inglese, rete manuale (IP, netmask, gateway e DNS della DMZ), hostname cryptpad o nginx, dominio vuoto.
  • Password di root vuota: root non accede e il primo utente ottiene sudo (password robusta).
  • Partizioni: Guided - use entire disk → All files in one partition.
  • Mirror deb.debian.org, Popularity contest no.
  • Software: solo SSH server e standard system utilities.
  • A fine installazione: Hardware → CD/DVD Drive → Do not use any media.

Poi, su entrambe le VM con il tuo utente:

sudo apt update
sudo apt full-upgrade -y
sudo apt install -y qemu-guest-agent
sudo reboot

CryptPad

Dove: Proxmox (Hardware → Add → Hard Disk, SCSI, 100 GiB), poi la VM con il tuo utente.

lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT

Atteso: un secondo disco da 100 GiB senza partizioni, di solito sdb (altrimenti adatta i comandi).

Attenzione: mkfs cancella tutto il disco indicato. Controlla due volte il nome.

sudo mkfs.ext4 -m 1 -L cryptpad-data /dev/sdb
sudo mkdir -p /var/lib/cryptpad
echo "UUID=$(sudo blkid -s UUID -o value /dev/sdb) /var/lib/cryptpad ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab
sudo systemctl daemon-reload
sudo mount -a
df -h /var/lib/cryptpad
tail -1 /etc/fstab

Atteso: il disco montato su /var/lib/cryptpad e una riga di fstab con il suo UUID.
-m 1 riserva a root l’1% invece del 5%.

Con il tuo utente:

sudo apt install -y git curl ca-certificates unzip
sudo adduser --disabled-password --gecos "" cryptpad
sudo chown cryptpad:cryptpad /var/lib/cryptpad

L’utente cryptpad non ha password: entra con sudo -iu cryptpad e installa NVM:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash

Esci (exit) e rientra (sudo -iu cryptpad) per caricare NVM, poi:

nvm install 24
node -v
command -v node

Atteso: v24.x.y e un percorso sotto /home/cryptpad/.nvm/.
Con il tuo utente Node dà Permission denied: è normale, /home/cryptpad è privata.

Con utente cryptpad:

Controlla l’ultima release (esclude i tag con prefisso, come opendesk-...):

git ls-remote --tags https://github.com/cryptpad/cryptpad | grep -oE 'refs/tags/[0-9]{4}\.[0-9]+\.[0-9]+$' | sed 's#refs/tags/##' | sort -V | tail -3

Atteso: l’ultima riga è 2026.5.1.
Se ce n’è una più recente, leggi prima le sue note di rilascio: la 2026.9.0 cambia server, configurazione ed editor office.

cd ~
git clone -b 2026.5.1 --depth 1 https://github.com/cryptpad/cryptpad.git cryptpad
cd cryptpad
npm ci
npm run install:components
./install-onlyoffice.sh --accept-license --trust-repository
ls www/common/onlyoffice/dist

L’ultimo script installa l’editor office (accetta la licenza di OnlyOffice) ed è facoltativo.
Atteso: le cartelle v1, v2b, …, x2t.
Gli avvisi su pacchetti deprecati sono normali; fermati se compare does not match expected checksum.

config.js

Imposta le variabili della tua variante (valgono solo nella shell corrente).
Variante A:

MAIN_ORIGIN="https://pad.example.com"
SANDBOX_ORIGIN="https://sandbox-pad.example.com"
CRYPTPAD_IP="10.99.0.201"

Variante B:

MAIN_ORIGIN="https://pad.example.com:49101"
SANDBOX_ORIGIN="https://sandbox-pad.example.com:49101"
CRYPTPAD_IP="10.99.0.201"

Poi crea config.js con domini, indirizzo e percorsi dei dati sul disco dati.
Il blocco riparte sempre dall’esempio, quindi si può rieseguire.

cd ~/cryptpad
cp config/config.example.js config/config.js
sed -i "s#^\(\s*\)httpUnsafeOrigin:.*#\1httpUnsafeOrigin: '${MAIN_ORIGIN}',#" config/config.js
sed -i "s#^\s*//\s*httpSafeOrigin:.*#    httpSafeOrigin: '${SANDBOX_ORIGIN}',#" config/config.js
sed -i "s#^\s*//\s*httpAddress:.*#    httpAddress: '${CRYPTPAD_IP}',#" config/config.js
sed -i \
 -e "s#^\(\s*\)filePath:.*#\1filePath: '/var/lib/cryptpad/datastore/',#" \
 -e "s#^\(\s*\)archivePath:.*#\1archivePath: '/var/lib/cryptpad/data/archive',#" \
 -e "s#^\(\s*\)pinPath:.*#\1pinPath: '/var/lib/cryptpad/data/pins',#" \
 -e "s#^\(\s*\)taskPath:.*#\1taskPath: '/var/lib/cryptpad/data/tasks',#" \
 -e "s#^\(\s*\)blockPath:.*#\1blockPath: '/var/lib/cryptpad/block',#" \
 -e "s#^\(\s*\)blobPath:.*#\1blobPath: '/var/lib/cryptpad/blob',#" \
 -e "s#^\(\s*\)blobStagingPath:.*#\1blobStagingPath: '/var/lib/cryptpad/data/blobstage',#" \
 -e "s#^\(\s*\)decreePath:.*#\1decreePath: '/var/lib/cryptpad/data/decrees',#" \
 -e "s#^\(\s*\)logPath:.*#\1logPath: '/var/lib/cryptpad/data/logs',#" config/config.js
sed -i "s#^\(\s*\)decreePath:.*#&\n\1base: '/var/lib/cryptpad/data',#" config/config.js
grep -nE "^\s*(httpUnsafeOrigin|httpSafeOrigin|httpAddress|filePath|archivePath|pinPath|taskPath|blockPath|blobPath|blobStagingPath|decreePath|base|logPath):" config/config.js

Atteso: tredici righe senza //, con i tuoi domini e il tuo IP.
httpAddress: '', significa variabili vuote: reimpostale e rifai il blocco.

application_config.js

Attenzione: il blocco genera ogni volta un loginSalt nuovo.
Eseguilo una sola volta, prima di creare account: dopo, bloccherebbe tutti gli accessi.

mkdir -p customize
cp customize.dist/application_config.js customize/application_config.js
SALT=$(tr -dc 'a-f0-9' </dev/urandom | head -c 64)
sed -i "s|^\(\s*\)return AppConfig;|\1AppConfig.loginSalt = '${SALT}';\n\1AppConfig.minimumPasswordLength = 12;\n\1AppConfig.disableAnonymousPadCreation = true;\n\1AppConfig.disableAnonymousStore = true;\n\1return AppConfig;|" customize/application_config.js
grep -nE "AppConfig\.(loginSalt|minimumPasswordLength|disableAnonymous)|return AppConfig" customize/application_config.js | sed -E "s/'[a-f0-9]{64}'/'(SALT)'/"

Atteso: quattro righe AppConfig sopra un solo return AppConfig; (il salt compare come (SALT)).

  • Salva il loginSalt (grep loginSalt customize/application_config.js) e includi customize/ nei backup: senza, gli account non entrano più.
  • Le righe disableAnonymous... impediscono a chi non è registrato di creare e salvare documenti; i link condivisi restano apribili.
  • Password minima di 12 caratteri.
  • Facoltativi: AppConfig.terms, AppConfig.privacy, AppConfig.imprint.

Infine:

npm run build

Servizio systemd

Con il tuo utente (exit da cryptpad).

NODE_BIN=$(sudo -u cryptpad bash -c 'export NVM_DIR=/home/cryptpad/.nvm; . "$NVM_DIR/nvm.sh" >/dev/null 2>&1; nvm which 24')
echo "$NODE_BIN"

Atteso: /home/cryptpad/.nvm/versions/node/v24.x.y/bin/node.

È il blocco ufficiale con due aggiunte: RequiresMountsFor (non parte senza il disco dati) e il disco dati in ReadWritePaths (necessario con ProtectSystem=strict).
Esegui il blocco da solo:

sudo tee /etc/systemd/system/cryptpad.service > /dev/null <<EOF
[Unit]
Description=CryptPad API server
RequiresMountsFor=/var/lib/cryptpad

[Service]
ExecStart=${NODE_BIN} /home/cryptpad/cryptpad/server.js
WorkingDirectory=/home/cryptpad/cryptpad
Restart=always
RestartSec=2
StandardOutput=journal
StandardError=journal+console
User=cryptpad
Group=cryptpad
Environment='PWD="/home/cryptpad/cryptpad"'
LimitNOFILE=1000000
ProcSubset=all
ProtectProc=invisible
CapabilityBoundingSet=
NoNewPrivileges=true
ProtectSystem=strict
PrivateTmp=true
PrivateDevices=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_INET
RestrictAddressFamilies=AF_INET6
RestrictAddressFamilies=AF_NETLINK
RestrictAddressFamilies=AF_UNIX
RestrictNamespaces=true
LockPersonality=true
RestrictRealtime=true
RestrictSUIDSGID=true
RemoveIPC=true
PrivateMounts=true
ProtectClock=true
SystemCallArchitectures=native
SystemCallFilter=~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid
SystemCallFilter=@chown
SystemCallFilter=pipe
SystemCallFilter=pipe2
ReadWritePaths=/home/cryptpad/cryptpad /var/lib/cryptpad

[Install]
WantedBy=multi-user.target
EOF
grep -E "ExecStart|ReadWritePaths|RequiresMountsFor" /etc/systemd/system/cryptpad.service
sudo systemctl daemon-reload
sudo systemctl enable --now cryptpad
sleep 5
systemctl is-active cryptpad
ss -tlnp | grep -E ':3000|:3003'
curl -sI http://10.99.0.201:3000 | head -3

Atteso: ExecStart con il percorso di Node, active, porte 3000 e 3003 in ascolto, HTTP 200.
La 3001 non serve: con httpSafeOrigin la sandbox passa dalla 3000.

URL di installazione dell’amministratore:

sudo journalctl -u cryptpad --no-pager | grep -i install

(forma https://pad.example.com/install/#...).
È monouso e riservato: annotalo senza aprirlo e usalo dalla LAN prima della pubblicazione.

Nginx

Con il tuo utente:

sudo apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg > /dev/null
gpg --show-keys --with-colons /usr/share/keyrings/nginx-archive-keyring.gpg | grep -c 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62

Atteso: almeno 1 (impronta della chiave); con 0 fermati.

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/debian `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx
sudo apt update
sudo apt install -y nginx
sudo nginx -v
apt-cache policy nginx | head -4
curl -sI http://10.99.0.201:3000 | head -1

Atteso: nginx 1.30.x o successivo da nginx.org e HTTP 200 da CryptPad.
nginx è in /usr/sbin, quindi serve sudo; il servizio resta inactive finché non è configurato.

Certificato

Come root (sudo -i):

curl https://get.acme.sh | sh -s email=admin@example.com
/root/.acme.sh/acme.sh --version
crontab -l | grep acme
/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt

Atteso: la versione e la riga di cron acme.sh --cron.\

Un comando per volta: incollando più righe, read prende la riga successiva come risposta.
Se il token finisce in una chat o in un file, revocalo e creane uno nuovo.

1. Token (non compare mentre lo incolli):

read -rsp "Token Cloudflare: " CF_Token; echo

2. Lunghezza del token, atteso più di zero (di solito circa 40):

echo ${#CF_Token}

3. Zone ID:

read -rp "Zone ID: " CF_Zone_ID

4. Lunghezza dello Zone ID, atteso esattamente 32:

echo ${#CF_Zone_ID}

5. Emissione:

export CF_Token CF_Zone_ID
/root/.acme.sh/acme.sh --issue --dns dns_cf -d pad.example.com -d sandbox-pad.example.com

Atteso: Cert success.
invalid domain = Zone ID sbagliato (spesso è l’Account ID); errori di permessi = token senza diritti DNS sulla zona.
acme.sh salva i valori in /root/.acme.sh/account.conf per i rinnovi: poi puoi fare unset CF_Token CF_Zone_ID.

Installa il certificato per nginx, con ricarica automatica a ogni rinnovo:

mkdir -p /etc/ssl/cryptpad
/root/.acme.sh/acme.sh --install-cert -d pad.example.com --ecc \
  --fullchain-file /etc/ssl/cryptpad/fullchain.pem \
  --key-file /etc/ssl/cryptpad/privkey.pem \
  --reloadcmd "systemctl reload-or-restart nginx"
ls -l /etc/ssl/cryptpad

Atteso: fullchain.pem e privkey.pem; il rinnovo è automatico (cron giornaliero di acme.sh).

Parametri Diffie-Hellman:

nohup openssl dhparam -out /etc/nginx/dhparam.pem 4096 >/dev/null 2>&1

Per controllare l’avanzamento:

pgrep -x openssl && echo "ancora in corso" || ls -l /etc/nginx/dhparam.pem

Configurazione nginx

Come root:

È l’esempio ufficiale del tag 2026.5.1 senza il webroot di Let’s Encrypt (si usa DNS-01), con i percorsi del certificato e l’IP di CryptPad al posto di localhost.
La location /cryptpad_websocket verso la 3003 è indispensabile.

rm -f /etc/nginx/conf.d/default.conf
nano /etc/nginx/conf.d/cryptpad.conf

Incolla la tua variante, salva con Ctrl+O, esci con Ctrl+X.

Variante A (443)

server {
    listen 80;
    server_name pad.example.com sandbox-pad.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;

    server_name pad.example.com sandbox-pad.example.com;

    ssl_certificate     /etc/ssl/cryptpad/fullchain.pem;
    ssl_certificate_key /etc/ssl/cryptpad/privkey.pem;
    ssl_dhparam         /etc/nginx/dhparam.pem;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

    location / {
        proxy_pass            http://10.99.0.201:3000;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      Host $host;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size  150m;

        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection upgrade;
    }

    location ^~ /cryptpad_websocket {
        proxy_pass            http://10.99.0.201:3003;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      Host $host;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection upgrade;
    }
}

Variante B (49101)

Senza il blocco sulla 80, con listen 49101 ssl; e Host $http_host in entrambe le location.
Se usi un’altra porta, cambiala qui e nelle origini di config.js.

server {
    listen 49101 ssl;
    http2 on;

    server_name pad.example.com sandbox-pad.example.com;

    ssl_certificate     /etc/ssl/cryptpad/fullchain.pem;
    ssl_certificate_key /etc/ssl/cryptpad/privkey.pem;
    ssl_dhparam         /etc/nginx/dhparam.pem;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

    location / {
        proxy_pass            http://10.99.0.201:3000;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      Host $http_host;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size  150m;

        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection upgrade;
    }

    location ^~ /cryptpad_websocket {
        proxy_pass            http://10.99.0.201:3003;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      Host $http_host;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection upgrade;
    }
}

Avvio e prove

Per il primo comando aspetta la fine di dhparam, senza il quale nginx -t fallisce.

while pgrep -x openssl >/dev/null; do sleep 5; done; ls -l /etc/nginx/dhparam.pem
nginx -t
systemctl enable nginx
systemctl restart nginx
ss -tlnp | grep -E ':443|:49101'

Variante A:

curl -sI --resolve pad.example.com:443:127.0.0.1 https://pad.example.com/ | head -3
curl -sI --resolve sandbox-pad.example.com:443:127.0.0.1 https://sandbox-pad.example.com/ | head -3

Variante B:

curl -sI --resolve pad.example.com:49101:127.0.0.1 https://pad.example.com:49101/ | head -3
curl -sI --resolve sandbox-pad.example.com:49101:127.0.0.1 https://sandbox-pad.example.com:49101/ | head -3

Websocket, direttamente su CryptPad:

curl -s -o /dev/null -w "%{http_code}\n" http://10.99.0.201:3003/

Atteso: syntax is ok, nginx in ascolto, due HTTP/2 200 senza errori di certificato, e dalla 3003 un codice qualsiasi (anche 404) ma non 000.
Poi exit dalla shell di root.

Amministratore e istanza

  • Port forward verso il proxy: TCP 443 e 80 (variante A) o la porta scelta (variante B).
    Su alcuni firewall serve anche una regola di forward WAN → DMZ con la stessa porta e destinazione solo il proxy: prova prima senza.
  • Apri /checkup/ e un documento condiviso.
  • Da entrambe le VM, curl -m 5 verso un servizio della LAN deve fallire (DMZ isolata).
  • Apri l’URL di installazione e crea l’account amministratore, con una password lunga poi logo, titolo e colore.
  • Attiva l’autenticazione a più fattori.
  • In /admin/: Close registration (dalla 4.5.0 non è più in config.js.
  • I nuovi account si creano con i link di invito di /admin/; CryptPad non invia email.

Manutenzione

Pulizia dell’archivio

VM CryptPad, con il tuo utente:

I documenti cancellati restano in archivio 15 giorni; evict-archived.js li elimina e va eseguito ogni notte.

NODE_BIN=$(sudo -u cryptpad bash -c 'export NVM_DIR=/home/cryptpad/.nvm; . "$NVM_DIR/nvm.sh" >/dev/null 2>&1; nvm which 24')
echo "$NODE_BIN"
sudo -u cryptpad bash -c "cd /home/cryptpad/cryptpad && $NODE_BIN scripts/evict-archived.js"
( sudo -u cryptpad crontab -l 2>/dev/null; echo "15 3 * * * cd /home/cryptpad/cryptpad && $NODE_BIN scripts/evict-archived.js >/dev/null 2>&1" ) | sudo -u cryptpad crontab -
sudo -u cryptpad crontab -l

Atteso: nessun errore e una sola riga di cron con il percorso di Node.
Ogni esecuzione aggiunge una riga: togli i doppioni con sudo -u cryptpad crontab -e.
Quando aggiorni Node, il percorso cambia: aggiornalo qui e in ExecStart.

Aggiornamento di CryptPad

Leggi le Upgrade notes di tutte le release tra la tua e la nuova, e fai un backup.
Con il tuo utente:

sudo systemctl stop cryptpad

Come cryptpad (sudo -iu cryptpad), con il numero della nuova versione:

NUOVA_VERSIONE="2026.x.y"
cd ~/cryptpad
git fetch --depth 1 origin tag "$NUOVA_VERSIONE"
git checkout "$NUOVA_VERSIONE"
npm ci
npm run install:components
./install-onlyoffice.sh --accept-license --trust-repository
npm run build

Lo script dell’editor office serve solo se lo avevi installato.
Poi exit e, con il tuo utente:

sudo systemctl start cryptpad
systemctl is-active cryptpad

Confronta le opzioni nuove con diff config/config.example.js config/config.js in ~/cryptpad.

Fonti