---
title: Self-hosting
description: Deploy Pile on your own Cloudflare account — worker, D1, Durable Objects, and secrets.
---

# Self-hosting

Pile is a single Cloudflare Worker with a D1 database for global metadata and a `WorkspaceDO` Durable Object class for per-workspace state.

## Requirements

- A Cloudflare account with Workers, D1, and Durable Objects enabled
- Node 22+ and pnpm
- `wrangler` (bundled as a dev dependency)

## Deploy

1. **Create the D1 database**

    ```bash
    wrangler d1 create pile-global
    ```

    Put the returned `database_id` into `wrangler.toml` under `[[env.production.d1_databases]]`.

2. **Apply migrations**

    ```bash
    wrangler d1 migrations apply pile-global --env production --remote
    ```

    Durable Object SQLite needs `new_sqlite_classes` in the `[[migrations]]`
    block — the repo's `wrangler.toml` already has it.

3. **Set secrets**

    ```bash
    wrangler secret put BETTER_AUTH_SECRET
    wrangler secret put TOKEN_HASH_SECRET
    ```

    Integration secrets (Slack, GitHub, email providers) are optional — a
    missing key just disables that capability. Check `wrangler.toml` and
    `.dev.vars.example` for the full list.

4. **Build and deploy**

    ```bash
    pnpm install
    pnpm -C apps/web run build   # member console assets
    pnpm exec wrangler deploy -e production
    ```

5. **Verify**

    ```bash
    curl -fsS https://<your-worker>/health
    ```

## Local dev

```bash
pnpm install
pnpm run dev        # wrangler dev + miniflare
```

`packages/docs` is a second worker (`pile-docs`) built with `blume build` and deployed with `pnpm -C packages/docs run deploy` — the docs you're reading now.

## CI note

This repo ships through an external artifacts→CI pipeline: pushes to `main` run `deps → build → migrate → deploy` in containers. If you self-host, `wrangler deploy` is enough; the pipeline is optional infrastructure.
