Con quale utente si avvia pm2 e quali permessi utilizza?

Risoluzione dei Problemi di Permessi su Cartelle e Processi PM2 in Linux

Quando si utilizzano applicazioni Node.js gestite da PM2, su macchine in cui accedono più utenti, è possibile imbattersi, come è capitato a me, in problemi di permessi su file e cartelle. In particolare, può accadere che un processo avviato da un utente non riesca a scrivere su una directory, nonostante l’utente appartenga apparentemente al gruppo corretto.

A volte aggiungi un utente a un gruppo, imposti i permessi corretti sulle cartelle… ma l’app continua a dare EACCES: permission denied. Perché? Perché PM2 (o il processo che lancia) non ha aggiornato i gruppi effettivi.

In questo articolo vediamo come diagnosticare questi problemi in modo chiaro usando una semplice app Node.js e quando è necessario riavviare PM2 o l’intero sistema.

Il Cuore del Problema

Aggiungi l’utente a un gruppo ➡️ Ma non basta

  • Il kernel non aggiorna i gruppi effettivi di un processo già in esecuzione.
  • PM2 eredita i gruppi al momento del lancio, e li mantiene finché il processo non viene riavviato.
  • A volte, solo un riavvio della macchina garantisce la ripartenza pulita di tutti i processi, specie se PM2 parte come servizio systemd.

L’Applicazione di Test dei Permessi

Creiamo una piccola app Node.js che:

  • Mostra l’utente attuale e i suoi gruppi
  • Controlla i permessi su una directory
  • Prova a scrivere un file di test

Sorgente applicazione di test

const os = require('os');
const fs = require('fs');
const util = require('util');
const exec = util.promisify(require('child_process').exec);

const targetFolder = '/percorso/della/cartella'; // <-- personalizza qui!
const testFile = `${targetFolder}/testfile.txt`;

(async () => {
console.log('=============================');
console.log('🧑‍💻 User & Group Info');
console.log('=============================');
console.log(`User: ${os.userInfo().username}`);
console.log(`UID : ${process.getuid()}`);
console.log(`GID : ${process.getgid()}`);

const { stdout: groups } = await exec('id');
console.log(`Groups: ${groups.trim()}`);

console.log('\n=============================');
console.log('📁 Folder Permissions');
console.log('=============================');
const folderStats = fs.statSync(targetFolder);
console.log(`Path : ${targetFolder}`);
console.log(`Owner UID : ${folderStats.uid}`);
console.log(`Owner GID : ${folderStats.gid}`);
console.log(`Permissions : ${folderStats.mode.toString(8)}`);

console.log('\n=============================');
console.log('📝 Test Write Access');
console.log('=============================');
try {
fs.writeFileSync(testFile, `Test scritto da ${os.userInfo().username} - ${new Date().toISOString()}\n`, { flag: 'a' });
console.log(`✅ Scrittura su ${testFile} OK`);
} catch (err) {
console.error(`❌ Non riesco a scrivere su ${testFile}`);
console.error(err.message);
}

console.log('\nFINE TEST');
})();

Salva questo test file (ad esempio index.js) su una cartella dalla quale puoi lanciare i seguenti comandi:

pm2 start index.js --name testpm2perm
pm2 logs testpm2perm

Io l’ho chiamata testpm2perm, tu fai come ti pare.

Con questo software riuscite a capire se ci sono dei path che vi sono preclusi e, soprattutto, con quale utente gira pm2.

Pertanto, potreste avere dei permessi insufficienti per manipolare i files di una cartella se lanciate il programma con pm2.

Una volta reimpostati i permessi e i gruppi degli utenti, in particolare all’utente che è dietro pm2, tali da consentirgli la manipolazione dei file, potreste essere costretti a riavviare il sistema, prima di riuscire a vedere il bug risolto e il vostro software funzionare.

Quando è Necessario il Reboot?

  • PM2 viene gestito da systemd e i processi non vengono aggiornati correttamente
  • Il gruppo è stato aggiunto, ma il processo parte troppo presto durante il boot
  • I processi sono zombie di vecchie sessioni non aggiornate

Lo script esposto in questo articolo è stato scritto con intelligenza artificiale e mi ha aiutato a risolvere una problematica reale.
Questo articolo è solo una scusa per appuntarmi questa soluzione e, perché no, renderla disponibile agli altri.