# Self-host BytesMap

Deploy the SaaS services and prepare persistent storage, credentials and backups.

The root `docker-compose.yml` runs the website, dashboard, API, worker, PostgreSQL metadata and Redis. It is the SaaS deployment profile. Local desktop development uses a different profile and storage path.

The current root Compose configuration includes paid Events Cloud integration and requires its Oblien credentials and registered image. It is not a minimal offline deployment preset. Customer Events instances run separately from the control plane.

## Prepare configuration

Copy `.env.compose.example` to a private `.env.compose`. Generate independent values for `POSTGRES_PASSWORD`, `BETTER_AUTH_SECRET`, `BYTESMAP_MASTER_KEY` and `BYTESMAP_CLOUD_BILLING_WEBHOOK_SECRET`:

```sh
openssl rand -hex 32
```

Run that command separately for each value. Hex is URL-safe for the Compose database URL. Keep the values stable across restarts and share the applicable backend secrets between API and worker.

Configure the API/dashboard HTTPS origins, cookie domain, SMTP service and Events Cloud provider settings. Social sign-in is optional; supply both the client ID and secret for each enabled provider.

`BYTESMAP_AUTH_MODE=local` means BytesMap-managed account authentication. It does not mean anonymous access. The SaaS profile also enables `BYTESMAP_REQUIRE_AUTH=true` and cloud deployment checks. Do not use the desktop-only anonymous mode behind a public proxy.

## Build and start

From the repository root:

```sh
docker compose --env-file .env.compose up -d --build
docker compose --env-file .env.compose ps
```

The default host bindings are loopback only:

| Service | Default host port | Purpose |
| --- | --- | --- |
| web | 3066 | Static public website and documentation |
| dashboard | 3077 | Authenticated product UI |
| api | 4080 | Authentication and product operations |
| worker | none | Scheduled report work |
| postgres / redis | none | Internal metadata and coordination |

Route public HTTPS domains through your reverse proxy. `NEXT_PUBLIC_API_URL` and the dashboard origin are build-time public configuration; rebuild the dashboard when changing them. Backend secrets must not become public build arguments or shared project-wide frontend variables.

The Compose API uses Redis for shared request budgets. Keep `BYTESMAP_RATE_LIMIT_NAMESPACE` and `BETTER_AUTH_SECRET` identical on all API replicas; use a distinct namespace for each deployment sharing Redis. If Redis is unavailable, protected operations return a retryable `503` instead of switching to a separate local budget. The API's `/health` endpoint is liveness, not proof that Redis is ready. See [API request budgets](https://bytesmap.com/docs/sources/safety.md#api-request-budgets) for limits and operating requirements.

## Verify access and delivery

Check the API `/health` endpoint and dashboard login. Create the intended account/workspace, connect a bounded test source and publish a small dashboard. Verify access using a second account with the intended grants.

Test SMTP through the normal authentication flow. Configure a test notification destination before trying report delivery or effectful workflows. A healthy worker does not prove an external provider accepted a message; inspect delivery history.

## Back up and upgrade

Preserve PostgreSQL metadata, Redis persistence where required, and encryption keys. Database backup without the credential key cannot restore encrypted source access. Keep keys separate from public artifacts and test restoration in an isolated environment.

Startup migrations are additive, but back up before upgrading. Read [source safety](https://bytesmap.com/docs/sources/safety.md#transport-and-credentials) before rotating either encryption or authentication secrets: legacy values and new versioned envelopes have different key requirements, and automatic re-encryption is not implemented.

See the repository's [SaaS deployment guide](https://github.com/oblien/bytesmap/blob/main/deploy/saas/README.md) and [environment template](https://github.com/oblien/bytesmap/blob/main/.env.compose.example) for the complete current settings.
