Summary
A project attaching to another project's box can declare managedServices the host does not run. ts-cloud attempts the work anyway and reports a failure with no remote output, so the operator cannot tell what went wrong.
What happened
config/cloud.ts:
cloud: { provider: 'hetzner', attachTo: 'uptime-status' },
infrastructure: { compute: { managedServices: { postgres: true }, database: { engine: 'postgres', ... } } }The deploy attached correctly, shipped both release tarballs, then:
ℹ Ensuring database 'loghq' + role exist on the shared box...
✗ Ensuring database 'loghq' failed: One or more SSH deploy commands failedThat is the entire error. No stderr from the SSH command, no indication of which command failed or why.
The actual cause, found by hand over SSH:
$ ps aux | grep postgres -> nothing
$ command -v psql -> not found
$ ss -ltn | grep 5432 -> nothing
$ docker ps -> docker not installed
$ grep DB_CONNECTION /var/www/<owner-site>/shared/.env
DB_CONNECTION="sqlite"The host runs SQLite. There is no Postgres to create a role and database in, and there never would be: attach mode skips provisioning by design, so nothing installs the managed service the tenant asked for. The two settings are structurally incompatible and nothing says so.
Two asks
1. Preflight the host during attach planning. ts-cloud resolves the target box before doing any work. At that point it can check whether the services in managedServices actually exist there, and fail with something like:
This project declares managedServices.postgres, but 'uptime-status' has no
postgres on <host>. Attach mode does not provision services on the owner's box.
Use an external database, or ask the owner to install it.That single sentence would have saved an afternoon.
2. Surface the remote stderr. One or more SSH deploy commands failed discards the one thing that explains the failure. Even under --verbose there was nothing. The commands are known, the output is available; print it, or at least the first failing command and its stderr.
This is the same shape as stacksjs/stacks#2344, where a swallowed HTTP status made an auth failure look like a missing server. That one was fixed by returning a typed failure with the status and body, and the same treatment fits here.
Environment
@stacksjs/ts-cloud0.9.4,@stacksjs/buddy0.72.34- Hetzner,
cloud.attachToto a box owned by another project