From 958c8afeede45901212e831c4d7defdc2a35d351 Mon Sep 17 00:00:00 2001 From: dirtydishes Date: Fri, 15 May 2026 21:13:02 -0400 Subject: [PATCH] Clarify Docker-first deploy workflow --- .beads/issues.jsonl | 1 + README.md | 8 +- deployment/docker/README.md | 6 +- deployment/native/README.md | 25 ++- ...-clarify-docker-first-deploy-workflow.html | 146 ++++++++++++++++++ scripts/deploy.ts | 44 +++++- 6 files changed, 213 insertions(+), 17 deletions(-) create mode 100644 docs/turns/2026-05-15-clarify-docker-first-deploy-workflow.html diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 32f80d5..2edb51c 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -10,6 +10,7 @@ {"_type":"issue","id":"islandflow-ayo","title":"Drop stale backlog events from live fanout","description":"Follow-up to live freshness rollout: /ws/live was still fanning out stale backlog events for freshness-gated channels, which kept tape panes in Live feed behind despite active synthetic ingest. Gate fanout and cache ingest by freshness for options/nbbo/equities/flow.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T21:26:39Z","created_by":"dirtydishes","updated_at":"2026-04-28T21:26:44Z","started_at":"2026-04-28T21:26:44Z","closed_at":"2026-04-28T21:26:44Z","close_reason":"Completed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-0v6","title":"Fix tape freshness, NBBO coverage, pause controls, and filter popup","description":"Implement the tape fixes requested for synthetic options notional sizing, strict live freshness, live-mode pause/resume behavior, stronger NBBO snapshot coverage, and moving flow filters behind a popup. Includes server-side live cache changes, web terminal state/UI changes, and tests for synthetic pricing, live snapshot freshness/NBBO retention, and live pause/filter interactions.","status":"closed","priority":1,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T21:02:52Z","created_by":"dirtydishes","updated_at":"2026-04-28T21:13:38Z","started_at":"2026-04-28T21:02:57Z","closed_at":"2026-04-28T21:13:38Z","close_reason":"Completed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-e4r","title":"Implement smart-money flow filtering and synthetic firehose modes","description":"Implement the approved multi-surface plan for named synthetic market profiles, options raw-vs-signal filtering, live/API filter contracts, Tape page client-side flow filters, firehose-readiness improvements, tests, and README updates.","status":"closed","priority":1,"issue_type":"feature","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-04-28T20:10:49Z","created_by":"dirtydishes","updated_at":"2026-04-28T20:29:29Z","started_at":"2026-04-28T20:10:53Z","closed_at":"2026-04-28T20:29:29Z","close_reason":"Implemented synthetic market profiles, options signal-path filtering, signal-aware API/replay contracts, Tape page filters, tests, and README updates. Follow-up tracked in islandflow-biq.","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"islandflow-4gj","title":"Clarify Docker-first deploy workflow and mark native runtime experimental","description":"After inspecting the live VPS, native deployment is not ready for routine use: Nginx Proxy Manager routes to Docker container names, Bun is not installed on the host, sudo systemctl is not passwordless, and no Islandflow units exist. Update deploy messaging and docs so Docker remains the clearly recommended deployment path and native runtime is labeled experimental/future-facing with server prerequisites called out.","notes":"Updated deploy messaging and docs after live VPS inspection. scripts/deploy.ts now marks Docker as the default and recommended runtime, labels native as experimental, switches native systemctl default to sudo -n systemctl, and prints explicit native precheck failures for missing Bun/systemctl access/units. Updated README.md, deployment/docker/README.md, and deployment/native/README.md to reflect the current Docker + Nginx Proxy Manager topology. Validation: ./deploy --help, ./deploy main --runtime native --no-build (fails fast with Bun-missing message), bun run check:docker-workspace.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-16T01:10:11Z","created_by":"dirtydishes","updated_at":"2026-05-16T01:12:39Z","started_at":"2026-05-16T01:10:14Z","closed_at":"2026-05-16T01:12:39Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-7p2","title":"Fix deploy wrapper argument forwarding for runtime flags","description":"The repo-root deploy wrapper currently invokes bun run without a -- separator, so flags like --runtime native are treated as Bun CLI flags instead of script arguments. Update the wrapper so ./deploy main --runtime native forwards arguments correctly to scripts/deploy.ts.","notes":"Cherry-picked the dual-runtime deploy workflow onto main and fixed the repo-root deploy wrapper to call Bun with a -- separator so flags like --runtime native are forwarded to scripts/deploy.ts correctly. Validation: ./deploy --help, ./deploy main --runtime native --force-recreate guard, bun run check:docker-workspace.","status":"closed","priority":2,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-16T00:51:05Z","created_by":"dirtydishes","updated_at":"2026-05-16T00:52:34Z","started_at":"2026-05-16T00:51:10Z","closed_at":"2026-05-16T00:52:34Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-qh7","title":"Implement dual-runtime deploy workflow with partial deploys","description":"Implement the planned refactor of the root deploy script and scripts/deploy.ts so deployment can target Docker and host-native runtimes during a transition period. Preserve local dev as Docker infra plus native Bun services/web, add explicit runtime selection, runtime-specific prechecks/rollout/verification, and support partial deploy scopes such as web-only or services-only. Update operator documentation for the new workflow.","notes":"Implemented dual-runtime deploy workflow. scripts/deploy.ts now supports --runtime docker|native, scope flags (--web-only, --api-only, --services-only), and --no-build. Docker verification now uses docker compose exec instead of hardcoded container names. Added deployment/native/README.md and updated README.md plus deployment/docker/README.md for the new workflow. Validation: bun run scripts/deploy.ts --help, bun run check:docker-workspace, guard checks for invalid flag combinations.","status":"closed","priority":2,"issue_type":"feature","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-15T23:38:31Z","created_by":"dirtydishes","updated_at":"2026-05-15T23:46:17Z","started_at":"2026-05-15T23:40:13Z","closed_at":"2026-05-15T23:46:17Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"islandflow-iiy","title":"Plan deploy workflow changes for Docker/native transition","description":"User requested a repo-specific plan for updating the root deploy script and deployment workflow to support Docker/native transition paths, faster local iteration, and partial deploy modes. This task covers confirming the target workflow, documenting current assumptions, and producing an implementation-ready plan without changing implementation files.","notes":"Confirmed transition strategy: local dev stays Docker-infra-only plus native Bun services/web; VPS deploy path should support both Docker and host-native runtimes during transition; partial deploys are desired; current main/current-branch modes may evolve. Produced an implementation-ready plan covering current assumptions, runtime split, CLI shape, prechecks, rollout, verification, rollback, docs, and validation scenarios. Follow-up implementation tracked in islandflow-qh7.","status":"closed","priority":2,"issue_type":"task","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-15T23:37:28Z","created_by":"dirtydishes","updated_at":"2026-05-15T23:38:41Z","started_at":"2026-05-15T23:37:30Z","closed_at":"2026-05-15T23:38:41Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} diff --git a/README.md b/README.md index 3542353..f6d0085 100644 --- a/README.md +++ b/README.md @@ -126,12 +126,12 @@ This keeps Docker in the local workflow where it helps most (NATS, ClickHouse, R ## Deployment Workflow -- `./deploy main` keeps the current VPS Docker rollout path as the default. -- `./deploy main --runtime native` targets a host-native Bun + systemd deployment. -- `./deploy current-branch` and `./deploy current-branch --runtime native` keep branch deploys available during the transition. +- `./deploy main` keeps the current VPS Docker rollout path as the default and recommended path. +- `./deploy main --runtime native` targets an experimental host-native Bun + systemd deployment. +- `./deploy current-branch` and `./deploy current-branch --runtime native` keep branch deploys available during the transition, but Docker remains the supported path for the current VPS. - Partial deploys are supported with `--web-only`, `--api-only`, `--services-only`, and `--no-build`. - Docker runtime details live in `deployment/docker/README.md`. -- Native runtime expectations live in `deployment/native/README.md`. +- Native runtime expectations and prerequisites live in `deployment/native/README.md`. ## Desktop Shell diff --git a/deployment/docker/README.md b/deployment/docker/README.md index 426a006..a6cc1d5 100644 --- a/deployment/docker/README.md +++ b/deployment/docker/README.md @@ -2,10 +2,10 @@ This directory contains the Docker runtime for Islandflow VPS deployments. -Docker remains the default server rollout path, but the repo-root `deploy` helper can now target either: +Docker remains the default and recommended server rollout path, but the repo-root `deploy` helper can now target either: - `--runtime docker` for this Docker Compose stack -- `--runtime native` for a host-native Bun + systemd rollout described in `deployment/native/README.md` +- `--runtime native` for an experimental host-native Bun + systemd rollout described in `deployment/native/README.md` The repo no longer ships or supports a separate `deployment/npm` stack. If you want a reverse proxy, point it at the host ports published by this stack. @@ -190,6 +190,8 @@ docker compose build web ## Safe rollouts on `152.53.80.229` +The current live VPS uses Nginx Proxy Manager on the shared Docker network and routes public traffic to the Docker `web` and `api` containers by container name. Because of that, this Docker path remains the operationally correct default for the live server today. + The checked-in deploy helper is meant to run from your local repo checkout, not from the VPS shell. It always targets: - SSH host: `delta@152.53.80.229` diff --git a/deployment/native/README.md b/deployment/native/README.md index fed5b74..03c5bf7 100644 --- a/deployment/native/README.md +++ b/deployment/native/README.md @@ -1,13 +1,13 @@ # Native Deployment -This directory documents the host-native Islandflow rollout path used by: +This directory documents the experimental host-native Islandflow rollout path used by: ```bash ./deploy main --runtime native ./deploy current-branch --runtime native ``` -This runtime is intended for faster server iteration during the transition away from Docker-only app rollouts. Local development should still prefer: +This runtime is intended for faster server iteration during the transition away from Docker-only app rollouts. It is not the recommended path for the current production VPS, which still uses Nginx Proxy Manager to reach the Docker `web` and `api` containers by container name on the shared Docker network. Local development should still prefer: - Docker for infra (`bun run dev:infra`) - native Bun services (`bun run dev:services`) @@ -57,7 +57,7 @@ Available overrides: By default the deploy helper uses: ```bash -sudo systemctl +sudo -n systemctl ``` If the server uses user units or another wrapper, override it locally before invoking `./deploy`: @@ -86,6 +86,23 @@ Scope behavior: - `--services-only`: restart API + backend units without touching the web unit - `--no-build`: skip `bun install --frozen-lockfile` and skip the web build step +## Current status + +On the current live VPS, native deploys should be treated as opt-in infrastructure work, not the default rollout path. Before a native deploy can succeed there, all of the following must be true at the same time: + +- Bun is installed on the host. +- The selected `systemctl` command works non-interactively. +- Islandflow systemd units exist for the requested scope. +- Host-native services can reach the intended NATS, ClickHouse, and Redis endpoints. +- If `web` or `api` move native, the reverse proxy topology is updated deliberately. + +Until that is prepared intentionally, prefer: + +```bash +./deploy main --runtime docker +./deploy current-branch --runtime docker +``` + ## Server preparation checklist Before the first native rollout, ensure the VPS has: @@ -115,7 +132,7 @@ Rollback remains manual for now: 2. rerun the appropriate native deploy command 3. if needed, restart only the affected units with `systemctl` -Docker remains available as the fallback runtime during the transition: +Docker remains the fallback and currently recommended runtime during the transition: ```bash ./deploy main --runtime docker diff --git a/docs/turns/2026-05-15-clarify-docker-first-deploy-workflow.html b/docs/turns/2026-05-15-clarify-docker-first-deploy-workflow.html new file mode 100644 index 0000000..7f40e58 --- /dev/null +++ b/docs/turns/2026-05-15-clarify-docker-first-deploy-workflow.html @@ -0,0 +1,146 @@ + + + + + + 2026-05-15: Clarify Docker-first deploy workflow + + + +
+
+ Turn document + 2026-05-15 + Issue: islandflow-4gj +
+

Clarify Docker-first deploy workflow

+

+ Updated deploy messaging and deployment docs so Docker is clearly the supported VPS path today, while the native runtime is labeled experimental and fails faster with clearer prerequisites. +

+ +
+

Summary

+

+ The deploy helper now warns when --runtime native is used, defaults native systemctl invocations to sudo -n systemctl so they fail fast instead of hanging for a password, and prints explicit precheck errors when Bun or systemd readiness is missing. Docs now describe Docker as the default and recommended VPS rollout path. +

+
+ +
+

Changes Made

+
    +
  • Updated scripts/deploy.ts help text to mark Docker as default and recommended, and native as experimental.
  • +
  • Changed the native systemctl default from sudo systemctl to sudo -n systemctl to avoid interactive hangs.
  • +
  • Added a runtime advisory banner for native deploy attempts.
  • +
  • Improved native remote precheck failures for missing Bun, missing systemctl access, and missing systemd units.
  • +
  • Updated README.md, deployment/docker/README.md, and deployment/native/README.md to reflect the live VPS reality: Docker plus Nginx Proxy Manager remains the supported deployment path.
  • +
+
+ +
+

Context

+

+ Live inspection of the VPS showed that Nginx Proxy Manager routes flow.deltaisland.io and API traffic to the Docker web and api containers by container name on the shared Docker network. The host does not currently have Bun installed, passwordless sudo systemctl is not configured, and no Islandflow systemd units are present. Because of that, native deployment should be treated as future infrastructure work rather than the recommended day-to-day path. +

+
+ +
+

Important Implementation Details

+
    +
  • Native rollout prechecks now fail with actionable messages instead of a silent command failure or a hanging sudo prompt.
  • +
  • The native docs now explicitly say the current VPS is not prepared for routine native rollouts.
  • +
  • Docker deployment behavior itself was not changed. This was a clarity and guardrail pass, not a runtime migration.
  • +
+
[deploy] Native runtime is experimental. Use --runtime docker for the current supported VPS path unless Bun, systemd units, and proxy routing have been prepared intentionally.
+
+ +
+

Validation

+
    +
  • Passed: ./deploy --help
  • +
  • Passed: bun run check:docker-workspace
  • +
  • Passed: ./deploy main --runtime native --no-build now fails quickly with an explicit Bun-missing message on the live VPS
  • +
+
./deploy --help
+./deploy main --runtime native --no-build
+bun run check:docker-workspace
+
+ +
+

Issues, Limitations, and Mitigations

+
    +
  • Native deploy remains experimental. Mitigation: docs and CLI output now say so directly.
  • +
  • The live VPS still depends on Docker-name routing through Nginx Proxy Manager. Mitigation: Docker remains the recommended deployment path.
  • +
  • No systemd units or Bun install were added in this change. That work remains a separate follow-up.
  • +
+
+ +
+

Follow-up Work

+
    +
  • Keep native deployment support available for future experimentation, but treat it as opt-in infrastructure work.
  • +
  • Open follow-up: islandflow-38p, add native deployment unit templates and rollback helpers if the host-native path is revived later.
  • +
+
+
+ + diff --git a/scripts/deploy.ts b/scripts/deploy.ts index f56598d..183f833 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -38,7 +38,7 @@ const PUBLIC_APP_URL = const PUBLIC_API_HEALTH_URL = process.env.DEPLOY_PUBLIC_API_HEALTH_URL?.trim() || null; const NATIVE_SYSTEMCTL_PREFIX = - process.env.DEPLOY_NATIVE_SYSTEMCTL_PREFIX?.trim() || "sudo systemctl"; + process.env.DEPLOY_NATIVE_SYSTEMCTL_PREFIX?.trim() || "sudo -n systemctl"; const NATIVE_UNITS = { web: process.env.DEPLOY_NATIVE_WEB_UNIT?.trim() || "islandflow-web", api: process.env.DEPLOY_NATIVE_API_UNIT?.trim() || "islandflow-api", @@ -79,8 +79,8 @@ Modes: current-branch Push the current local branch, switch the server to it, and deploy it. Runtimes: - docker Roll out from deployment/docker with Docker Compose (default). - native Roll out host-native Bun services managed by systemd. + docker Roll out from deployment/docker with Docker Compose (default, recommended). + native Experimental host-native Bun services managed by systemd. Scopes: default Full rollout (web + API + backend services). @@ -97,7 +97,7 @@ Options: Environment: DEPLOY_PUBLIC_APP_URL Override the public app URL (default: https://flow.deltaisland.io). DEPLOY_PUBLIC_API_HEALTH_URL Optional separate public API health URL for two-origin deployments. - DEPLOY_NATIVE_SYSTEMCTL_PREFIX Override systemctl invocation for native rollouts (default: sudo systemctl). + DEPLOY_NATIVE_SYSTEMCTL_PREFIX Override systemctl invocation for native rollouts (default: sudo -n systemctl). DEPLOY_NATIVE_WEB_UNIT Override native web systemd unit name. DEPLOY_NATIVE_API_UNIT Override native api systemd unit name. DEPLOY_NATIVE_COMPUTE_UNIT Override native compute systemd unit name. @@ -277,7 +277,17 @@ function shellPattern(value: string): string { } function describeRuntime(runtime: DeployRuntime): string { - return runtime === "docker" ? "Docker Compose" : "native systemd/Bun"; + return runtime === "docker" ? "Docker Compose" : "experimental native systemd/Bun"; +} + +function printRuntimeAdvisory(runtime: DeployRuntime): void { + if (runtime !== "native") { + return; + } + + console.warn( + "[deploy] Native runtime is experimental. Use --runtime docker for the current supported VPS path unless Bun, systemd units, and proxy routing have been prepared intentionally." + ); } function describeScope(scope: DeployScope): string { @@ -497,8 +507,26 @@ docker compose version >/dev/null set -euo pipefail cd ${shellEscape(REMOTE_REPO)} -command -v bun >/dev/null 2>&1 -command -v systemctl >/dev/null 2>&1 + +if ! command -v bun >/dev/null 2>&1; then + echo "Refusing native rollout: bun is not installed on the server." >&2 + echo "The current supported VPS path remains --runtime docker." >&2 + echo "See deployment/native/README.md for native prerequisites." >&2 + exit 1 +fi + +if ! command -v systemctl >/dev/null 2>&1; then + echo "Refusing native rollout: systemctl is not available on the server." >&2 + echo "See deployment/native/README.md for native prerequisites." >&2 + exit 1 +fi + +if ! ${NATIVE_SYSTEMCTL_PREFIX} --version >/dev/null 2>&1; then + echo "Refusing native rollout: cannot run ${NATIVE_SYSTEMCTL_PREFIX}." >&2 + echo "If the server uses user units, try DEPLOY_NATIVE_SYSTEMCTL_PREFIX='systemctl --user'." >&2 + echo "If the server uses system units, ensure passwordless sudo for this command or use --runtime docker." >&2 + exit 1 +fi declare -a units=(${units}) for unit in "\${units[@]}"; do @@ -506,6 +534,7 @@ for unit in "\${units[@]}"; do if [[ -z "$load_state" || "$load_state" == "not-found" ]]; then echo "Refusing native rollout: missing systemd unit $unit" >&2 echo "See deployment/native/README.md for expected unit names and overrides." >&2 + echo "Use --runtime docker for the current supported VPS path." >&2 exit 1 fi done @@ -696,6 +725,7 @@ function publicVerification(scope: DeployScope): void { function main(): void { const options = parseArgs(process.argv.slice(2)); assertSshKeyExists(); + printRuntimeAdvisory(options.runtime); console.log( `Deploying ${options.mode === "main" ? "origin/main" : "the current local branch"} ` +