Skip to content

fix: repair seven lifecycle and domain mode bugs - #112

Merged
arthware-dev merged 7 commits into
feat/domain-modefrom
fix/domain-mode-findings
Sep 22, 2026
Merged

arthware-dev merged 7 commits into
feat/domain-modefrom
fix/domain-mode-findings

Conversation

@arthware-dev

Copy link
Copy Markdown
Contributor

Summary

Seven independent fixes, one commit each. Merge with Rebase and merge so each lands as its own changelog line.

Commit What users get
fix(infra): show the next-step hints after stack up infra stack up infra prints its hints
fix(stack): treat https = false as plain HTTP [core] https = false no longer produces https URLs
fix(stack): remove the containers of a stacklet whose first up failed stack destroy cleans up after a failed first stack up
fix(stack): show why compose failed when a stacklet cannot start errors name the cause, e.g. a port already in use
fix(messages): point Element and phones at the current homeserver URL Element keeps working after a move to domain mode or HTTPS
fix(stack): rebuild locally built images on current base images built images (Caddy, bots, wiki) get base image updates; offline still starts
fix(code): make SSH clone URLs work in domain mode ssh://git@code.<domain>:222/… clones work from the LAN

Stacked on #111; retarget to main once that merges.

The hints were written below `[ports]`, so TOML read them as a port
named `hints`. `stack up infra` never showed them, and the runtime
built a `{infra_hints_url}` template variable from the list.

They are now a top-level key. A new test checks that every `[ports]`
entry in a shipped manifest is a port number.
`[core] https` reached the URL scheme as the string "False", which
is truthy, so `https = false` made every domain-mode URL https just
like `https = true`.

The value is now compared with "true". Nothing else reads a boolean
from stack.toml this way.
When a first `stack up` failed after compose had started containers,
on a port conflict for instance, the stacklet had no setup-done marker.
`stack destroy` then treated it as never set up and only deleted its
data. The containers kept their names and ports, and the next
`stack up` ran into them.

A stacklet that is not installed but has containers now goes through
the full destroy: confirmation, `docker compose down`, and the usual
cleanup. Without containers, destroy still just deletes leftover data.
`stack up` printed "Failed to start services" and dropped compose's
output, which holds the reason, such as a port another container
already uses. The admin had to rerun compose by hand to find out.

Errors now show the last lines of the tool's output below the message.
This covers `stack up`, `stack down` and `stack destroy`, which all
carry compose's output in the same field.
Element's homeserver URL was written into `element-config.json` once,
at install. A move to domain mode, or HTTPS turned on later, left
Element calling the old address. Served over https, the browser blocks
calls to an http homeserver as mixed content, so nobody could log in.
The `stack up messages` hint for phones named the port-mode address in
every mode.

`stack up messages` now sets Element's `base_url` to the Synapse URL
the stack renders, leaving the rest of the file as it is, and the phone
hint shows the same URL.
Stacklets with `build = true` (agent, core, infra, memory) were built
without `--pull`, so the build cache kept the base image first pulled
for good. Watchtower does not update locally built images, so security
fixes in those bases, and newer Caddy releases for infra, never
arrived.

`stack up` now builds with `--pull`. An unchanged base costs a
registry lookup and the cached layers are reused; a newer one triggers
a rebuild. When the pull fails, offline for instance, the build runs
again from the cache so the stacklet still starts.
In domain mode Forgejo's SSH port was published on the Mac's loopback
only, like every service behind the proxy, and the clone URLs Forgejo
and `stack up code` showed named the LAN IP instead of the web host.
Neither worked from another machine.

- SSH is published on every interface in both modes. It does not go
  through Caddy, and it is encrypted and authenticated by itself.
- The clone URLs name the host of the web UI: `code.<domain>` in
  domain mode, the Mac's address in port mode. A new template variable,
  `{url_host}`, is the host of a stacklet's `{url}`.
@arthware-dev
arthware-dev merged commit 52be360 into feat/domain-mode Sep 22, 2026
1 check passed
@arthware-dev
arthware-dev deleted the fix/domain-mode-findings branch October 7, 2026 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant