Compare commits

...

3 Commits

Author SHA1 Message Date
Alexandre
dac8efba60 fix(scrutiny_original): keep real /init as PID 1 so s6 supervision starts (#2991)
* fix(scrutiny_original): keep real /init as PID 1 so s6 supervision starts

collector-once's s6-svwait -u /run/service/scrutiny fails because
ha_entrypoint.sh (not the image's own /init) was PID 1 and never runs
real s6 supervision, so /run/service/* never gets created. Same root
cause and fix as scrutiny/scrutiny_fa (#2878): keep /init as PID 1 and
let ha_entrypoint.sh act only as the S6_STAGE2_HOOK.

Verified against the actual analogj/scrutiny:latest-omnibus image
(pulled via the GHCR registry API): its collector-once run script is
byte-identical to the one that caused #2877, and it bundles the same
s6-overlay-3.1.6.2.

Closes #2989

* fix(scrutiny_original): symlink /command into /usr/bin at build time

With /init as PID 1, ha_entrypoint.sh's own PID1 branch (which creates
this same symlink at runtime, and rewrites service run-file shebangs)
never runs. nginx/run and finish use #!/usr/bin/with-contenv bashio,
which only resolves if /usr/bin/with-contenv exists — so without this,
nginx (ingress) fails to start. scrutiny/Dockerfile and
scrutiny_fa/Dockerfile already do this in their "Install apps" stage;
this was missed when porting their PID-1 fix over.

Caught by chatgpt-codex-connector's PR review.
2026-08-18 21:36:49 +02:00
Alexandre
87f69ce79b fix(scrutiny_fa_original): keep real /init as PID 1 so s6 supervision starts (#2992)
Same bug and root cause as scrutiny_original (#2991) and scrutiny/scrutiny_fa
(#2878): collector-once's `s6-svwait -u /run/service/scrutiny` fails because
ha_entrypoint.sh (not the image's own /init) was PID 1 and never runs real s6
supervision, so /run/service/* never gets created.

scrutiny_fa_original shares the exact same rootfs (byte-identical cont-init.d
and services.d/nginx scripts) as scrutiny_original and builds from the same
ghcr.io/analogj/scrutiny:latest-omnibus image, so the same fix applies:
keep /init as PID 1, patch ha_entrypoint.sh to hand off to real s6-rc
supervision, and symlink /command into /usr/bin at build time (nginx/run and
finish use #!/usr/bin/with-contenv bashio, which only resolves once that
symlink exists — a P1 finding from scrutiny_original's PR review that
applies here identically).

Keeps the existing bashio::require.unprotected guard in
/etc/cont-init.d/90-run.sh unchanged.
2026-08-18 21:36:35 +02:00
Alexandre
84dfd1b996 fix(seerr): stop rewriting the root link inside the JS bundle (#2975) (#2986)
* fix(seerr): stop rewriting the root link inside the JS bundle (#2975)

3.4.1.1 appended a trailing slash to both the server-rendered "Discover"
link and its counterpart inside Seerr's JavaScript bundle. The slash is
correct in the HTML - Home Assistant routes ingress on
"/api/hassio_ingress/{token}/{path:.*}" and rejects a slash-less entry -
but it cannot survive in the bundle: next/link resolves a pushed href
through normalizePathTrailingSlash(), which drops a trailing slash while
`trailingSlash` is false, and Next.js then hard navigates to the
slash-less URL, recreating the same 404. On the root page it instead
throws "Invariant: attempted to hard navigate to the same URL" and the
click does nothing.

Dropping the bundle rewrite leaves the link as "/", which the client
router matches against its own "/" route and transitions to in-app -
the same path every other sidebar entry already takes, none of which are
rewritten here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(seerr): drop text/html from sub_filter_types

nginx pre-seeds text/html into sub_filter_types, so listing it emits
`[warn] duplicate MIME type "text/html"` on every config load. Verified
against nginx 1.22.1 locally: with the type dropped, `nginx -t` is
warning free and an HTML response is still filtered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 13:29:01 +02:00
9 changed files with 88 additions and 21 deletions

View File

@@ -1,4 +1,7 @@
## v0.9.3.1 (2026-08-18)
- Fix startup crash: `collector-once` failed with `s6-svwait: fatal: unable to subscribe to events for /run/service/scrutiny` because the add-on entrypoint never started real s6 supervision. Keep the upstream image's own `/init` as PID 1, same as `scrutiny_original` (#2991) and `scrutiny`/`scrutiny_fa` (#2878).
## v0.9.3 (2026-08-13)
- Update to latest version from analogj/scrutiny (changelog : https://github.com/analogj/scrutiny/releases)

View File

@@ -33,7 +33,8 @@ ENV S6_CMD_WAIT_FOR_SERVICES=1 \
# Add rootfs
COPY rootfs/ /
RUN find . -type f \( -name "*.sh" -o -name "run" -o -name "finish" \) -print -exec chmod +x {} \;
RUN find . -type f \( -name "*.sh" -o -name "run" -o -name "finish" \) -print -exec chmod +x {} \; && \
if [ -d /command ]; then ln -sf /command/* /usr/bin/; fi
# Uses /bin for compatibility purposes
# hadolint ignore=DL4005
@@ -61,19 +62,35 @@ RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.
# 4 Entrypoint #
################
# Add entrypoint
# Keep the repository initialization hook, but return after it has prepared the
# cont-init scripts. Upstream s6 remains responsible for supervising services.
ENV S6_STAGE2_HOOK=/ha_entrypoint.sh
COPY ha_entrypoint.sh /ha_entrypoint.sh
RUN chmod 777 /ha_entrypoint.sh
RUN chmod 0755 /ha_entrypoint.sh && \
awk '!inserted && $0 == "if $PID1; then" { \
print "if ! $PID1; then"; \
print " echo \"Initialization hook complete\""; \
print " exit 0"; \
print "fi"; \
inserted=1 \
} { print }' /ha_entrypoint.sh > /ha_entrypoint.sh.tmp && \
mv /ha_entrypoint.sh.tmp /ha_entrypoint.sh && \
chmod 0755 /ha_entrypoint.sh
# Install bashio
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
RUN chmod 0755 /usr/local/lib/bashio-standalone.sh
RUN test -x /init && \
test -x /ha_entrypoint.sh && \
bash -n /ha_entrypoint.sh && \
grep -q 'Initialization hook complete' /ha_entrypoint.sh
RUN sed -i "1a if ! bashio::require.unprotected; then bashio::addon.stop; fi" /etc/cont-init.d/90-run.sh
ENTRYPOINT [ "/usr/bin/env" ]
CMD [ "/ha_entrypoint.sh" ]
# Scrutiny's image already includes s6-overlay and defines all services under
# /etc/services.d. Keep /init as PID 1 so service readiness and s6-svc calls work.
ENTRYPOINT [ "/init" ]
############
# 5 Labels #

View File

@@ -45,4 +45,4 @@ schema:
slug: scrutiny_fa_original
udev: true
url: https://github.com/analogj/scrutiny
version: "v0.9.3"
version: "v0.9.3.1"

View File

@@ -1,4 +1,7 @@
## v0.9.3.1 (2026-08-18)
- Fix startup crash: `collector-once` failed with `s6-svwait: fatal: unable to subscribe to events for /run/service/scrutiny` because the add-on entrypoint never started real s6 supervision. Keep the upstream image's own `/init` as PID 1 (same fix already shipped for `scrutiny`/`scrutiny_fa` in #2878). Closes #2989.
## v0.9.3 (2026-08-13)
- Update to latest version from analogj/scrutiny (changelog : https://github.com/analogj/scrutiny/releases)

View File

@@ -33,7 +33,8 @@ ENV S6_CMD_WAIT_FOR_SERVICES=1 \
# Add rootfs
COPY rootfs/ /
RUN find . -type f \( -name "*.sh" -o -name "run" -o -name "finish" \) -print -exec chmod +x {} \;
RUN find . -type f \( -name "*.sh" -o -name "run" -o -name "finish" \) -print -exec chmod +x {} \; && \
if [ -d /command ]; then ln -sf /command/* /usr/bin/; fi
# Uses /bin for compatibility purposes
# hadolint ignore=DL4005
@@ -61,17 +62,33 @@ RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.
# 4 Entrypoint #
################
# Add entrypoint
# Keep the repository initialization hook, but return after it has prepared the
# cont-init scripts. Upstream s6 remains responsible for supervising services.
ENV S6_STAGE2_HOOK=/ha_entrypoint.sh
COPY ha_entrypoint.sh /ha_entrypoint.sh
RUN chmod 777 /ha_entrypoint.sh
RUN chmod 0755 /ha_entrypoint.sh && \
awk '!inserted && $0 == "if $PID1; then" { \
print "if ! $PID1; then"; \
print " echo \"Initialization hook complete\""; \
print " exit 0"; \
print "fi"; \
inserted=1 \
} { print }' /ha_entrypoint.sh > /ha_entrypoint.sh.tmp && \
mv /ha_entrypoint.sh.tmp /ha_entrypoint.sh && \
chmod 0755 /ha_entrypoint.sh
# Install bashio
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
RUN chmod 0755 /usr/local/lib/bashio-standalone.sh
ENTRYPOINT [ "/usr/bin/env" ]
CMD [ "/ha_entrypoint.sh" ]
RUN test -x /init && \
test -x /ha_entrypoint.sh && \
bash -n /ha_entrypoint.sh && \
grep -q 'Initialization hook complete' /ha_entrypoint.sh
# Scrutiny's image already includes s6-overlay and defines all services under
# /etc/services.d. Keep /init as PID 1 so service readiness and s6-svc calls work.
ENTRYPOINT [ "/init" ]
############
# 5 Labels #

View File

@@ -113,4 +113,4 @@ schema:
slug: scrutiny_original
udev: true
url: https://github.com/analogj/scrutiny
version: "v0.9.3"
version: "v0.9.3.1"

View File

@@ -1,4 +1,8 @@
## 3.4.1.2 (2026-08-18)
- Fixed **Discover** in the sidebar still failing through ingress after 3.4.1.1 (#2975). The trailing slash added in 3.4.1.1 was also applied to the copy of the link inside Seerr's JavaScript bundle, and Next.js' client-side router strips a trailing slash before navigating: it then sent the click to a URL Home Assistant does not route, so it either landed on the same `404: Not Found` or threw `Invariant: attempted to hard navigate to the same URL` and did nothing at all. The bundle is no longer rewritten, so **Discover** routes inside the app exactly like **Requests**, **Issues** and **Settings** already did. The server-rendered link keeps its trailing slash. Only ingress was affected; the directly published port 5055 always worked.
## 3.4.1.1 (2026-08-16)
- Fixed `404: Not Found` when clicking **Discover** in the sidebar through ingress (#2975). Seerr's Discover link points at `/`, which nginx rewrote to the ingress entry without a trailing slash; Home Assistant only routes ingress on `/api/hassio_ingress/<token>/…`, so the request was rejected by Home Assistant before reaching the add-on. Only ingress was affected; the directly published port 5055 always worked.

View File

@@ -96,4 +96,4 @@ schema:
slug: seerr
udev: true
url: https://github.com/alexbelgium/hassio-addons/tree/master/seerr
version: "3.4.1.1"
version: "3.4.1.2"

View File

@@ -43,17 +43,40 @@ server {
sub_filter_once off;
# Do not rewrite every response type blindly.
sub_filter_types text/html application/javascript text/javascript application/json;
# Do not rewrite every response type blindly. text/html is implicit and
# must not be listed - nginx pre-seeds it and warns "duplicate MIME type"
# on every config load if it appears here as well.
sub_filter_types application/javascript text/javascript application/json;
# The trailing slash is required: Home Assistant routes ingress on
# "/api/hassio_ingress/{token}/{path:.*}", so the bare entry without it
# matches no route and Home Assistant answers its own plain-text
# "404: Not Found" before the request ever reaches this add-on. Seerr's
# Discover link is href="/", so without the slash every click on it 404s.
# Seerr's "Discover" sidebar entry, the header logo and the 404 and
# error pages are all <Link href="/">. The server-rendered anchor has to
# carry the ingress prefix *with* a trailing slash: Home Assistant routes
# ingress on "/api/hassio_ingress/{token}/{path:.*}", so a slash-less
# entry matches no route and Home Assistant answers its own plain-text
# "404: Not Found" before the request ever reaches this add-on (#2975).
sub_filter 'href="/"' 'href="$app/"';
sub_filter 'href="/login"' 'href="$app/login"';
sub_filter 'href:"/"' 'href:"$app/"';
# A matching rule for 'href:"/"' - the form those same links take once
# compiled into the JS bundle - used to sit here. It is gone on purpose
# and must not come back: it fed the ingress prefix into Next.js' own
# route table, and next/link resolves a pushed href through
# normalizePathTrailingSlash(), which drops a trailing slash while
# `trailingSlash` is false (Seerr sets no override). Next therefore hard
# navigated to the slash-less URL and recreated the same 404; on the root
# page it instead threw "Invariant: attempted to hard navigate to the
# same URL" and the click did nothing. That is the state PR #2976 left
# #2975 in. Left alone the href stays "/", which removeTrailingSlash()
# preserves, so the router matches its own "/" route and transitions
# in-app - the path every other sidebar entry ("/requests", "/issues",
# "/users", "/settings") already takes. Prefixing belongs in the rendered
# anchor, never in the router's route table.
#
# Note that none of these rules are response-type scoped - sub_filter_types
# includes JavaScript - so the anchor rule above avoids the bundle only
# because the compiled output spells the prop 'href:"/"' and not
# 'href="/"'. These are textual substitutions over someone else's minified
# output: recheck them whenever Seerr or Next.js is upgraded.
sub_filter '\/_next' '%%ingress_entry_escaped%%\/_next';
sub_filter '/_next' '$app/_next';
sub_filter '/api/v1' '$app/api/v1';