Skip to content

How to Deploy PocketBase on a VPS

Updated Sep 2026

We earn commissions when you shop through the links below. Full disclosure →

Self-host PocketBase on your own VPS — a single Go binary with embedded SQLite, built-in auth, realtime subscriptions, and an admin dashboard, running as a systemd service behind HTTPS.

Before you start
  • A VPS with 512 MB+ RAM (PocketBase's own minimum — a 1 GB tier gives comfortable headroom for the OS and a reverse proxy)
  • A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
  • A domain you can point at the server — the admin dashboard shouldn't be run over plain HTTP
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What PocketBase is

PocketBase is an open-source backend that ships as a single Go binary: an embedded SQLite database, built-in authentication, realtime subscriptions, file storage, and an admin dashboard, with zero external services to run alongside it. There's no separate database container, no cache, no queue — the binary you download is the backend. It's MIT-licensed, rated 1 / 5 to deploy, and happily starts on 512 MB of RAM.

That "one file" pitch is the whole appeal for self-hosting: you're not operating a database server, just a process and a data directory. This guide covers getting that process onto a VPS the right way — running as a system service (not a foreground ./pocketbase serve in a terminal you'll eventually disconnect from), behind HTTPS, with real backups and an upgrade path. For help deciding which VPS and tier to put it on, see Best VPS for PocketBase — this guide picks up from "you have a server" and covers the install itself.

Server sizing

PocketBase's own documented minimum is 512 MB RAM, and because SQLite is embedded in the binary, there's no separate database process competing for that memory — the number you see in htop for the pocketbase process is close to the whole footprint. Add a small reverse proxy (Caddy, covered below) and the OS itself, and a 1 GB VPS has real headroom to spare for a personal project or small team.

Disk, not RAM, is what to watch as usage grows. Everything PocketBase owns — the SQLite database file, uploaded files, and backup archives — lives under one pb_data directory on the same volume as the binary. A hobby project barely touches it; an app that accepts file uploads from users can grow that directory steadily. Pick a plan with NVMe/SSD storage you can expand later rather than over-provisioning RAM PocketBase won't use.

Prepare the server

Start from a fresh Ubuntu 24.04 or 26.04 server and create a non-root user:

apt update && apt -y upgrade
adduser deploy
usermod -aG sudo deploy

Log back in as deploy for the rest of this guide, then set up a basic firewall — SSH plus the two ports the reverse proxy will need:

ssh deploy@your-server-ip
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

PocketBase itself needs no port open to the internet — it will listen only on 127.0.0.1, and the reverse proxy is the sole public door (same pattern as every other app on this site).

Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
1 vCPU · 1 GB RAM · 25 GB SSD · $6.00/mo
Deploy on DigitalOcean → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install PocketBase

Grab the current release directly from GitHub rather than hardcoding a version number that will go stale — this resolves whatever the latest tagged release is at the time you run it:

sudo apt-get update && sudo apt-get install -y unzip curl

PB_VERSION=$(curl -fsSL https://api.github.com/repos/pocketbase/pocketbase/releases/latest \
  | grep '"tag_name"' | cut -d '"' -f4)
echo "Installing PocketBase ${PB_VERSION}"

sudo mkdir -p /opt/pocketbase
curl -LO "https://github.com/pocketbase/pocketbase/releases/download/${PB_VERSION}/pocketbase_${PB_VERSION#v}_linux_amd64.zip"
sudo unzip -o "pocketbase_${PB_VERSION#v}_linux_amd64.zip" -d /opt/pocketbase
rm "pocketbase_${PB_VERSION#v}_linux_amd64.zip"
sudo chown -R deploy:deploy /opt/pocketbase

That unpacks a single pocketbase executable into /opt/pocketbase. Running it directly confirms the binary works before you wire it into systemd:

/opt/pocketbase/pocketbase --version

Run it as a systemd service, not a terminal session that dies on disconnect. Bind to loopback only — --http=127.0.0.1:8090 — because Caddy is about to become the only thing the internet can reach:

sudo tee /etc/systemd/system/pocketbase.service > /dev/null <<'EOF'
[Unit]
Description=PocketBase
After=network.target

