Skip to content

Share installed components across self-hosted installations - #805

Merged
SaladDay merged 1 commit into
mainfrom
share-installed-components-across-self-hosted-installations
Oct 21, 2026
Merged

SaladDay merged 1 commit into
mainfrom
share-installed-components-across-self-hosted-installations

Conversation

@SaladDay

@SaladDay SaladDay commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Every self-hosted installation (one per self_hosted Session) copied node and its Harness into its own components/, about 560 MiB each: ten Sessions on the mx test machine left 5.4 GB under ~/.oac/environments (#802, remaining item 1). The archive cache added in #804 kept another 180–280 MiB of archives only to skip later downloads.

Design

All changes stay in the native installer (oac-daemon install, start, uninstall); Core is unchanged.

  • Store: <Runtime home>/components/<version>/<name>/, one verified copy per component and daemon version per machine. A component is staged in the version directory, checked against bundle.json, given its receipt, made read-only (files 0400/0500, directories 0500) and renamed into place. Read-only stops accidental changes (for example npm i -g against the bundled node); all Sessions run as the same account, so start verifies the components and refuses changed ones.
  • daemon/installation.json records component_directory; start, verification, the readiness probe and the Harness environment use it. Installations no longer own a components/ entry. No links.
  • Users: users/<sha256 of the installation directory> holds that directory. Install registers under the store lock; uninstall removes its entry and collects garbage: entries whose directory is gone are dropped, a version with no users is removed (made writable first), stale staging is cleaned. Anything unreadable counts as a user; collection never follows a link out of the store.
  • Lock: runtimefs.LockDirectory on the store, held only for registration, collection and installing missing components. A second installer waits (one line, retry every second, at most 10 minutes) only on the new typed runtimefs.ErrLocked; other lock errors fail at once.
  • Downloads: native-download/<version>/*.part stays only for Range resume; a verified archive is extracted straight into the store staging (only files listed in bundle.json) and deleted. The archive cache, its reuse and its lock are deleted.
  • Extracted distribution: a component missing from the store is copied from the bundle; one already in the store is used.
  • A damaged store component fails naming the directory to delete after stopping the installations that use it; uninstall prints whether the shared components were removed or are kept for N other installations.
  • Components are still ensured before the credential claim. A first install that fails drops only its own entry, without the store lock and without collecting, so a rerun reuses what it installed. A rerun uses the store its installation.json records.

Measurements

Real linux-amd64 archives of b50d1712, two installations in one Runtime home (du -sb of the home and both installation directories), daemon from main 77927d9f before and from this branch after:

Harnesses Before, 1 / 2 installations After, 1 / 2 installations
codex 575.0 / 1150.1 MB 575.1 / 592.0 MB
codex, claude, minimax 913.1 / 1826.2 MB 913.1 / 930.0 MB

Each further installation adds about 17 MB (its oac-daemon copy).

mx e2e

Fresh install on mx of e2e-805-806 (main + this PR + #806) from a release-shaped offline archive (950 MiB); README ~/.oac/tests/e2e-acceptance-20261020, logs logs/run-pr806/.

Harness hosted (microsandbox on mx2) self_hosted (mx)
codex 9/9 9/9
claude_sdk 9/9 9/9

Tests run

  • From apps/daemon: go test ./internal/cli/... ./internal/runtimefs; go vet ./...; go vet of ./internal/cli/... and internal/runtimefs with GOOS=darwin and GOOS=windows.
  • go test ./services/core/internal/nativeinstaller/..., node --test scripts/build-native-installer.test.mjs.
  • New tests: two installations share one read-only copy and uninstall keeps, then removes it; stale entries and unused versions are collected; lock wait and timeout; one download per component across two Sessions with no archive left; a damaged component names its directory.
  • scripts/native-onboarding-smoke.mjs locally against the real archives with a branch-built daemon (store present, no per-installation copy, no archive left, store removed at uninstall). macOS and Windows run in this PR's native jobs.
  • Not run: the website translation check (no node_modules here); the Chinese source_hash is refreshed.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@SaladDay
SaladDay force-pushed the share-installed-components-across-self-hosted-installations branch from ed8b43a to a626dec Compare October 21, 2026 05:29
@blacksmith-sh

This comment has been minimized.

@SaladDay
SaladDay force-pushed the share-installed-components-across-self-hosted-installations branch 4 times, most recently from 5e78c45 to 87bd549 Compare October 21, 2026 07:01
@SaladDay
SaladDay merged commit 90ba725 into main Oct 21, 2026
22 checks passed
@SaladDay
SaladDay deleted the share-installed-components-across-self-hosted-installations branch October 21, 2026 07:08
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