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

# Self-Hosting

> Deploy Pwnbook on your own infrastructure using Docker Compose. This guide covers prerequisites, environment configuration, and getting the full stack running.

## Prerequisites

Before you begin, make sure you have the following installed and available:

* **Docker** 24.0 or later
* **Docker Compose** v2.20 or later
* A domain or hostname where Pwnbook will be accessible (required when using WorkOS authentication)

<Note>The Docker Compose setup includes PostgreSQL and Redis containers. You do not need to provision those separately unless you want to use external managed instances.</Note>

## Choosing an authentication provider

Pwnbook supports two authentication modes, configured via the `AUTH_PROVIDER` environment variable:

| Mode           | `AUTH_PROVIDER` value | Description                                                                                                      |
| -------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------- |
| **Local auth** | `local`               | Built-in email/password authentication. No external dependencies. Best for self-hosted or internal deployments.  |
| **WorkOS**     | `workos`              | Delegates authentication to WorkOS. Enables SSO, MFA, SAML, SCIM, and directory sync. Requires a WorkOS account. |

For most self-hosted deployments, **local auth is recommended**. It requires no external accounts and works immediately.

## Environment variables

Create a `.env` file in your deployment directory. The following variables are required or commonly configured:

### Required (all modes)

| Variable         | Description                                                                         |
| ---------------- | ----------------------------------------------------------------------------------- |
| `AUTH_PROVIDER`  | Authentication mode. Set to `local` or `workos`.                                    |
| `DATABASE_URL`   | PostgreSQL connection string. Example: `postgresql://user:password@db:5432/pwnbook` |
| `SESSION_SECRET` | A random 32+ character secret for signing session tokens.                           |
| `REDIS_URL`      | Redis connection string. Example: `redis://redis:6379`                              |
| `PORT`           | Port the backend API listens on (default: `3001`)                                   |
| `FRONTEND_URL`   | The public URL of your Pwnbook frontend. Example: `https://pwnbook.example.com`     |

### Local auth variables

Required when `AUTH_PROVIDER=local`:

| Variable         | Description                                                                  |
| ---------------- | ---------------------------------------------------------------------------- |
| `ADMIN_EMAIL`    | Email address for the auto-seeded admin account (default: `admin@local.net`) |
| `ADMIN_PASSWORD` | Password for the auto-seeded admin account (default: `@dminUser`)            |

<Warning>Change `ADMIN_EMAIL` and `ADMIN_PASSWORD` from their defaults before deploying to any non-local environment.</Warning>

### WorkOS variables

Required when `AUTH_PROVIDER=workos`:

| Variable              | Description                                                                  |
| --------------------- | ---------------------------------------------------------------------------- |
| `WORKOS_API_KEY`      | Your WorkOS API key                                                          |
| `WORKOS_CLIENT_ID`    | Your WorkOS application client ID                                            |
| `WORKOS_REDIRECT_URI` | The OAuth callback URL. Example: `https://pwnbook.example.com/auth/callback` |

### Optional

| Variable                   | Service   | Description                                                          |
| -------------------------- | --------- | -------------------------------------------------------------------- |
| `STRIPE_SECRET_KEY`        | backend   | Enables billing features. Obtain from your Stripe dashboard.         |
| `STRIPE_WEBHOOK_SECRET`    | backend   | Required to verify Stripe webhook events.                            |
| `ANTHROPIC_API_KEY`        | ai-worker | Enables the AI assistant using Anthropic's Claude models.            |
| `OPENAI_API_KEY`           | ai-worker | Enables the AI assistant using OpenAI's GPT models.                  |
| `RESEND_API_KEY`           | backend   | Enables transactional email (invitations, notifications).            |
| `EMAIL_FROM`               | backend   | Sender address for transactional email.                              |
| `GITHUB_APP_ID`            | backend   | GitHub App ID for PR integration.                                    |
| `GITHUB_APP_CLIENT_ID`     | backend   | GitHub App client ID.                                                |
| `GITHUB_APP_CLIENT_SECRET` | backend   | GitHub App client secret.                                            |
| `GITHUB_APP_PRIVATE_KEY`   | backend   | GitHub App private key (PEM, base64-encoded or raw).                 |
| `GITHUB_WEBHOOK_SECRET`    | backend   | Secret used to verify GitHub webhook signatures.                     |
| `SLACK_CLIENT_ID`          | backend   | Slack app client ID for Slack integration.                           |
| `SLACK_CLIENT_SECRET`      | backend   | Slack app client secret.                                             |
| `STORAGE_PATH`             | backend   | Local filesystem path for uploaded files (default: `/data/uploads`). |
| `STORAGE_BASE_URL`         | backend   | Public URL prefix for serving stored files.                          |
| `ELECTRON_FRONTEND_URL`    | backend   | URL used by the Electron desktop app to connect to this instance.    |

<Warning>Never commit your `.env` file to version control. Store secrets in a secrets manager or use Docker secrets in production.</Warning>

## Setup

