G.STANCUTA
Publicat · 2026 · 04 · 288 min de citit

Ploi: Echipa de Server pe care Nu A Trebuit să o Angajez

  • devops
  • vps
  • ploi
  • automation

Un dashboard, o API și câteva fișiere markdown. Iată cum Ploi gestionează tot ce are nevoie un operator solo de la un server de producție, fără să te lege de ceva din care nu poți scăpa prin SSH.

Gestionarea infrastructurii de producție ca dezvoltator solo însemna înainte una din două lucruri: plătești pentru o platformă gestionată care adaugă 40 de procente la factura de hosting, sau petreci serile de duminică citind configurații nginx și depanând hook-uri certbot. Ploi este o a treia cale. Se poziționează deasupra propriului tău VPS, gestionează provisionarea, deployment-urile, SSL, cron și cozile, și nu îți stă în cale. Serverul este al tău. Ploi comunică pur și simplu cu el prin SSH.

Provisionarea unui VPS Întărit în Mai Puțin de Zece Minute

Conectează contul tău DigitalOcean, Hetzner sau Vultr prin token-ul API Ploi și dashboard-ul va crea droplet-ul pentru tine. Sau îndreaptă Ploi spre un server pe care îl deții deja, introducând un IP și lăsându-l să instaleze agentul. În ambele cazuri, scriptul de bootstrap configurează un utilizator sudo non-root, blochează SSH la autentificarea bazată pe cheie, setează ufw cu valori implicite rezonabile, instalează PHP (sau Node, sau ambele), nginx, MySQL sau PostgreSQL, Redis și supervisor. Totul cu un singur clic.

Ceea ce primești la final nu este un sistem fragil. Fișierele vhost nginx, configurațiile supervisor și intrările cron sunt toate pe disc la căi previzibile. Poți intra prin SSH, inspecta totul și edita direct. Ploi va sincroniza înțelegerea serverului la următorul deployment, sau îl poți ajusta prin dashboard. Fără cutii negre.

Diagramă izometrică a unui VPS care este provisionat cu servicii pe straturi
Ploi stivuiește servicii pe VPS-ul tău fără să abstractizeze accesul SSH.

Deployment-uri Git Fără Timp de Nefuncționare

Fiecare site pe care îl creezi în Ploi primește un script de deployment. Cel implicit este rezonabil: pull de la remote-ul git, instalare dependințe, rulare migrări, ștergere cache, reîncărcare php-fpm. Poți să îl editezi după cum ai nevoie. Ploi folosește implicit abordarea cu symlink atomic în stilul deployer, astfel că cererile primite continuă să lovească versiunea veche până când cea nouă este complet construită.

Declanșează un deployment prin push pe branch-ul tău, printr-un webhook de la GitHub Actions sau apelând REST API-ul Ploi. Ultima opțiune este importantă: înseamnă că orice proces automatizat, inclusiv un agent AI de scriere de cod, poate porni un deployment de producție cu un singur apel HTTP, fără acces suplimentar la serverul tău.

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."

Lipește acel script în editorul de script de deployment al Ploi. Fiecare git push pe main îl declanșează prin webhook-ul pe care Ploi îl înregistrează automat în GitHub. Repornirea cozii este sigură deoarece supervisor menține workerii în funcțiune până când joburile vechi sunt procesate și noul binar worker preia.

SSL, Cron, Workeri pentru Cozi și Backup-uri

SSL cu reînnoire automată este o bifă. Ploi rulează certbot, scrie stanza nginx și reînnoiește înainte de expirare. Nu vei mai atinge niciodată un certificat dacă nu vrei să aduci propriul tău.

Job-urile cron trăiesc în dashboard-ul Ploi ca intrări lizibile. Completezi programul, comanda și utilizatorul site-ului care să o ruleze. Ploi scrie linia efectivă din crontab pe server. Iată un program tipic pentru o aplicație 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

Workerii cozilor sunt procese supervisor. Ploi scrie o configurație supervisor per grup de workeri, setează politica de repornire și îți dă un buton pentru a-i reporni sau pauza. Dacă un worker se blochează, repornește automat. Poți defini mai multe grupuri de workeri cu cozi și niveluri de concurență diferite, ceea ce acoperă 90 la sută din configurațiile reale de producție.

Backup-urile bazei de date sunt și ele programate din dashboard: alegi o bază de date, un program și o destinație (S3, Backblaze sau un endpoint personalizat compatibil S3). Ploi rulează un mysqldump sau pg_dump, îl comprimă, îl încarcă și șterge backup-urile vechi conform ferestrei de retenție pe care o setezi. Fișierele ajung în propriul tău bucket de stocare, nu în cel al Ploi.

SSH Efemer prin API

Acesta este aspectul pe care majoritatea oamenilor îl ratează. Ploi expune o REST API completă pentru tot ce poate face dashboard-ul, inclusiv gestionarea cheilor. Un agent AI, o conductă CI sau un script poate crea o pereche nouă de chei SSH, atașa cheia publică la un server specific, să își facă treaba prin SSH și apoi să șteargă cheia. Serverul nu păstrează niciodată o acreditare persistentă.

