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

# Self-Host Gotchas

> Common problems specific to running PostQueen yourself

The things that catch people out on their own install. Find your symptom and open it.

<AccordionGroup>
  <Accordion title="pnpm runs out of heap during install" icon="memory">
    The monorepo is large enough to overflow the default Node heap on a small VM.

    ```bash theme={"system"}
    NODE_OPTIONS="--max-old-space-size=4096" pnpm install
    ```

    <Warning>
      Do not set the heap above the VM's actual memory. That trades an OOM in Node for being killed
      by the kernel. On a 2 GB box, build the image elsewhere and deploy the artifact.
      [System requirements](/installation/system-requirements) has the minimums.
    </Warning>
  </Accordion>

  <Accordion title="postgres ECONNREFUSED" icon="database">
    The backend cannot reach Postgres.

    | Check               | What to look for                                                                             |
    | ------------------- | -------------------------------------------------------------------------------------------- |
    | `DATABASE_URL` host | `localhost` fails from a container without host networking. Use the service name, `postgres` |
    | Postgres is up      | `docker compose logs postgres` shows *database system is ready to accept connections*        |
    | Port mapping        | Exposed only on the Docker network is fine. External `psql` will not work, the backend will  |
  </Accordion>

  <Accordion title="Default ports, and which one to open" icon="plug">
    | How you run her                                   | Ports                                                                                                                      |
    | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
    | Official image `ghcr.io/gkhankinay/postqueen-app` | One port, `5000`. The shipped compose maps it to `4007:5000`, so you reach her at `http://localhost:4007/`                 |
    | From source, `pnpm dev`                           | Frontend `4200`, backend `3000` (override with `PORT`). Put a [reverse proxy](/reverse-proxies/caddy) in front for one URL |

    Temporal listens on `7233`, and its UI on `8080`, either way.
  </Accordion>

  <Accordion title="Email is not sending" icon="envelope">
    She sends no email at all unless `EMAIL_PROVIDER` is exactly `resend` or `nodemailer`. Unset
    means the no-op provider.

    <Warning>
      Check this before anything else, because it also decides activation. `EMAIL_PROVIDER=resend`
      with no `RESEND_API_KEY` still counts as a provider, so new signups are created **inactive** and
      wait for a mail that can never arrive.
    </Warning>

    With no provider configured at all she auto-activates users instead, so signup still works.
    SMTP setup and the full variable list: [Email configuration](/configuration/emails).
  </Accordion>

  <Accordion title="Mounting the uploads volume" icon="folder">
    With `STORAGE_PROVIDER=local`, point `UPLOAD_DIRECTORY` at the path she should write to, mount
    it into the container, and set `NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY` so the frontend knows where
    the files are served from. Next rewrites `/uploads/:path*` to `/api/uploads/:path*` when local
    storage is active.

    Running more than one container? Share the volume across all of them, or move to
    [Cloudflare R2](/configuration/r2). Detail: [Uploads and storage](/configuration/uploads).
  </Accordion>

  <Accordion title="Can I deploy on Vercel?" icon="triangle-exclamation">
    **Frontend, yes.** It is a standard Next.js app.

    **Backend, no.** It is a NestJS server that also embeds a Temporal worker, so it needs a
    long-running Node host: Fly.io, Render, Railway, a VM, a Kubernetes pod. Serverless functions
    will not work.
  </Accordion>

  <Accordion title="Hiding a provider from the interface" icon="eye-slash">
    There is no environment variable for this today. The only way is to set the per-organization
    `disabled` field on the Integration row in the database after connecting the channel.
  </Accordion>

  <Accordion title="Temporal is not reachable" icon="clock">
    She schedules every post through Temporal, so the backend must reach the Temporal frontend at
    `TEMPORAL_ADDRESS`. If it cannot, posts are accepted and never publish.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Configuration reference" icon="list" href="/configuration/reference">
    Every environment variable she reads
  </Card>

  <Card title="Domain and HTTPS" icon="lock" href="/installation/domain-and-https">
    The reverse proxy step, done with you
  </Card>
</CardGroup>
