G.STANCUTA
Pubblicato · 2026 · 04 · 288 min di lettura

Ploi: Il Team di Server che Non Ho Mai Dovuto Assumere

  • devops
  • vps
  • ploi
  • automation

Una dashboard, una API e qualche file markdown. Ecco come Ploi gestisce tutto ciò di cui un operatore solitario ha bisogno da un server di produzione, senza vincolarti a nulla da cui non puoi uscire via SSH.

Gestire l'infrastruttura di produzione come sviluppatore solitario significava una di due cose: pagare per una piattaforma gestita che aggiunge il 40 percento al conto di hosting, oppure trascorrere le domeniche sera a leggere configurazioni nginx e a fare il debug degli hook di certbot. Ploi è una terza via. Si posiziona sopra il tuo VPS, gestisce provisioning, deployment, SSL, cron e code, e non ti intralcia. Il server è tuo. Ploi ci parla semplicemente via SSH.

Provisioning di un VPS Protetto in Meno di Dieci Minuti

Connetti il tuo account DigitalOcean, Hetzner o Vultr tramite il token API di Ploi e la dashboard creerà il droplet per te. Oppure punta Ploi su un server che già possiedi inserendo un IP e lasciandogli installare il suo agente. In entrambi i casi, lo script di bootstrap configura un utente sudo non root, blocca SSH all'autenticazione solo con chiave, imposta ufw con valori predefiniti ragionevoli, installa PHP (o Node, o entrambi), nginx, MySQL o PostgreSQL, Redis e supervisor. Tutto questo con un solo clic.

Quello che ottieni alla fine non è un sistema fragile. I file vhost di nginx, le configurazioni di supervisor e le voci cron sono tutti su disco in percorsi prevedibili. Puoi connetterti via SSH, ispezionare tutto e modificarlo direttamente. Ploi sincronizzerà la sua comprensione del server al prossimo deployment, oppure puoi aggiustarlo tramite la dashboard. Nessuna scatola nera.

Diagramma isometrico di un VPS in fase di provisioning con servizi a strati
Ploi accumula servizi sul tuo VPS senza astrarre l'accesso SSH.

Deploy Git Senza Downtime

Ogni sito che crei in Ploi ottiene uno script di deploy. Il predefinito è ragionevole: pull dal tuo remote git, installazione delle dipendenze, esecuzione delle migrazioni, pulizia della cache, ricaricamento di php-fpm. Puoi modificarlo in base alle tue esigenze. Ploi utilizza di default l'approccio con symlink atomico in stile deployer, così le richieste in arrivo continuano a puntare alla vecchia release finché quella nuova non è completamente costruita.

Avvia un deploy facendo push sul tuo branch, tramite un webhook da GitHub Actions, o chiamando la REST API di Ploi. L'ultima opzione è importante: significa che qualsiasi processo automatizzato, incluso un agente AI per la scrittura di codice, può avviare un deploy di produzione con una singola chiamata HTTP senza ulteriore accesso al tuo server.

bash
#!/usr/bin/env bash
# deploy.sh  --  called by CI or by a Ploi deploy hook
set -euo pipefail

APP_DIR="/var/www/myapp/current"

cd "$APP_DIR"

echo "[deploy] pulling latest release..."
git fetch --depth=1 origin main
git reset --hard origin/main

echo "[deploy] installing dependencies..."
composer install --no-dev --optimize-autoloader --no-interaction

echo "[deploy] running migrations..."
php artisan migrate --force

echo "[deploy] warming cache..."
php artisan config:cache
php artisan route:cache
php artisan view:cache

echo "[deploy] restarting queue workers..."
php artisan queue:restart

echo "[deploy] reloading php-fpm..."
sudo systemctl reload php8.3-fpm

echo "[deploy] done."

Incolla quello script nell'editor dello script di deploy di Ploi. Ogni git push su main lo attiva tramite il webhook che Ploi registra automaticamente in GitHub. Il riavvio della coda è sicuro perché supervisor mantiene i worker in esecuzione finché i vecchi job non vengono completati e il nuovo binario worker subentra.

SSL, Cron, Worker delle Code e Backup

Il rinnovo automatico SSL è una casella da spuntare. Ploi esegue certbot, scrive la stanza nginx e rinnova prima della scadenza. Non toccherai mai più un certificato a meno che tu non voglia portarne uno tuo.

I job cron vivono nella dashboard di Ploi come voci leggibili dall'uomo. Compili il piano, il comando e quale utente del sito deve eseguirlo. Ploi scrive la riga effettiva del crontab sul server. Ecco un piano tipico per un'app Laravel:

yaml
# Ploi cron entries (stored in dashboard, written to server crontab)
# Schedule: every minute
# Command:  cd /var/www/myapp/current && php artisan schedule:run >> /dev/null 2>&1
# User:     ploi

# Schedule: 0 3 * * *
# Command:  cd /var/www/myapp/current && php artisan backup:run --only-db
# User:     ploi

# Schedule: 0 4 * * 0
# Command:  certbot renew --quiet --deploy-hook "systemctl reload nginx"
# User:     root

