Skip to content

feat: non-interactive recovery and current Jellyfin/Seerr support (v1.2.2) - #8

Merged
LavX merged 4 commits into
mainfrom
fix/v1.2.2-noninteractive-recovery
Oct 19, 2026
Merged

LavX merged 4 commits into
mainfrom
fix/v1.2.2-noninteractive-recovery

Conversation

@LavX

@LavX LavX commented Oct 19, 2026

Copy link
Copy Markdown
Owner

What

Closes the remaining recovery gap from #6: a failed install can now be finished without the interactive wizard, and the Jellyfin/Jellyseerr wiring works against the current upstream images.

  • arrstack install --resume --yes: reads state.json and admin.txt and reruns the full pipeline non-interactively. Covers Jellyfin, Jellyseerr, qBittorrent, and arr wiring, not just the arr logins that update repairs. --yes requires --resume.
  • Jellyfin 12.x support: AuthenticateByName returns 400 without Authorization: MediaBrowser ... because 12.x disables legacy X-Emby-Authorization. Send both headers and skip Startup/User when a prior attempt already created the user (403).
  • Seerr 3.x support: use POST /settings/jellyfin/library/sync and PUT /settings/jellyfin/library/:id, with the legacy query API as fallback. Log in without hostname fields when the hostname is already configured.
  • Compose: drop depends_on edges to services the user deselected instead of rendering a project Docker rejects.
  • Retry: retry sockets that close mid-request (Jellyfin closes them during startup configuration).

Why

Issue #6 recovery previously required the interactive TUI, and install --resume aborted on current Jellyfin 12.2.0 and Seerr 3.3.0 images.

How it was tested

Full end-to-end run with a simulated aborted install (Sonarr, Radarr, Jellyfin, Jellyseerr, qBittorrent; no install_completed_at; unconfigured containers):

Setting up Jellyfin admin and libraries... ok (0.2s)
Linking Jellyseerr to Jellyfin... ok (0.3s)
Configuring qBittorrent categories and settings... ok (0.1s)
Seeding sonarr admin credentials... ok (0.0s)
Seeding radarr admin credentials... ok (0.0s)
Configuring Sonarr root folders and download client... ok (0.3s)
Configuring Radarr root folders and download client... ok (0.6s)
Linking Jellyseerr to Sonarr and Radarr... ok (0.4s)
Write state... ok (0.0s)

Install complete.

Afterward:

  • Sonarr/Radarr POST /login: 302 to /
  • qBittorrent POST /auth/login: 204
  • Jellyfin AuthenticateByName: 200
  • Jellyseerr settings/public.initialized: true
  • arrstack doctor: all checks passed, exit 0

Unit suite: 341 pass. Typecheck clean.

Checklist

  • bun test passes
  • tsc --noEmit passes
  • No em dashes added
  • No AI attribution
  • No TUI change
  • Docs updated
  • New code has tests

LavX added 4 commits October 19, 2026 11:06
arrstack install --resume --yes reads state.json and admin.txt and reruns
the full install pipeline without the wizard. This makes recovery from an
aborted install scriptable and covers every wiring step, including
Jellyfin and Jellyseerr, not just the arr logins that update repairs.
Jellyfin 12.x disables legacy X-Emby-Authorization by default and rejects
AuthenticateByName without the standard Authorization header (400,
request.App null). Send both headers, and skip Startup/User when an
earlier attempt already created the first user (Jellyfin answers 403).

Seerr 3.x replaced the library sync and bulk-enable query parameters with
POST /library/sync and PUT /library/:id. Use the new endpoints with a
legacy fallback, and log in without hostname fields when the server is
already configured (500 "hostname already configured").
Retry requests whose socket closes mid-flight (Jellyfin startup does
this during configuration). Drop depends_on edges to services the user
deselected instead of rendering a compose project Docker rejects with
"depends on undefined service".
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T09:10:30.257395Z 9985b53 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@LavX
LavX merged commit 3cc8222 into main Oct 19, 2026
2 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9985b539fd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/wiring/jellyfin.ts
// A previous attempt may have created the first user before failing later
// (or the user answered part of the startup wizard). POSTing /Startup/User
// again returns 403, so only create the user when none exists.
if (!startupUser?.Name) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not treat the startup user's name as configured

On every fresh Jellyfin installation, GET /Startup/User initializes and returns the placeholder first user with a nonempty Name; it does not indicate that the user has already been configured. Consequently this condition skips the required POST /Startup/User, leaves the placeholder credentials unchanged, and the subsequent authentication with the requested admin username/password fails, aborting the default install. Detect prior configuration by authenticating or attempting the update and handling the specific already-configured response instead.

Useful? React with 👍 / 👎.

Comment thread src/cli.ts
Comment on lines +73 to +76
if (opts.yes) {
if (!opts.resume) {
console.error("\n--yes requires --resume. Use 'arrstack install --resume --yes' to finish an existing install.\n");
process.exit(1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate --yes before purging a fresh install

When an existing user runs arrstack install --fresh --yes without --resume, the --fresh block has already stopped the stack and deleted state.json, admin.txt, .env, and the entire service config/ tree before this newly added validation exits with an error. Since --yes is rejected in this combination, validate it before performing any --fresh side effects (and likewise reject --fresh --resume --yes before purging) to avoid destructive data loss from an invalid invocation.

Useful? React with 👍 / 👎.

Comment thread src/renderer/compose.ts
Comment on lines +329 to +331
const dependsOn: DependsOnEntry[] = svc.dependsOn
.filter((service) => enabledIds.has(service))
.map((service) => ({ service }));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve mandatory dependencies for partial selections

When the independently toggleable Jellyseerr service remains selected but Jellyfin is deselected, this blanket filter removes Jellyseerr's declared jellyfin dependency and lets Compose start the partial project, but runInstall still unconditionally calls linkJellyseerr, whose bootstrap connects to hostname jellyfin; the install therefore fails after deploying containers. Required dependencies need to be auto-included or rejected during selection rather than being discarded alongside optional ordering edges.

Useful? React with 👍 / 👎.

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