> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pullbase.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Bare-Metal Deployment

> Run the Pullbase server and agent directly on VMs or physical hosts.

Deploy Pullbase without containers by running the server and agent binaries directly with systemd. This is the recommended approach for production Linux servers.

## Prerequisites

* Ubuntu 22.04+, Debian 12, Rocky Linux 9, or a similar systemd-based distribution
* `curl` and `openssl`
* (Production) Reverse proxy for TLS termination or certificates for native TLS

<Info>
  **Database:** Pullbase uses SQLite by default — no external database required. For high-availability deployments, PostgreSQL 15+ is recommended.
</Info>

## Configure the server

Create a directory for configuration:

```bash theme={null}
sudo mkdir -p /etc/pullbase
sudo mkdir -p /var/lib/pullbase/git-repos
```

## Install the server

<Steps>
  <Step title="Download the server binary">
    Download the latest release with the web UI embedded:

    ```bash theme={null}
    curl -fsSL -o pullbase-server "https://github.com/pullbase/pullbase/releases/latest/download/pullbase-server-linux-amd64"
    sudo install -m 0755 pullbase-server /usr/local/bin/pullbase-server
    ```

    For ARM64 systems, use `pullbase-server-linux-arm64`.
  </Step>

  <Step title="Download pullbasectl">
    The CLI tool is used for bootstrapping, managing servers, and automation:

    ```bash theme={null}
    curl -fsSL -o pullbasectl "https://github.com/pullbase/pullbase/releases/latest/download/pullbasectl-linux-amd64"
    sudo install -m 0755 pullbasectl /usr/local/bin/pullbasectl
    ```

    For ARM64 systems, use `pullbasectl-linux-arm64`.

    Verify the installation:

    ```bash theme={null}
    pullbasectl --help
    ```
  </Step>

  <Step title="Download migrations">
    ```bash theme={null}
    curl -fsSL "https://github.com/pullbase/pullbase/releases/latest/download/migrations.tar.gz" | sudo tar -xzf - -C /var/lib/pullbase/
    ```
  </Step>
</Steps>

Create an environment file with secrets and connection details:

```bash theme={null}
cat <<EOF | sudo tee /etc/pullbase/pullbase.env
# Database configuration (SQLite is default — no setup required)
PULLBASE_DB_TYPE=sqlite
PULLBASE_DB_PATH=/var/lib/pullbase/pullbase.db

# Server configuration
PULLBASE_SERVER_PORT=8080
PULLBASE_SERVER_HOST=0.0.0.0

# Authentication
PULLBASE_JWT_SECRET=$(openssl rand -hex 32)
PULLBASE_JWT_EXPIRY_HOURS=24

# Webhooks
PULLBASE_WEBHOOK_SECRET_KEY=$(openssl rand -hex 32)

# Git integration (set to true when configuring GitHub App)
PULLBASE_GIT_ENABLED=false
PULLBASE_GIT_CLONE_PATH=/var/lib/pullbase/git-repos
PULLBASE_GIT_POLL_INTERVAL=60

# GitHub App (when using private repos)
# PULLBASE_GITHUB_APP_ID=your-app-id
# PULLBASE_GITHUB_APP_PRIVATE_KEY_PATH=/etc/pullbase/github-app.pem

# Migrations
PULLBASE_MIGRATIONS_PATH=file:///var/lib/pullbase/migrations
EOF
sudo chmod 600 /etc/pullbase/pullbase.env
```

<Tip>
  Store long-lived secrets in a vault or parameter store and template this environment file during provisioning.
</Tip>

### Using PostgreSQL instead

For high-availability or large-scale deployments, use PostgreSQL:

```bash theme={null}
# First, create the PostgreSQL database
sudo -u postgres psql <<'SQL'
CREATE ROLE pullbaseuser WITH LOGIN PASSWORD 'change-me';
CREATE DATABASE pullbasedb OWNER pullbaseuser;
GRANT ALL PRIVILEGES ON DATABASE pullbasedb TO pullbaseuser;
SQL
```

Then update `/etc/pullbase/pullbase.env`:

```bash theme={null}
# Database configuration (PostgreSQL)
PULLBASE_DB_TYPE=postgres
PULLBASE_DB_HOST=localhost
PULLBASE_DB_PORT=5432
PULLBASE_DB_USER=pullbaseuser
PULLBASE_DB_PASSWORD=change-me
PULLBASE_DB_NAME=pullbasedb
PULLBASE_DB_SSLMODE=disable
```

