> ## Documentation Index
> Fetch the complete documentation index at: https://p-bitm-2269ecee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployment

> Deploy P-BitM in development or production and shut it down safely.

## Select an environment

Set `app.environment` in `config.yaml`:

<Tabs>
  <Tab title="Development" icon="laptop">
    `development` selects `server/docker-compose-dev.yml`, local TLS, path-based
    campaign routing, and MailHog.
  </Tab>

  <Tab title="Production" icon="server">
    `production` selects `server/docker-compose.yml`, per-campaign hostnames,
    and the configured Traefik DNS challenge.
  </Tab>
</Tabs>

Run setup after changing the environment:

```bash theme={"system"}
python3 p-bitm.py setup
python3 p-bitm.py doctor
```

## Configure the production DNS challenge

Before running `setup` in production, replace the DNS challenge placeholders
in `config.yaml`. Set `ssl.dns_challenge.provider` to the Traefik/lego provider
that manages the deployment domain, then list that provider's required
environment-variable names under `ssl.dns_challenge.credentials`.

```yaml theme={"system"}
ssl:
  # Required in production for ACME certificate notifications.
  acme_email: "<ACME_EMAIL>"

  dns_challenge:
    provider: "<DNS_PROVIDER>"
    credentials:
      - "<PROVIDER_REQUIRED_ENV_VAR>"
    environment: {}
```

`credentials` contains variable names, not credential values. The CLI prompts
for the values securely during `setup` and stores them in local secret files.

<Warning>
  The shipped placeholders are intentionally not valid production values. Do not
  leave them unchanged, and do not store DNS tokens in `config.yaml`. If
  `ssl.auto_generate` is enabled, also replace the certificate identity
  placeholders before running `setup`.
</Warning>

Use Traefik's [DNS challenge provider reference](https://doc.traefik.io/traefik/https/acme/#providers)
to find the supported provider identifier and its required environment variables. See the
[configuration reference](/reference/configuration) for the complete
configuration contract.

## Build and start

```bash theme={"system"}
python3 p-bitm.py up --build
```

The CLI builds the configured VNC, Selkies, campaign, and egress images, then
starts the Compose control-plane services. Later starts can omit `--build`
unless source or dependencies changed.

## Production checklist

* Keep the dashboard bound to loopback.
* Permit public inbound traffic only on ports 80 and 443.
* Point approved campaign hostnames to the deployment host.
* Configure DNS provider credential names in `config.yaml`.
* Store provider values through `setup`, not in tracked files.
* Run `doctor --strict` before an engagement.
* Confirm backup, retention, monitoring, and emergency-stop procedures.

## Stop

Run the global shutdown command:

```bash theme={"system"}
python3 p-bitm.py down
```

`down` is terminal for the current runtime. It stops the control plane,
force-removes every app-owned campaign, target-browser, and campaign-egress
container, removes campaign networks, and marks active, paused, or scheduled
campaigns as completed. A later `up` does not resume them.

If any dynamic campaign resource cannot be removed, the command exits
unsuccessfully and leaves campaign state unchanged so an operator is not given
a false completed status. Resolve the reported Docker error and run `down`
again.
