Docker
TryPost ships two Compose files:Which database Compose gives you
Both files bundle PostgreSQL 16. That is the packaged path, and the one TryPost Cloud runs. MySQL is equally supported by the application, but no Compose file ships it. To run TryPost on MySQL with Docker, point the app at your own MySQL and take the bundled Postgres out of the file — including thedepends_on entry, or Compose refuses to start on a service that no longer exists:
pgsql: service itself and the pgdata volume it declared.
The container’s readiness check uses
pg_isready, so on MySQL it cannot confirm the database is up. It gives up after 60 seconds and continues, and migrations then run normally — so every boot takes about a minute longer. Nothing is lost; the container just waits out the check first.Requirements
- Docker Desktop (Mac, Windows) or Docker Engine (Linux)
- Docker Compose v2
Production self-hosting
No local PHP/Node install required. The published image includes the built frontend.What you do vs what the container does
1. Clone the repository
compose.prod.yaml (and optionally Caddyfile). The app image comes from GHCR.
2. Generate an app key and edit the compose file
APP_KEY in compose.prod.yaml. Also set:
APP_URL— your public URL (e.g.https://post.yourdomain.com)DB_PASSWORD/POSTGRES_PASSWORD(must match)REVERB_APP_SECRETPASSPORT_PRIVATE_KEY/PASSPORT_PUBLIC_KEY— required in production (file keys understorage/are not on a persisted volume). Generate once:
\n for newlines). Do not regenerate after users have issued API or MCP tokens.
Leave REVERB_APP_KEY as trypost-reverb-key unless you rebuild the image — it must match the key baked into the published frontend bundle.
Queues, cache, session, and broadcast are already set to Redis / Reverb / database in compose.prod.yaml. Configure mail (defaults to log) and optional social/AI credentials in the same file — see Configuration.
3. Start the stack
- waits for the database (PostgreSQL only — see above if you run MySQL)
- runs migrations
- creates
storage:linkif missing (unused if you later switch to S3 / R2 / Spaces) - loads Passport keys from
PASSPORT_PRIVATE_KEY/PASSPORT_PUBLIC_KEY(exits if unset in production) - ensures the Passport Personal Access Client (
PassportSeeder) - caches config / routes / views / events
- starts nginx, php-fpm, Horizon, Reverb, and
schedule:work
4. Seed plans and admin user (one-time)
Change the admin password on first login. Extra accounts come from workspace invites (Settings → Members).
5. Optional HTTPS with Caddy
- Point DNS at the host
- Set
APP_URLtohttps://your-domainandAPP_DOMAINon thecaddyservice - Start with the proxy profile:
http://localhost:8000.
6. Verify
- Open
APP_URLand sign in as admin - Create an API key (Settings → API Keys) — proves Passport keys + Personal Access Client exist
- Connect an MCP client via OAuth (Settings → MCP), if you use assistants
- Schedule a post — Horizon must show as running
Access
Reverb on a custom domain
The published image bakesVITE_REVERB_* at build time (localhost:8080). For HTTPS on your domain, rebuild:
compose.prod.yaml at that image. Changing only runtime REVERB_HOST / PORT / SCHEME does not update the browser client.
Common production commands
Running
migrate --force to move an existing instance to a newer version? Back the database up first and check Upgrading — some releases rewrite data as well as schema.Local development
Usecompose.yaml when you want a bind-mounted source tree.
1. Clone and start
.env from docker/.env.docker.example, install Composer/npm deps if missing, generate APP_KEY, migrate, storage:link, and passport:keys. Horizon, Reverb, the scheduler, and Vite start via Supervisor.
For local media URLs, set FILESYSTEM_DISK=public in .env (the Docker example ships with local) and ensure storage:link ran.
2. Seed admin + Passport client
Access (dev)
Common development commands
Troubleshooting
Port conflicts
Permission issues (Linux)
Database connection refused
could not find driver on MySQL
The image predates the MySQL driver. Check and pull a newer one:
v1.0.8 shipped pdo_pgsql only — see above.
Boot hangs for a minute on MySQL
Expected. The readiness check ispg_isready, so it cannot confirm a MySQL server is up; it gives up after 60 seconds and migrations run normally. Watch it happen with docker compose -f compose.prod.yaml logs -f app.
API key creation fails with “Personal access client not found”
Seed the Passport client:Horizon not processing jobs
Next steps
- Configuration — mail, storage, social OAuth, AI
- Production setup — bare-metal Nginx / Supervisor if you are not using
compose.prod.yaml - Installation — clone-and-install without Docker

