Appearance
Services PRO
Pro Feature
Managed services require Corral Pro. Learn more →
Corral can install and manage local development services — databases, caches, search engines, and more — as native binaries. No Docker, no Homebrew, no manual setup. Click Install, then Start.
Available Services
| Service | Category | Default Ports | Description |
|---|---|---|---|
| Valkey | Cache, Queue | 6379 | Redis-compatible in-memory data store |
| Mailpit | smtp=1025, web=8025 | Local SMTP trap with a captured-mail web UI | |
| PostgreSQL | Database | sql=5432 | Relational database with concurrent multi-version installs (15, 16, 17 can run side-by-side) |
| MariaDB | Database | sql=3306 | GPL-2.0 MySQL-wire-compatible relational database with concurrent multi-version installs across LTS branches (10.11, 11.4, 11.8) and rolling 12.x; bare-name installs land on the newest LTS via the catalog's LTS-aware default-version policy |
| OpenSearch | Search | http=9200, transport=9300 | Open-source search engine (Apache-2.0 fork of Elasticsearch); bundles JDK 21, runs the single-node min distribution |
| Meilisearch | Search | 7700 | MIT-licensed search API with a built-in web dashboard served on the same HTTP port |
| MinIO | Storage | api=9000, console=9001 | S3-compatible object storage with a built-in object browser; AGPL-3.0; pinned to RELEASE.2025-09-07T16-13-09Z (date-based upstream tags) |
| Typesense | Search | api=8108, peering=8107 | GPL-3.0 search engine with built-in API key auth; mandatory --api-key at startup defaulted to xyz (the upstream tutorial dialect); no built-in web dashboard |
More services are coming: MySQL, Elasticsearch, Qdrant, NATS, ClickHouse, FerretDB, and others.
Installing a Service
Via CLI
sh
corral service catalog # Browse available services
corral service install valkey # Single port, default version
corral service install mailpit # Multi-port: SMTP + web UI
corral service install postgres@16 # Latest 16.x from the catalog
corral service install [email protected] # Exact version
corral service install mariadb # Newest LTS (currently 11.4.x); LTS-aware default
corral service install [email protected] # Latest 11.4.x
corral service install [email protected] # Exact version
corral service install opensearch@3 # Latest 3.x
corral service install meilisearch # Search API + web dashboard on port 7700
corral service install minio # S3-compatible object storage + object browser
corral service install typesense # GPL-3.0 search engine with built-in API key auth (defaulted to xyz)For services that support concurrent multi-version installs (PostgreSQL and MariaDB today), the name@version form is the canonical way to reference a specific install — the command accepts it anywhere a service name is accepted. See Multiple Versions below.
LTS-aware default-version selection. For services with multiple LTS branches in flight (MariaDB today: 10.11, 11.4, 11.8 LTS plus rolling 12.x), the bare-name install resolves to the newest LTS rather than the newest version overall. The reasoning: a rolling-release default would surprise dev users with quarterly upgrade cycles; LTS branches receive bug-fix-only updates and stable release windows of three years or more. The catalog metadata that drives this (lts_branches + default_version_policy) is per-service, so it doesn't change behavior for services like PostgreSQL where every supported major is a long-term branch.
Via macOS App
- Open the sidebar and hover over the Services section header — click Browse
- Find the service in the catalog grid
- Click the tile and confirm the install in the sheet
The binary is downloaded, verified (SHA-256), and extracted automatically. A progress indicator shows download status.
Starting and Stopping
Via CLI
sh
corral service start valkey
corral service stop valkey
corral service restart valkey
corral service start postgres@16 # Target a specific installed major
corral service stop postgres@17 # Multi-version services use name@versionVia macOS App
Select the service in the sidebar and use the toolbar Start/Stop/Restart buttons, or right-click for a context menu.
Multiple Versions
Services that support concurrent multi-version installs (PostgreSQL today) can have several majors installed at the same time. Each (service, version) install is isolated — its own port, its own data directory, its own row in the sidebar — so that installing Postgres 17 never touches Postgres 16's data.
Referring to a specific version. Anywhere a service name is accepted — install, uninstall, start/stop/restart, info, set, and project services links — the canonical form is name@version:
sh
corral service install postgres@16 # Prefix: install the newest 16.x in the catalog
corral service install [email protected] # Exact: install this specific build
corral service start postgres@17 # Target an installed major
corral service info postgres@16 # Connection string, ports, data path for this major
corral service uninstall postgres@15 # Uninstall one major; others untouchedBare-name resolution. Bare corral service start postgres works when:
- Exactly one version of that service is installed, or
- A default version has been set via
corral service set postgres default-version <version>.
If multiple versions are installed and no default is set, the command errors with AmbiguousVersion and lists the installed candidates.
sh
corral service set postgres default-version 16.4.1 # Pin bare-name resolution
corral service set postgres default-version - # Unset; bare name is now ambiguousThe sidebar in the macOS app shows a star (or equivalent marker) next to whichever version is the current default. Linking services to projects can use either form — services: ["postgres@16"] pins a specific major, services: ["postgres"] resolves through default-version.
Upgrading. Installing a new major never migrates data. To move from Postgres 16 to 17, install 17 alongside (it takes its own port, gets its own data directory), then migrate data yourself with pg_upgrade or pg_dumpall when ready. Uninstall the old major only after you've moved.
Connection Strings
Every installed service provides a connection string — the machine-readable URL apps use to connect:
redis://127.0.0.1:6379 # Valkey
smtp://127.0.0.1:1025 # Mailpit (app-facing SMTP)
postgresql://[email protected]:5432/corral # PostgreSQL (trust auth on localhost)
mysql://corral:[email protected]:3306/corral # MariaDB (mysql:// scheme is universal across JS clients)
http://127.0.0.1:9200 # OpenSearch
http://127.0.0.1:7700 # Meilisearch (dashboard + API share the port)
http://127.0.0.1:9000 # MinIO (S3 endpoint; console served separately at :9001)
http://127.0.0.1:8108 # Typesense (API; the API key is a separate client constructor arg, parallel to the AWS SDK pattern)MariaDB transport-agnostic auth. MariaDB seeds the corral user across three host literals — localhost (unix socket), 127.0.0.1 (IPv4 TCP), and ::1 (IPv6 TCP) — so the documented connection string authenticates regardless of which transport your client picks. MariaDB's grant matching is by literal host string (not host equivalence), so a single 'corral'@'localhost' grant would silently break TCP connections to 127.0.0.1 with ERROR 1045 Access denied. This mirrors how mariadb-install-db itself sets up root for multiple hosts.
The macOS app displays the connection string prominently in the service detail view with a one-click copy button. In the CLI, corral service info <name> prints it under Connection:. For services with multiple installed versions, the detail view also offers a version switcher that navigates between installed versions — navigation only; it does not migrate data.
Environment Variables
Each service exposes an ordered list of KEY=value pairs for pasting into your project's .env file. The service detail view renders these in an Environment variables card with a per-row copy button; the CLI shows them under corral service info.
Valkey:
REDIS_URL=redis://127.0.0.1:6379Mailpit:
SMTP_HOST=127.0.0.1
SMTP_PORT=1025
SMTP_FROM=corral@localhostPostgreSQL:
DATABASE_URL=postgresql://[email protected]:5432/corral
PGHOST=127.0.0.1
PGPORT=5432
PGUSER=corral
PGDATABASE=corralDATABASE_URL is the canonical ORM-friendly form (Prisma, Drizzle, Knex, Sequelize). The split PG* variables are what psql, pg_dump, and anything else that honors libpq environment conventions read directly — set alongside DATABASE_URL so both classes of tooling work with zero further config.
MariaDB:
DATABASE_URL=mysql://corral:[email protected]:3306/corral
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=corral
MYSQL_PASSWORD=corral
MYSQL_DATABASE=corralDATABASE_URL uses the mysql:// scheme — universal across the JS ecosystem (Drizzle, Prisma, TypeORM, Sequelize, mysql2). The split MYSQL_* variables are what every mysql client tool reads directly (the canonical names work the same way across MariaDB and Oracle MySQL since they share the wire protocol and command-line conventions). The default credentials are corral / corral — visible in the values above. Unlike Postgres (which uses trust auth on localhost), MariaDB requires a real password, so the seed SQL creates the corral user with IDENTIFIED BY 'corral' at install time.
OpenSearch:
OPENSEARCH_URL=http://127.0.0.1:9200
OPENSEARCH_NODE=http://127.0.0.1:9200
OPENSEARCH_HOSTS=http://127.0.0.1:9200OPENSEARCH_URL matches Corral's *_URL convention. OPENSEARCH_NODE is what the official JS client (@opensearch-project/opensearch) reads natively. OPENSEARCH_HOSTS covers JVM and Python clients. All three carry the same URL so switching client libraries requires no config change.
Meilisearch:
MEILISEARCH_HOST=http://127.0.0.1:7700Single env var matching Laravel Scout and what the official meilisearch JS client expects as its host constructor argument. No master key is required — Corral runs Meilisearch in --env development mode, where auth is disabled — so no MEILISEARCH_API_KEY var is exposed.
MinIO:
AWS_ENDPOINT_URL=http://127.0.0.1:9000
AWS_ACCESS_KEY_ID=minioadmin
AWS_SECRET_ACCESS_KEY=minioadmin
AWS_REGION=us-east-1
MINIO_ENDPOINT=http://127.0.0.1:9000
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadminAWS-style vars come first because the AWS SDK family (@aws-sdk/client-s3, boto3, etc.) reads them natively — pasting these into a project's .env gives a zero-config experience for any S3 client. The MinIO-native vars follow for tools that prefer the upstream names. The credentials match MinIO's upstream defaults (minioadmin/minioadmin), pinned in the child process's environment so they remain accurate regardless of MINIO_ROOT_USER/MINIO_ROOT_PASSWORD exported in your shell.
Typesense:
TYPESENSE_HOST=http://127.0.0.1:8108
TYPESENSE_API_KEY=xyzEndpoint URL plus API key. typesense-js and the official client libraries take both as separate constructor arguments — neither is read from the environment natively, so this block is purely for ergonomic copy-paste into a project's .env. The xyz key matches what every Typesense getting-started tutorial, the upstream Homebrew formula, and the JS/CLI client READMEs use as their example value, so Stack Overflow answers and the official quickstart translate 1:1 (the same reasoning applies to MinIO's minioadmin/minioadmin defaults).
The JSON shape (corral service list --json / service info --json) is an array of {"key": "...", "value": "..."} objects, preserving declaration order.
Web UI
Services with a browser-facing interface — like Mailpit's captured-mail inbox at http://127.0.0.1:8025 or Meilisearch's search dashboard at http://127.0.0.1:7700 — expose a Web UI card in the detail view with an Open in Browser button. The button launches the URL in your preferred browser (see Settings → Preferred browser) and is disabled with an explanatory tooltip when the service isn't running.
Configuration
Each service has these settings:
| Setting | CLI | Description |
|---|---|---|
| Port | corral service set valkey port 6380 | Shorthand for services whose sole port role is main (Valkey). Must be >= 1024. |
| Port role | corral service set mailpit port.smtp 1026 | Role-qualified port for any service with named roles (port.smtp, port.web for Mailpit; port.sql for Postgres; port.http, port.transport for OpenSearch; port.api, port.console for MinIO; port.api, port.peering for Typesense). Each port must be >= 1024 and unique across roles. |
| Auto-start | corral service set valkey auto-start true | Start automatically when the daemon launches. |
| Default version | corral service set postgres default-version 16.4.1 | For services with concurrent multi-version installs, the version resolved by bare-name lookups. Use - to unset. See Multiple Versions. |
Port changes take effect on the next start — they're deferred while the service is running so the reported ports always match what's actually bound.
Project Service Dependencies
Projects can declare which services they depend on. When you start a project, Corral automatically starts its declared services first.
Configure via the CLI:
sh
corral project set my-api services valkeyOr in the macOS app under the project's Settings tab.
Uninstalling
sh
corral service uninstall valkey # Keep data directory
corral service uninstall valkey --delete-data # Remove everything
corral service uninstall postgres@15 # Uninstall just Postgres 15; 16/17 untouched
corral service uninstall postgres@15 --delete-dataIn the macOS app, go to the service's Settings tab and click Uninstall Service.
Security
All services bind exclusively to 127.0.0.1 — they are never exposed to the local network. Corral enforces this in the process configuration regardless of the service's defaults.
Data Directory
Service binaries and data are stored in ~/.corral/services/:
~/.corral/services/
├── registry.json — (name, version)-keyed registry (schema v3) with a `default_versions` map
├── catalog.json — cached remote catalog
├── valkey/
│ └── 8.1.1/
│ ├── bin/ — valkey-server, valkey-cli
│ └── data/ — persistent Valkey .rdb snapshot
├── mailpit/
│ └── 1.29.7/
│ ├── bin/mailpit
│ └── data/mailpit.db — SQLite store of captured mail
├── postgres/
│ ├── 16.4/ — one directory per installed major
│ │ ├── bin/{postgres,initdb,pg_isready,psql,pg_dump,pg_restore,pg_ctl,...}
│ │ ├── lib/{libicu*.dylib,libssl*.dylib,...} — dylibs bundled into the tarball
│ │ ├── share/postgresql/ — initdb template files
│ │ └── data/ — per-version data directory (isolated)
│ └── 17.2/ — concurrent install, own data dir, own port
│ └── ...
├── opensearch/
│ └── 3.6.0/
│ ├── bin/opensearch
│ ├── jdk.app/Contents/Home/ — bundled JDK 21
│ └── data/
│ ├── config/ — per-install writable copy of the config tree (OPENSEARCH_PATH_CONF points here)
│ ├── data/ — indices
│ └── logs/ — node logs
├── meilisearch/
│ └── 1.42.1/
│ ├── bin/meilisearch
│ └── data/
│ └── data.ms/ — LMDB store (Meilisearch's default layout)
├── minio/
│ └── RELEASE.2025-09-07T16-13-09Z/
│ ├── bin/minio
│ └── data/
│ └── .minio.sys/ — MinIO's auto-created config + bucket metadata
└── typesense/
└── 30.2/
├── bin/typesense-server
├── LICENSE — upstream LICENSE.txt fetched at bundle time
├── SOURCE.txt — Corresponding Source pointer (GPL-3.0 §6 compliance)
└── data/
├── db/ — RocksDB store (search documents + collections)
├── meta/ — RocksDB metadata
└── state/ — Raft log + snapshots (peering-port state, single-node)Data directories are version-scoped for every service: uninstalling one major version never touches another's data, and a binary from one major can never read another major's on-disk format by accident. Data persists across restarts and is never deleted without an explicit --delete-data flag.