Skip to main content
The postqueen-docker-compose repository is the supported way to run PostQueen. Its docker-compose.yaml starts PostQueen with PostgreSQL, Redis and Temporal. This page is the reference for that file. For a guided install, follow Try it locally or Deploy to a server.

What the stack starts

docker compose up -d starts eight containers: A ninth service, spotlight, starts only with docker compose --profile debug up -d: a local Sentry Spotlight viewer for development. postqueen waits until PostgreSQL, Redis and Temporal report healthy, and has a health check of its own. On a server, change its port line to "127.0.0.1:4007:5000", because Docker publishes ports past a host firewall: see Deploy to a server.

Where settings live

Every setting is an environment variable on the postqueen service, and the place to put them is a .env file next to docker-compose.yaml. The Compose file reads it in two ways:
  1. env_file passes every line of .env into the container. The file is optional (required: false), which needs Compose v2.24 or newer. This is how variables the YAML does not list, such as NOT_SECURED or NEYNAR_APP_FID, reach PostQueen.
  2. ${VAR:-default} fills the variables the YAML does list from the same .env, and falls back to the default after :- when the file does not set them.
.env
The syntax is KEY=value, one per line. Configuration reference lists every variable.
A literal value in environment: beats .env. Compose gives the environment: block priority over env_file for the same key. The ${VAR:-default} form is what lets .env win, so keep that form if you edit the YAML: replacing "${FRONTEND_URL:-http://localhost:4007}" with a fixed string means .env no longer changes it.
The postqueen-config volume is not a settings folder. The Compose file mounts it at /config, but nothing in the image reads files there. Use .env.

Apply a change

Recreate the app container so it reads the new values. A plain docker restart or docker compose restart keeps the old container and its old environment. In the folder that holds docker-compose.yaml, recreate only the postqueen service:
The database, Redis and Temporal keep running. Avoid docker compose down for a settings change: on a host that runs other Compose services in the same project, it stops them too. On Kubernetes, see Kubernetes with Helm. Then check the backend’s own verdict on the settings. It logs each problem at startup and keeps running regardless:
No output means the required settings passed. A line such as FRONTEND_URL should not end with / names what to fix.

Settings most installs change

Leave these as they ship:
  • BACKEND_INTERNAL_URL, http://localhost:3000: the web app’s path to the API inside the container.
  • DATABASE_URL, REDIS_URL and TEMPORAL_ADDRESS: they point at the bundled services by name. Change them only to use your own.
  • RUN_CRON, true: it starts the recurring workflows, such as the sweep that picks up posts that failed to schedule. Any value turns it on, false included, and the YAML falls back to true when .env leaves it out. To turn it off, delete its line from docker-compose.yaml.
  • UPLOAD_DIRECTORY, /uploads, and NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY, uploads: the image’s nginx serves exactly that folder.

Pin the image

The file ships with image: ghcr.io/gkhankinay/postqueen-app:latest, which moves with every release. On a real install, pin a release tag:
Tags carry a v and are listed on the app’s tags and the image package. The GitHub Releases page is behind, so do not take the version from there. Each image is built for amd64 and arm64.
Only move the tag forward. Every start applies the image’s database schema, and by default it does so with prisma db push --accept-data-loss. Starting an image older than the one that last ran can drop columns the newer release added. Backups and upgrades covers upgrades and the safer migration mode.

Run the image without Compose

If PostgreSQL, Redis and a Temporal server already run elsewhere, you can run the image on its own. Keep the settings in a file and pass it with --env-file:
postqueen.env
  • --network has to be the Docker network your databases are on. On the default bridge, container names do not resolve, and the connection fails.
  • The host port is 5000 here, not 4007. Point your reverse proxy at localhost:5000.
  • Do not start from .env.example in the app repository. It is written for running from source: its addresses point at localhost:4200, RUN_CRON is commented out, and POSTQUEEN_GENERIC_OAUTH="false" counts as on, which replaces the Google sign-in button with an unconfigured single sign-on button.

Next steps

Channel developer apps

Each network’s app, variables and redirect URI.

Email

Resend or SMTP, so password resets and invitations arrive.

Uploads and storage

Media on the local disk, or in Cloudflare R2.

Backups and upgrades

The volumes to back up, and how to move to a newer image.
Last modified on September 23, 2026