Deploying PocketBase - Open-Source Go Backend Platform on Linux
DEV Community

Deploying PocketBase - Open-Source Go Backend Platform on Linux

PocketBase is an open-source backend written in Go that bundles a real-time SQLite database, authentication, file uploads, and an admin dashboard into a single binary. This guide deploys PocketBase using Docker Compose with Traefik handling automatic HTTPS, admin credentials injected via environment variables, and a sample collection queried through the REST API. By the end, you'll have PocketBase serving a working backend securely at your domain.

Set Up the Directory Structure

  1. Create the project folder and data directory:

    $ mkdir -p ~/pocketbase/pb_data
    $ cd ~/pocketbase
    
  2. Create the environment file:

    $ nano .env
    DOMAIN=pocketbase.example.com
    LETSENCRYPT_EMAIL=admin@example.com
    PB_ADMIN_EMAIL=admin@example.com
    PB_ADMIN_PASSWORD="SecurePassword123"
    

    Keep the quotes around the password if it contains special characters.

Deploy with Docker Compose

  1. Create the Docker Compose manifest:

    $ nano docker-compose.yaml
    
    services:
      traefik:
        image: traefik:v3.6
        container_name: traefik
        command:
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.websecure.address=:443"
          - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
          - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
          - "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
          - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "letsencrypt:/letsencrypt"
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
        restart: unless-stopped
    
      pocketbase:
        image: ghcr.io/muchobien/pocketbase:0.36.2
        container_name: pocketbase
        environment:
          - PB_ADMIN_EMAIL=${PB_ADMIN_EMAIL}
          - PB_ADMIN_PASSWORD=${PB_ADMIN_PASSWORD}
        expose:
          - "8090"
        volumes:
          - "./pb_data:/pb_data"
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.pocketbase.rule=Host(`${DOMAIN}`)"
          - "traefik.http.routers.pocketbase.entrypoints=websecure"
          - "traefik.http.routers.pocketbase.tls.certresolver=letsencrypt"
          - "traefik.http.services.pocketbase.loadbalancer.server.port=8090"
        restart: unless-stopped
    
    volumes:
      letsencrypt:
    

    Note: PocketBase auto-creates the admin account only on first startup, when pb_data is empty. To reinitialize the admin on an existing install: sudo rm -rf ~/pocketbase/pb_data/* - this permanently deletes all stored data.

  2. Start the services:

    $ docker compose up -d
    
  3. Verify both services are running:

    $ docker compose ps
    $ docker compose logs
    

Access the Admin Dashboard

Open https://pocketbase.example.com/_/ and sign in with PB_ADMIN_EMAIL / PB_ADMIN_PASSWORD from .env. The dashboard covers:

  • Collections - schemas, fields, validation, API rules
  • Users - accounts, email verification, access control
  • Logs - request/error history
  • Settings - email delivery, external storage, OAuth, scheduled backups

Create a Collection and Query the API

  1. Click + New collection, name it tasks, and add fields:

    • title - Plain text
    • completed - Bool
  2. In API Rules, set:

    • List/Search and View: leave empty (public read)
    • Create / Update / Delete: @request.auth.id != "" (requires auth)

    Click Save changes.

  3. Add a record - title: "Learn PocketBase API", completed unchecked.

  4. Query the collection over HTTPS:

    $ curl -s https://pocketbase.example.com/api/collections/tasks/records | jq
    
    {
      "items": [
        {
          "collectionId": "pbc_2602490748",
          "collectionName": "tasks",
          "completed": false,
          "id": "z35xnphgqng0bff",
          "title": "Learn PocketBase API"
        }
      ],
      "page": 1,
      "perPage": 30,
      "totalItems": 1,
      "totalPages": 1
    }
    
  5. Filter with a query parameter:

    $ curl -s "https://pocketbase.example.com/api/collections/tasks/records?filter=(completed=false)" | jq '.items[].title'
    "Learn PocketBase API"
    

Next Steps

PocketBase is running and served securely over HTTPS. From here you can:

  • Build a frontend against the auto-generated REST/Realtime API
  • Back up the entire app by copying the pb_data directory - no separate database dump needed
  • Configure SMTP, OAuth providers, and S3-compatible file storage under Settings

For the full guide with additional tips, visit the original article on Vultr Docs.

Comments

No comments yet. Start the discussion.