DEV Community

Cover image for Introducing the PocketBase Cloud CLI: run PocketBase locally, deploy, and manage production
Phat Tran
Phat Tran

Posted on

Introducing the PocketBase Cloud CLI: run PocketBase locally, deploy, and manage production

PocketBase is one binary, and that's a big part of why people like it. The
workflow around it usually isn't: you build locally in the dashboard, copy your
collections across by hand, upload hooks somewhere, and then click through a
second dashboard to change anything in production.

The PocketBase Cloud CLI, pbc, keeps that whole loop in one terminal. This
post follows a small shop backend from an empty folder to production: run
PocketBase on your laptop, model the data, test a hook, deploy the same folder,
and manage it live. The 80-second version:

Install

On macOS and Linux:

curl -fsSL https://raw.githubusercontent.com/pocketbasecloud/cli/main/scripts/install.sh | sh
Enter fullscreen mode Exit fullscreen mode
==> Installing pbc 0.9.9
==> Detected platform: macOS (Apple Silicon)
==> Resolved version: 0.9.9
==> Downloading pbc
==> Installing standalone package to /usr/local/bin/pbc
==> /usr/local/bin is already on PATH
pbc 0.9.9 installed successfully.
Enter fullscreen mode Exit fullscreen mode

On Windows, unzip the win32 build from the
latest release onto
your PATH. Either way, pbc self upgrade keeps it current.

Install pbc

1. Run PocketBase locally

mkdir acme-shop && cd acme-shop && pbc local init
Enter fullscreen mode Exit fullscreen mode
Downloaded pocketbase 0.41.1 (darwin/arm64) → /Users/ada/acme-shop/pocketbase
  created  /Users/ada/acme-shop/pb_hooks/main.pb.js
  created  /Users/ada/acme-shop/README.md
  created  /Users/ada/acme-shop/pb_migrations
  created  /Users/ada/acme-shop/.gitignore
  updated  /Users/ada/acme-shop/pbc.json (pocketbaseVersion: 0.41.1)

Start PocketBase with:
  ./pocketbase serve
Enter fullscreen mode Exit fullscreen mode

That's a real PocketBase binary for your platform, plus the folder layout the
cloud expects: pb_hooks, pb_migrations and a pbc.json that remembers the
PocketBase version. Add a superuser and start it:

./pocketbase superuser upsert ada@example.com 'kiwi-Pebble-42'
./pocketbase serve
Enter fullscreen mode Exit fullscreen mode
Server started at http://127.0.0.1:8090
> Dashboard: http://127.0.0.1:8090/_/
> REST API:  http://127.0.0.1:8090/api/
Enter fullscreen mode Exit fullscreen mode

PocketBase running locally

2. Model the data

pbc admin talks to any PocketBase over its API. Log in to the local one and
save it as a profile called local:

pbc admin login --url http://127.0.0.1:8090 --name local
Enter fullscreen mode Exit fullscreen mode

Then describe the collection in JSON. orders.json:

{
  "name": "orders",
  "type": "base",
  "fields": [
    { "name": "customer", "type": "text", "required": true },
    { "name": "qty", "type": "number" },
    { "name": "price", "type": "number" },
    { "name": "total", "type": "number" },
    { "name": "status", "type": "text" }
  ]
}
Enter fullscreen mode Exit fullscreen mode
pbc admin collections create "$(cat orders.json)"
Enter fullscreen mode Exit fullscreen mode
Created collection orders (pbc_2456927940).
Enter fullscreen mode Exit fullscreen mode

The collection shows up in the dashboard, and because PocketBase is running
locally with serve, it writes the migration for you:
pb_migrations/1794446332_created_orders.js. That file is what carries the
schema to production later.

The orders collection and its fields

3. Add a hook and test it

A hook that fills in each order's total, in pb_hooks/orders.pb.js:

/// <reference path="../pb_data/types.d.ts" />
onRecordCreateRequest((e) => {
  const qty = e.record.getInt("qty")
  const price = e.record.getFloat("price")
  e.record.set("total", qty * price)
  e.next()
}, "orders")
Enter fullscreen mode Exit fullscreen mode