I worker delle code sono processi supervisor. Ploi scrive una configurazione supervisor per ogni gruppo di worker, imposta la politica di riavvio e ti dà un pulsante per riavviarli o metterli in pausa. Se un worker si blocca, si riavvia automaticamente. Puoi definire più gruppi di worker con code e livelli di concorrenza diversi, il che copre il 90 percento dei setup di produzione reali.

Anche i backup del database sono pianificati dalla dashboard: scegli un database, un piano e una destinazione (S3, Backblaze o un endpoint compatibile con S3 personalizzato). Ploi esegue un mysqldump o pg_dump, lo comprime, lo carica e rimuove i backup vecchi in base alla finestra di conservazione che hai impostato. I file finiscono nel tuo bucket di archiviazione, non in quello di Ploi.

SSH Effimero, via API

Questa è la parte che la maggior parte delle persone non considera. Ploi espone una REST API completa per tutto ciò che la dashboard può fare, inclusa la gestione delle chiavi. Un agente AI, una pipeline CI o uno script possono creare una nuova coppia di chiavi SSH, allegare la chiave pubblica a un server specifico, svolgere il proprio lavoro via SSH e poi eliminare la chiave. Il server non mantiene mai una credenziale persistente.

Ecco un flusso condensato. Il tuo agente genera una coppia di chiavi RSA in memoria, registra la chiave pubblica tramite l'API di Ploi, si connette via SSH, esegue ciò per cui è stato chiamato e poi chiama DELETE sulla risorsa chiave:

ts
import { execSync } from 'child_process';
import { generateKeyPairSync } from 'crypto';

const PLOI_TOKEN = process.env.PLOI_TOKEN!;
const SERVER_ID  = process.env.PLOI_SERVER_ID!;
const SERVER_IP  = process.env.SERVER_IP!;
const BASE       = 'https://ploi.io/api';

// 1. Generate ephemeral key pair in memory
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
  modulusLength: 4096,
  publicKeyEncoding:  { type: 'pkcs1', format: 'pem' },
  privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
});

