Deployment guide

Hosting PocketBase on a VPS: complete guide

Deploy on a VPS Cloud →

Tutorial

Hosting PocketBase on a VPS: complete guide

Databases10 min read5 steps

PocketBase fits in a single Go binary: embedded SQLite database, authentication, file storage, REST API and real-time subscriptions, all with a built-in admin UI. It is the ideal backend to self-host on a lightweight VPS for your web and mobile applications. This complete guide takes you from Docker installation to HTTPS configuration, OAuth authentication, automatic backups and advanced tuning.

Contents· Why self-host PocketBase on a VPS1/11
  1. 01Why self-host PocketBase on a VPS
  2. 02Concrete benefits of self-hosting PocketBase
  3. 03Precise requirements: VPS, system and software
  4. 04Deploy PocketBase on VPS step by step
  5. 05Configure OAuth authentication (Google, GitHub, GitLab)
  6. 06Automatic backups: SQLite and files
  7. 07SQLite WAL mode and performance
  8. 08Troubleshooting: common errors
  9. 09Going further: admin CLI, collections and hooks
  10. 10PocketBase vs self-hosted alternatives
  11. 11Official documentation

Why self-host PocketBase on a VPS

PocketBase is an open source backend-as-a-service distributed as a single binary: no separate Postgres, no Redis, no complex stack to orchestrate. Everything runs on SQLite, making it perfectly suited to an entry-level VPS.

By self-hosting, you retain full control over your user data and files, without depending on a managed Firebase or Supabase with quotas and latency that can be problematic depending on your region. A VPS gives you a fixed IP, a custom domain and backups that you fully control.

Because PocketBase writes to a single pb_data folder, your backup strategy comes down to copying that directory, which simplifies operations enormously compared to a classic database cluster. You can migrate your backend by moving a single folder.

Concrete benefits of self-hosting PocketBase

  • A single binary to deploy: starts in seconds, minimal memory footprint (often less than 100 MB of RAM).
  • Embedded SQLite database: zero database service to manage, backup by simply copying the pb_data folder.
  • Full authentication (email/password, OAuth2, OTP, LDAP) and granular access rules per collection.
  • Real-time API via Server-Sent Events to automatically sync your clients without additional WebSocket.
  • Complete web admin interface to manage collections, users, permissions and files without writing SQL.
  • Data sovereignty: your users and their files stay on your infrastructure, behind your domain.
  • Predictable cost: the VPS price does not change with traffic, unlike per-request billing.

Precise requirements: VPS, system and software

PocketBase is extremely lightweight. Here is what you need based on your load:

Absolute minimum: 1 vCPU, 512 MB of RAM. Sufficient for a development project or a small application with fewer than 1,000 active users.

Recommended in production: 1 vCPU, 1 GB of RAM. PocketBase handles a small to medium-sized project easily with this configuration; the SQLite cache and real-time traffic spikes are absorbed comfortably.

For high volumes: 2 vCPU, 2 GB of RAM. The limit of PocketBase is usually concurrent writes to SQLite, not CPU.

For storage, plan for 20 to 40 GB SSD NVMe depending on the volume of files uploaded by your users. Since SQLite is a single file, an NVMe disk noticeably improves concurrent write performance — avoid network drives (NFS, CIFS) which can corrupt the database when locks are mishandled.

Required software: Docker 24+ and Docker Compose v2 (or the PocketBase binary alone with systemd), a domain name or subdomain pointing to the VPS IP via an A record, a reverse proxy (Caddy, Nginx or Traefik) to handle TLS.

