public function upload_chunk( string $upload_url, string $auth_token, int $part_number, string $file_chunk ): array {
$response = wp_remote_post( $upload_url, [
'headers' => [
'Authorization' => $auth_token,
'X-Bz-Part-Number' => $part_number,
'X-Bz-Content-Sha1' => sha1( $file_chunk ),
'Content-Type' => 'b2/x-auto',
],
'body' => $file_chunk,
'timeout' => 60,
] );
if ( is_wp_error( $response ) ) {
throw new \Exception( $response->get_error_message() );
}
return json_decode( wp_remote_retrieve_body( $response ), true );
}Salutare tuturor! M-am săturat să plătesc licențe lunare de 50$+ pentru pluginuri de backup pe cele 14 site-uri pe care le am în administrare, așa că am scris propriul meu plugin dedicat pentru Backblaze B2. Proiectul e 100% open-source, iar săptămâna trecută a fost aprobat oficial în directorul WordPress.org după un proces destul de riguros de review.
De ce Backblaze B2 și nu AWS S3?
Alegerea a fost pur financiară și practică. La un volum total de vreo 350 GB de backup-uri agregate (baze de date + directoare wp-content), pe AWS S3 plăteam în jur de 9-10$ pe lună plus traficul de ieșire la eventuale teste de restore. La Backblaze B2 am primii 10 GB gratuiți, iar apoi tariful e de 0.006$ pe GB/lună. Practic, factura mea lunară a scăzut cu vreo 75%.
Trade-off-ul principal? B2 nu are toate mecanismele avansate de lifecycle management sau opțiunile de arhivare tip Glacier pe care le găsești în AWS. Dacă vrei arhivare cold-storage pe ani de zile cu politici complexe de acces, S3 e clar peste. Dar pentru un backup simplu rotit la 30 de zile, B2 e ieftin, rapid și extrem de predictibil la costuri.
Provocările tehnice pe shared hosting
Cea mai mare durere de cap când scrii un plugin de backup pentru ecosistemul WordPress e că nu știi niciodată pe ce server va rula. Am un client cu o arhivă media de 4.2 GB găzduit pe un shared hosting obosit unde max_execution_time e setat la 30 de secunde și n-am acces la SSH sau CLI.
Dacă încerci să faci un zip gigantic și să-l urci dintr-o singură bucată prin HTTP, o să primești timeout în 99% din cazuri. Am fost nevoit să implementez upload în bucăți (chunked upload folosind API-ul B2 de b2_start_large_file și b2_upload_part). În plus, procesul de arhivare rulează într-un queue asincron, salvând starea în baza de date după fiecare 500 de fișiere împachetate. Dacă scriptul moare din cauza limitei de memorie, următorul apel de WP-Cron reia procesul exact de unde a rămas.
Ce am învățat din review-ul celor de la WordPress.org
Procesul de review a durat aproximativ 3 săptămâni. Mă așteptam să fie o simplă verificare automată cu un linter, dar un reviewer uman a trecut prin cod la linie.
Am fost respins la prima încercare din două motive principale:
- Folosisem
curl_exec()direct pentru apelurile API către Backblaze. Regula WP.org spune clar că trebuie să folosești HTTP API-ul nativ (wp_remote_post(),wp_remote_get()) ca să asiguri compatibilitatea cu mediile unde extensia cURL nu e instalată sau e blocată de provider. - Nu făcusem sanitizare la sânge pe o rută AJAX din admin panel și lipsea verificarea de
noncela un buton de "Trigger Manual Backup". Greșeală de începător, recunosc, dar când scrii cod repede pentru tine, ai tendința să sari peste pașii ăștia.
După ce am refăcut apelurile HTTP folosind wp_remote_post și am securizat toate endpoint-urile din admin, pluginul a fost aprobat în 48 de ore.
Concluzie
Codul e public pe GitHub și deja activ în directorul oficial WP. A fost un exercițiu excelent de refactoring și m-a obligat să respect standardele stricte de securitate din ecosistemul WordPress, pe care de multe ori le ignorăm când facem scripturi interne.
Voi ce soluții folosiți pentru backup-urile site-urilor mici? Preferați un plugin dedicat, un script de bash direct pe server sau faceți snapshot-uri la nivel de VPS?