Alessio Forti

Configurare PocketBase su Plesk

PocketBase sta diventando un’alternativa molto valida alle altre “bases”, come Firebase o Supabase, e per ottime ragioni. Prima tra tutte la semplicità del setup e la portabilità. PocketBase infatti, a differenza degli altri, può essere scaricato tranquillamente e caricato su un server. Farlo girare su un server pulito è molto semplice e basta seguire la documentazione, ma se lo vogliamo farlo funzionare su un server dotato di un panel (come Plesk o cPanel) serve qualche accorgimento in più. Visto che non so stare fermo ho fatto qualche prova e in questa piccola guida vediamo come poterlo configurare su un server Plesk.

Configurare PocketBase su Plesk

Cos’è PocketBase?

Se sei atterrato su questa pagina cercando informazioni su come configurare PocketBase, le probabilità che tu sappia già cosa sia sono molto alte. In ogni caso meglio fare un breve recap nel caso non lo sapessi.

PocketBase, come recita anche la sua home page, è un backend open source scritto in Go e attraverso API (o dal pannello di amministrazione) possiamo accedere a tante belle funzionalità come Auth, database SQLite (anche realtime), file storage e tanto altro.

Tutto questo è racchiuso in 1 solo file eseguibile.

Infatti, per poter creare il servizio di backend, basta scaricare l’eseguibile di PocketBase per la propria piattaforma e lanciarlo da shell con un semplice ./pocketbase serve. Una volta avviato verrà creato un server su http://127.0.0.1:8090, e si può accedere alla dashboard da http://127.0.0.1:8090/_/ o chiamare le API da http://127.0.0.1:8090/api/. Puoi leggere di più direttamente nella documentazione.

Eseguire PocketBase su server

Dunque, abbiamo scaricato l’eseguibile, abbiamo verificato che si tratta di una gran figata e abbiamo fatto un mockup veloce di una semplice applicazione front-end per provarlo. Ora non vediamo l’ora di caricarlo su un server per vedere se funziona. La strategia di deploy descritta nella documentazione mostra come caricare PocketBase in /root su un server tramite SSH. Inoltre, sia nella documentazione che nella discussione della repository su Github vengono descritti diversi servizi dove poter fare il deploy: per esempio si consiglia di usare Docker su fly.io, oppure si scopre che qualcuno ha inventato un servizio di hosting ad hoc per PocketBase (guarda un po’ si chiama PocketHost.io).

Ma noi, indomiti, pieni di coraggio e senso dell’avventura, decidiamo di seguire la strada più tortuosa e lo vogliamo far girare sul nostro server VPS con Plesk.

A dirla tutta credo che questa strada abbia molti più vantaggi. Il fatto che PocketBase sia racchiuso in un singolo file (più 3 cartelle contenenti i file e il DB) lo rende altamente portabile tra macchine diverse: per esempio potremmo ipotizzare di trasferire tutto su un altro server semplicemente scaricando e ricaricando i file nella nuova destinazione. Se abbiamo la possibilità di fare questa operazione tramite drag & drop da Plesk o tramite FTP probabilmente faremo prima e avremo meno mal di testa.

Altra questione da considerare è il fatto che possiamo usare PocketBase anche come framework, nel senso che è possibile estendere le sue funzionalità creando degli script in Go o JavaScript nella cartella pb_hooks. Potrebbe essere più agevole poter accedere a questi file anche da browser o tramite FTP, per caricarne di nuovi o modificare quelli già esistenti, invece di dover accedere tramite SSH alla cartella /root.

Di seguito vediamo tre possibili configurazioni, simili ma leggermente diverse tra di loro: come configurare PocketBase su un sotto dominio, come configurare più istanze nello stesso sotto dominio e infine come configurare più istanze in sotto domini diversi.

Darò per scontato alcuni passaggi come, per esempio, la creazione e il puntamento DNS di un sotto dominio, come accedere tramite SSH al server e come usare Vi (o il tuo editor preferito) per modificare i file sul server. Dunque iniziamo.

Installare PocketBase su un sotto dominio

I passaggi descritti qui di seguito sono sostanzialmente validi anche per gli altri tipi di configurazione e ricalcano in buona sostanza quello che si trova nella guida di PocketBase, quindi iniziamo dalle cose semplici.

1 – Caricare l’eseguibile di PocketBase nella cartella del sotto dominio

Anche se può sembrare banale, tengo a specificare questo passaggio perché, trascinati dalla lettura entusiasmante delle mie spiegazioni (!), si potrebbe esser tentati di caricare tutto dentro la root del sotto dominio. Nonostante PocketBase sia sostanzialmente sicuro e i vari file e cartelle non siano direttamente accessibili, è sempre meglio fare un piccolissimo sforzo iniziale e invece di fare drag & drop in httpdocs, creiamo una cartella chiamata pocketbase (o il nome che si addice di più) nella directory superiore rispetto ad httpdocs. Così facendo evitiamo di esporre pubblicamente l’eseguibile e i file, pur mantenendo i vantaggi di potervi accedere tramite panel o FTP.

