ReviewOS

stacks/ts-cloud

Server consolidation has no path: move an app between servers, attach an app as a site, rename a server

#167
Closed glennmichael123 opened this 24 days ago · 0 comments
24 days ago

Summary

There is no supported path for consolidating servers. Moving a deployed app from one server to another, hosting a second app on an existing server, and renaming a server are all manual today — which makes a routine "three boxes should be one box" cleanup an afternoon of SSH rather than a planned, reviewable operation.

The case that surfaced it

Three Hetzner servers, one app each:

serverappnote
statushqStatusHQlargest box of the three
bughqBugHQ
loghqLogHQ

The intended end state:

  1. bughq and loghq move onto the statushq box, attached as sites
  2. that server is renamed to something like hq-production-server
  3. the two now-empty servers are deleted
  4. StatusHQ then monitors all three sites plus the host

Every step of that is a supported concept in ts-cloud's model except the transitions between them. You can stand up a server with an app on it; you cannot move an app to a different server, add an app to a server that already has one, or rename a server without recreating it.

What's missing

Three operations, in rough dependency order:

1. Attach an additional app to an existing server as a site. The current model is effectively one app per server. Consolidation is impossible without this: it needs per-site isolation (user, directory, service unit, log stream), its own TLS certificate and vhost, and its own env/secret scope on a shared host.

2. Move a deployed app between servers. Code, environment and secrets, persistent data, TLS, scheduled jobs and queue workers, then a DNS cutover — with the source left intact until the target is verified, so the operation is reversible up to the cutover point.

3. Rename a server in place. Purely an identity change (inventory record, hostname, DNS, provider label) that today implies destroy-and-recreate, which is not an acceptable cost for a naming-convention fix.

Requirements

To fit the control-plane principles in #132:

  • Plan first. --dry-run prints the operation graph — what moves, what is created, what is deleted, what DNS changes — before anything is touched.
  • Idempotent and resumable. A migration that dies halfway (network, token expiry, a full disk on the target) can be re-run and continues rather than starting over or double-applying.
  • Typed confirmation for the destructive half. Deleting the drained source server is the one irreversible step and should be gated accordingly, separately from the move itself.
  • Non-interactive. The whole sequence must be drivable from CI with flags and env vars only — this is the "fully automatable" requirement, not a nicety.
  • Audited. Each step appends to the operation log with secrets redacted, so a migration can be reviewed after the fact.
  • No hidden state. After the move, the config in the repo describes the new topology; the dashboard shows drift rather than silently reconciling.

Acceptance criteria

  • An app can be attached to a server that already hosts another app, with isolated TLS, env, service unit and logs
  • An app can be moved from server A to server B, including data and scheduled work, without a manual SSH step
  • DNS cutover is part of the operation (Porkbun in this case) and is reversible until the source server is deleted
  • A server can be renamed without being recreated
  • The full sequence runs unattended from CI and is safe to re-run after a failure
  • --dry-run shows the complete plan, including deletions

Out of scope

Monitoring the resulting three sites and the host is StatusHQ's side of this and will be tracked separately. Provider credentials referenced here are HCLOUD_TOKEN for Hetzner and the Porkbun API keys for DNS — named only so the operation's inputs are clear.

  • #132 — production-grade application delivery and cloud control plane
  • #134 — Phase 2, git-native application delivery
  • CLI surface for this in stacksjs/stacks (linked below once filed)

Sign in to comment on this issue.