// 2. Register public key on the target server
const addRes = await fetch(`${BASE}/servers/${SERVER_ID}/ssh-keys`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${PLOI_TOKEN}`,
    'Content-Type': 'application/json',
    Accept: 'application/json',
  },
  body: JSON.stringify({ name: 'agent-ephemeral', key: publicKey }),
});
const { id: keyId } = (await addRes.json()).sshKey;

// 3. Write private key to a temp file, chmod 600, connect and run command
const keyFile = `/tmp/agent-${Date.now()}.pem`;
require('fs').writeFileSync(keyFile, privateKey, { mode: 0o600 });
try {
  const output = execSync(
    `ssh -i "${keyFile}" -o StrictHostKeyChecking=no ploi@${SERVER_IP} "php artisan queue:restart"`,
    { encoding: 'utf8' }
  );
  console.log('[agent] remote output:', output.trim());
} finally {
  // 4. Delete the key via API and remove the temp file
  await fetch(`${BASE}/servers/${SERVER_ID}/ssh-keys/${keyId}`, {
    method: 'DELETE',
    headers: { Authorization: `Bearer ${PLOI_TOKEN}`, Accept: 'application/json' },
  });
  require('fs').unlinkSync(keyFile);
  console.log('[agent] ephemeral key deleted, server secured.');
}

Nessuna chiave persistente, nessun segreto condiviso in un file .authorized_keys che si accumula nel tempo. Ogni esecuzione dell'agente è isolata. Se l'agente si blocca dopo il passaggio 2 e non raggiunge mai il passaggio 4, puoi scrivere un job di pulizia che chiama GET /servers/:id/ssh-keys e rimuove qualsiasi chiave il cui nome inizia con agent-ephemeral ed è più vecchia di un'ora.

Nessun Vincolo, Solo SSH

L'intero modello di Ploi è che gestisce il tuo server via SSH. Non esegue un processo sidecar, non intercetta il traffico e non richiede l'installazione permanente di software specifico di Ploi. Le configurazioni nginx, le unità supervisor, i crontab e gli script di deploy sono tutti file standard su una box Linux standard.

Se Ploi sparisse domani, il tuo server continuerebbe a funzionare. Perderesti la dashboard e i webhook di deploy, ma l'infrastruttura reale rimarrebbe invariata. Confrontalo con un PaaS dove nel momento in cui smetti di pagare i tuoi container evaporano.

Ploi non possiede la tua infrastruttura. Ci parla soltanto. Questa distinzione è tutto.

Schema di un agente AI che legge un file markdown di memoria e chiama l'API di Ploi
Un agente AI usa un file AGENTS.md persistente per ricordare ID server, percorsi delle credenziali e convenzioni di deploy.

Usare Ploi con un Agente AI per la Scrittura di Codice

Quando un agente AI per la scrittura di codice (Claude Code, Cursor o qualsiasi strumento che legge markdown a livello di progetto) lavora su un codebase distribuito via Ploi, deve conoscere la topologia del server, quali comandi avviano i deploy e come recuperare da errori comuni. Senza quel contesto, ogni sessione riparte da zero e l'agente farà ipotesi conservative o ti farà le stesse domande più volte.

La soluzione è un file AGENTS.md persistente, committato nel repository. L'agente lo legge all'inizio di ogni sessione e lo usa come memoria a lungo termine per l'infrastruttura. Ecco un esempio realistico:

md
# AGENTS.md — Infrastructure Memory for AI Coding Agents

## Ploi Server Setup

- Provider: Hetzner CX22, Ubuntu 24.04
- Ploi server ID: 4821  (env: PLOI_SERVER_ID)
- Public IP: 95.111.42.7  (env: SERVER_IP)
- Site ID: 9103  (for deploy webhook calls)
- PHP: 8.3, nginx, PostgreSQL 16, Redis 7, supervisor

## Deploy

Trigger a deploy by calling the Ploi API:

  POST https://ploi.io/api/sites/9103/deploy
  Authorization: Bearer $PLOI_TOKEN

Zero-downtime: symlink swap. Old release stays live until new release is fully built.
Deploy script path on server: /etc/ploi/deploy-scripts/site-9103.sh

## Queues

Workers are managed by supervisor. To restart after a code change:

  ssh ploi@95.111.42.7 "php artisan queue:restart"

Or trigger via the ephemeral SSH flow in scripts/agent-ssh.ts.
Worker logs: /var/www/myapp/current/storage/logs/worker-*.log

## Cron

PHP scheduler runs every minute:
  cd /var/www/myapp/current && php artisan schedule:run

DB backup runs daily at 03:00 UTC, sent to Backblaze bucket `myapp-backups`.

## SSL

Managed by certbot via Ploi. Cert path: /etc/letsencrypt/live/myapp.com/
Renews automatically. Do not touch unless domain changes.

## Common Gotchas

- After editing .env on the server, run `php artisan config:cache` or changes are ignored.
- Queue workers cache config on boot. Always run `queue:restart` after a deploy.
- The ploi user owns /var/www. Do not sudo-write files there or nginx will 403.
- Ploi writes supervisor configs to /etc/supervisor/conf.d/ploi-*.conf. Do not rename them.

## Cleanup Protocol

After any agent session that used ephemeral SSH keys:
  GET https://ploi.io/api/servers/4821/ssh-keys
  DELETE any key with name prefix "agent-ephemeral" older than 60 minutes.

Con questo file in uso, l'agente sa dove cercare, cosa eseguire e cosa evitare. Non ha bisogno di riscoprire l'ID del server dalle variabili d'ambiente o di indovinare il comando di deploy. Il file AGENTS.md registra anche il protocollo di pulizia per le chiavi effimere, così anche se una sessione dell'agente viene interrotta prima del completamento, la sessione successiva sa cosa pulire.

Tratta AGENTS.md come un documento vivo. Quando aggiungi un nuovo worker della coda, aggiorna la sezione supervisor. Quando modifichi lo script di deploy, aggiorna il percorso. L'investimento è piccolo e il risultato è un agente che si comporta come se gestisse la tua infrastruttura da mesi.

Quanto Costa e Quando Ha Senso

Ploi addebita una tariffa mensile fissa per server, attualmente intorno a otto euro per il primo server. Questo copre siti illimitati su quel server. Aggiungi un Hetzner CX22 da cinque euro e hai un host di qualità produzione per una manciata di app a meno di quindici euro al mese in totale. Vercel o Railway a utilizzo equivalente ti costeranno da tre a cinque volte tanto.

Il compromesso è reale: possiedi il server, il che significa che possiedi le patch del sistema operativo, il disco e l'eventuale crash alle 2 di notte. Per i progetti che necessitano di un database, di job in background o di un binario personalizzato, i calcoli favoriscono nettamente un VPS con Ploi rispetto a qualsiasi PaaS gestito. Per un semplice sito statico o una pura API serverless, il PaaS probabilmente vince per comodità.

  • Adatto al meglio: Laravel, Rails, Django, o qualsiasi app con database, code e cron.
  • Buon adattamento: servizi Node che necessitano di un processo persistente e di una connessione Redis.
  • Adattamento neutro: siti statici che hanno solo bisogno di un CDN veloce. Usa un CDN.
  • Adattamento scarso: team che vogliono GitOps, Kubernetes o infrastruttura come codice nel controllo di versione. Ploi non è Terraform.

Per uno sviluppatore solitario o un piccolo team in cui una persona gestisce l'infrastruttura, Ploi elimina il carico operativo senza aggiungere una nuova astrazione con cui devi combattere. Il server è tuo, i file sono normali e la chiave SSH è nelle tue mani. Questo è l'intero punto.

Portfolio · Cartiglio
Disegnato da
G. STANCUTA
Disciplina
AI & AUTOMATION
Luogo
MORTER · SÜDTIROL
Stato
Disponibile
Lingue
IT · EN · RO · DE+
Stack
PLOI · HETZNER
Revisione
REV 2026.A
2026

© 2026 Gabriel Stancuta · jumpinotech.com — Progettato con l'AI, costruito per funzionare da solo.