Walkthrough — Postgres + API server
This walkthrough deploys a real production stack: a Postgres database on Neon, an API server on Fly.io, with credentials auto-injected into the API process. End-to-end with rollback verified.
What you’ll have at the end:
https://my-app-api.fly.dev/healthreturns 200, the database URL is a real Neon connection string, andss inspectshows the deploy receipts.
What you need
Section titled “What you need”- Neon account — free tier works
- Fly.io account +
flyctlinstalled (the provisioner uses the Machines API butflyctl authis the easiest way to get a token) - A starsystem.yaml file in your project root
1. Write the config
Section titled “1. Write the config”version: "2"name: my-app
services: app-db: type: database description: Cold-layer Postgres for app data. capabilities: [relational] depends_on: []
api: type: process description: HTTP API server. depends_on: [app-db] inject_from: app-db: - DATABASE_URL # auto-injected at deploy timeversion: "2"environment: prod
services: app-db: target: type: neon region: us-east-2 credential_env: NEON_API_KEY project_name: my-app
api: target: type: fly app: my-app-api region: iad image: ghcr.io/me/my-app-api:latest credential_env: FLY_API_TOKEN port: 3000 health_check_path: /health env: NODE_ENV: productionThe inject_from block on the api service tells Starsystem: at
deploy time, look up DATABASE_URL in the vault under the app-db
namespace and pass it into the API process’s env. So Neon writes the
credential after provisioning, and Fly reads it when launching the
container — no manual copy-paste.
2. Add credentials to the vault
Section titled “2. Add credentials to the vault”$ ss vault set neon.api_token nk_...$ ss vault set fly.api_token fo1_...Or use the device-flow auth helpers:
$ ss auth fly # opens browser; pastes back automatically$ ss auth neon # paste-token flowThe vault is AGE-encrypted at ~/.starsystem/vault/. Never committed.
3. Validate
Section titled “3. Validate”$ ss validate --env=prod✓ starsystem.yaml (2 services)✓ starsystem.prod.yaml (2 services)Configuration is valid.4. Plan
Section titled “4. Plan”$ ss plan --env=prod + app-db neon · will create (Neon project + branch + role + db) + api fly · will create (Fly app + machine, region=iad)
Plan: 2 to create, 0 to update, 0 unchanged.5. Deploy
Section titled “5. Deploy”$ ss deploy --env=prod→ app-db via neon... ✓ Project created: my-app-quiet-mountain-1234 ✓ DATABASE_URL written to vault
→ api via fly... ✓ App created: my-app-api ✓ Machine launched in iad ✓ Health check passing at https://my-app-api.fly.dev/health
✓ Deploy complete: 2 provisionedProvisioner order respects depends_on — Neon completes before Fly
starts, so inject_from resolution works.
6. Inspect
Section titled “6. Inspect”$ ss inspect --env=prodss inspect ed060a44-5f97-461c-8ff6-3d8cae953092
status: ✓ completed duration: 87.3s started: 2026-05-02 14:32:01 UTC ended: 2026-05-02 14:33:28 UTC
── Timeline ── ✓ ss.deploy.service.app-db (12.4s) ✓ ss.deploy.service.api (74.9s)
── Next actions ── Check drift ss drift --env=prod Re-deploy ss deploy --env=prod List deploys ss inspect --list --env=prodPass --state for the full provision state (URLs, resource IDs,
metadata) or --json for machine-readable output.
7. Verify the deploy
Section titled “7. Verify the deploy”$ curl https://my-app-api.fly.dev/health{"status":"ok"}
$ ss inspect ed060a44 --env=prod --state | grep url url: postgresql://...neon.tech/neondb... url: https://my-app-api.fly.dev8. Roll back if needed
Section titled “8. Roll back if needed”Make a config change (bump the image tag), redeploy, then roll back:
$ vim starsystem.prod.yaml # change image to v2$ ss deploy --env=prod # rolling update; image swapped$ ss rollback --env=prod --list # see deploy history$ ss rollback --env=prod --to=ed060a44✓ Rolled back to deploy ed060a44 — credentials and overlay state restored. Re-deploy services that depend on rolled-back credentials.ss rollback does NOT auto-re-provision the infrastructure (the v2
image is still running on Fly). It restores the vault credentials and
the overlay YAML’s _state block to the historical snapshot. Run
ss deploy again to re-converge to the rolled-back config.
9. Drift detection
Section titled “9. Drift detection”Set up a nightly check:
on: { schedule: [{ cron: "0 6 * * *" }] }jobs: drift: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pnpm install - run: pnpm --filter @celestial/starsystem-cli build - run: ./packages/starsystem-cli/dist/cli.js drift --env=prod --json env: NEON_API_KEY: ${{ secrets.NEON_API_KEY }} FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}If something drifts, the workflow exits non-zero and you get a notification.
10. Telemetry
Section titled “10. Telemetry”export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io/v1/tracesexport OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=$HONEYCOMB_KEY
ss deploy --env=prodNow every deploy emits spans:
ss.cli.deploy(root)ss.deploy(engine)ss.provision.neon(per service)ss.provision.fly
Open Honeycomb, filter by service.name=starsystem, see your deploys
flowing as traces. Click any deploy span → the next-actions in the
inspect view link back into the trace.
CLI commands recap
Section titled “CLI commands recap”ss validate --env=prod # schema checkss plan --env=prod # previewss deploy --env=prod # applyss inspect [<id>] [--env=prod] # receipts viewss inspect --list [--env=prod] # deploy historyss drift --env=prod # detect out-of-band changesss rollback --env=prod --to=<id> # restore from snapshotss destroy --env=prod # tear down (with confirmation)ss ssh / exec / logs <service> # day-2 ops over SSH (VPS providers)ss graph render --services # mermaid topology diagramWhen things go wrong
Section titled “When things go wrong”- Provisioner errors → check vault credentials with
ss vault get neon.api_token - Fly health-check fails →
ss logs api --env=prod(usesfly logsunder the hood) - Plan shows “skip” → no provisioner registered for the target type; check for typos
- Drift detected, no obvious change → may be vendor-side; check the provider dashboard
See also
Section titled “See also”- Provisioner catalog
- Custom provisioners
- MCP tool reference — agentic workflows