## Create a systemd service

Create the service user:

```bash theme={null}
sudo useradd --system --home /var/lib/pullbase --shell /usr/sbin/nologin pullbase
sudo chown -R pullbase:pullbase /var/lib/pullbase
```

Create the systemd unit:

```ini /etc/systemd/system/pullbase.service theme={null}
[Unit]
Description=Pullbase Server
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
EnvironmentFile=/etc/pullbase/pullbase.env
ExecStart=/usr/local/bin/pullbase-server
Restart=on-failure
RestartSec=5
User=pullbase
Group=pullbase
WorkingDirectory=/var/lib/pullbase

[Install]
WantedBy=multi-user.target
```

Enable and start the service:

```bash theme={null}
sudo systemctl daemon-reload
sudo systemctl enable --now pullbase.service
sudo systemctl status pullbase.service
```

<Check>
  Verify the health endpoint: `curl http://localhost:8080/api/v1/healthz`
</Check>

## Bootstrap the admin

On first start, Pullbase generates a one-time bootstrap secret. Use it to create your admin account:

```bash theme={null}
# Read the bootstrap secret
sudo cat /var/lib/pullbase/config/bootstrap-admin-secret.txt

# Create the admin user
pullbasectl auth bootstrap-admin \
  --server-url http://localhost:8080 \
  --bootstrap-secret "YOUR_SECRET" \
  --username admin \
  --password 'YourSecurePassword123!'
```

<Tip>
  The bootstrap secret file is automatically deleted after successful admin creation.
</Tip>

Alternatively, use the secret file directly:

```bash theme={null}
pullbasectl auth bootstrap-admin \
  --server-url http://localhost:8080 \
  --bootstrap-secret-file /var/lib/pullbase/config/bootstrap-admin-secret.txt \
  --username admin \
  --password 'YourSecurePassword123!'
```

## TLS configuration

Pullbase supports two approaches for TLS:

### Option 1: Native TLS (simpler)

Enable native TLS by adding these variables to `/etc/pullbase/pullbase.env`:

```bash theme={null}
PULLBASE_TLS_ENABLED=true
PULLBASE_TLS_CERT_PATH=/etc/pullbase/certs/server.crt
PULLBASE_TLS_KEY_PATH=/etc/pullbase/certs/server.key
```

For development, generate self-signed certificates:

```bash theme={null}
pullbase-server --generate-dev-certs
```

**Use CA-signed certificates in production.**

### Option 2: Reverse proxy (for existing infrastructure)

Place Pullbase behind a reverse proxy that terminates TLS:

```nginx /etc/nginx/sites-available/pullbase theme={null}
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://127.0.0.1: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;
    }
}
```

## Install agents on managed servers

Once the central server is running, install agents on each server you want to manage.

### Recommended: Install script

After creating a server and token in the Pullbase UI, run the install script on each managed server:

```bash theme={null}
curl -fsSL "https://pullbase.example.com/api/v1/servers/web-01/install-script?token=pbt_xxx" | sudo bash
```

The script downloads the agent, creates a systemd service, and starts it automatically.

<Tip>
  Get the complete install command from the UI: **Servers > \[your server] > Install**
</Tip>

### Manual installation

For more control, see [Agent Operations](/agent-operations#manual-systemd-setup) for step-by-step manual installation.

## Next steps

* [Bootstrap your first admin](/bootstrapping) using the generated secret
* [Integrate a GitHub App](/github-app-integration) if you pull from private repositories
* Review [Security & Hardening](/security-hardening) to lock down secrets, TLS, and network access

***

## Building from source (optional)

If you need to build Pullbase yourself (for development or custom builds):

<Steps>
  <Step title="Prerequisites">
    Install Go 1.22+ and Node.js 20+.
  </Step>

  <Step title="Clone and build">
    ```bash theme={null}
    git clone https://github.com/pullbase/pullbase.git
    cd pullbase
    ./scripts/build-with-ui.sh
    ```

    The server binary (with embedded UI) is written to `bin/pullbase-server`.
  </Step>

  <Step title="Build the agent">
    ```bash theme={null}
    cd agent
    go build -o pullbase-agent
    ```
  </Step>
</Steps>
