Skip to the article

Installation reference

Choose a verified release and installation profile, install the full, managed or source profile and check its operating limits.

Start with the step-by-step installer. Use this article for technical details and additional checks.

Start installation

Install a self-hosted instance from a verified release and the matching profile: full, managed Supabase or source. Establish compatibility first, then follow the selected installation procedure and acceptance checks before admitting users.

MCP availability and network access

MCP is included in self-hosted minddy and starts with the application. It works out of the box at /api/mcp on the instance origin configured with MINDDY_PUBLIC_APP_URL. OAuth discovery and dynamic client registration are included: you do not need a separate MCP server, a dedicated OAuth application or a minddy Cloud proxy. Connect your MCP client to your instance endpoint, then sign in and grant access through the browser consent flow.

Availability does not guarantee network reachability. Both the MCP client and the browser used for authorization must be able to reach the advertised MCP and OAuth URLs. If you configure an explicit OAUTH_ISSUER override, that origin must also be reachable. The client must support the connection, OAuth flow and chosen network path; some clients require HTTPS even on private networks.

Choose an origin reachable from the MCP client and its authorization browser. On the same computer, a compatible client can use http://localhost:6463/api/mcp. On another LAN/VPN computer, use the server’s configured address, for example http://192.168.1.50/api/mcp, with its listening address, application port, firewall and routing allowing access. localhost and 127.0.0.1 always point to the computer making the connection, so the server’s localhost URL will not work there. A loopback-only process remains unreachable directly. Outside the private network, use a reachable HTTPS endpoint such as https://tickets.example.com/api/mcp or a supported network path, subject to client requirements. A hosted agent needs that route too; local hosting does not automatically expose the instance to the Internet.

Read the MCP network guidance before connecting a remote client.

Select a supported release and installation profile

Use an immutable release from the public mangue-dev/minddy repository and read the requirements from the row of deploy/self-hosted/compatibility.json whose minddyRelease matches it. A package version without its own row is not a supported self-hosted release. Every published row supports Linux amd64 and arm64 production hosts, Node.js 24, pnpm 10.28.0, Docker Engine 27.0.0 or later and Compose plugin 2.29.0 or later. The full profile pins official Supabase self-hosted/v0.7.2 at commit 549db119c44c25167461812041ba198bde2b31a4. Keep its complete image set; upgrading one service separately creates an operator-managed variant.

The managed profile connects to a Supabase project on supabase.com. It must expose PostgreSQL, Auth, Storage and Realtime and pass the release verification. PostgreSQL alone is insufficient. The Supabase CLI local stack is for development and evaluation, not a public production service.

Annotated source tag
Assets and SHA256SUMS
Official OCI signature and digest
Selected compatibility profile
Read the stages in order. Annotated source tag. Assets and SHA256SUMS. Official OCI signature and digest. Selected compatibility profile.

Verify before execution

Check the annotated tag, release assets, SHA256SUMS and official OCI signature before installing dependencies or executing the release. The following Bash commands start in the selected tagged checkout and leave IMAGE set to its verified digest. Stop on a failed check. Install Cosign using its official instructions first. The command preserves source and image identity; it does not prove the deployment works.

Bash
set -euo pipefail
export SOURCE_DIR="$PWD"
export RELEASE_TAG="$(git describe --tags --exact-match)"
git rev-parse "$RELEASE_TAG^{tag}"
export RELEASE_ASSETS="$(mktemp -d)"
ASSET_BASE="https://github.com/mangue-dev/minddy/releases/download/$RELEASE_TAG"
for ASSET in SHA256SUMS RELEASE_NOTES.md UPDATE.md release-manifest.json \
  "minddy-$RELEASE_TAG-container.txt" "minddy-$RELEASE_TAG-source.tar.gz" \
  "minddy-$RELEASE_TAG-migrations.tar.gz"; do
  curl --fail --show-error --location "$ASSET_BASE/$ASSET" --output "$RELEASE_ASSETS/$ASSET"
