ssmod field reference
A *.ssmod.yaml file declares one module — a unit of services
that ss composes into a workspace. This page is the field-by-field
reference for the module schema. For the broader composition model
(modules → workspace → environment) see the
Workspaces walkthrough.
Top-level fields
Section titled “Top-level fields”# yaml-language-server: $schema=https://schema.celestialintelligence.co/ssmod-v1.json
module: dashboard-server # required — module idlabel: "Dashboard Server" # optional — human labeldescription: "Hosted dashboard runtime." # optional — one-line summarycolor: "#8b5cf6" # optional — used by topology renderers
requires: # other modules that must compose first - starsystem - scribe
paths: # repo-relative source roots (optional) - packages/dashboard-server
services: # named map of service blocks (see below) web: target: { ... } _artifact: { ... } _systemd: { ... }
vault: # vault keys this module reads required: - WORKOS_API_KEY - DASHBOARD_SESSION_SECRET
pipelines: [] # optional Starflow pipelines| Field | Required | Notes |
|---|---|---|
module | yes | The module id. Used as the prefix when services are referenced as <module>.<service> (e.g. dashboard-server.web). |
label, description, color | no | Display-only metadata. The color shows up in topology views. |
requires | no | Compose ordering. ss errors at compose time if a required module isn’t present. |
paths | no | Source roots for IDE tooling. Doesn’t affect deploy. |
services | usually | The substantive surface — see below. |
vault.required | no | Documents which secrets the module reads from the workspace+env app-secret namespace. Used by ss workspace doctor (the vault-required check) and the --fix flag (auto-promotes provider keys when names match). |
pipelines | no | Starflow pipeline declarations. |
services.<id> block
Section titled “services.<id> block”Each service has a target (where it runs) and provisioning helpers
(_artifact, _systemd) depending on the target type.
services: web: target: type: external # see "Target types" below host: 5.161.83.131 remote_user: root
_host_requires: # platform pre-flight; ss verifies these on the host node: "22" packages: [curl]
_artifact: # build + ship a tarball (target: external or local-process) workspace_packages: ["@celestial/dashboard-server"] transitive: true build_script: "build:with-dashboard" staging_files: - { from: packages/dashboard/dist, to: dashboard-dist } cmd: "/usr/bin/node ./node_modules/@celestial/dashboard-server/dist/server.js" deploy_to: /opt/dashboard-server keep_revs: 5
_systemd: # systemd unit (target: external) description: "celestial hosted dashboard" restart: on-failure restart_sec: 10 env: PORT: "8788" env_from_vault: - WORKOS_API_KEY - DASHBOARD_SESSION_SECRETTarget types
Section titled “Target types”type: | Used for | Required adjuncts |
|---|---|---|
external | A VPS / bare-metal host you SSH into | host, remote_user; usually _artifact + _systemd |
local-process | A process running on the operator’s local machine | usually _local (cmd, args, port) |
cloudflare-pages | Static site on CF Pages | project, production_branch, custom_domains? |
web-frontend | NEW — composite hosting target (DNS + reverse-proxy + TLS + systemd) | see web-frontend |
asset-hosting | Multi-tenant CDN bucket (Cloudflare R2 today) | bucketName?, publicDomain? |
auth-tenant | WorkOS organization | name, domains? |
dns | Domain + records via Porkbun / CF | provision: { provider, domain, records } |
database, app, web, tls, storage, email, queue, observability | provider-specific job types | see ss catalog |
_artifact block (full reference)
Section titled “_artifact block (full reference)”Used when target.type is external or local-process. ss builds a
tarball from declared workspace packages, ships it, vendors deps,
restarts the systemd unit.
_artifact: workspace_packages: ["@celestial/dashboard-server"] transitive: true # auto-vendor transitive workspace deps build_script: "build:with-dashboard" # npm script to run for each seed (default "build") staging_files: # extra files to drop into the bundle root - { from: packages/dashboard/dist, to: dashboard-dist } runtime_files: # files copied with their repo-relative path - migrations/ cmd: "/usr/bin/node ./node_modules/@celestial/X/dist/server.js" deploy_to: /opt/X # remote install root keep_revs: 5 # how many past releases to keep on the hostworkspace_packages (required)
Section titled “workspace_packages (required)”The list of @celestial/* workspace packages whose dist/ is shipped
inside node_modules/@celestial/<name> in the bundle. The first entry
is treated as the “seed” — build_script applies to it (and only it
when transitive: true walks the graph for the rest).
transitive: true (optional, default false) — K2
Section titled “transitive: true (optional, default false) — K2”When true, ss walks each seed’s package.json dependencies, finds
every @celestial/* or workspace:* or file:* reference, and
auto-vendors them all (with cycle safety). Stops the “I added a
workspace dep, prod bundle ERR_MODULE_NOT_FOUND at runtime” footgun.
Without transitive: true, the operator must list every transitive
workspace dep explicitly. With it, just list the direct seeds:
# Before (manual transitive list):workspace_packages: - "@celestial/dashboard-server" - "@celestial/shared" # required transitively - "@celestial/agent-host-ports" # required by shared - "@celestial/potus" # required by shared
# After:workspace_packages: ["@celestial/dashboard-server"]transitive: trueNon-workspace deps (hono ^4.0.0, @aws-sdk/client-s3 ^3) are
unaffected — they go through npm install as normal external deps.
build_script (optional, default "build") — new
Section titled “build_script (optional, default "build") — new”The npm run <build_script> invoked for each seed package during the
artifact build. Defaults to "build". Use a non-default script when
the package needs extra build steps beyond tsc — bundling a sibling
SPA, generating typings, running a code-gen pass.
build_script: "build:with-dashboard"The script must exist in the seed package’s package.json. When
transitive: true, the override applies only to the seed;
transitively-vendored packages still run npm run build (so each
workspace dep’s plain build script must produce a working dist/).
staging_files (optional) — new
Section titled “staging_files (optional) — new”A list of { from, to } pairs copied into the staged tarball at the
bundle root (not into the vendored node_modules/). Use this to
land assets next to the runtime CWD — typically a built SPA the server
needs to serve from disk.
staging_files: - from: packages/dashboard/dist # repo-relative source to: dashboard-dist # bundle-root-relative destinationThe to path is anchored under the bundle root. Escapes (../) are
rejected at build time.
runtime_files (optional)
Section titled “runtime_files (optional)”Copies files from the repo into the bundle preserving their repo-relative path. Use for migrations, configs, lookup tables that the runtime expects to read.
runtime_files: - migrations/ - config/email-templates.yamlWhere staging_files is “land this at <bundle-root>/X”,
runtime_files is “land this at <bundle-root>/<repo-relative-path>”.
cmd, deploy_to, keep_revs
Section titled “cmd, deploy_to, keep_revs”cmd— the systemd ExecStart command, run insidedeploy_to. The classic shape is/usr/bin/node ./node_modules/@celestial/<id>/dist/server.js.deploy_to— the install root on the host. ss creates<deploy_to>/<commit>/for each release and symlinkscurrentto the active one.keep_revs— how many old releases to retain on disk for rollback. Default 5.
Target type: web-frontend (K3)
Section titled “Target type: web-frontend (K3)”A single ssmod stanza that owns **DNS + reverse-proxy + TLS + systemd
- health check + instance-row** — the composite of everything a hosted web app needs. Two runtime variants.
runtime: node (Caddy-on-VPS)
Section titled “runtime: node (Caddy-on-VPS)”services: dashboard: target: type: web-frontend provider: caddy-on-vps runtime: node domain: dashboard.example.com port: 8788 tls: caddy # | cloudflare | none health: /health logPathOwner: caddy # chowned at deploy time _artifact: { ... } # existing artifact pipeline _systemd: { ... }ss provisions:
- DNS A/CNAME record (via the host’s owning DNS provider — CF, Porkbun)
- A marker-fenced Caddy block in
/etc/caddy/Caddyfile(idempotent byte-exact replace — siblings preserved) - The log file pre-created with
logPathOwnerownership - Health check polled post-reload (expects 2xx within 30s)
- An instance row in
celestial_service_state(Phase J1)
runtime: static (Cloudflare Pages)
Section titled “runtime: static (Cloudflare Pages)”services: lens: target: type: web-frontend provider: cloudflare-pages runtime: static domain: lens.example.com tls: cloudflare projectName: example-lens buildOutputDir: packages/lens/distss provisions:
- A CF Pages project (find-or-create)
- DNS CNAME to the project’s
.pages.devsubdomain - Upload of
buildOutputDir - Instance row
The tls knob:
caddy— Caddy handles ACME (default forruntime: node)cloudflare— CF terminates TLS (default forruntime: static)none— bare HTTP (development only)
Idempotency rule for both variants: rerunning ss apply with
identical inputs is a no-op. State is reconciled, not recomputed.
_systemd block
Section titled “_systemd block”Maps to a systemd unit. Lands at /etc/systemd/system/<service>.service.
_systemd: description: "celestial hosted dashboard" restart: on-failure # | always | no restart_sec: 10 wants: [postgresql.service] env: # plain env vars PORT: "8788" LOG_LEVEL: info env_from_vault: # resolved from workspace+env app-secrets - WORKOS_API_KEY - DASHBOARD_SESSION_SECRETVault keys listed in env_from_vault need to exist as app-secrets
in the workspace+env namespace. Use ss vault promote to lift them
from a provider-key (e.g. workos.api_key → WORKOS_API_KEY); see
the vault promote section.
_host_requires
Section titled “_host_requires”Pre-flight checks ss runs on the deploy target before doing anything mutating.
_host_requires: node: "22" # major-version match packages: [curl, jq, git] # apt-style namesMissing requirements abort the deploy with a clear “install X first” error.
Validating your ssmod
Section titled “Validating your ssmod”# Pre-flight diagnostics — checks transitive deps, vault gaps, ts package# layout, ESM import-suffix compliance, stale shim, and more. Run before# every deploy.ss workspace doctor --workspace-file=<your.ssws.yaml>
# JSON for agents:ss workspace doctor --workspace-file=<your.ssws.yaml> --json
# Auto-apply mechanical fixes (vault promotions, etc.):ss workspace doctor --workspace-file=<your.ssws.yaml> --fixSee also
Section titled “See also”- BYO-agent runbook — how to drive the above with a 50-line script
- ADR-011 — artifact-based service deploys (the
_artifactdesign) - ADR-027 — jobs over resources (the
target.typemodel) - ADR-028 — topology projection (how composed ssmods land in Supabase)