Run Benkyou with Docker Compose and a private Postgres service.
Docker Compose is the recommended self-host path. Node and pnpm remain the development path when you want to work directly in the repo.
Requirements
- Recommended
- Docker and Docker Compose for the web app plus Postgres.
- Development
- Node.js 22 and pnpm when running outside Docker.
- Network
- Port 3000 for the app. Postgres stays on the internal Compose network.
Environment
Use the root environment template for self-hosting. Keep real values in .env, not in docker-compose.yml.
cp .env.example .env- POSTGRES_PASSWORD
- Set a long random password. Do not commit it.
- BETTER_AUTH_SECRET
- Generate a strong session secret and rotate the placeholder.
- BETTER_AUTH_URL
- Set to the canonical app URL, for example http://localhost:3000.
- PUBLIC_SITE_URL
- Set to the public canonical URL used by metadata, robots.txt, and sitemap.xml.
- AI_API_KEY
- Required for real AI generation. Keep it server-side.
- YOUTUBE_API_KEY
- Optional for YouTube metadata enrichment.
- GENERATION_RATE_LIMIT_MAX / WINDOW_HOURS
- Optional quota controls. Defaults are 5 attempts per 24 hours.
Docker start
The Compose stack builds the app, starts Postgres, waits for the database healthcheck, runs migrations, then starts the web server.
docker compose up --buildThe Compose file publishes only the web app by default. Postgres is reachable to containers as db, not as a public host port.
Health check
curl http://localhost:3000/api/healthUse /api/health for deployment readiness checks. It is simple, unauthenticated, and does not expose application data.
Development path
Use Node and pnpm when contributing locally or running against your own Postgres instance.
pnpm install
pnpm --filter @benkyou/db db:migrate
pnpm --filter @benkyou/web devOperations
- Migrations
- Run automatically before the web server starts in the Docker image.
- Backups
- Back up the Postgres volume before upgrades or destructive maintenance.
- Public deploy
- Put Benkyou behind a reverse proxy with TLS before exposing it beyond localhost.
Rotate every placeholder secret in .env. The values in.env.example are a template, not production credentials.