[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/opt/pocketbase
ExecStart=/opt/pocketbase/pocketbase serve --http=127.0.0.1:8090
Restart=always
RestartSec=5
LimitNOFILE=4096

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now pocketbase
sudo systemctl status pocketbase

WorkingDirectory=/opt/pocketbase is what determines where the pb_data directory (database, uploads, logs) gets created — pass --dir explicitly instead if you want it somewhere else.

HTTPS + domain

Create an A record for your subdomain (e.g. pb.example.com) pointing at the server's public IP, and confirm it resolves before requesting a certificate:

dig +short pb.example.com

Then put Automatic HTTPS with Caddy in front of the loopback address PocketBase is already listening on — the whole config is one block:

pb.example.com {
    reverse_proxy 127.0.0.1:8090
}

Because PocketBase sits behind a proxy, it sees every request coming from 127.0.0.1 unless you tell it otherwise. Set the trusted proxy headers under Dashboard → Settings → Application (or the equivalent pocketbase.io docs section on reverse proxies) so rate limiting, logs, and auth rules see the real client IP from X-Forwarded-For rather than the proxy's own address.

First superuser and hardening

Create the first admin account from the command line rather than exposing an open signup page to the internet — PocketBase has no public registration for superusers by default, but setting it explicitly up front avoids ever depending on the dashboard's first-run flow being reachable before anything else is:

sudo -u deploy /opt/pocketbase/pocketbase superuser create you@example.com 'a-long-random-password'

Then, before opening the app up to real users:

  1. Load https://pb.example.com/_/ and confirm you can sign in as that superuser — this is the admin dashboard, separate from your app's own collections and API.
  2. Set collection-level API rules deliberately. PocketBase collections are locked down by default (empty rule = admin-only); every collection you expose to your app's users needs its own list/view/create/update/delete rules reviewed, not left on whatever the scaffold generated.
  3. Turn on the encrypted-settings env var (--encryptionEnv=SOME_VAR, set as an Environment= line in the systemd unit) if you store OAuth secrets or SMTP credentials in PocketBase's own settings, so they aren't sitting in pb_data/data.db in plaintext.
  4. Keep /opt/pocketbase and pb_data owned by the deploy user only — the systemd unit already runs as that user, not root; don't widen the permissions to fix an unrelated problem.

Backups

Everything PocketBase owns lives under one pb_data directory, which makes backup strategy simple: back that directory up, and you have the database, uploaded files, and migrations in one piece.

Built-in backups (simplest). From Dashboard → Settings → Backups, PocketBase can produce a ZIP snapshot of pb_data on demand or on a schedule, and ship it to local disk or an S3-compatible bucket. For a personal or small-team instance this is enough on its own — point it at object storage so the backup survives the VPS itself dying.

Manual backup (scriptable, cron-friendly). Stop the service first so the SQLite file isn't mid-write when you copy it:

sudo systemctl stop pocketbase
tar -czf "pocketbase-backup-$(date +%F).tar.gz" -C /opt/pocketbase pb_data
sudo systemctl start pocketbase

Move the archive off the box — object storage, another machine, your laptop — and restore it once into a throwaway instance so you find out now, not during an outage, that the archive is actually complete: unzip it into a fresh pb_data, point a test binary at it with --dir, and confirm your data is there.

Upgrades

PocketBase upgrades are a binary swap, not a package manager operation:

sudo systemctl stop pocketbase
PB_VERSION=$(curl -fsSL https://api.github.com/repos/pocketbase/pocketbase/releases/latest \
  | grep '"tag_name"' | cut -d '"' -f4)
curl -LO "https://github.com/pocketbase/pocketbase/releases/download/${PB_VERSION}/pocketbase_${PB_VERSION#v}_linux_amd64.zip"
sudo unzip -o "pocketbase_${PB_VERSION#v}_linux_amd64.zip" -d /opt/pocketbase
rm "pocketbase_${PB_VERSION#v}_linux_amd64.zip"
sudo chown -R deploy:deploy /opt/pocketbase
sudo systemctl start pocketbase

Take a pb_data backup first (previous section) — PocketBase applies database migrations automatically on startup, and those are one-way. Skim the release notes before jumping a minor version; a single-maintainer project moves fast and occasionally changes a default.

Troubleshooting

systemctl status pocketbase shows the service repeatedly restarting. Run the ExecStart command by hand as the deploy user (/opt/pocketbase/pocketbase serve --http=127.0.0.1:8090) to see the actual error instead of systemd's exit code — a bad --dir permission or a port already in use are the usual causes.

The dashboard loads over HTTP but Caddy never gets a certificate. Confirm dig +short pb.example.com actually resolves to the server, and that your cloud provider's network-level firewall (not just ufw on the box) allows inbound 80 and 443 — a provider firewall blocking port 80 silently breaks the ACME challenge with nothing in Caddy's own logs to explain why.

Rate limiting or audit logs show the proxy's IP instead of real clients. The trusted-proxy header setting from the HTTPS section above wasn't applied — every request is arriving from 127.0.0.1 as far as PocketBase can tell until you configure it to trust X-Forwarded-For from the proxy.

A restore comes back with the app running but files or auth broken. The restore only copied part of pb_data. Database, uploads, and migrations all live in that one directory — a partial copy (say, database only) is not a complete restore.

Verification + next steps

You're done when you can: load https://pb.example.com/_/ with a valid certificate, sign in as the superuser you created from the CLI, confirm systemctl is-enabled pocketbase reports enabled (it survives a reboot), create a collection with API rules you set deliberately rather than left on defaults, and restore a backup archive you've actually tested.

From there, the natural next steps are wiring up the JS or Dart SDK from your frontend, configuring OAuth2 providers under Settings → Auth providers if you need social login, and turning on the built-in email service (or your own SMTP) so account verification and password-reset mail actually sends. For the ranked VPS picks for this workload, see Best VPS for PocketBase.

Next steps

How to self-host PocketBase →More self-hosted backend & baas tools →Best VPS for PocketBase →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.