Skip to main content
This is the fastest path from a fresh clone to publishing your first post against a self-hosted API. It uses Docker Compose for Postgres + Redis only — the API, worker, and dashboard run via pnpm so you keep watch mode, fast iteration, and stack traces in your terminal. For a production deploy (separate API + worker services, managed Postgres / Redis, custom domain), see deploying once you’ve gotten this working locally.

Prerequisites

  • Node >= 24
  • pnpm 10.33.0+corepack enable if you haven’t already
  • Docker + Docker Compose — only for the Postgres + Redis containers
  • An S3-compatible bucket for media (you can defer this if you only need text posts to start with)

1. Clone and install

2. Start Postgres and Redis

The repo ships a docker-compose.dev.yml that runs only Postgres and Redis — nothing else. The API, worker, and dashboard run from your shell via pnpm. This keeps reloads instant and stack traces native.
Ports are deliberately non-standard so they don’t collide with whatever you already have running: The Postgres database is seeded with user letmepost, password letmepost, db letmepost.

3. Configure environment

Copy the example file and fill in the bare minimum to boot:
The minimum required to start the server is:
KEK_MASTER is the AES-256-GCM master key that wraps every encrypted token at rest. Keep it. Rotating it without a re-wrap script locks every connected account. Every other variable is either optional with a sensible default or only required when you connect a specific platform. See environment for the full list.

4. Run database migrations

Schema lives in apps/api/drizzle/. Drizzle Kit applies the SQL files in order. Re-running is safe — already-applied migrations are skipped.

5. Start the stack

In separate terminal tabs:
Or run everything via Turbo from the repo root:
The worker is bundled into the API process in dev mode, so the same pnpm --filter @letmepost/api dev command runs the HTTP server and the BullMQ consumer in one process. In production you split them — see deploying.

6. Verify the API

If you get connection refused, check that the Postgres and Redis containers are up: docker compose -f docker-compose.dev.yml ps.

7. Sign in and connect Bluesky

Open http://localhost:3001 and sign up with email + password. Bluesky is the easiest platform to connect for a first smoke test — no OAuth app required, just an app password. Once the account is connected, copy its id from the Accounts page and follow quickstart — every example works against your local API once you swap https://api.letmepost.dev for http://localhost:3000.

Next

Environment variables

Every var the API reads, what defaults to what, and which ones are optional.

Platform credentials

OAuth client setup for LinkedIn, X, Pinterest, Meta, Threads, Instagram.

Deploying to production

Two-service split, managed Postgres + Redis, custom domain.

Troubleshooting

Common boot failures and how to read them.