<Steps>
  <Step title="Clone the deployment repository">
    ```bash theme={null}
    git clone https://github.com/pwnbook/pwnbook-deploy.git
    cd pwnbook-deploy
    ```
  </Step>

  <Step title="Configure your environment">
    Copy the example environment file and fill in your values:

    ```bash theme={null}
    cp .env.example .env
    ```

    Edit `.env` with your editor. At minimum, set `AUTH_PROVIDER`, `SESSION_SECRET`, and the database/Redis URLs.
  </Step>

  <Step title="Configure authentication">
    <Tabs>
      <Tab title="Local auth (recommended)">
        Set the following in your `.env`:

        ```bash theme={null}
        AUTH_PROVIDER=local
        ADMIN_EMAIL=you@example.com
        ADMIN_PASSWORD=change-me-to-something-secure
        ```

        No external accounts or redirects are required. The admin account is seeded automatically on first startup.
      </Tab>

      <Tab title="WorkOS">
        1. Log in to the [WorkOS dashboard](https://dashboard.workos.com).
        2. Create a new **Application** in the Applications section.
        3. Under **Redirects**, add your `WORKOS_REDIRECT_URI` (e.g., `https://pwnbook.example.com/auth/callback`).
        4. Copy the **Client ID** and **API Key** into your `.env` file.

        ```bash theme={null}
        AUTH_PROVIDER=workos
        WORKOS_API_KEY=sk_...
        WORKOS_CLIENT_ID=client_...
        WORKOS_REDIRECT_URI=https://pwnbook.example.com/auth/callback
        ```

        <Tip>WorkOS offers built-in support for SSO, MFA, and directory sync. These features are automatically available once you configure your WorkOS application.</Tip>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Start the services">
    ```bash theme={null}
    docker compose up -d
    ```

    This starts the following containers:

    * `frontend` — React web application
    * `backend` — Fastify API server
    * `recon-worker` — Python recon scanning service
    * `ai-worker` — Python AI assistant service
    * `db` — PostgreSQL database
    * `redis` — Redis for the job queue
    * `caddy` — Reverse proxy with automatic HTTPS

    Database migrations run automatically on startup.
  </Step>

  <Step title="Verify the deployment">
    Check that all services are healthy:

    ```bash theme={null}
    docker compose ps
    ```

    All services should show a status of `running` or `healthy`. You can also check individual service logs:

    ```bash theme={null}
    docker compose logs backend
    docker compose logs recon-worker
    ```

    Navigate to your configured `FRONTEND_URL` in a browser to confirm the application is accessible.
  </Step>
</Steps>

## Optional services

### Enabling billing with Stripe

To enable subscription billing:

1. Create a Stripe account and obtain your secret key from the Stripe dashboard.
2. Add `STRIPE_SECRET_KEY` to your `.env` file.
3. Configure your Stripe webhook endpoint to point to `https://your-domain.com/api/billing/webhook`.
4. Restart the backend service: `docker compose restart backend`.

See [Billing Administration](/admin/billing) for full details on configuring plans and webhooks.

### Enabling AI features

AI features require at least one of the following:

* `ANTHROPIC_API_KEY` — Uses Claude models (recommended)
* `OPENAI_API_KEY` — Uses GPT models

Add the key(s) to your `.env` file and restart the ai-worker:

```bash theme={null}
docker compose restart ai-worker
```

Once running, server admins can configure the default AI provider through the admin panel. See [AI Providers](/admin/ai-providers) for more.

## Reverse proxy configuration

The Docker Compose stack includes **Caddy** as the reverse proxy. Caddy automatically provisions and renews TLS certificates via Let's Encrypt — no manual certificate management required.

Set `FRONTEND_URL` to your public domain (e.g., `https://pwnbook.example.com`) and Caddy will handle the rest on startup.

<Tip>Caddy requires ports 80 and 443 to be reachable from the internet for ACME certificate issuance. For internal-only deployments, configure a custom `Caddyfile` to use a private CA or self-signed certificates.</Tip>

## Database backup and restore

### Manual backup

```bash theme={null}
docker compose exec db pg_dump -U <db-user> <db-name> > backup.sql
```

### Export / import

Pwnbook includes built-in scripts for exporting and importing the database, useful for migrating between hosts or creating portable snapshots:

```bash theme={null}
# Export database (creates a timestamped archive in ./exports/)
docker compose exec backend npm run db:export

# Import a previously exported archive
docker compose exec backend npm run db:import
```

<Warning>Always back up your database before upgrading.</Warning>

## Upgrading

To upgrade to a new Pwnbook version:

```bash theme={null}
docker compose pull
docker compose up -d
```

Database migrations run automatically on startup. If you need to run them manually:

```bash theme={null}
docker compose exec backend npm run db:migrate
```

## Health checks

The backend exposes a health check endpoint at `GET /api/health`. You can use this with your monitoring system or load balancer:

```bash theme={null}
curl https://pwnbook.example.com/api/health
# {"status":"ok","timestamp":"2025-01-01T00:00:00.000Z"}
```