Iată un flux condensat. Agentul tău generează o pereche de chei RSA în memorie, înregistrează cheia publică prin API-ul Ploi, se conectează prin SSH, rulează ce i s-a cerut și apoi apelează DELETE pe resursa cheie:

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.');
}

Fără chei persistente, fără secrete partajate într-un fișier .authorized_keys care se acumulează în timp. Fiecare rulare a agentului este izolată. Dacă agentul se blochează după pasul 2 și nu ajunge niciodată la pasul 4, poți scrie un job de curățare care apelează GET /servers/:id/ssh-keys și elimină orice cheie al cărei nume începe cu agent-ephemeral și are mai mult de o oră.

Fără Blocare, Doar SSH

Întregul model al Ploi este că gestionează serverul tău prin SSH. Nu rulează un proces sidecar, nu interceptează traficul și nu necesită instalarea permanentă a niciunui software specific Ploi. Configurațiile nginx, unitățile supervisor, crontab-urile și scripturile de deployment sunt toate fișiere standard pe o mașină Linux standard.

Dacă Ploi ar dispărea mâine, serverul tău ar continua să funcționeze. Ai pierde dashboard-ul și webhook-urile de deployment, dar infrastructura reală rămâne neschimbată. Compară asta cu un PaaS unde, în momentul în care nu mai plătești, containerele tale se evaporă.

Ploi nu deține infrastructura ta. Comunică pur și simplu cu ea. Această distincție este totul.

Schemă a unui agent AI care citește un fișier markdown de memorie și apelează API-ul Ploi
Un agent AI folosește un fișier AGENTS.md persistent pentru a reține ID-uri de server, căi de acreditare și convenții de deployment.

Utilizarea Ploi cu un Agent AI de Scriere de Cod

Când un agent AI de scriere de cod (Claude Code, Cursor sau orice instrument care citește markdown la nivel de proiect) lucrează pe o bază de cod deployment-ată prin Ploi, trebuie să cunoască topologia serverului, care comenzi declanșează deployment-uri și cum să se recupereze din defecțiuni comune. Fără acel context, fiecare sesiune pornește de la zero și agentul va face presupuneri conservative sau îți va pune aceleași întrebări în mod repetat.

Soluția este un fișier AGENTS.md persistent, comis în repository. Agentul îl citește la începutul fiecărei sesiuni și îl folosește ca memorie pe termen lung pentru infrastructură. Iată un exemplu realist:

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.

Cu acest fișier disponibil, agentul știe unde să caute, ce să ruleze și ce să evite. Nu trebuie să redescopere ID-ul serverului din variabilele de mediu sau să ghicească comanda de deployment. AGENTS.md înregistrează și protocolul de curățare pentru cheile efemere, astfel că chiar dacă o sesiune a agentului a fost întreruptă înainte de finalizare, sesiunea următoare știe ce să curețe.

Tratează AGENTS.md ca pe un document viu. Când adaugi un nou worker de coadă, actualizează secțiunea supervisor. Când schimbi scriptul de deployment, actualizează calea. Investiția este mică iar rezultatul este un agent care se comportă ca și cum ar gestiona infrastructura ta de luni de zile.

Cât Costă și Când Are Sens

Ploi percepe o taxă lunară fixă per server, în prezent aproximativ opt euro pentru primul server. Aceasta acoperă site-uri nelimitate pe acel server. Adaugă un Hetzner CX22 de cinci euro și ai un host de calitate producție pentru câteva aplicații la sub cincisprezece euro pe lună în total. Vercel sau Railway la utilizare echivalentă te vor costa de trei până la cinci ori mai mult.

Compromisul este real: deții serverul, ceea ce înseamnă că deții patch-urile OS, disk-ul și eventualul crash la 2 noaptea. Pentru proiectele care au nevoie de o bază de date, joburi în fundal sau un binar personalizat, calculele favorizează puternic un VPS cu Ploi față de orice PaaS gestionat. Pentru un site static simplu sau o API pur serverless, PaaS-ul câștigă probabil la comoditate.

  • Cea mai bună potrivire: Laravel, Rails, Django sau orice aplicație cu bază de date, coadă și cron.
  • Potrivire bună: servicii Node care au nevoie de un proces persistent și o conexiune Redis.
  • Potrivire neutră: site-uri statice care au nevoie doar de un CDN rapid. Folosește un CDN.
  • Potrivire slabă: echipe care vor GitOps, Kubernetes sau infrastructure-as-code în controlul versiunilor. Ploi nu este Terraform.

Pentru un dezvoltator solo sau o echipă mică în care o persoană deține infrastructura, Ploi elimină costul operațional fără a adăuga o nouă abstractizare cu care trebuie să lupți. Serverul este al tău, fișierele sunt normale și cheia SSH este în mâinile tale. Acesta este întregul punct.

Portofoliu · Indicator
Desenat de
G. STANCUTA
Disciplină
AI & AUTOMATION
Locație
MORTER · SÜDTIROL
Stare
Disponibil
Limbi
IT · EN · RO · DE+
Stack
PLOI · HETZNER
Revizie
REV 2026.A
2026

© 2026 Gabriel Stancuta · jumpinotech.com — Proiectat cu AI, construit să funcționeze singur.