Deploy PocketBase on VPS step by step

  1. Prepare the VPS and DNS

    Connect via SSH, update the system with apt update && apt upgrade -y, then install Docker with the official script: curl -fsSL https://get.docker.com | sh. Add your user to the Docker group with usermod -aG docker $USER to avoid sudo on every command.

    Then create an A DNS record pointing app.your-domain.com to the public IP of your VPS. Propagation takes from a few minutes to 24 hours — verify with dig app.your-domain.com.

  2. Create the file structure

    Create a dedicated directory and the compose file:

    mkdir -p /opt/pocketbase && cd /opt/pocketbase

    Create the docker-compose.yml file with the following content:

    services:
      pocketbase:
        image: ghcr.io/muchobien/pocketbase:latest
        restart: unless-stopped
        volumes:
          - ./pb_data:/pb_data
        expose:
          - "8090"

    Do not publish port 8090 directly to the Internet (no ports:) — let the reverse proxy handle it.

  3. Configure HTTPS with Caddy (recommended reverse proxy)

    Caddy automatically obtains and renews Let's Encrypt certificates. Create /opt/pocketbase/Caddyfile:

    app.your-domain.com {
        reverse_proxy pocketbase:8090
    }

    Add the Caddy service in docker-compose.yml:

      caddy:
        image: caddy:2-alpine
        restart: unless-stopped
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ./Caddyfile:/etc/caddy/Caddyfile
          - caddy_data:/data
        depends_on:
          - pocketbase
    
    volumes:
      caddy_data:

    Caddy enables WebSockets (used by PocketBase real-time subscriptions) by default. If you prefer Nginx, add the Upgrade and Connection headers in your location / so SSE connections pass through correctly.

  4. Start and verify

    Start the stack with docker compose up -d then follow the logs:

    docker compose logs -f pocketbase

    You should see a line indicating PocketBase is listening on 0.0.0.0:8090 and the URL /_/ for the admin interface. Verify that HTTPS works: curl -I https://app.your-domain.com/_/ should return HTTP/2 200.

  5. Create the super-admin account

    Open https://app.your-domain.com/_/ in your browser. On first access, PocketBase prompts you to create a super-admin account (email + password). Do this immediately after startup — before making the URL public — because anyone reaching /_/ can create this first account on a fresh instance.

    Once logged in, explore the interface: Collections, Users, Logs and Settings.

Configure OAuth authentication (Google, GitHub, GitLab)

PocketBase natively supports OAuth2 with several providers: Google, GitHub, GitLab, Discord, Twitter/X, Microsoft, Apple and others. Configuration is done entirely from the admin interface, without touching code.

For Google OAuth:
1. Open the Google Cloud Console, create a project and enable the "OAuth consent screen" API.
2. Under "Credentials", create an "OAuth 2.0 Client ID" of type "Web application".
3. Add https://app.your-domain.com/api/oauth2-redirect as an authorized redirect URI.
4. Copy the Client ID and Client secret.
5. In PocketBase /_/, go to Settings → Auth providers → Google, enable it and paste your credentials.

For GitHub OAuth:
1. On GitHub, go to Settings → Developer settings → OAuth Apps → New OAuth App.
2. Set https://app.your-domain.com as the Homepage URL and https://app.your-domain.com/api/oauth2-redirect as the Authorization callback URL.
3. Copy the Client ID and generate a Client Secret.
4. Enable GitHub under Settings → Auth providers in PocketBase.

Each active provider will automatically appear on the login page generated by PocketBase. Your frontend only needs to call pb.collection('users').authWithOAuth2({ provider: 'google' }) via the JavaScript SDK.

Automatic backups: SQLite and files

PocketBase stores everything in the pb_data folder: the SQLite database (pb_data/data.db), uploaded files (pb_data/storage/) and logs. A complete backup is simply archiving that folder.

Method 1 — simple cron: add this line to your crontab (crontab -e) for a daily archive at 3am:

0 3 * * * tar czf /var/backups/pocketbase-$(date +\%F).tar.gz /opt/pocketbase/pb_data && find /var/backups -name 'pocketbase-*.tar.gz' -mtime +7 -delete

This command creates a dated archive and deletes backups older than 7 days.

Method 2 — built-in PocketBase backups: from the /_/ interface, go to Settings → Backups. PocketBase can create pb_data archives directly from the admin or via the API (POST /api/backups). You can download these archives or send them to an S3-compatible storage.

Method 3 — rclone to S3: for automatic off-site copying, use rclone:

0 4 * * * rclone sync /opt/pocketbase/pb_data your-remote:pocketbase-backup/

your-remote is an rclone profile configured to Backblaze B2, AWS S3 or any compatible object storage. Always keep a copy off the server — if the disk fails, a local-only backup is useless.

