Skip to content

fix: preserve per-project config.json (ports) across both init and update#38

Open
mann1x wants to merge 2 commits into
cytostack:mainfrom
mann1x:fix/update-preserve-config-json
Open

fix: preserve per-project config.json (ports) across both init and update#38
mann1x wants to merge 2 commits into
cytostack:mainfrom
mann1x:fix/update-preserve-config-json

Conversation

@mann1x
Copy link
Copy Markdown

@mann1x mann1x commented May 8, 2026

Problem

On a host with more than one OpenWolf project registered, every project's
daemon tries to bind the same dashboard port and all but the first
crash-loop on EADDRINUSE. Root cause is that config.json — which holds the
per-project openwolf.daemon.port / openwolf.dashboard.port — was being
force-overwritten with the hardcoded template defaults (18790 / 18791) by
both CLI commands:

  1. openwolf update listed config.json in ALWAYS_OVERWRITE, so every
    update reset every registered project back to 18790/18791. (Tracked in openwolf update overwrites every project's config.json with template defaults — mass port collision #37.)
  2. openwolf init also listed config.json in its own ALWAYS_OVERWRITE,
    so any re-init/upgrade reset it too — and there was no port allocation at
    all
    , so even two fresh inits on the same host produced identical ports.

Observed in the wild: three projects on one host, all stamped 18791; after a
reboot only the first daemon bound and the other two sat errored with
thousands of restart attempts (EADDRINUSE :::18791).

Fix

config.json is user data, not a template, and is now treated as such in
both commands:

  • update.ts — move config.json out of ALWAYS_OVERWRITE into
    USER_DATA_FILES (still backed up by restore). An existing config is never
    overwritten on update.
  • init.ts — remove config.json from ALWAYS_OVERWRITE; handle it via a
    new reconcileConfig():
    • create-if-missing only — an existing config is left completely untouched, so
      a re-init never resets a user's ports;
    • on a fresh create, allocate the next free daemon/dashboard port pair by
      scanning other registered projects' config.json, so two fresh inits no
      longer collide.

No behavior change for single-project users; multi-project hosts stop
colliding. tsc --noEmit clean.

Verification

Deployed the built init.js + update.js to a live multi-project host and ran
openwolf update: all three projects' custom dashboard ports survived
(previously they were reset to 18791). Output confirms templates updated were
only OPENWOLF.md, reframe-frameworks.mdconfig.json untouched.

Closes #37 (and the init-side half of the same defect).

mann1x and others added 2 commits May 8, 2026 15:59
…ostack#37)

`update.ts` was unconditionally copying `src/templates/config.json`
over every registered project's `.wolf/config.json`. That file is
not template content — it carries each project's daemon port,
dashboard port, scan intervals, and exclude patterns. Overwriting it
across all projects in one shot resets every registered project to
the same defaults (`daemon=18790`, `dashboard=18791`), so only the
first daemon to start binds and the rest crash-loop on `EADDRINUSE`.

Move `config.json` from `ALWAYS_OVERWRITE` to `USER_DATA_FILES`. It
is still included in `BACKUP_FILES` via the spread, so `openwolf
restore` can still recover it.

Reproduced on Linux (PVE 7) and Windows 11. After local apply, ten
projects on one host kept their unique ports through a simulated
update; pre-patch, all ten fell to defaults inside one second.

No behavior change for `OPENWOLF.md` or `reframe-frameworks.md` —
those remain protocol-doc overwrites.
openwolf init listed config.json in ALWAYS_OVERWRITE, so every re-init
(and upgrade) re-stamped the file with the hardcoded default ports
(daemon 18790 / dashboard 18791). With more than one project registered,
all daemons then tried to bind the same dashboard port; only the first to
start won and the rest crash-looped on EADDRINUSE.

- Remove config.json from ALWAYS_OVERWRITE; handle it via reconcileConfig().
- reconcileConfig: create-if-missing only; an existing config is left
  untouched so re-init never resets a user's ports.
- On a fresh create, allocate the next free daemon/dashboard port pair by
  scanning other registered projects' config.json, so two fresh inits no
  longer collide.

Pairs with the update.ts change on this branch (config.json moved to
USER_DATA_FILES) so neither init nor update can reset per-project ports.
@mann1x mann1x changed the title fix(update): preserve config.json across openwolf update (fixes #37) fix: preserve per-project config.json (ports) across both init and update May 24, 2026
@mann1x
Copy link
Copy Markdown
Author

mann1x commented May 24, 2026

Pushed a second commit (d9691ea) extending this PR to the init side: openwolf init also force-overwrote config.json and had no port allocation, so multi-project hosts collided even without ever running update. The branch now fixes both commands. Updated the title/description accordingly.

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.

openwolf update overwrites every project's config.json with template defaults — mass port collision

2 participants