La struttura dei file dovrebbe essere simile a questa:

/api.dominio.it/
...
/error_docs/
/httpdocs/
/logs/
...
/pocketbase/

In pratica la creazione del sottodominio in Plesk ci serve solo per fare correttamente il bind dei DNS nella sotto zona, e per aggiornare la sua configurazione di Ngnix. La cartella /api.dominio.it/ può benissimo rimanere vuota.

2 – Modificare le regole di Ngnix del sottodominio

Ora dobbiamo fare in modo che il traffico che confluisce su https://api.dominio.it venga reindirizzato internamente al server sulla porta di Pocketbase che, di default, è http://127.0.0.1:8090. Per poter ottenere questo comportamento sfruttiamo Ngnix (che già dovrebbe essere installato su Plesk) usandolo come reverse proxy.

Nella schermata di Plesk del nostro sotto dominio andiamo sulla scheda Hosting e DNS > Apache e nginx. Al suo interno togliamo la spunta dalle opzioni Modalità proxy e Servi file statici direttamente da nginx, poi in fondo alla pagina impostiamo le direttive Nginx aggiuntive:

location / {
  proxy_set_header Connection '';
  proxy_http_version 1.1;
  proxy_read_timeout 360s;
  
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;

  proxy_pass http://127.0.0.1:8090;
}

Bonus: a questo punto, se volessimo testare la situazione, possiamo collegarci in SSH e:

$ cd /var/www/vhosts/dominio.it/api.dominio.it/pocketbase/ 
$ ./pocketbase serve
Server started at http://127.0.0.1:8090
├─ REST API: http://127.0.0.1:8090/api/
└─ Admin UI: http://127.0.0.1:8090/_/

Quindi, se tutto funziona, potresti già accedere alla dashboard di PocketBase da https://api.dominio.it/_/.

Ricordati di uscire correttamente dal processo altrimenti la porta rimarrà occupata e il punto successivo sarà meno agevole.

3 – Abilitare il servizio di sistema

Per quanto possiamo già essere super eccitati dei risultati raggiunti fino a questo momento, ricordiamoci che eseguire direttamente l’eseguibile tramite serve comporta che il processo verrà terminato se si chiude la sessione della shell. È possibile gestire meglio il processo creando un servizio di sistema che possiamo avviare e chiudere in modo migliore e che, inoltre, si possa riavviare automaticamente in caso di riavvio del server o di errore.

Per farlo conviene accedere come root al server tramite SSH e creare il servizio di sistema:

$ cd /lib/systemd/system/
$ touch pocketbase-dominio.service
$ vi pocketbase-dominio.service

All’interno del file .service:

[Unit]
Description = pocketbase

[Service]
Type           = simple
User           = root
Group          = root
LimitNOFILE    = 4096
Restart        = always
RestartSec     = 5s
StandardOutput = append:/var/www/vhosts/dominio.it/pocketbase/errors.log
StandardError  = append:/var/www/vhosts/dominio.it/pocketbase/errors.log
ExecStart      = /var/www/vhosts/dominio.it/pocketbase/pocketbase serve

[Install]
WantedBy = multi-user.target

Una volta che hai capito come salvare il file e uscire da Vi (esc, :wq, invio) possiamo procedere ad abilitare il servizio e ad avviarlo:

systemctl enable pocketbase-dominio.service
systemctl start pocketbase-dominio

Alcuni comandi da tenere sottomano e che potrebbero tornare utili in questo momento:

// Disabilita il servizio
systemctl disable pocketbase-dominio.service

// Controlla lo status del servizio
systemctl status pocketbase-dominio

// Fermare il servizio
systemctl stop pocketbase-dominio

// Reload di tutti i servizi
// (se viene modificato il file .service già caricato)
systemctl daemon-reload

// Le porte sono occupate?
netstat -alpn | grep pocketbase
netstat -alpn | grep 8090

Se tutto è andato secondo i piani ora abbiamo le carte in regola per poter accedere a PocketBase:

api.dominio.it/
api.dominio.it/_/
api.dominio.it/api/

🎉 🎉 🎉 🎉 🎉 🎉

Configurare più istanze nello stesso sotto dominio

Ora che abbiamo visto le basi e abbiamo visto che la cosa ci piace molto, ci viene in mente che, invece di usarlo per una sola applicazione, possiamo sfruttare questo sistema per più di un solo backend. In questo esempio distinguiamo i due servizi in A e B per andare a modificare in modo adeguato le configurazioni.

In questo scenario vogliamo che ad https://api.dominio.it/a sia associata un’istanza di PocketBase, mentre su https://api.dominio.it/b vogliamo che risponda un’altro backend. Dobbiamo quindi creare un nuovo servizio per ciascuno dei backend che vogliamo far girare e in più dobbiamo modificare le impostazioni di proxy di ngnix puntandole al path appropriato.

Per i nuovi servizi possiamo usare:

# Da inserire in /lib/systemd/system/pocketbase-a.service
[Unit]
Description = pocketbase A