SQLite WAL mode and performance

PocketBase enables SQLite WAL (Write-Ahead Logging) mode by default in recent versions. This mode allows concurrent reads during writes, preventing an insert from blocking all reads. If you experience timeouts under heavy load, check with PRAGMA journal_mode; in PocketBase's SQL admin — the response should be wal, not delete.

For high traffic, place pb_data on an NVMe volume and avoid any network file system. SQLite on NFS can corrupt the database when locks are mishandled.

Troubleshooting: common errors

Port already in use: if docker compose up fails with bind: address already in use on port 80 or 443, check with ss -tlnp | grep ':80' which service is using the port. An nginx or Apache installed on the host conflicts with Caddy. Stop it (systemctl stop nginx) or change its ports.

Permissions on pb_data: PocketBase runs as user nobody (UID 65534) in the official container. If you mount a folder created by root, the process cannot write. Fix with chown -R 65534:65534 /opt/pocketbase/pb_data.

/_/ inaccessible after startup: verify that the reverse proxy points to the Docker service name (pocketbase:8090) and not localhost:8090. In a Docker Compose network, services communicate by their name, not via localhost.

Updating PocketBase: change the image tag in docker-compose.yml (e.g. ghcr.io/muchobien/pocketbase:0.23) then docker compose pull && docker compose up -d. PocketBase performs schema migrations automatically on startup. Back up pb_data before any major update.

Let's Encrypt certificate not obtained: Caddy needs ports 80 and 443 accessible from the Internet for the HTTP-01 challenge. Check your firewall (ufw status) and your hosting provider's security group rules.

Going further: admin CLI, collections and hooks

Admin CLI: PocketBase exposes a CLI for common operations without going through the web interface. From the container: docker exec -it pocketbase_pocketbase_1 /pb/pocketbase --help. You can create a super-admin from the command line, run migrations or check the database health.

Custom collections: in /_/, create your collections (equivalent to tables) by defining typed fields (text, number, bool, date, file, relation, select, JSON). API rules are expressed in PocketBase syntax (@request.auth.id != "" to restrict to logged-in users, @request.auth.id = id to limit to one's own record).

Hooks (server-side JavaScript): since PocketBase v0.17, you can extend the backend with JavaScript scripts running server-side (pb_hooks/*.pb.js). Example uses: send an email when a user is created, validate complex data before insertion, trigger a webhook to Slack. These hooks are files mounted in the container:

volumes:
  - ./pb_data:/pb_data
  - ./pb_hooks:/pb_hooks

JavaScript SDK: the official SDK (npm install pocketbase) simplifies calls from your React, Vue or mobile frontend. It handles authentication, token refresh and real-time subscriptions (pb.collection('tasks').subscribe('*', callback)).

PocketBase vs self-hosted alternatives

Scroll the table

CriterionPocketBaseSupabase self-hostedAppwrite
Installation complexityVery low (1 binary or 1 container)High (docker-compose of 10+ services)Medium (docker-compose of 6 services)
Minimum RAM512 MB4 GB+2 GB+
DatabaseEmbedded SQLitePostgreSQLMariaDB
OAuth authenticationYes (native)Yes (GoTrue)Yes (native)
Real-timeServer-Sent EventsWebSocket (Realtime server)WebSocket
File storageYes (local + S3)Yes (S3 compatible)Yes (local + S3)
Horizontal scalingNo (single-file SQLite)Yes (PostgreSQL)Limited

Official documentation

For advanced configuration and tool-specific options, refer to the official PocketBase documentation. This guide covers deployment on VPS; the editor documentation remains the reference for fine-tuning, major updates and specific use cases.

If you want to test PocketBase without Docker, download the Linux binary from github.com/pocketbase/pocketbase/releases, run ./pocketbase serve --http=0.0.0.0:8090 and create a systemd service so it restarts automatically. This approach is even lighter than Docker on small VPS.

Launch your PocketBase backend in minutes

The ServOrbit Cloud VPS gives you a ready-to-use Docker environment, a fixed IP, and fast SSD disks to host PocketBase with automatic SSL and simplified backups.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab