Operations

Upgrade a self-hosted Mogplex safely, manage its secrets, expose the MCP endpoint, and understand the known constraints.

Check your setup

pnpm setup:doctor          # configuration checks
pnpm setup:doctor --live   # also tests Trigger.dev and Vercel credentials

# Docker: the image ships the same doctor
docker compose exec app node scripts/doctor.cjs [--live]

The doctor checks the database (connection, pending migrations, runtime role), auth, the GitHub App, Trigger.dev, sandboxes, models, required secrets, and user access. Each result is pass, warn, or fail, with a link to the page that fixes it. It never prints secret values. It exits non-zero on a failure, so you can use it as a deploy gate.

For uptime monitoring, GET /api/health returns 200 when the database is reachable and 503 when it is not. The response lists which services are configured and contains no secrets. models counts as configured with an AI Gateway key or an OpenAI-compatible endpoint that lists at least one model.

Upgrades

Release notes on the releases page list breaking changes to env vars and migrations. For each upgrade:

  1. Pull main or a tagged release into your fork.
  2. Add any new variables to the app and to Trigger.dev.
  3. Apply migrations: pnpm exec tsx scripts/apply-neon-migrations.ts. With Docker Compose, set MOGPLEX_VERSION to the new release and run docker compose up -d; the migrate service applies them before the new app starts.
  4. Deploy the app.
  5. Deploy the Trigger.dev tasks from the same commit: pnpm trigger:deploy.
  6. Run pnpm setup:doctor, or docker compose exec app node scripts/doctor.cjs with Docker.

Migrations stay compatible with the previous app release, so apply them before you deploy the new code. Production uses the same order.

Production does this in CI

.github/workflows/deploy-production.yml is a working example. It applies migrations, deploys with the Vercel CLI, and then calls /api/cron/production-smoke to detect schema drift. Point its secrets at your own accounts to reuse it.

Secrets

SecretRotation
BETTER_AUTH_SECRETRotating it signs out every user.
CRON_SECRET, INTERNAL_API_SECRETRotate freely. On Docker, update your cron jobs at the same time.
EMAIL_UNSUBSCRIBE_SECRETRotating it invalidates unsubscribe links already sent.
CONNECTIONS_ENCRYPTION_KEYEncrypts saved connection tokens and API keys. Re-encrypt before you rotate (below).
GITHUB_WEBHOOK_SECRET, SLACK_SIGNING_SECRETChange the value in GitHub or Slack and in your env at the same time.

Store secrets in your platform's secret store. Never commit them.

Rotate CONNECTIONS_ENCRYPTION_KEY

If you change the key without re-encrypting, every saved connection becomes unreadable. Use the rotation script. It runs a dry run by default and backs up the original ciphertexts.

OLD_CONNECTIONS_ENCRYPTION_KEY=<old> \
NEW_CONNECTIONS_ENCRYPTION_KEY=$(openssl rand -hex 32) \
DATABASE_URL=<owner connection> \
  pnpm exec tsx scripts/rotate-connections-encryption-key.ts            # dry run
# Review the counts, then run again with --execute

Take a database snapshot first, and rotate during low traffic. Switch the env var and redeploy right after the script finishes. Then run the script once more to re-encrypt rows that were written in between.

Hosted API and MCP endpoint

Your deployment serves the same hosted API and MCP endpoint as mogplex.com, at https://<domain>/api/v1/mogplex/mcp. Users authenticate with a Mogplex key from Settings → Mogplex Keys, or through OAuth.

Better Auth is the OAuth authorization server. It supports dynamic client registration, PKCE, and refresh tokens. No extra setup is needed when the public URL is NEXT_PUBLIC_APP_URL. Verify it:

curl https://<domain>/.well-known/oauth-protected-resource/api/v1/mogplex/mcp
curl https://<domain>/.well-known/oauth-authorization-server

The first response must name your domain as both the resource and the authorization server.

  • Set MOGPLEX_MCP_RESOURCE_URL only when the MCP endpoint is served from a different URL than NEXT_PUBLIC_APP_URL.
  • Set MOGPLEX_MCP_ALLOWED_ORIGINS for browser-based MCP clients.

When you install MCP clients, replace mogplex.com with your domain.

Mogplex CLI

To point the Mogplex CLI at your deployment instead of mogplex.com, set MOGPLEX_URL:

export MOGPLEX_URL="https://mogplex.example.com"

See CLI automation.

Known constraints

  • Sandboxes require Vercel Sandbox. No other sandbox backend exists yet. A pluggable backend would be a welcome contribution. Open a discussion before you start so the interface is agreed first.
  • Cron routes need a scheduler. Vercel and the Compose cron service schedule them. On other hosts, schedule them yourself.
  • Bring-your-own Vercel compute for end users is not available. Sandboxes always bill to the deployment's PLATFORM_VERCEL_* account.
  • Team-shared connections are not available yet. Connections belong to personal accounts.

Troubleshooting

SymptomLikely cause
Runs fail with "requires a positive billing balance"MOGPLEX_SELF_HOSTED is off, or ignored because STRIPE_SECRET_KEY is set. See Give users access.
"Sandbox service not configured"PLATFORM_VERCEL_TOKEN or the project ID is missing.
Automations and Slack runs never startTrigger.dev is not configured, the tasks are not deployed, or the tasks are missing env vars.
pnpm trigger:deploy stops with project-ref guidanceTRIGGER_PROJECT_REF is unset.
The app container is unhealthy/api/health cannot reach the database. Check DATABASE_URL and the migrate service logs.
GitHub deliveries return 401GITHUB_WEBHOOK_SECRET does not match the App.
A changed NEXT_PUBLIC_* value has no effectRebuild. These values are fixed at build time.
Auth routes return errorsDATABASE_URL and MOGPLEX_RUNTIME_DATABASE_URL are both unset, or migrations have not run.
Email sign-up never completesRESEND_API_KEY is missing, or the sender domain is not verified.
Edit on GitHub

On this page