> ## 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.

# Security & Hardening

> Secure secrets, TLS, and operational access before running Pullbase in production.

Pullbase manages critical infrastructure. Follow these guidelines to reduce risk when operating at scale.

## Secret management

* Store `PULLBASE_JWT_SECRET`, `PULLBASE_WEBHOOK_SECRET_KEY`, and database credentials in your secret manager (AWS Secrets Manager, HashiCorp Vault, etc.). Inject them into Docker at runtime rather than committing them to disk.
* Mount GitHub App private keys from a read-only path (`/config/github-app.pem`) and restrict filesystem permissions so only the Pullbase container can read them.
* Rotate agent tokens regularly. Tokens are hashed at rest, but compromised tokens allow full configuration access for that server.
* Use unique credentials per environment when possible.

## TLS configuration

Pullbase supports two approaches for securing connections:

### Option 1: Native TLS

Pullbase can handle TLS directly without a reverse proxy:

```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, you can rely on Pullbase to auto-generate self-signed ECDSA P-256 certificates when TLS is enabled and cert/key files are missing (or use the `--generate-dev-certs` flag). **Never use self-signed certificates in production.**

Native TLS is ideal for:

* Simple deployments without existing reverse proxy infrastructure
* Direct agent-to-server communication
* Reduced architectural complexity

### Option 2: Reverse proxy TLS termination

For production environments with existing infrastructure:

* Deploy a reverse proxy (NGINX, Traefik, Caddy, or cloud load balancer) in front of Pullbase.
* Terminate TLS at the reverse proxy using CA-signed certificates.
* Ensure agents connect to the HTTPS endpoint, not the internal HTTP port.
* Distribute the CA chain to agents if using internal PKI.
* Set `X-Forwarded-Proto: https` so secure cookies remain marked `Secure` even when TLS is terminated upstream.

```nginx theme={null}
# Example: NGINX TLS termination
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;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    
    location / {
        proxy_pass http://localhost:8080;
        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;
    }
}
```

<Warning>
  Never expose the internal HTTP port directly to the internet. Agent tokens and user credentials are transmitted in requests.
</Warning>

## Agent TLS verification

Agents validate the TLS certificate of the Pullbase server:

* Set `CACERT_PATH` to a CA bundle that trusts your certificate.
* Never enable `SKIP_TLS_VERIFY=true` in production—it disables certificate validation.
* Keep CA bundles up to date across your fleet.

## Access control

* Create dedicated viewer accounts for read-only dashboards and audits.
* Enforce strong passwords (12+ characters with complexity) and rotate admin credentials periodically.
* Restrict CLI usage to secure workstations. Store admin tokens in environment variables only temporarily.
* Monitor audit logs (stored in the `audit_log` table) for suspicious activity. Integrate with your SIEM by streaming logs from the container.
* **CORS policy:** In production, only explicitly configured origins (`PULLBASE_CORS_ORIGINS`) and same-origin requests are allowed. Avoid setting `PULLBASE_ENV=development` in production—it enables permissive localhost origins.

## Database hardening

Pullbase supports SQLite (default) and PostgreSQL. Choose hardening steps based on your deployment.

### SQLite (single-instance deployments)

* Store `pullbase.db` outside the container on a persistent volume with strict file permissions (`chmod 600`).
* Schedule file-level backups (e.g., `sqlite3 pullbase.db ".backup /backups/pullbase-$(date +%Y%m%d).db"`).
* Enable WAL mode for better concurrency: `PRAGMA journal_mode=WAL;` (applied automatically by Pullbase).
* Keep the database file on fast local storage; network-attached storage may introduce latency.

### PostgreSQL (high-availability deployments)

* Enable TLS connections between Pullbase and PostgreSQL. Set `PULLBASE_DB_SSLMODE=require` or `PULLBASE_DB_SSLMODE=verify-full`.
* Grant Pullbase a least-privilege Postgres role (ownership of the `pullbasedb` database only).
* Schedule automated backups using `pg_dump` and test restore procedures.

### General

* Without the database, you lose environment definitions, tokens, and drift history. Test restores regularly.

## Network segmentation

* Place Pullbase in a private subnet behind a load balancer. Expose only port 443 (TLS) via the reverse proxy.
* Allow outbound connections only to required destinations: your Git provider, webhook endpoints, and package repositories.
* Restrict inbound traffic between agents and Pullbase using security groups or firewall rules.

## Agent security

* Run agents with minimal privileges. Grant access only to files and services defined in `config.yaml`.
* For containerized agents, carefully consider host filesystem mounts—they effectively grant root access.
* Rotate agent tokens regularly. Create a new token, update the agent, then revoke the old token.
* Monitor agent status for unexpected disconnections or authentication failures.

## Webhook notification security

When configuring notification webhooks for environments:

* **Use HTTPS endpoints only.** Pullbase validates TLS certificates by default.
* **Validate webhook source.** If your receiving service supports it, verify requests come from your Pullbase server's IP.
* **Keep webhook URLs confidential.** Treat them like secrets; leaked URLs could be used for social engineering.
* **Monitor webhook failures.** Failed deliveries may indicate network issues or compromised endpoints.

Webhooks are retried 3 times with exponential backoff (1s, 2s, 4s). Configure alerts in your receiving service for gaps in expected notifications.

## Logging & monitoring

* Forward container logs to your log aggregation platform. Use `PULLBASE_LOG_FORMAT=json` for structured logging.
* Collect agent logs (especially when running as systemd units) for drift diagnostics.
* Monitor GitHub App rate limits and webhook delivery failures; increasing poll intervals or adjusting webhook retries can prevent throttling.
* Consider adding synthetic checks that call `/api/v1/healthz` to detect API regressions.

## Upgrades and patching

* Pin Pullbase and agent images (`pullbaseio/pullbase:vX.Y.Z`) to avoid unintended upgrades.
* Review release notes (GitHub Releases) and test upgrades in staging. Watch migration logs closely.
* Apply OS patches to hosts running agents—Pullbase focuses on desired state, not OS patch management.

<Tip>
  Document your disaster recovery plan: bootstrap steps, database restore procedures, certificate replacement, and token rotation. Regular tabletop exercises help ensure you can rebuild Pullbase quickly if needed.
</Tip>
