Skip to main content
This guide covers deploying the Pullbase central server using containers. The central server coordinates environments, monitors Git repositories, and serves the web dashboard.
Agents should run natively on your Linux servers, not in containers. Container agents require privileged access and have significant limitations. See Agent Operations for native agent installation.This page is for deploying the central server only.
Pullbase publishes a container image for the central server (pullbaseio/pullbase). This guide shows how to deploy it with Docker Compose, but the same environment variables apply if you run the image under Kubernetes, Nomad, or another orchestrator.

Prerequisites

  • Docker 24.0+ with the Compose plugin (or an equivalent container runtime)
  • PostgreSQL 15+ (container service or managed instance)
  • Git repository containing your environment configuration (config.yaml)
  • (Production) Reverse proxy for TLS termination
For production clusters, place PostgreSQL on managed infrastructure, store secrets in a vault, and terminate TLS at a reverse proxy. The examples below target a single host for clarity.

Directory layout

/opt/pullbase/
├── docker-compose.yml
├── .env
├── config/
│   └── github-app.pem   # optional, mounted read-only
└── logs/                # optional bind mount for log shipping
  • config/ holds the GitHub App private key or other secrets you mount read-only.
  • logs/ can be bound if you prefer file-based log collection; otherwise rely on docker logs.

Compose template

docker-compose.yml
services:
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: pullbaseuser
      POSTGRES_PASSWORD: pullbasepass
      POSTGRES_DB: pullbasedb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U pullbaseuser -d pullbasedb']
      interval: 10s
      timeout: 5s
      retries: 5

  pullbase:
    image: pullbaseio/pullbase:latest
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      # Database
      PULLBASE_DB_HOST: db
      PULLBASE_DB_PORT: 5432
      PULLBASE_DB_USER: pullbaseuser
      PULLBASE_DB_PASSWORD: pullbasepass
      PULLBASE_DB_NAME: pullbasedb
      PULLBASE_DB_SSLMODE: disable
      # Server
      PULLBASE_SERVER_PORT: 8080
      PULLBASE_SERVER_HOST: 0.0.0.0
      # Authentication
      PULLBASE_JWT_SECRET: ${PULLBASE_JWT_SECRET}
      PULLBASE_JWT_EXPIRY_HOURS: 24
      # Webhooks
      PULLBASE_WEBHOOK_SECRET_KEY: ${PULLBASE_WEBHOOK_SECRET_KEY}
      # Git integration
      PULLBASE_GIT_ENABLED: ${PULLBASE_GIT_ENABLED:-false}
      PULLBASE_GIT_CLONE_PATH: /app/git-repos
      PULLBASE_GIT_POLL_INTERVAL: 60
      # GitHub App (when using private repos)
      PULLBASE_GITHUB_APP_ID: ${PULLBASE_GITHUB_APP_ID:-}
      PULLBASE_GITHUB_APP_PRIVATE_KEY_PATH: /config/github-app.pem
      PULLBASE_GITHUB_APP_API_BASE_URL: https://api.github.com
    volumes:
      - ./config:/config:ro
    ports:
      - '8080:8080'

volumes:
  postgres_data:
Populate secrets in .env:
cat <<EOF > .env
 PULLBASE_JWT_SECRET=$(openssl rand -hex 32)
 PULLBASE_WEBHOOK_SECRET_KEY=$(openssl rand -hex 32)
 PULLBASE_GIT_ENABLED=false
EOF

Launch the stack

1

Start services

docker compose up -d
2

Verify health

curl http://localhost:8080/api/v1/healthz
3

Tail logs

docker compose logs -f pullbase

TLS configuration

Pullbase supports two approaches for TLS in production.

Option 1: Native TLS

Enable native TLS by adding these environment variables to your Compose file:
environment:
  PULLBASE_TLS_ENABLED: "true"
  PULLBASE_TLS_CERT_PATH: /config/server.crt
  PULLBASE_TLS_KEY_PATH: /config/server.key
Mount your certificates in the config volume:
volumes:
  - ./config:/config:ro  # Contains server.crt, server.key, github-app.pem
For development, you can start the server with --generate-dev-certs to auto-generate self-signed certificates.

Option 2: Reverse proxy

For existing infrastructure, place Pullbase behind a reverse proxy that handles TLS:

NGINX example

server {
    listen 443 ssl http2;
    server_name pullbase.example.com;
    
    ssl_certificate /etc/ssl/certs/pullbase.crt;
    ssl_certificate_key /etc/ssl/private/pullbase.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    
    location / {
        proxy_pass http://pullbase:8080;
        proxy_http_version 1.1;
        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_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Traefik example

# Add to docker-compose.yml
traefik:
  image: traefik:v3.6.2
  command:
    - "--providers.docker=true"
    - "--entrypoints.websecure.address=:443"
    - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
    - "[email protected]"
    - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
  ports:
    - "443:443"
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - letsencrypt:/letsencrypt

# Add labels to pullbase service
pullbase:
  labels:
    - "traefik.enable=true"
    - "traefik.http.routers.pullbase.rule=Host(`pullbase.example.com`)"
    - "traefik.http.routers.pullbase.entrypoints=websecure"
    - "traefik.http.routers.pullbase.tls.certresolver=letsencrypt"
Always use TLS in production. Agents transmit authentication tokens over the network, and the web UI handles user credentials.

External databases

Using Amazon RDS, Azure Database for PostgreSQL, or another managed service?
  1. Create the database and grant Pullbase a dedicated user.
  2. Set PULLBASE_DB_HOST, PULLBASE_DB_USER, PULLBASE_DB_PASSWORD, and PULLBASE_DB_NAME to match the instance.
  3. Enable TLS by setting PULLBASE_DB_SSLMODE=require or PULLBASE_DB_SSLMODE=verify-full.
  4. Remove the db service from docker-compose.yml.

Upgrades

  • Pin the image tag (for example, pullbaseio/pullbase:vX.Y.Z) and update intentionally.
  • Run docker compose pull && docker compose up -d to roll forward with minimal downtime.
  • Review release notes for database migrations and watch container logs during the upgrade.
Automate backups before upgrades: docker compose exec db pg_dump -U pullbaseuser pullbasedb > backup.sql. Managed databases often provide scheduled snapshots—enable them.