2.3 Writing a minimal tenant config
A tenant config declares one application: its mounts and a few top-level
settings. With tenantsDir: "./tenants" and tenant main, the file is
./tenants/main.json.
The smallest useful tenant
{
"mounts": [
{ "path": "/files", "service": "file",
"config": { "access": "open" } }
]
}
That's a complete, valid tenant: a streamed file store at /files. mounts is
the only required top-level key. The explicit "access": "open" matters:
mounts fail closed when access is absent, so public access is always a choice,
never an accident. Start the node (or reload — see below) and /files is live.
A more realistic starting point
{
"mounts": [
{ "path": "/files", "service": "file",
"config": { "access": "open" } },
{ "path": "/data", "service": "data",
"config": { "access": "open" } },
{ "path": "/services", "service": "services",
"config": { "access": "open" } }
]
}
This gives you file storage, a JSON record store, and the self-config API at
/services — the last of which lets you edit the tenant over HTTP instead of
editing the file and restarting (Part 10). Most tenants want services mounted
from the start.
This is a loopback-only bootstrap config: all three mounts are open so the
first-request tutorial works and rs2 auth init can create the first operator.
Keep the node bound to 127.0.0.1; Part 5 adds auth, and the bootstrap command
then locks the data/control mounts. Never expose this starting config directly
to a network.
Anatomy of a mount
{ "path": "/data", "service": "data", "config": { "enforceSchema": true } }
path— the URL prefix. Routing is longest-prefix on segment boundaries, so more specific mounts win.service— a prebuilt service (file,data,pipeline,wrapper,query,template,auth,proxy,sms,services, orlog) or a customcode:<name>@<version>.config— service-specific options plus the standard cross-cutting keys that work on any mount:access,retry,caching,schedule, named-secret grants, and agent-surface metadata (x-agent,description, …). These are introduced where they're relevant and gathered in Appendix B. Every mount should setaccess; no policy means no access.
Duplicate paths are rejected, and the whole config is validated before it goes
live — an invalid tenant never partially loads.
Loading changes
- Editing the file on disk takes effect on a node restart (or any
PUT /services/rawround-trip that triggers a reload). - Editing through
PUT /services/raw(theservicesmount) validates, dry-builds, and hot-swaps the tenant atomically with no restart — the preferred path on a running server.
For now, edit ./tenants/main.json and restart the node. With a tenant in
place, let's make a real request.
← Previous: 2.2 Running your first node · Manual home · Next: 2.4 Making your first request →