Overview
A workbench can run backing services - databases, caches, object storage, queues - next to your code. Curated services come fully wired with sensible dev defaults, a readiness healthcheck, and a connection env injected into the workspace; any other Docker image works too. This page covers the shared model; each curated service has its own page with details.
New to Monoceros? Start with Installation.
Curated services
Section titled “Curated services”Add a curated service by name, at init or later:
monoceros init acme --with-services=postgresmonoceros add-service acme redisThe curated set:
| Service | For |
|---|---|
| PostgreSQL | relational database |
| pgvector | Postgres + vector search (embeddings) |
| MySQL | relational database |
| MongoDB | document database |
| Redis | in-memory key-value store / cache |
| RustFS | S3-compatible object storage |
| Mailpit | local SMTP catcher with web inbox |
| Keycloak | identity & access management (OAuth2 / OIDC / SAML) |
| Caddy | reverse proxy: app and services under one address |
The workspace waits for service_healthy (not just started), so your code only
runs once the service is actually ready.
Connection env in the workspace
Section titled “Connection env in the workspace”Each curated service injects a connection env into the workspace container,
prefixed with the service name uppercased - e.g. a postgres service gives
POSTGRES_URL, POSTGRES_HOST, POSTGRES_PORT, … The app/agent reads those
instead of hardcoding anything. Monoceros does not inject a bare
DATABASE_URL (that’s a project/framework concern); map <NAME>_URL in your
project’s own .env if a tool expects a specific name.
More than one of the same engine
Section titled “More than one of the same engine”Service names are unique, and the connection-env prefix derives from the name -
so you can run two of the same engine without collision. Add the second under a
different name with --as:
monoceros init acme --with-services=postgresmonoceros add-service acme postgres --as=analyticsThat yields POSTGRES_URL and ANALYTICS_URL, each pointing at its own
instance with its own data dir.
Custom services
Section titled “Custom services”Any image works as a service, not only the curated ones: give a name and the image, and Monoceros scaffolds the block.
Talking to a service that already exists elsewhere (a managed database, say)?
Don’t add a service at all - put its connection string in your project’s own
.env, the same place your framework reads it.
Credentials and data
Section titled “Credentials and data”Service credentials are ${VAR} references in the yml; the real values live in
acme.env, with dev defaults seeded for you (see
Workbench configuration).
Reaching a service from the host
Section titled “Reaching a service from the host”A database port is TCP, so the HTTP proxy does not apply. Open a tunnel:
monoceros tunnel acme postgresSee Proxy and tunnels.
A service with a web interface has two more ways out, both from the same line in
the yml: an httpPort. On the host the proxy gives it a permanent address,
acme-<service>.localhost, with no command to keep running. From another device
on your network, monoceros share serves it
over HTTPS alongside the app. Keycloak declares 8080, the Mailpit inbox 8025, the
RustFS console 9001. Databases have no httpPort and stay inside.