# Deploying Podcast Distribution AI on Dokploy Containerized deploy: one image, two services (`web` + `worker`) via Docker Compose, a persistent volume for generated assets, an **external** Postgres, and **no Redis**. Dokploy's bundled Traefik handles the domain, TLS, and SSE streaming. Artifacts: [`Dockerfile`](../Dockerfile), [`docker-compose.yml`](../docker-compose.yml), [`.dockerignore`](../.dockerignore). ## 1. Create the app in Dokploy - New Project → **Create Service → Compose**. - **Provider:** Git → `https://git.serfaty.co/admin/podcastdistributiona`, branch `main`. - **Compose path:** `docker-compose.yml`. ## 2. Environment (Dokploy → Environment tab) These feed both the build args (`NEXT_PUBLIC_*`) and runtime env. Minimum: ``` DATABASE_URL=postgresql://user:pass@host:5432/db?schema=public BETTER_AUTH_SECRET= BETTER_AUTH_URL=https://podcastdistributionai.com NEXT_PUBLIC_APP_URL=https://podcastdistributionai.com EMAIL_FROM=Podcast Distribution AI OPENAI_API_KEY=... ELEVENLABS_API_KEY=... RESEND_API_KEY=... # optional (emails) GOOGLE_CLIENT_ID=... # optional (OAuth) GOOGLE_CLIENT_SECRET=... # Billing (optional until you sell) STRIPE_SECRET_KEY=... STRIPE_WEBHOOK_SECRET=... NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=... STRIPE_PRICE_CREATOR_MONTHLY=... # + PRO/AGENCY, _YEARLY PAYPAL_CLIENT_ID=... PAYPAL_CLIENT_SECRET=... PAYPAL_WEBHOOK_ID=... PAYPAL_API_BASE=https://api-m.paypal.com PAYPAL_PLAN_CREATOR=... # + PRO/AGENCY ``` `STORAGE_DIR` and `PORT` are set in the compose file — don't override. ## 3. Domain + SSL Dokploy → the **web** service → **Domains** → add your domain, container port **3000**, enable HTTPS (Let's Encrypt). Traefik streams responses, so the episode-generation SSE works with no extra config. ## 4. Deploy Hit **Deploy**. The build installs deps + ffmpeg, runs `next build`, and starts: - `web` runs `prisma migrate deploy` (applies all migrations) then `next start`. - `worker` runs the pg-boss consumer (ffmpeg available in-image). Both share the `storage` volume at `/app/storage` (mp3/art/exports). Add a volume backup schedule in Dokploy. ## 5. First admin Dokploy → web service → **Terminal** (or `docker exec`): ```bash npx tsx scripts/make-admin.ts you@email.com ``` Then visit `/admin`. ## 6. Webhooks - Stripe → `https://your-domain/api/webhooks/stripe` (events `checkout.session.completed`, `customer.subscription.created/updated/deleted`); set `STRIPE_WEBHOOK_SECRET` + the `STRIPE_PRICE_*`. - PayPal → `https://your-domain/api/webhooks/paypal` (`BILLING.SUBSCRIPTION.*`); set `PAYPAL_WEBHOOK_ID` + `PAYPAL_PLAN_*`. ## Redeploys Push to `main` → Dokploy auto-deploys (enable the Git webhook), or click **Redeploy**. Migrations run automatically on each `web` boot. ## Notes - **Assets** are served by the app (authed `/api/assets/...`, public `/api/public/episodes/[shareId]/...`) — no separate static route needed. - **Scaling:** the `worker` can be scaled or moved to its own Compose/host pointing at the same `DATABASE_URL`; swap local disk for S3/R2 by adding `lib/storage/s3.ts` and switching the registry in `lib/storage/index.ts`. - **Build args:** `NEXT_PUBLIC_*` are baked at image-build time; changing them requires a rebuild (Dokploy does this on deploy).