[Service]
Type           = simple
User           = root
Group          = root
LimitNOFILE    = 4096
Restart        = always
RestartSec     = 5s
StandardOutput = append:/var/www/vhosts/dominio.it/pocketbase/a/errors.log
StandardError  = append:/var/www/vhosts/dominio.it/pocketbase/a/errors.log
ExecStart      = /var/www/vhosts/dominio.it/pocketbase/a/pocketbase serve --http=127.0.0.1:8091

[Install]
WantedBy = multi-user.target

# Da inserire in /lib/systemd/system/pocketbase-b.service
[Unit]
Description = pocketbase B

[Service]
Type           = simple
User           = root
Group          = root
LimitNOFILE    = 4096
Restart        = always
RestartSec     = 5s
StandardOutput = append:/var/www/vhosts/dominio.it/pocketbase/b/errors.log
StandardError  = append:/var/www/vhosts/dominio.it/pocketbase/b/errors.log
ExecStart      = /var/www/vhosts/dominio.it/pocketbase/b/pocketbase serve --http=127.0.0.1:8092

[Install]
WantedBy = multi-user.target

Da notare che questa volta specifichiamo la porta di PocketBase tramite il flag --http. Abilitiamo i servizi e avviamoli.

NB: non usare le virgolette nel flag perché systemctl cerca di fare l’escape (a modo suo) e il servizio non riuscirà a partire!

Per quanto riguarda la configurazione ngnix del sottodominio invece, al contrario della configurazione standard che reindirizzava tutte le richieste su /, questa volta abbiamo bisogno di smistarle in base al path. Inoltre facciamo un rewrite:

location /a/ {
  proxy_set_header Connection '';
  proxy_http_version 1.1;
  proxy_read_timeout 360s;

  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;

  rewrite /a/(.*) /$1  break;

  proxy_pass http://127.0.0.1:8091;
}

location /b/ {
  proxy_set_header Connection '';
  proxy_http_version 1.1;
  proxy_read_timeout 360s;

  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;

  rewrite /b/(.*) /$1  break;

  proxy_pass http://127.0.0.1:8092;
}

Se tutto fila liscio, possiamo accedere ai due diversi backend:

api.dominio.it/a/_/
api.dominio.it/b/_/

Configurare più istanze in sotto domini diversi

A questo punto credo si sia capito che per avere due backend di PocketBase su due sotto domini distinti basta impostare correttamente il percorso all’eseguibile nel file di descrizione del servizio, mentre per quanto riguarda ngnix vanno impostate le regole iniziali, puntando a / senza rewrite, per ciascun sotto dominio.

Per quanto riguarda i servizi avremo quindi:

# Da inserire in /lib/systemd/system/pocketbase-dominio1.service
[Unit]
Description = pocketbase dominio 1

...

StandardOutput = append:/var/www/vhosts/dominio1.it/pocketbase/errors.log
StandardError  = append:/var/www/vhosts/dominio1.it/pocketbase/errors.log
ExecStart      = /var/www/vhosts/dominio1.it/pocketbase/pocketbase serve --http=127.0.0.1:8093

[Install]
WantedBy = multi-user.target

# Da inserire in /lib/systemd/system/pocketbase-dominio2.service
[Unit]
Description = pocketbase dominio 2

...

StandardOutput = append:/var/www/vhosts/dominio2.it/pocketbase/errors.log
StandardError  = append:/var/www/vhosts/dominio2.it/pocketbase/errors.log
ExecStart      = /var/www/vhosts/dominio2.it/pocketbase/pocketbase serve --http=127.0.0.1:8094

[Install]
WantedBy = multi-user.target

Mentre per quanto riguarda ngnix (cambiare le porte in modo appropriato):

location / {
  ...

  proxy_pass http://127.0.0.1:8093; // o :8094
}

Conclusioni

Trovo che chi ha avuto l’idea di creare PocketBase sia un genio. Sicuramente affidarsi a servizi come Firebase o Supabase ci mette al sicuro da problemi di scalabilità della nostra applicazione. Questi due girano in cloud e le risorse di cui hanno bisogno sono gestite in automatico in base al carico.

Al contrario, PocketBase si scontra con la capacità del nostro server di gestire le richieste: questo può essere ovviamente risolto aumentando la capacità del server. Nonostante questo, credo che PocketBase sia molto più adatto ad applicazioni medio/piccole, piccoli progetti, side hustles o API di servizio collegate ad un progetto più importante. La sua versatilità è disarmante e molto probabilmente il tempo impiegato per fare il setup di PocketBase è una frazione del tempo necessario per impostare un progetto su Firebase.

Personalmente lo sto usando in queste settimane per sviluppare un mio piccolo progetto: Dev Jobs Italia è una bacheca di annunci di lavoro per sviluppatori e aziende italiane. Ho pubblicato la prima versione, veramente un MVP, giusto la settimana scorsa e lo stack che sto usando è composto da Nuxt 3.8 appoggiato su Netlify come framework full stack, mentre per la gestione del backend, ovviamente, PocketBase.

Hai già provato PockeBase o stai usando una configurazione diversa rispetto alla mia?

Fammelo sapere nei commenti!