Production Checklist
Use this page before putting a real OpenPost instance behind a public domain. It is operator-facing: product usage lives in User Docs, while code changes live in Developer Docs.
Baseline
- [ ] Copy the root
.env.exampleto.envor mirror every required value in your secret manager. - [ ] Generate fresh
OPENPOST_JWT_SECRETandOPENPOST_ENCRYPTION_KEY. - [ ] Keep both secrets at least 32 characters long.
- [ ] Store secrets outside the repository and outside container images.
- [ ] Use
<VARIABLE>_FILEvariants for Docker/Podman/Kubernetes/NixOS secrets, and leave the direct variable unset when the file value should win. - [ ] Set
OPENPOST_APP_URLto the public HTTPS app origin. - [ ] Set
OPENPOST_PUBLIC_URLto the same public HTTPS app origin unless you have a specific split-origin reason. - [ ] Configure
OPENPOST_EMAIL_PROVIDER,OPENPOST_EMAIL_FROM, and that provider's credentials; verify signup, password-reset, and one opted-in operational notification without logging codes or secrets. - [ ] If the mail provider can report delivery, set
OPENPOST_EMAIL_DELIVERY_WEBHOOK_SECRET, configurePOST /api/v1/email/delivery/webhook, and verify Sent changes to Delivered only after a signed callback. - [ ] If Google login is enabled, register the exact
/api/v1/auth/oidc/google/callbackURL and storeOPENPOST_AUTH_GOOGLE_CLIENT_SECRETthrough a file-backed secret. - [ ] Keep
OPENPOST_EXTRA_CORS_ORIGINSexplicit and do not use*. - [ ] Configure a reverse proxy with HTTPS before connecting OAuth providers.
- [ ] Align reverse-proxy and CDN request-body limits with the largest video you accept, and disable request buffering for streamed uploads.
- [ ] Decide whether to enable automatic image alt text. If enabled, store
OPENROUTER_API_KEYthroughOPENROUTER_API_KEY_FILEand review OpenRouter and model provider privacy and retention terms. - [ ] Decide whether to enable the meme generator. If enabled, review Memegen's privacy, content, template-rights, watermark, rate-limit, and output terms; prefer a private service for unpublished drafts, and use
OPENPOST_MEMEGEN_API_KEY_FILEfor a hosted key. - [ ] Confirm
GET /api/v1/healthreturns{"status":"ok"}. - [ ] Confirm
GET /api/v1/readyreturns{"status":"ready","database":"ok"}. - [ ] Use
/api/v1/healthfor process liveness and/api/v1/readyfor traffic admission, rollouts, and dependency-aware monitoring. - [ ] Confirm
openpost instance health --instance <public-url>succeeds against the public URL. - [ ] Capture
openpost instance diagnostics --instance <public-url> --jsonfor the launch/support handoff. - [ ] Decide whether to enable PostHog telemetry. Self-hosted instances keep it disabled unless the operator explicitly chooses an operator-owned project and updates their privacy notice.
Self-Hosted Storage
- [ ] Keep
OPENPOST_EDITION=selfhostor leave it unset. - [ ] Use SQLite/local storage unless you intentionally operate Postgres/S3 yourself.
- [ ] Persist the SQLite database path, usually
/data/db/openpost.db. - [ ] Persist the local media directory, usually
/data/media. - [ ] Set
OPENPOST_MEDIA_URLto the public media base URL. - [ ] Back up database files, media files, and secrets together.
- [ ] Run at least one test restore before relying on the backup.
Managed Or Hosted Operators
- [ ] Set
OPENPOST_EDITION=cloud. - [ ] Set
OPENPOST_DATABASE_DRIVER=postgres. - [ ] Set
OPENPOST_DATABASE_URLto the production Postgres URL. - [ ] Set
OPENPOST_STORAGE_DRIVER=s3. - [ ] Set
OPENPOST_S3_REGION,OPENPOST_S3_BUCKET,OPENPOST_S3_ACCESS_KEY_ID, andOPENPOST_S3_SECRET_ACCESS_KEY. - [ ] Set
OPENPOST_S3_PUBLIC_BASE_URLto a stable public media origin. - [ ] Verify the S3 bucket lifecycle policy and object access model before launch.
- [ ] Set
OPENPOST_PADDLE_API_KEY,OPENPOST_PADDLE_ENVIRONMENT=production,OPENPOST_PADDLE_CLIENT_TOKEN,OPENPOST_PADDLE_WEBHOOK_SECRET, andOPENPOST_PADDLE_CHECKOUT_RETURN_URL. - [ ] Set the monthly and annual
OPENPOST_PADDLE_<PLAN>_<PERIOD>_PRICE_IDvalues for Starter, Founder, Pro, Team, and Agency. - [ ] Confirm the production API key and client token have live prefixes; never deploy sandbox credentials to the managed app.
- [ ] Configure Paddle to send customer, subscription, and
transaction.completedevents to/api/v1/billing/paddle/webhook; send a signed test event and confirm it is stored once and reconciled through the billing job. - [ ] Set the minimum and maximum quantity to
1for every Paddle plan price so buyers cannot add duplicate copies of a workspace subscription. - [ ] Before upgrading from Whop billing, migrate every active customer to Paddle and confirm the Paddle subscription is reconciled locally. Historical Whop rows do not grant entitlements after the upgrade.
- [ ] Complete an embedded checkout smoke: plan and period selection, $0 trial start, return to OpenPost, local
trialingstatus, and billing management URL. - [ ] Confirm a new hosted user can create the bootstrap workspace and is blocked from extra workspaces before checkout.
- [ ] Confirm team invitations are blocked once active members plus pending invites reach the plan limit.
- [ ] Configure one EU PostHog production project for the app, backend, marketing site, and documentation; use separate staging and development projects.
- [ ] Disable PostHog IP capture, autocapture, session replay, console capture, and network bodies; enable cookieless server hashing and set event retention to no more than 12 months.
- [ ] Set the PostHog project token and server, browser, and UI hosts; keep the personal API key only in CI source-map upload secrets.
- [ ] Verify
GET /api/v1/telemetry/configexposes only the browser-safe project token and ingestion configuration. - [ ] Verify a browser intent event, a server outcome event, and one sanitized test exception arrive without content, credentials, email, names, query strings, or raw URLs.
Providers
- [ ] Start with Bluesky or Mastodon for the first end-to-end publish smoke.
- [ ] Update callback URLs for X, LinkedIn, Threads, Facebook, Instagram, TikTok, and YouTube to the production HTTPS app origin.
- [ ] Add Facebook through
OPENPOST_PROVIDER_APPSor the instance-admin provider app API if Facebook Pages publishing is enabled, and confirmOPENPOST_MEDIA_URLserves public HTTPS media for media posts. - [ ] Add Instagram through
OPENPOST_PROVIDER_APPSor the instance-admin provider app API if Instagram professional publishing is enabled, and confirmOPENPOST_MEDIA_URLserves public HTTPS media. - [ ] Add TikTok through
OPENPOST_PROVIDER_APPSor the instance-admin provider app API if short-form video publishing is enabled, and confirmOPENPOST_MEDIA_URLserves public HTTPS media. - [ ] Add YouTube through
OPENPOST_PROVIDER_APPSor the instance-admin provider app API if video uploads are enabled, and confirm the Google Cloud project has YouTube Data API v3 enabled. - [ ] Configure Mastodon servers in
MASTODON_SERVERSif you need fixed self-hosted Mastodon apps. - [ ] Confirm custom Mastodon instance registration works if you rely on dynamic Mastodon connections.
- [ ] Limit each new social network until OAuth, media, publishing, token refresh, retries, and API limits pass a live account test.
- [ ] Create one test account connection per enabled provider.
- [ ] Publish a private or low-risk test post with and without media for every enabled provider.
Product Smoke
- [ ] Create the first admin account.
- [ ] Confirm email-and-password signup cannot create a session until the six-digit code is accepted, and confirm resend invalidates the prior code.
- [ ] Confirm Google can create a new account, then link and unlink Google from an existing password account without email-based auto-linking.
- [ ] Decide whether to set
OPENPOST_DISABLE_REGISTRATIONS=true. - [ ] Create a workspace.
- [ ] Invite a second user, accept the link, and confirm both members appear in Settings -> Organization.
- [ ] Connect at least one social account.
- [ ] Upload a small image and confirm it appears in the media library.
- [ ] If automatic alt text is enabled, add an image without alt text to the text-and-thread composer, confirm OpenPost fills its shared alt text, and confirm a manual edit is not replaced.
- [ ] Create a draft and scheduled post from the web app.
- [ ] Create a draft or scheduled post through the CLI.
- [ ] Create a draft or scheduled post through MCP if assistant access is enabled.
- [ ] Confirm scheduled publishing creates and completes a background job.
Operations
- [ ] Point dependency-aware uptime monitoring at
/api/v1/ready; keep container or orchestrator liveness on/api/v1/health. - [ ] Confirm logs include startup configuration, database readiness errors, provider publish failures, and MCP tool-call failures.
- [ ] Document your deployment rollback path.
- [ ] Document where database backups, media backups, and secret backups live.
- [ ] Verify the release artifact or container image matches the version you intended to deploy.