done
cd "$RELEASE_ASSETS"
if command -v sha256sum >/dev/null 2>&1; then
  sha256sum --check SHA256SUMS
else
  shasum -a 256 --check SHA256SUMS
fi
test "$(node -p 'require("./release-manifest.json").release.tag')" = "$RELEASE_TAG"
test "$(node -p 'require("./release-manifest.json").release.commit')" = \
  "$(git -C "$SOURCE_DIR" rev-parse "$RELEASE_TAG^{commit}")"
export IMAGE="$(node -p 'require("./release-manifest.json").container.reference')"
test "$IMAGE" = "$(sed -n 's/^reference=//p' "minddy-$RELEASE_TAG-container.txt")"
printf '%s\n' "$IMAGE" | LC_ALL=C grep -Eq '^ghcr\.io/mangue-dev/minddy@sha256:[a-f0-9]{64}$'
cosign verify \
  --certificate-identity 'https://github.com/mangue-dev/minddy/.github/workflows/release.yml@refs/heads/production' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  "$IMAGE"
cd "$SOURCE_DIR"
Bash
gh attestation verify "oci://$IMAGE" --repo mangue-dev/minddy
docker buildx imagetools inspect "$IMAGE" \
  --format '{{ json .SBOM }}' > minddy.sbom.spdx.json
test -s minddy.sbom.spdx.json

Plan operation and upgrades

Install one published release at a time. Migrations are forward-only; incompatible rollback restores a matching database, Storage, configuration and application set. minddy maintains release tooling and offers best-effort diagnosis of reproducible core defects. You operate DNS, TLS, host capacity, backups, restore drills and optional providers. A moving image tag or derivative Supabase stack does not inherit the release support contract.

The published v0.11.0 profiles also start an agent-runner service that fails before the application becomes healthy. Later releases remove that runner and its code sandboxes entirely: Numo does not run code, and no service receives the Docker socket. Install such a release rather than adapting v0.11.0.

Install the reference server profile

Start from a verified tagged checkout and immutable image digest. Linux amd64 and arm64 are supported. Allow 4 GB RAM, two cores and 20 GB SSD for managed Supabase; allow 8 GB RAM, four cores and 60 GB SSD when Supabase shares the host. Public service requires DNS and HTTPS on your own origins. HTTP is accepted only on localhost or a private IPv4 network. Restrict private HTTP to a trusted LAN and never forward router ports. The full profile exposes the app on port 80 and its API on 8000 in that mode.

Verified release and protected environment
Installer: full reference profile
Official Supabase, app, scheduler
Account, file and recovery acceptance
Read the stages in order. Verified release and protected environment. Installer: full reference profile. Official Supabase, app, scheduler. Account, file and recovery acceptance.
The full profile keeps the application and Supabase on your server. In this example, their private network access is restricted to the LAN.

Configure and run the installer

Run pnpm self-host:install from the release directory. Select managed or full, your application origin and administrator address. For full, first fetch the pinned upstream checkout. The installer writes a mode-0600 environment, generates distinct missing secrets, pulls the selected profile, starts it and runs idempotent bootstrap. It retains an existing image pin and secrets. The installer also asks whether to encrypt workspace content; --encryption enabled (the default) or --encryption disabled answers non-interactively, and it writes MINDDY_CONTENT_ENCRYPTION_ENABLED with an independent MINDDY_DATA_ROOT_KEY. A rerun keeps the saved choice and refuses a conflicting one; see workspace encryption before changing it. The example uses the IMAGE digest verified in the compatibility section. For real Auth email, add --skip-start first, then configure SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_ADMIN_EMAIL and SMTP_SENDER_NAME in the protected file before rerunning. Keep ENABLE_EMAIL_AUTOCONFIRM=false. The placeholder supabase-mail is not a production inbox.

Before starting, compare MINDDY_RELEASE and MINDDY_IMAGE in the protected file with the selected compatibility row and verified container asset. The installer copies MINDDY_RELEASE from the release's deployment template, and --image changes only the image reference; there is no --release flag. The v0.11.0 template, for example, still says 0.10.30. When the value differs from the release you install, prepare the file with --skip-start, set MINDDY_RELEASE to that release explicitly and keep the verified immutable image reference. Do not replace generated credentials or encryption keys.

