Operations
Quickstart
Section titled “Quickstart”meta.svc config generate minimal > .meta.yamlmkdir -p myapp/pages && echo "title: Home" > myapp/pages/home.yamlmeta.svc -f .meta.yamlcurl -H "X-Customer: acme" "http://localhost:8080/product/myapp/file/pages/home.yaml"Embedded config profiles: minimal, product-git, fs-cache, multi-customer, marketplace, full, list with meta.svc config list, print with config generate <profile>.
Server configuration (.meta.yaml)
Section titled “Server configuration (.meta.yaml)”name: metaport: "8080"products: acme: # customer - name: myapp # product url: ./myapp type: local - name: storefront url: https://git.example.com/acme/storefront.git type: remote ref: main reftype: branch watchduration: 60s cachetype: fs cachedir: /var/lib/meta/cache allowedversions: - name: main - pattern: "v[0-9]+\\.[0-9]+\\.[0-9]+" access: read: "true" write: "false"Per-repo keys: name, url, type (local|remote), readonly, watchduration, ref, reftype, pinversion, allowedversions (names or regex pattern), cachetype (memory|fs), cachedir, stalewarningduration (default 1h), entitlement, access.read / access.write.
${env:VAR} interpolation keeps git tokens out of the file. Global keys: istenantproductmandatory, defaultallowrepoaccess (default false), tenantproductspath. The retired services: and remoteservices: sections are ignored, with a warning: a block’s own definitions ship in its binary, and meta serves products only.
Run flags: -f config file, -m/--mode meta|product|marketplace, -A/--apikey, -l/--log.
Config changes trigger a stop-the-world repository refresh.
meta serve: the dev server
Section titled “meta serve: the dev server”A lightweight single-command server for local product development:
meta.svc serve acme:myapp # serves ./myappmeta.svc serve acme:myapp:./somewhere # explicit pathmeta.svc serve -f .meta.yaml acme:myapp # apply the matching config entry's settingsmeta.svc serve # no args: serve the binary's embedded products- A git repo at the path is auto-detected (full branch/tag support); a plain folder is served as-is.
- Flags:
-p/--port(8080),-k/--apikey(empty = no auth),--readonly(default true),--license. - Repo access defaults open in serve mode, and a single-customer serve defaults the
X-Customerheader: zero-friction local loops.
Embedding products
Section titled “Embedding products”Ship products inside the binary for appliance-style installs:
meta.svc embed ./myproduct:<entitlement> ./docs --key <key> --output out.binmeta.svc embed-info --license <key> # inspect what's insideA folder’s .git is never embedded. Embedding and unpacking are CLI-only. There is deliberately no HTTP surface for it.
Health and readiness
Section titled “Health and readiness”/health: up with the HTTP server. Liveness never fails for repository problems (a restart cannot fix an expired token)./ready: deferred until repositories load. All product repos failing → 500 (meta can serve nothing); a partial failure → ready, with CRITICAL logs.
Caching and staleness
Section titled “Caching and staleness”cachetype | Behavior |
|---|---|
memory | Mirror in RAM; a full fetch on restart. Dev |
fs | Mirror at cachedir/<name>/; survives restarts and credential expiry: mount a persistent volume in production |
- Stale escalation relative to
stalewarningduration(default 1h): WARN at 1×, ERROR at 4×, CRITICAL at 12×. - Per-hostname concurrent fetch limit (default 3) protects the git provider.
- Git tokens embedded in URLs are watched: warnings at <7 days, <24 hours, and on expiry.
- Health escalates after 3 consecutive fetch failures on a repo.
Failure modes
Section titled “Failure modes”| Symptom | Action |
|---|---|
| Repo serving stale content, ERROR/CRITICAL staleness logs | The fetch loop is failing: usually an expired git token. Rotate the credential; the fetch loop recovers on its own. Restarting does not fix it (and with cachetype: memory a restart loses the last good mirror) |
403 on writes | Repo is readonly (the default in serve mode) |
403 “version … is not allowed” | Add the ref to allowedversions |
| 403 with valid auth | Entitlement gate or per-repo access rule |
400 “customer not found in context” | Send X-Customer (API key) or authenticate a tenant |