Create a test order from the terminal:

pbc admin records create orders '{"customer":"Mara Quinn","qty":2,"price":64}'
Enter fullscreen mode Exit fullscreen mode
Created record k2v9x81m0qz4tdp.
Enter fullscreen mode Exit fullscreen mode

Open the record in the dashboard: total is 128. The hook works, on your
laptop, before anything is deployed.

The hook filled in the total

4. Deploy

pbc login
pbc deploy
Enter fullscreen mode Exit fullscreen mode
Detected a PocketBase instance (pb_hooks/) — running `pbc pocketbase deploy`.
✓ Connecting to PocketBase Cloud
Environment: production — new PocketBase acme-shop
✓ Packaged 3 file(s), 2.4 KB.
✓ Uploaded data.zip 4s
✓ acme-shop is running 12s
  https://acme-shop.pocketbasecloud.com
  https://acme-shop.pocketbasecloud.com/_/ (admin)
✓ Reachable.
Enter fullscreen mode Exit fullscreen mode

pbc deploy looks at the folder and works out what it is. Here it sees
pb_hooks/ and runs the PocketBase deploy: hooks, migrations and public files
go up, the migration creates the orders collection on the cloud instance, and
it's live with its own URL. The same command deploys a frontend or a backend
when the folder holds one. The deploy is recorded in pbc.json, so the next
one needs no flags.

Deployed to PocketBase Cloud

5. Manage production from the terminal

The admin commands you used locally work on production too. Log in to the cloud
instance as a second profile:

pbc admin login --url https://acme-shop.pocketbasecloud.com --name cloud
pbc admin records ls orders --fields customer,total,status
Enter fullscreen mode Exit fullscreen mode
ID               CUSTOMER        TOTAL  STATUS
r8m2kq7v1xw4tzn  Theo Lindqvist  42.5   paid
c5y9pd3h0ja6lbe  Ines Okafor     310    shipped
w1n4fs8u2go7rkq  June Albers     76.4   paid

Page 1/1 — 30 per page, 3 total.
Enter fullscreen mode Exit fullscreen mode

Lock down who can list orders:

pbc admin rules set orders --list-rule "@request.auth.id != ''"
Enter fullscreen mode Exit fullscreen mode
Updated rules on orders.
Enter fullscreen mode Exit fullscreen mode

pbc admin profiles lists the local and cloud logins side by side.
Switch with pbc admin use local, or pass --profile cloud to a single
command, without logging in again.
And pbc admin isn't tied to PocketBase Cloud: point it at a PocketBase on
your own server and the same commands work there.

The new API rule in production

6. Deploy on every push

pbc ci init
Enter fullscreen mode Exit fullscreen mode
Wrote /Users/ada/acme-shop/.github/workflows/deploy.yml — deploys this PocketBase instance on every push to main.
Enter fullscreen mode Exit fullscreen mode

The workflow it writes:

name: Deploy

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pocketbasecloud/cli/action@v0.9.9
        with:
          token: ${{ secrets.PBC_TOKEN }}
          kind: pb
Enter fullscreen mode Exit fullscreen mode

Copy the CLI access token from the Deploy From CI card on your Account page
in the portal and add it as a PBC_TOKEN repository secret. Commit the
workflow, push, and from then on every push to main deploys.

Every push deploys

The whole loop

Step Command
Run PocketBase locally pbc local init
Model the data pbc admin collections create
Test with real records pbc admin records create
Ship it pbc deploy
Manage production pbc admin login --name cloud, pbc admin rules set
Deploy on every push pbc ci init

One folder from start to finish: the thing you test on your laptop is the
thing that goes live.

Install and the full command reference:
Installing the CLI.
The source is on GitHub.

Where do you test PocketBase changes before production today: a local
instance, a staging copy, or straight to live? I'm curious what people's setup
looks like.

Top comments (0)