Bash
node scripts/fetch-official-supabase.mjs --destination /srv/minddy/supabase
pnpm self-host:install -- --non-interactive --mode full \
  --app-url http://192.168.1.50 --admin-email ops@example.com \
  --supabase-dir /srv/minddy/supabase --image "$IMAGE" --skip-start

The command above creates deploy/self-hosted/.env in the selected release directory. Edit that protected file, then rerun the same command without --skip-start to start the profile and run bootstrap. Existing origins, image and secrets remain in the protected file.

If you run this full profile on macOS Docker Desktop, apply the filesystem Storage volume override before the first start and retain RESTORE_OVERRIDE for every later Compose operation. The Linux host bind-mount layout and this named-volume profile require different byte archives; use the matching backup and restoration procedure.

Check before admitting users

The reference profiles include the scheduler; they contain no code runner and mount no Docker socket. Never publish PostgreSQL or internal service ports to the Internet. Run the doctor with the installed environment and full-profile upstream Compose file. Test confirmation, sign-in, MFA, reset, project and issue creation, attachment upload/download and Realtime in two sessions. A 200 response from /api/health only proves application liveness. If interrupted, rerun the installer with the same Compose context and protected environment; do not reset data. Establish an off-host backup and blank-target restore before onboarding a team.

Install with managed Supabase or from source

Managed Supabase describes who operates the backend. It can accompany the official OCI application profile or a source application server. Keep these deployments distinct in installation and acceptance records. Your backend must expose PostgreSQL, Auth, Storage and Realtime. For the guided managed OCI profile, supply a project on supabase.com, its public URL, anon and service-role keys and a PostgreSQL connection reachable from bootstrap tooling. Use your own project; minddy Cloud credentials are not installation inputs.

Your managed Supabase project
PostgreSQL, Auth, Storage, Realtime
OCI profile OR tagged source application
Profile-specific jobs and backup procedure
A managed backend can serve either deployment method, with scheduling and backups configured for the chosen profile.

Install the managed OCI profile

From the verified release directory, run the guided command below. IMAGE is the digest verified in the compatibility section. Values containing ... are examples, not usable credentials. Obtain real values privately and avoid command history or shared logs containing secrets. The installer preserves an existing protected environment, includes its scheduler and keeps optional services off until configured. Configure Auth SMTP and exact redirects separately in your Supabase project.

The published v0.11.0 managed OCI profile has the same failing runner as the full profile, so its unchanged installer cannot complete startup; use a later release without the runner. The command below prepares configuration with --skip-start. Review that protected file while preserving the verified image and generated secrets, then rerun the command without --skip-start. Verify the managed profile before admitting users. Do not run full-profile local backend commands against a provider project.

Bash
pnpm self-host:install -- --non-interactive --mode managed \
  --app-url https://tickets.example.com --admin-email ops@example.com \
  --supabase-url https://project.supabase.co --anon-key '...' \
  --service-role-key '...' --db-url 'postgresql://postgres:...@db.example.com:5432/postgres' \
  --image "$IMAGE" --skip-start

Complete a source deployment

For source delivery, install frozen dependencies from the tagged checkout, supply the required application and Supabase environment, run bootstrap, build and run the production server behind your reverse proxy. Set runtime MINDDY_PUBLIC_* values before startup. You provide a durable scheduler with the authenticated schedules documented in the scheduled-work section; a source build alone supplies no running jobs. Verify database migrations and Storage, then exercise Auth, issue creation, file bytes and Realtime. Back up this instance through the logical/provider procedure. Do not test an OCI installation by switching to a source server.

Bash
pnpm install --frozen-lockfile
pnpm bootstrap:supabase -- --db-url "$SUPABASE_DB_URL" --env-file .env.local
pnpm build
pnpm start

Related articles