Compare commits

..

19 Commits

Author SHA1 Message Date
Alexandre
04eb7d2d15 fix(claude_desktop): stop exporting HEADROOM_CONTEXT_TOOL in claude wrapper (#3121)
Headroom 0.36 removed CLI context tools and aborts headroom wrap when
HEADROOM_CONTEXT_TOOL is set, so every PATH-based Claude Code launch failed.
RTK remains configured by the add-on's own rtk hook.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 14:02:01 +02:00
github-actions
de6f5efb72 GitHub bot : README updated 2026-10-14 17:06:06 +00:00
Alexandre
af230f6b7b Add entry to CHANGELOG for artwork exclusion 2026-10-14 15:32:42 +02:00
Alexandre
e18f5606cd Update config.yaml 2026-10-14 15:32:00 +02:00
Alexandre
eaa01c4eb0 fix(templates): forward the container stop to services supervised by ha_entrypoint (#3118)
* fix(templates): forward the container stop to services supervised by ha_entrypoint

When ha_entrypoint.sh is PID 1 (init: false add-ons on images without
s6-overlay: comicarr, komga, degoog, ...), terminate() signals only its
direct children. Those are the per-service restart-loop subshells, which
died on SIGTERM without passing it on; PID 1 then exited and the kernel
SIGKILLed every service. No service ever got a chance to shut down cleanly.

Each loop now runs its service (and the restart delay) in the background,
traps TERM/INT, forwards SIGTERM to that process, waits for it to exit, and
leaves the loop instead of restarting it. The "Termination signal received"
line the postgres add-ons sed into is unchanged.

Implementation drafted by Codex (gpt-5.6-sol), reviewed and tested here.

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

* fix(templates): stop the service's whole process group, and wait for it to empty

A run file that does not exec its daemon only had its wrapper shell
signalled: portainer_agent's own run file, and LinuxServer's svc-transmission
in base images we cannot edit. Each loop subshell now runs with job control
(set -m), so every service is its own process group; the stop is sent to the
group and PID 1 waits until the group is empty, so the daemon drains instead
of being SIGKILLed when PID 1 exits. Docker's stop timeout still bounds it.

Revision drafted by Codex (gpt-5.6-sol); the group-drain wait was added after
a PID-1 test showed the daemon got TERM but was killed mid-drain.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 06:58:19 +02:00
dependabot[bot]
92d2862e0e build(deps): bump anthropics/claude-code-action from 1.0.240 to 1.0.248 (#3119)
Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1.0.240 to 1.0.248.
- [Release notes](https://github.com/anthropics/claude-code-action/releases)
- [Commits](ed670b4cf9...1d6de8cb0c)

---
updated-dependencies:
- dependency-name: anthropics/claude-code-action
  dependency-version: 1.0.248
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-14 06:57:34 +02:00
Alexandre
5ba5a894e2 feat(degoog): new add-on for the Degoog search aggregator (#3117)
* feat(degoog): new add-on for the Degoog search aggregator (#3116)

Degoog mounts every route, and builds every url, under DEGOOG_BASE_URL.
The add-on sets that to its ingress entry, so ingress works with no url
rewriting beyond the one script tag upstream emits without its base path
(/public/t.js in render.tsx). A bundled nginx fronts both the ingress port
and the direct port 4444 and puts the stripped entry back, so
http://homeassistant:4444/search?q=%s works as a browser search engine.

Structure follows comicarr: the upstream image is plain alpine/bun with no
s6-overlay, so ha_entrypoint runs as pid 1 and supervises the app and
nginx. Data lives in /config (addon_config), the equivalent of upstream's
./data:/app/data volume.

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

* refactor(degoog): drop the TZ block, resolver include and HASSIO_TOKEN env nothing uses

The bun alpine image ships no tzdata, so the zoneinfo link never ran; every
proxy_pass targets a literal 127.0.0.1, so nginx never resolves a name.

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

* fix(degoog): keep the forced listener settings, and stop logging search queries

00-global_var.sh injects the env_vars option right after the shebang of
/entrypoint.sh, so a user's DEGOOG_PORT, DEGOOG_BIND_ADDRESS, DEGOOG_BASE_URL
or DEGOOG_DATA_DIR would have been put back over the values the run file
forces. Start bun with su-exec from the run file instead, where the injected
block sits above those exports, and clear DEGOOG_UNIX_SOCKET, which would
take the app off TCP and leave nginx returning 502.

Turn nginx's access log off: every request line, and so every search query,
was being written to the add-on log.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:42:18 +02:00
BirdNET-Go Addon Builder
274a806cce birdnet-go-dev: rebuild against the fixed fork PRs
Two open PRs of the fork did not compile, so the 20261006 and 20261013
builds failed and were auto-reverted:
- species-workspace called an undefined isSpectrogramFileFor
  (alexbelgium/birdnet-go e73bca4, now specfile.IsRenderFor)
- reanalyze called DetectionCache.Flush, which does not exist
  (alexbelgium/birdnet-go 3f91fd7, now Invalidate)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 11:18:46 +02:00
GitHub Actions
839d8fbb33 Revert "birdnet-go-dev: rebuild against the fixed fork PRs"
This reverts commit 46bb4b9037.
2026-10-13 09:16:42 +00:00
BirdNET-Go Addon Builder
46bb4b9037 birdnet-go-dev: rebuild against the fixed fork PRs
The 20261006 build failed to compile - the species-workspace PR of the
fork called isSpectrogramFileFor, which it never defined - and the bump
was auto-reverted. The PR now uses the shared specfile grammar
(alexbelgium/birdnet-go e73bca4), so rebuild.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 11:11:02 +02:00
GitHub Actions
006bab1196 Revert "birdnet-go-dev: bump to 20261013"
This reverts commit c1a40720ac.
2026-10-13 07:26:07 +00:00
alexbelgium
c1a40720ac birdnet-go-dev: bump to 20261013
Fork synced with upstream; merge conflicts in fork PRs #62, #63, #79 and #80
resolved so the build's PR merge sequence is clean again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 09:19:13 +02:00
Alexandre
61eb86731e feat(joplin): optional SSL with ssl/certfile/keyfile (#3114) (#3115)
* feat(joplin): optional SSL via nginx using ssl/certfile/keyfile (#3114)

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

* refactor(joplin): single minimal nginx config, fail fast on invalid cert

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

* docs(joplin): changelog date format and spacing

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

* chore(joplin): trim nginx defaults, document LAN access

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 08:32:28 +02:00
github-actions
3f12463ef0 Github bot : image compressed 2026-10-11 23:15:22 +00:00
github-actions
f2f60a70d8 GitHub bot : README updated 2026-10-11 17:05:55 +00:00
Alexandre
f2c888f0ed fix(joplin_desktop): drop --disable-dev-shm-usage, Joplin rejects unknown flags (#3113)
Joplin validates its argv against an allow-list (processStartFlags.ts) and
aborted with "Unknown flag: --disable-dev-shm-usage", so the app never opened.
Bump to 3.7.21.1 so Supervisor offers the rebuild, and record the trap in the
workflow skill.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:43:22 +02:00
Alexandre
8a0ec37f6b feat(joplin_desktop): new add-on streaming Joplin desktop via Selkies (#3112)
* feat(joplin_desktop): new add-on streaming Joplin desktop via Selkies (#3100)

Wraps lscr.io/linuxserver/joplin (amd64 only; Joplin ships no Linux arm64
build) and shares the Selkies startup scripts with webtop/claude_desktop by
symlink, the same way webtop_kde does. Chromium is told to keep shared memory
out of /dev/shm because Home Assistant ignores shm_size.

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

* joplin_desktop: admin-only panel; steer direct access to https/ingress in README

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

* joplin_desktop: drop panel_admin (admin-only is the default; linter rejects it)

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

* fix(90-ssl): honour own certificates when data_location is relocated

20-folders.sh rewrites the data path in /defaults/default.conf before 90-ssl.sh
runs, so the literal /config/data/ssl/... match missed and own certificates were
silently ignored. Replace whatever path the ssl_certificate directives hold.
Shared with webtop/webtop_kde; their versions are intentionally not bumped, so
they pick this up on their next release. Also restores panel_admin: false.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:22:27 +02:00
Alexandre
5949321a55 fix(filebrowser_quantum): remove doubled status-bar inset in the HA app (#3111)
* fix(filebrowser_quantum): drop the doubled status-bar inset in the HA app

2.0 sets viewport-fit=cover and pads its header by env(safe-area-inset-top);
inside the ingress panel HA's toolbar already handles that inset. Rewrite it
to viewport-fit=auto on the ingress listener only.

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

* fix(filebrowser_quantum): zero only the top safe-area inset on ingress

Replace the viewport-fit rewrite with --safe-area-top: 0px set on <html>
from the existing nonce script. It touches only the top inset (bottom and
side insets keep upstream behaviour) and works whether or not the browser
passes the parent's insets into the ingress iframe.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 08:31:54 +02:00
Alexandre
4199b7e292 fix(filebrowser_quantum): write the v2 config format so 2.0.0 starts (#3110)
* fix(filebrowser_quantum): write the v2 config format so 2.0.0 starts

v2 rejects the string server.database, the 1.x server.port/listen/baseURL
keys and the FILEBROWSER_DATABASE variable, so both fresh installs and
upgrades died at startup. Write http.* and server.database.path, and point
migrateFrom at an existing 1.x BoltDB so upstream migrates it on first start.

Fixes #3109

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

* fix(filebrowser_quantum): reset 1.x configs to the v2 default on upgrade

Old installs carry a config copied from a 1.x image default, whose
userDefaults layout v2 rejects as unknown fields. Deleting keys one by one
cannot cover every 1.x variant, so back the file up and start from the v2
default, which the script then fills in as on a fresh install.

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

* docs(filebrowser_quantum): clarify migrateFrom comment

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

* fix(filebrowser_quantum): follow the v2 migration guide and upstream healthcheck

Set migrateFrom only until the SQLite database exists, set
http.trustProxyHeaders for the nginx subpath, and check upstream's
${baseURL}health endpoint instead of an nginx-only stub.

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

* fix(filebrowser_quantum): convert 1.x configs in place instead of resetting

Resetting to the v2 default dropped extra sources (breaking shares on them)
and auth/OIDC settings. Both 1.x and 2.0 reject unknown keys, so the keys a
1.5.x config can hold that 2.0 lacks are exactly the settings-struct diff:
move the server http keys under http and drop the removed ones.

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

* docs(filebrowser_quantum): fix CHANGELOG entry

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

* fix(filebrowser_quantum): ask users to back up before the 2.0 upgrade

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

* fix(filebrowser_quantum): keep server.database siblings, sanitize direct XFF

Set only server.database.path (dropping migrateFrom) so user-set keys such
as activity survive, and replace X-Forwarded-For on the published 8071
listener now that FileBrowser trusts proxy headers for login rate limits.

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

* fix(filebrowser_quantum): drop panel_admin default flagged by the add-on linter

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

* Revert "fix(filebrowser_quantum): drop panel_admin default flagged by the add-on linter"

Keep panel_admin: true explicit, per maintainer.

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

* fix(filebrowser_quantum): simplify the healthcheck

Curl the app root: v2 answers 200, or 301 to the baseURL, which curl -f
accepts, so the baseURL no longer has to be read from the config.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 08:01:34 +02:00
193 changed files with 1180 additions and 30 deletions

View File

@@ -220,6 +220,14 @@ Assistant **ignores** the add-on's `shm_size`, so the real size varies per insta
on one host. Detect at runtime rather than assuming either way; keep the flag when the size
cannot be determined, because the crash it prevents is worse than its overhead.
**Not every Electron app accepts arbitrary Chromium switches.** Joplin parses its own argv
against an allow-list and aborts on anything else: `--disable-dev-shm-usage` produced
`An error occurred: Unknown flag: --disable-dev-shm-usage` and no app window
(`packages/lib/utils/processStartFlags.ts`; it accepts `--no-sandbox`, `--ozone-platform=`,
`--disable-gpu` and a few others). The build-time `grep` that "verified" the flag only proved
the text was in the wrapper, not that the app tolerated it. Check the app's argument parser before
passing a Chromium flag to anything that is not Chromium itself (joplin_desktop, PR #3112, fixed in the follow-up PR).
## CI and review bots
**What CI actually gates** — checked against the workflows, because assuming costs a cycle.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 KiB

After

Width:  |  Height:  |  Size: 70 KiB

BIN
.github/stats.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -125,7 +125,7 @@ jobs:
- name: Analyse and fix
if: steps.batch.outputs.count != '0'
uses: anthropics/claude-code-action@ed670b4cf9de2a5a570d130d2f6197b9e543cd64 # v1
uses: anthropics/claude-code-action@1d6de8cb0c237e7c15e9e1bdf973826ebae490cc # v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Skip the OIDC -> Claude App token exchange. The scheduled path

View File

@@ -64,7 +64,7 @@ jobs:
fetch-depth: 1
- name: Run Claude Code
uses: anthropics/claude-code-action@ed670b4cf9de2a5a570d130d2f6197b9e543cd64 # v1
uses: anthropics/claude-code-action@1d6de8cb0c237e7c15e9e1bdf973826ebae490cc # v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# AI_PR_TOKEN, not GITHUB_TOKEN, so a PR Claude opens triggers CI.

View File

@@ -135,7 +135,7 @@ jobs:
- name: Execute the plan
if: steps.bundle.outputs.has_plan == 'true'
uses: anthropics/claude-code-action@ed670b4cf9de2a5a570d130d2f6197b9e543cd64 # v1
uses: anthropics/claude-code-action@1d6de8cb0c237e7c15e9e1bdf973826ebae490cc # v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Skip the OIDC -> Claude App token exchange, which 401s whenever

View File

@@ -166,7 +166,7 @@ jobs:
id: classify
if: github.event_name != 'issue_comment' || steps.claim.outputs.go == 'true'
continue-on-error: true
uses: anthropics/claude-code-action@ed670b4cf9de2a5a570d130d2f6197b9e543cd64 # v1
uses: anthropics/claude-code-action@1d6de8cb0c237e7c15e9e1bdf973826ebae490cc # v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Without this the action falls back to the OIDC -> Claude App token

View File

@@ -79,7 +79,7 @@ jobs:
- name: Address CodeRabbit comments
if: steps.claim.outputs.go == 'true'
uses: anthropics/claude-code-action@ed670b4cf9de2a5a570d130d2f6197b9e543cd64 # v1
uses: anthropics/claude-code-action@1d6de8cb0c237e7c15e9e1bdf973826ebae490cc # v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Skip the OIDC -> Claude App token exchange, which 401s whenever

View File

@@ -437,9 +437,34 @@ if $PID1; then
(
restart_count=0
max_restarts=5
# terminate() signals only PID 1's direct children, which are these loop subshells.
# Give each background job its own process group and forward the stop to the whole
# group, so wrappers and their daemons can shut down before PID 1 exits.
set -m
stopping=false
service_pid=
trap 'stopping=true; [ -z "$service_pid" ] || kill -TERM -- "-$service_pid" 2>/dev/null || true' TERM INT
wait_for_service() {
local pid="$service_pid"
if $stopping; then
kill -TERM -- "-$pid" 2>/dev/null || true
fi
_svc_rc=0
wait "$pid" 2>/dev/null || _svc_rc=$?
if $stopping; then
wait "$pid" 2>/dev/null || true
# A run file that does not exec its daemon dies first; wait for the whole group
while kill -0 -- "-$pid" 2>/dev/null; do sleep 0.2; done
service_pid=
return 1
fi
service_pid=
}
while true; do
_svc_rc=0
"$runfile" || _svc_rc=$?
"$runfile" &
service_pid=$!
wait_for_service || break
if [ "$_svc_rc" -eq 126 ] && [ -n "${BASHIO_LIB:-}" ]; then
echo "Direct exec of $runfile failed (rc=126, likely E2BIG), retrying via source..."
_svc_rc=0
@@ -448,7 +473,9 @@ if $PID1; then
. "$BASHIO_LIB" 2>/dev/null || true
# shellcheck disable=SC1090
. "$runfile"
) || _svc_rc=$?
) &
service_pid=$!
wait_for_service || break
fi
rc=$_svc_rc
if [ "$rc" -eq 0 ]; then
@@ -461,7 +488,9 @@ if $PID1; then
break
fi
echo -e "\e[38;5;214m$(date) WARNING: $runfile exited (code $rc), restarting (#${restart_count}/${max_restarts}) in 5s...\e[0m"
sleep 5
sleep 5 &
service_pid=$!
wait_for_service || break
done
) &
done

View File

@@ -56,7 +56,7 @@ If you want to do add the repository manually, please follow the procedure highl
### Number of addons
- In the repository : 143
- In the repository : 145
- Installed : 286452
### Top 3
@@ -329,6 +329,14 @@ If you want to do add the repository manually, please follow the procedure highl
![smb][smb-badge]
![localdisks][localdisks-badge]
&#10003; ![image](https://api.iconify.design/mdi/magnify.svg) [Degoog](degoog/) : Search aggregator that queries many engines at once, with themes and a plugin store
&emsp;&emsp;![Version](https://img.shields.io/badge/dynamic/yaml?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fdegoog%2Fconfig.yaml)
![Update](https://img.shields.io/badge/dynamic/json?label=Updated&query=%24.last_update&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fdegoog%2Fupdater.json)
![aarch64][aarch64-badge]
![amd64][amd64-badge]
![ingress][ingress-badge]
&#10003; [Elasticsearch server](elasticsearch/) : Free and Open, Distributed, RESTful Search Engine
&emsp;&emsp;![Version](https://img.shields.io/badge/dynamic/yaml?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Felasticsearch%2Fconfig.yaml)
@@ -564,6 +572,16 @@ If you want to do add the repository manually, please follow the procedure highl
![amd64][amd64-badge]
![ingress][ingress-badge]
&#10003; ![image](https://api.iconify.design/mdi/notebook-edit.svg) [Joplin Desktop](joplin_desktop/) : Joplin desktop note-taking app accessible via any modern web browser
&emsp;&emsp;![Version](https://img.shields.io/badge/dynamic/yaml?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fjoplin_desktop%2Fconfig.yaml)
![Update](https://img.shields.io/badge/dynamic/json?label=Updated&query=%24.last_update&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fjoplin_desktop%2Fupdater.json)
![aarch64no][aarch64no-badge]
![amd64][amd64-badge]
![ingress][ingress-badge]
![smb][smb-badge]
![localdisks][localdisks-badge]
&#10003; [Joplin Server](joplin/) : Self-hosted open source note-taking application
&emsp;&emsp;![Version](https://img.shields.io/badge/dynamic/yaml?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fjoplin%2Fconfig.yaml)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,3 +1,7 @@
## 20261013.1 (13-10-2026)
- Rebuild against the current open PRs of the fork, after fixing two that did not compile: the species-workspace PR called an undefined `isSpectrogramFileFor` (now the shared `specfile` grammar), and the reanalyze PR called `DetectionCache.Flush`, which does not exist (now `Invalidate`). The 20261006 and first 20261013 builds failed on those and were auto-reverted.
## 20260929.1 (30-09-2026)
- New `INGRESS_SKIP_AUTH` option (default `false`): when `true`, BirdNET-Go no longer asks for its own login when opened through the Home Assistant sidebar (ingress), since Home Assistant has already signed you in. Direct access on port 8080 still requires the login.
- Security: the ingress web server now only accepts connections from the Home Assistant Supervisor, as Home Assistant requires.

View File

@@ -129,5 +129,5 @@ slug: birdnet-go-dev
udev: true
url: https://github.com/alexbelgium/hassio-addons
usb: true
version: "20260929.1"
version: "20261013.1"
video: true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,4 +1,7 @@
## 07308545.15 (15-10-2026)
- Fix terminal Claude Code sessions failing to start with `Error: CLI context tools (rtk, lean-ctx) have been removed from Headroom`. The `/usr/local/bin/claude` wrapper exported `HEADROOM_CONTEXT_TOOL=rtk` before `headroom wrap`, and Headroom 0.36 now rejects that variable. The export is gone. RTK is still configured by the add-on through its own `rtk hook claude` hook (`install_rtk`), which Headroom's leftover cleanup does not touch.
## 07308545.14 (2026-10-10)
- Update to latest version from aaddrick/claude-desktop-debian (changelog : https://github.com/aaddrick/claude-desktop-debian/releases)
- Upstream tag : v3.3.9+claude2.26454.2

View File

@@ -175,5 +175,5 @@ schema:
slug: claude_desktop
udev: true
url: https://github.com/alexbelgium/hassio-addons
version: "07308545.14"
version: "07308545.15"
video: true

View File

@@ -42,7 +42,6 @@ if bashio::config.true 'install_headroom' && bashio::config.true 'headroom_wrap_
if [ -x "$HEADROOM_BIN" ] && curl -fsS --max-time 2 "${HEADROOM_URL}/health" > /dev/null 2>&1; then
# Put /usr/bin before /usr/local/bin while Headroom resolves its upstream `claude`
# executable; otherwise it would resolve this wrapper recursively.
export HEADROOM_CONTEXT_TOOL="rtk"
exec env PATH="/usr/bin:/bin:/usr/local/bin" \
"$HEADROOM_BIN" wrap claude --no-proxy -- \
"${CLAUDE_PERMISSION_ARGS[@]}" "$@"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

3
degoog/CHANGELOG.md Normal file
View File

@@ -0,0 +1,3 @@
## 1.1.0 (2026-10-13)
- Initial release, based on upstream degoog-org/degoog 1.1.0 (changelog : https://github.com/degoog-org/degoog/releases)
- Home Assistant ingress support, and direct access on port 4444, through a bundled nginx reverse proxy

119
degoog/Dockerfile Normal file
View File

@@ -0,0 +1,119 @@
#============================#
# ALEXBELGIUM'S DOCKERFILE #
#============================#
# _.------.
# _.-` ('>.-`"""-.
# '.--'` _'` _ .--.)
# -' '-.-';` `
# ' - _.' ``'--.
# '---` .-'""`
# /`
#=== Home Assistant Addon ===#
#################
# 1 Build Image #
#################
ARG BUILD_FROM
ARG BUILD_VERSION
ARG BUILD_UPSTREAM="1.1.0"
FROM ghcr.io/degoog-org/degoog:${BUILD_UPSTREAM}
##################
# 2 Modify Image #
##################
USER root
# No S6_* tuning here : the upstream image is a plain oven/bun alpine image with
# no s6-overlay, so the vars the other addons set would be read by nobody
##################
# 3 Install apps #
##################
# Add rootfs
# Absolute paths on purpose : the upstream image sets WORKDIR /app, so
# the relative "find ." used by the other addons would miss /etc entirely
COPY rootfs/ /
RUN find /etc/cont-init.d /etc/services.d -type f \( -name "*.sh" -o -name "run" \) -print -exec chmod +x {} \;
# Uses /bin for compatibility purposes
# hadolint ignore=DL4005
RUN if [ ! -f /bin/sh ] && [ -f /usr/bin/sh ]; then ln -s /usr/bin/sh /bin/sh; fi && \
if [ ! -f /bin/bash ] && [ -f /usr/bin/bash ]; then ln -s /usr/bin/bash /bin/bash; fi
# Modules
ARG MODULES="00-banner.sh 00-global_var.sh 01-custom_script.sh"
# Automatic modules download
COPY ha_automodules.sh /ha_automodules.sh
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
# Manual apps
ENV PACKAGES="nginx"
# Automatic apps & bashio
COPY ha_autoapps.sh /ha_autoapps.sh
RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.sh
################
# 4 Entrypoint #
################
# The upstream image ships no s6-overlay, so ha_entrypoint runs as pid 1 : it
# executes /etc/cont-init.d, then supervises /etc/services.d. It replaces the
# upstream /entrypoint.sh, whose su-exec start services.d/degoog/run reproduces.
COPY ha_entrypoint.sh /ha_entrypoint.sh
RUN chmod 0755 /ha_entrypoint.sh
ENTRYPOINT ["/ha_entrypoint.sh"]
# Install bashio
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
RUN chmod 0755 /usr/local/lib/bashio-standalone.sh
############
# 5 Labels #
############
ARG BUILD_ARCH
ARG BUILD_DATE
ARG BUILD_DESCRIPTION
ARG BUILD_NAME
ARG BUILD_REF
ARG BUILD_REPOSITORY
ARG BUILD_VERSION
ENV BUILD_VERSION="${BUILD_VERSION}"
LABEL \
io.hass.name="${BUILD_NAME}" \
io.hass.description="${BUILD_DESCRIPTION}" \
io.hass.arch="${BUILD_ARCH}" \
io.hass.type="addon" \
io.hass.version=${BUILD_VERSION} \
maintainer="alexbelgium (https://github.com/alexbelgium)" \
org.opencontainers.image.title="${BUILD_NAME}" \
org.opencontainers.image.description="${BUILD_DESCRIPTION}" \
org.opencontainers.image.vendor="Home Assistant Add-ons" \
org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.url="https://github.com/alexbelgium" \
org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \
org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/README.md" \
org.opencontainers.image.created=${BUILD_DATE} \
org.opencontainers.image.revision=${BUILD_REF} \
org.opencontainers.image.version=${BUILD_VERSION}
#################
# 6 Healthcheck #
#################
# Goes through nginx on the direct port, which maps / onto the app's base path,
# so one probe covers both processes
ENV HEALTH_PORT="4444" \
HEALTH_URL="/readyz"
HEALTHCHECK \
--interval=30s \
--retries=5 \
--start-period=90s \
--timeout=25s \
CMD curl -A "HealthCheck: Docker/1.0" -s -f "http://127.0.0.1:${HEALTH_PORT}${HEALTH_URL}" >/dev/null 2>&1 || exit 1

68
degoog/README.md Normal file
View File

@@ -0,0 +1,68 @@
# Home Assistant Add-on: Degoog
Self-hosted search aggregator: one query, results from many search engines, with themes and a
plugin store.
[Degoog](https://github.com/degoog-org/degoog) works like SearXNG: it sends your search to the
engines you pick and merges what they return. Engines, plugins, themes and autocomplete
providers are installed from its built-in store.
## About
- Results from many engines at once, merged into one page
- Engines, plugins, themes and transports installed from git-based store repositories
- Bangs, shortcuts, autocomplete and an optional local result indexer
- Works as your browser's default search engine (OpenSearch)
## Installation
1. Add this repository to Home Assistant.
2. Install the **Degoog** add-on.
3. Set `DEGOOG_SETTINGS_PASSWORDS` (see below), then start the add-on.
4. Open it from the sidebar (ingress), or at `http://homeassistant:4444`.
5. Go to **Settings → Store** and install at least one search engine: a fresh install has none,
so searches return no web results until you do.
## Configuration
| Option | Description |
|--------|-------------|
| `DEGOOG_SETTINGS_PASSWORDS` | Password for the settings and admin pages. Several passwords can be given, comma separated. If empty, Degoog generates a new one-off password at every start and prints it in the add-on log. |
| `PUID` / `PGID` | User Degoog runs as, and owner of its data directory. Defaults to `0` (root). |
| `TZ` | Timezone, e.g. `Europe/Paris`. |
| `env_vars` | Extra environment variables passed to Degoog, e.g. `DEGOOG_PUBLIC_INSTANCE` or `DEGOOG_I18N`. See the [upstream list](https://degoog-org.github.io/docs/environment-variables.html) and the [wiki](https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2). |
The add-on sets `DEGOOG_BASE_URL`, `DEGOOG_DATA_DIR`, `DEGOOG_PORT` and `DEGOOG_BIND_ADDRESS`
itself, and clears `DEGOOG_UNIX_SOCKET`, because ingress, the direct port and the health check
are built around them: setting them in `env_vars` has no effect.
## Ingress, direct access and search-engine use
Degoog serves every page under a base path. The add-on sets that base path to the Home Assistant
ingress path, so ingress needs no rewriting, and the bundled nginx maps port `4444` onto the same
path. As a result, pages opened on port `4444` show an address such as
`http://homeassistant:4444/api/hassio_ingress/<token>/search?q=...`. That is expected, and the
short form keeps working too.
To use Degoog as your browser's search engine, use the direct port, not the Home Assistant
sidebar url, for example `http://homeassistant:4444/search?q=%s`. Ingress urls only work inside
a logged-in Home Assistant session.
Behind nginx every client appears to Degoog as `127.0.0.1`, so its per-IP rate limits apply to
all users together. Its bot trap never bans private addresses, so this cannot lock you out. If
you put the add-on behind your own reverse proxy and want per-client limits, add
`DEGOOG_DISTRUST_PROXY=0` in `env_vars`. Degoog then trusts the `X-Forwarded-For` header, which
clients can forge, so only do this when port `4444` is reachable only through your proxy.
## Data
Settings, installed extensions and the index database live in `/config` inside the add-on.
Home Assistant maps that to this add-on's own configuration directory,
`/addon_configs/<repository_id>_degoog`, and it is included in add-on backups. It is the
equivalent of the upstream `./data:/app/data` compose volume, so the contents of an existing
`data` folder can be copied in as is.
## Support
- [Degoog upstream project](https://github.com/degoog-org/degoog)
- [Add-on repository issues](https://github.com/alexbelgium/hassio-addons/issues)

66
degoog/apparmor.txt Normal file
View File

@@ -0,0 +1,66 @@
#include <tunables/global>
profile degoog_addon flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
capability chown,
capability dac_override,
capability fowner,
capability setgid,
capability setuid,
capability sys_chroot,
file,
signal,
mount,
umount,
remount,
network udp,
network tcp,
network dgram,
network stream,
network inet,
network inet6,
network netlink raw,
network unix dgram,
# Entrypoint stack
/init ix,
/run/{s6,s6-rc*,service}/** ix,
/package/** ix,
/command/** ix,
/run/{,**} rwk,
/dev/tty rw,
/bin/** ix,
/usr/bin/** ix,
/usr/lib/bashio/** ix,
/etc/s6/** rix,
/run/s6/** rix,
/etc/services.d/** rwix,
/etc/cont-init.d/** rwix,
/etc/cont-finish.d/** rwix,
/init rix,
/var/run/** mrwkl,
/var/run/ mrwkl,
/dev/i2c-1 mrwkl,
# Files required
/dev/fuse mrwkl,
/dev/sda1 mrwkl,
/dev/sdb1 mrwkl,
/dev/nvme0 mrwkl,
/dev/nvme1 mrwkl,
/dev/mmcblk0p1 mrwkl,
/dev/* mrwkl,
/tmp/** mrkwl,
# Data access
/data/** rw,
# suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
ptrace (trace,read) peer=docker-default,
# docker daemon confinement requires explicit allow rule for signal
signal (receive) set=(kill,term) peer=/usr/bin/docker,
}

6
degoog/build.json Normal file
View File

@@ -0,0 +1,6 @@
{
"build_from": {
"aarch64": "ghcr.io/degoog-org/degoog:latest",
"amd64": "ghcr.io/degoog-org/degoog:latest"
}
}

32
degoog/config.yaml Normal file
View File

@@ -0,0 +1,32 @@
arch:
- aarch64
- amd64
description:
Search aggregator that queries many engines at once, with themes and a
plugin store
image: ghcr.io/alexbelgium/degoog-{arch}
ingress: true
init: false
map:
- addon_config:rw
name: Degoog
options:
env_vars: []
PGID: 0
PUID: 0
panel_icon: mdi:magnify
ports:
4444/tcp: 4444
ports_description:
4444/tcp: Web interface
schema:
DEGOOG_SETTINGS_PASSWORDS: password?
env_vars:
- name: match(^[A-Za-z0-9_]+$)
value: str?
PGID: int
PUID: int
TZ: str?
slug: degoog
url: https://github.com/alexbelgium/hassio-addons/tree/master/degoog
version: "1.1.0"

BIN
degoog/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
degoog/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,14 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -e
# Degoog keeps its settings, plugins, themes, engines and sqlite indexer in its
# data directory. services.d/degoog/run points DEGOOG_DATA_DIR at /config, the
# addon_config mount, which matches the upstream compose file's
# "./data:/app/data" volume : an existing data folder can be copied in as is.
bashio::log.info "Data stored in /config"
# Recursive, like the upstream entrypoint does for /app/data : plugins and
# themes are installed by the app itself, so a PUID change must hand them over
# too. Numbered 20- so it sorts after 00-global_var.sh, which exports PUID/PGID.
chown -R "${PUID:-0}:${PGID:-0}" /config

View File

@@ -0,0 +1,17 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -e
#################
# NGINX SETTING #
#################
declare ingress_interface
declare ingress_port
declare ingress_entry
ingress_port=$(bashio::addon.ingress_port)
ingress_interface=$(bashio::addon.ip_address)
ingress_entry=$(bashio::addon.ingress_entry)
sed -i "s/%%port%%/${ingress_port}/g" /etc/nginx/servers/ingress.conf
sed -i "s/%%interface%%/${ingress_interface}/g" /etc/nginx/servers/ingress.conf
sed -i "s|%%ingress_entry%%|${ingress_entry}|g" /etc/nginx/servers/ingress.conf

View File

@@ -0,0 +1,96 @@
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
font/woff woff;
font/woff2 woff2;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.presentation odp;
application/vnd.oasis.opendocument.spreadsheet ods;
application/vnd.oasis.opendocument.text odt;
application/vnd.openxmlformats-officedocument.presentationml.presentation
pptx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx;
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}

View File

@@ -0,0 +1,48 @@
# Run nginx in foreground.
daemon off;
# This is run inside Docker.
user root;
# Pid storage location.
pid /var/run/nginx.pid;
# Set number of worker processes.
worker_processes 1;
# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;
# Write error log to Hass.io add-on log.
error_log /proc/1/fd/1 error;
# Load dynamic modules.
include /etc/nginx/modules-enabled/*.conf;
# Max num of simultaneous connections by a worker process.
events {
worker_connections 512;
}
http {
include /etc/nginx/includes/mime.types;
# No access log : request lines carry every search query
access_log off;
client_max_body_size 4G;
default_type application/octet-stream;
gzip on;
keepalive_timeout 65;
sendfile on;
server_tokens off;
tcp_nodelay on;
tcp_nopush on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
include /etc/nginx/servers/*.conf;
}

View File

@@ -0,0 +1,50 @@
server {
# Ingress, and the direct port. Both are served the same way : Degoog runs
# with its base path set to the ingress entry (services.d/degoog/run), and
# Home Assistant strips that entry before forwarding, so it is put back here.
listen %%interface%%:%%port%% default_server;
listen 4444 default_server;
client_max_body_size 0;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Search results are sent to the page as server-sent events
proxy_buffering off;
proxy_read_timeout 30m;
proxy_send_timeout 30m;
# The one url upstream builds without its base path
# (src/server/routes/pages/render.tsx)
proxy_set_header Accept-Encoding "";
sub_filter 'src="/public/t.js' 'src="%%ingress_entry%%/public/t.js';
# Degoog answers <entry>/ with a redirect to the slashless <entry>, which
# Home Assistant does not route : ask for the slashless form directly.
location = / {
proxy_pass http://127.0.0.1:4445%%ingress_entry%%;
}
# Links in the pages already carry the entry ; only the direct port sees
# them, since ingress strips it. No trailing slash, so the bare entry
# (the target of Degoog's own trailing-slash redirect) matches too.
location %%ingress_entry%% {
proxy_pass http://127.0.0.1:4445;
}
# Transport websockets are the only routes upstream mounts outside its base
# path (src/server/index.ts)
location /ws/ {
proxy_pass http://127.0.0.1:4445;
}
location / {
proxy_pass http://127.0.0.1:4445%%ingress_entry%%/;
}
}

View File

@@ -0,0 +1,24 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -e
# ==============================================================================
# Every route Degoog serves, and every url it generates, lives under
# DEGOOG_BASE_URL. Setting it to the ingress entry makes the pages correct under
# ingress as they are ; nginx maps the direct port onto the same path.
# The listener is forced because nginx and the healthcheck are built around it.
DEGOOG_BASE_URL="$(bashio::addon.ingress_entry)"
export DEGOOG_BASE_URL
export DEGOOG_DATA_DIR=/config
export DEGOOG_PORT=4445
export DEGOOG_BIND_ADDRESS=127.0.0.1
unset DEGOOG_UNIX_SOCKET
# Started here rather than through the upstream /entrypoint.sh : 00-global_var.sh
# injects the env_vars option right after that script's shebang, which would put
# a user's DEGOOG_PORT or DEGOOG_DATA_DIR back over the values above. The same
# block lands at the top of this file, before them. The entrypoint's only other
# work is a chown of /app/data, which is unused here (20-config_location.sh).
bashio::log.info "Starting Degoog..."
cd /app
exec su-exec "${PUID:-0}:${PGID:-0}" bun run src/server/index.ts

View File

@@ -0,0 +1,7 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -e
# ==============================================================================
bashio::log.info "Starting NGinx..."
exec nginx

10
degoog/updater.json Normal file
View File

@@ -0,0 +1,10 @@
{
"github_beta": "false",
"github_fulltag": false,
"last_update": "2026-10-13",
"repository": "alexbelgium/hassio-addons",
"slug": "degoog",
"source": "github",
"upstream_repo": "degoog-org/degoog",
"upstream_version": "1.1.0"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,4 +1,7 @@
## 2.0.0.2 (2026-10-11)
- Remove the empty band above the search bar in the Home Assistant app (portrait): 2.0 padded its header for the phone status bar, which HA already does. The top inset is set to 0 on ingress only.
## 2.0.0.1 (2026-10-11)
- ⚠️ **Back up before updating.** FileBrowser 2.0 changes the config format and the database. This add-on converts both automatically, but you should first create a Home Assistant backup of the add-on, or copy `/addon_configs/*filebrowser_quantum*/` (`config.yaml` and `database.db`). Your 1.x `database.db` is left untouched, but downgrading after the migration loses any changes made in 2.0.
- Fix startup on 2.0.0, for fresh installs and upgrades (#3109).
@@ -11,7 +14,6 @@
- Users, shares and settings in `/config/database.db` are migrated to `/config/database.sqlite` on first start.
- `http.trustProxyHeaders` is set to `true`, because the add-on always runs behind nginx on a subpath.
- The container healthcheck now checks FileBrowser directly on port 8080 instead of an nginx stub.
- Remove the empty band above the search bar in the Home Assistant app: 2.0 padded its header for the phone status bar, which HA already does. This applies to ingress only.
- Direct access on port 8071 no longer passes on a client-supplied `X-Forwarded-For`, so the IP-based login lockout cannot be bypassed now that proxy headers are trusted. Ingress keeps the forwarded chain.
## 2.0.0 (2026-10-10)

View File

@@ -117,4 +117,4 @@ schema:
slug: filebrowser_quantum
udev: true
url: https://github.com/alexbelgium/hassio-addons
version: "2.0.0.1"
version: "2.0.0.2"

View File

@@ -13,12 +13,12 @@ server {
proxy_read_timeout 30m;
proxy_pass %%protocol%%://backend%%subpath%%;
# Two things the ingress panel needs that a plain browser tab does not.
# Three things the ingress panel needs that a plain browser tab does not.
# Both are injected into the page's existing nonce-carrying inline script
# rather than next to <div id="app">: FileBrowser sends
# script-src 'self' 'nonce-<random>', so a standalone inline <script>
# would be blocked. If upstream ever drops that
# window.__pwaDeferredPrompt line the filter stops matching and both
# window.__pwaDeferredPrompt line the filter stops matching and all three
# behaviours revert, which is the state before either fix.
#
# 1. Opening a folder. The tool views (Tools -> File Size Analyzer and
@@ -106,12 +106,12 @@ server {
# links inside a document FileBrowser renders in its own iframe -- the
# pdf viewer, the srcdoc markdown/html preview, OnlyOffice -- because a
# listener on this document never sees another document's clicks.
# 2.0 asks for viewport-fit=cover and pads its header by
# env(safe-area-inset-top). In the Home Assistant app the panel already
# sits below HA's toolbar, which handles that inset, so it was applied
# twice (an empty band above the search bar). The direct port is untouched.
sub_filter "viewport-fit=cover" "viewport-fit=auto";
sub_filter "window.__pwaDeferredPrompt = null;" "window.__pwaDeferredPrompt = null;(function(){var o=window.open;window.open=function(u,n,f){try{var b=(window.globalVars||{}).baseURL;if(u&&n==='_blank'&&!f&&b){if(b.slice(-1)!=='/')b+='/';var t=new URL(u,location.href);if((t.protocol==='http:'||t.protocol==='https:')&&t.origin===location.origin&&(t.pathname.indexOf(b+'files/')===0||t.pathname.indexOf(b+'public/share/')===0)){location.assign(t.href);return window}}}catch(e){}return o.apply(window,arguments)};document.addEventListener('click',function(e){try{if(e.button||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;var a=e.target&&e.target.closest?e.target.closest('a'):null;if(!a||!a.href)return;var b=(window.globalVars||{}).baseURL;if(!b)return;if(b.slice(-1)!=='/')b+='/';var t=new URL(a.href,location.href);if(t.origin!==location.origin)return;if(!a.hasAttribute('download')&&t.searchParams.get('inline')!=='true'&&(t.pathname===b+'api/resources/download'||t.pathname===b+'public/api/resources/download')){a.download='';a.removeAttribute('target');return}if(a.target==='_blank'&&t.pathname.indexOf(b)===0&&navigator.userAgent.indexOf('Mobile/HomeAssistant')!==-1){a.removeAttribute('target')}}catch(err){}},true)})();";
# 3. The status-bar inset. 2.0 pads its header by env(safe-area-inset-top)
# (--safe-area-top), but inside the Home Assistant app the panel already
# sits below HA's toolbar, which handles that inset, so in portrait it
# was applied twice: an empty band above the search bar. Zero it on
# <html>, which overrides the :root rule; the direct port is untouched.
sub_filter "window.__pwaDeferredPrompt = null;" "window.__pwaDeferredPrompt = null;document.documentElement.style.setProperty('--safe-area-top','0px');(function(){var o=window.open;window.open=function(u,n,f){try{var b=(window.globalVars||{}).baseURL;if(u&&n==='_blank'&&!f&&b){if(b.slice(-1)!=='/')b+='/';var t=new URL(u,location.href);if((t.protocol==='http:'||t.protocol==='https:')&&t.origin===location.origin&&(t.pathname.indexOf(b+'files/')===0||t.pathname.indexOf(b+'public/share/')===0)){location.assign(t.href);return window}}}catch(e){}return o.apply(window,arguments)};document.addEventListener('click',function(e){try{if(e.button||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;var a=e.target&&e.target.closest?e.target.closest('a'):null;if(!a||!a.href)return;var b=(window.globalVars||{}).baseURL;if(!b)return;if(b.slice(-1)!=='/')b+='/';var t=new URL(a.href,location.href);if(t.origin!==location.origin)return;if(!a.hasAttribute('download')&&t.searchParams.get('inline')!=='true'&&(t.pathname===b+'api/resources/download'||t.pathname===b+'public/api/resources/download')){a.download='';a.removeAttribute('target');return}if(a.target==='_blank'&&t.pathname.indexOf(b)===0&&navigator.userAgent.indexOf('Mobile/HomeAssistant')!==-1){a.removeAttribute('target')}}catch(err){}},true)})();";
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,4 +1,8 @@
## 3.7.2.1 (2026-10-13)
- Add optional SSL: set `ssl: true` with `certfile`/`keyfile` from /ssl to serve the web interface over https on port 22300 (#3114)
## 3.7.2 (2026-09-12)
- Update to latest version from etechonomy/joplin-server (changelog : https://github.com/etechonomy/joplin-server/releases)

View File

@@ -56,7 +56,7 @@ COPY ha_automodules.sh /ha_automodules.sh
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
# Manual apps
ENV PACKAGES="procps sqlite3 postgresql-client"
ENV PACKAGES="procps sqlite3 postgresql-client nginx"
# Automatic apps & bashio
COPY ha_autoapps.sh /ha_autoapps.sh

View File

@@ -46,6 +46,9 @@ Webui can be found at `<your-ip>:22300`.
|--------|------|---------|-------------|
| `APP_BASE_URL` | str | `http://your_domain:port` | Base public URL where the service will be running |
| `data_location` | str | `/config/addons_config/joplin` | Path where Joplin data is stored |
| `ssl` | bool | `false` | Serve the web interface over https on port 22300 |
| `certfile` | str | `fullchain.pem` | Certificate file in `/ssl` (used when `ssl` is true) |
| `keyfile` | str | `privkey.pem` | Private key file in `/ssl` (used when `ssl` is true) |
| `DB_CLIENT` | str | | Database client type. Only `pg` (PostgreSQL) is supported. MariaDB/MySQL is NOT supported. |
| `POSTGRES_HOST` | str | | PostgreSQL server hostname |
| `POSTGRES_PORT` | int | | PostgreSQL server port |
@@ -82,6 +85,15 @@ MAILER_NOREPLY_NAME: "Joplin Server"
MAILER_NOREPLY_EMAIL: "noreply@yourdomain.com"
```
### HTTPS
Joplin Server only accepts requests whose host (and port) match `APP_BASE_URL` exactly. To reach it securely from outside:
1. Put your certificate and key in `/ssl` (the DuckDNS and Let's Encrypt add-ons already write `fullchain.pem` and `privkey.pem` there).
2. Set `ssl: true` (and `certfile`/`keyfile` if your files have other names).
3. Set `APP_BASE_URL` to the exact URL you will type, for example `https://yourname.duckdns.org:22300`.
4. Forward port 22300 on your router to Home Assistant, restart the add-on, and use that same URL in browsers and in the Joplin clients. Use it on your LAN too: if that fails at home, your router lacks hairpin NAT, so add a local DNS entry pointing the domain to your Home Assistant IP.
### Database Setup
Joplin Server uses SQLite by default, but for production use, PostgreSQL is recommended.

View File

@@ -70,11 +70,15 @@ image: ghcr.io/alexbelgium/joplin-{arch}
map:
- config:rw
- share:rw
- ssl
name: Joplin Server
options:
env_vars: []
APP_BASE_URL: http://your_domain:port
certfile: fullchain.pem
data_location: /config/addons_config/joplin
keyfile: privkey.pem
ssl: false
ports:
22300/tcp: 22300
ports_description:
@@ -100,9 +104,12 @@ schema:
POSTGRES_PASSWORD: str?
POSTGRES_PORT: int?
POSTGRES_USER: str?
certfile: str?
data_location: str?
keyfile: str?
ssl: bool?
slug: joplin
udev: true
url: https://github.com/alexbelgium/hassio-addons
version: "3.7.2"
version: "3.7.2.1"
webui: "[PROTO:ssl]://[HOST]:[PORT:22300]"

View File

@@ -141,6 +141,20 @@ bashio::config.has_value 'MAILER_ENABLED' && export MAILER_ENABLED="$(bashio::co
export APP_BASE_URL="$(bashio::config 'APP_BASE_URL')"
export ALLOWED_HOSTS="*"
# -------------------
# SSL
# -------------------
if bashio::config.true 'ssl'; then
bashio::config.require.ssl
sed -i "s|%%certfile%%|$(bashio::config 'certfile')|g" /etc/nginx/joplin.conf
sed -i "s|%%keyfile%%|$(bashio::config 'keyfile')|g" /etc/nginx/joplin.conf
# nginx terminates TLS on 22300 and proxies to Joplin on 22301
export APP_PORT=22301
nginx -c /etc/nginx/joplin.conf -t -q || bashio::exit.nok "Invalid ssl certificate or key, check certfile and keyfile"
nginx -c /etc/nginx/joplin.conf &
bashio::log.info "Ssl enabled, please use https for connection"
fi
bashio::log.info 'Starting Joplin. Initial user is "admin@localhost" with password "admin"'
cd /home/joplin || exit 1

View File

@@ -0,0 +1,42 @@
# TLS front-end for Joplin, only started when ssl is enabled.
# Run nginx in foreground.
daemon off;
worker_processes auto;
# Write error log to Hass.io add-on log.
error_log /proc/1/fd/1 error;
events {
worker_connections 1024;
}
http {
access_log off;
server_tokens off;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 22300 ssl;
client_max_body_size 0;
ssl_certificate /ssl/%%certfile%%;
ssl_certificate_key /ssl/%%keyfile%%;
location / {
proxy_pass http://127.0.0.1:22301;
proxy_http_version 1.1;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,8 @@
## 3.7.21.1 (2026-10-11)
- Fix Joplin not opening ("An error occurred: Unknown flag: --disable-dev-shm-usage"): Joplin only accepts its own list of command-line flags, so the extra Chromium flag added in 3.7.21 is removed
## 3.7.21 (2026-10-11)
- Initial release: Joplin desktop streamed to the browser with Selkies, based on linuxserver/docker-joplin (amd64 only, as Joplin publishes no Linux arm64 build)
- Shares the Selkies startup scripts with the webtop and claude_desktop add-ons (data location, GPU permissions, ingress, SSL)
- Own SSL certificates (`use_own_certs`) now also apply when `data_location` is changed: the shared `90-ssl.sh` replaces whatever certificate path nginx holds instead of a fixed `/config/data/ssl/...` string, and warns instead of reporting success when it cannot

129
joplin_desktop/Dockerfile Normal file
View File

@@ -0,0 +1,129 @@
#============================#
# ALEXBELGIUM'S DOCKERFILE #
#============================#
# _.------.
# _.-` ('>.-`"3.7.21""-.
# '.--'` _'` _ .--.)
# -' '-.-';` `
# ' - _.' ``'--.
# '---` .-'"3.7.21"`
# /`
#=== Home Assistant Addon ===#
#################
# 1 Build Image #
#################
ARG BUILD_FROM
ARG BUILD_VERSION
FROM ${BUILD_FROM}
##################
# 2 Modify Image #
##################
# Set S6 wait time
ENV S6_CMD_WAIT_FOR_SERVICES=1 \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_SERVICES_GRACETIME=0
USER root
# load volume
VOLUME [ "/sys/fs/cgroup" ]
# Set shell
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Allow UID and GID setting
# hadolint ignore=SC2015,DL4006,SC2013,SC2086
RUN \
# Change home folder location
usermod --home /config/data abc && \
\
# Set +e
if [[ -d /etc/services.d ]] && ls /etc/services.d/*/run 1> /dev/null 2>&1; then sed -i "1a set +e" /etc/services.d/*/run; fi
# Global LSIO modifications
COPY ha_lsio.sh /ha_lsio.sh
ARG CONFIGLOCATION="/config/data"
RUN chmod 744 /ha_lsio.sh && if grep -qr "lsio" /etc; then /ha_lsio.sh "$CONFIGLOCATION"; fi && rm /ha_lsio.sh
##################
# 3 Install apps #
##################
# Add rootfs
COPY rootfs/ /
RUN find . -type f \( -name "*.sh" -o -name "run" -o -name "finish" \) -print -exec chmod +x {} \;
# Uses /bin for compatibility purposes
# hadolint ignore=DL4005
RUN if [ ! -f /bin/sh ] && [ -f /usr/bin/sh ]; then ln -s /usr/bin/sh /bin/sh; fi && \
if [ ! -f /bin/bash ] && [ -f /usr/bin/bash ]; then ln -s /usr/bin/bash /bin/bash; fi
# Modules
ARG MODULES="00-banner.sh 01-custom_script.sh 00-local_mounts.sh 00-smb_mounts.sh 90-dns_set.sh"
# Automatic modules download
COPY ha_automodules.sh /ha_automodules.sh
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
# Manual apps
ENV PACKAGES="nginx"
# Automatic apps & bashio
COPY ha_autoapps.sh /ha_autoapps.sh
RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.sh
################
# 4 Entrypoint #
################
# Add entrypoint
#ENV S6_STAGE2_HOOK=/ha_entrypoint.sh
COPY ha_entrypoint.sh /ha_entrypoint.sh
RUN chmod 777 /ha_entrypoint.sh
# Install bashio
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
RUN chmod 0755 /usr/local/lib/bashio-standalone.sh
#WORKDIR /
ENTRYPOINT [ "/usr/bin/env" ]
CMD [ "/ha_entrypoint.sh" ]
############
# 5 Labels #
############
ARG BUILD_ARCH
ARG BUILD_DATE
ARG BUILD_DESCRIPTION
ARG BUILD_NAME
ARG BUILD_REF
ARG BUILD_REPOSITORY
ARG BUILD_VERSION
ENV BUILD_VERSION="${BUILD_VERSION}"
LABEL \
io.hass.name="${BUILD_NAME}" \
io.hass.description="${BUILD_DESCRIPTION}" \
io.hass.arch="${BUILD_ARCH}" \
io.hass.type="addon" \
io.hass.version=${BUILD_VERSION} \
maintainer="alexbelgium (https://github.com/alexbelgium)" \
org.opencontainers.image.title="${BUILD_NAME}" \
org.opencontainers.image.description="${BUILD_DESCRIPTION}" \
org.opencontainers.image.vendor="Home Assistant Add-ons" \
org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.url="https://github.com/alexbelgium" \
org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \
org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/README.md" \
org.opencontainers.image.created=${BUILD_DATE} \
org.opencontainers.image.revision=${BUILD_REF} \
org.opencontainers.image.version=${BUILD_VERSION}
####################
# 6 HealthcheckNOT #
####################

Some files were not shown because too many files have changed in this diff Show More