# Self-hosted Mogplex. # # cp .env.example .env # set APP_URL, BETTER_AUTH_SECRET, CRON_SECRET, ... # docker compose up -d # # This pulls the published multi-arch image ghcr.io/mogplex/mogplex. Pin a # release with MOGPLEX_VERSION in .env (default: latest). To build from this # checkout instead, for example to bake in build-time NEXT_PUBLIC_* values: # # docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build # # Services: # postgres Postgres 17 with pgvector. Runs only with the `postgres` profile, # which .env.example turns on (COMPOSE_PROFILES=postgres). To use # an external database, set DATABASE_URL and DATABASE_URL_UNPOOLED # in .env and remove COMPOSE_PROFILES; no local Postgres starts. # migrate Applies neon/baseline.sql and neon/migrations, then exits. # app The Next.js web app on port 3000, started after migrate succeeds. # cron Calls the vercel.json cron routes on schedule with CRON_SECRET. # # Trigger.dev, the sandbox runtime, the GitHub App, and model providers are # still external services. https://docs.mogplex.com/self-hosting lists each # one and the env vars it needs. Questions: # https://github.com/Mogplex/mogplex/discussions x-image: &image ${MOGPLEX_IMAGE:-ghcr.io/mogplex/mogplex}:${MOGPLEX_VERSION:-latest} x-database-env: &database-env # An external database in .env (DATABASE_URL / DATABASE_URL_UNPOOLED) wins # over the bundled postgres service. DATABASE_URL: ${DATABASE_URL:-postgres://mogplex:${POSTGRES_PASSWORD:-mogplex}@postgres:5432/mogplex} DATABASE_URL_UNPOOLED: ${DATABASE_URL_UNPOOLED:-postgres://mogplex:${POSTGRES_PASSWORD:-mogplex}@postgres:5432/mogplex} services: postgres: image: pgvector/pgvector:pg17 profiles: [postgres] environment: POSTGRES_USER: mogplex POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mogplex} POSTGRES_DB: mogplex volumes: - postgres-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U mogplex -d mogplex"] interval: 5s timeout: 5s retries: 20 restart: unless-stopped migrate: image: *image command: ["node", "scripts/migrate.cjs"] environment: <<: *database-env # The image's healthcheck probes the web server, which this service does # not run. healthcheck: disable: true # Waits for the bundled postgres when its profile is on. With an external # database the service is not started, and required: false lets migrate # run without it. depends_on: postgres: condition: service_healthy required: false restart: "no" app: image: *image # Server-side runtime env. Copy .env.example to .env and fill in the # values for the services you provisioned. env_file: - .env # Set APP_URL there: the app reads its public URL at runtime, so one # image serves any domain. environment: <<: *database-env ports: - "${MOGPLEX_PORT:-3000}:3000" depends_on: migrate: condition: service_completed_successfully restart: unless-stopped cron: image: *image command: ["node", "scripts/self-host-cron.mjs"] environment: CRON_SECRET: ${CRON_SECRET:?set CRON_SECRET in .env} CRON_TARGET_URL: http://app:3000 healthcheck: disable: true depends_on: app: condition: service_started restart: unless-stopped volumes: postgres-data: