Skip to content

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.

Add a curated service by name, at init or later:

Terminal window
monoceros init acme --with-services=postgres
monoceros add-service acme redis

The curated set:

ServiceFor
PostgreSQLrelational database
pgvectorPostgres + vector search (embeddings)
MySQLrelational database
MongoDBdocument database
Redisin-memory key-value store / cache
RustFSS3-compatible object storage
Mailpitlocal SMTP catcher with web inbox
Keycloakidentity & access management (OAuth2 / OIDC / SAML)
Caddyreverse 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.

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.

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:

Terminal window
monoceros init acme --with-services=postgres
monoceros add-service acme postgres --as=analytics

That yields POSTGRES_URL and ANALYTICS_URL, each pointing at its own instance with its own data dir.

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.

Service credentials are ${VAR} references in the yml; the real values live in acme.env, with dev defaults seeded for you (see Workbench configuration).

A database port is TCP, so the HTTP proxy does not apply. Open a tunnel:

Terminal window
monoceros tunnel acme postgres

See 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.