From 98d5504097bbfbf3b7a530eeea1205ea395f5ec5 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 15 Jun 2026 08:00:47 +0200 Subject: [PATCH] v0.66.2: FileBrowser umask 002 via entrypoint wrapper gtstef/filebrowser is a single Go binary that ignores a UMASK env (verified live: -e UMASK=002 leaves PID1 0022), so RenderFileBrowserCompose wraps the entrypoint sh -c 'umask 002; exec /home/filebrowser/filebrowser'. Customer-created folders now come out 2775 (group-writable) so group-1000 apps can write into them. Test asserts the wrapper is rendered. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 11 +++++++++++ controller/internal/infra/infra.go | 5 +++++ controller/internal/infra/infra_test.go | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdbc7db..2a89646 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ ## Changelog +### v0.66.2 — FileBrowser umask 002 (customer folders group-writable) (2026-06-15) + +FileBrowser (uid 1000) created folders with umask 022 → mode 2755 (setgid from the parent, but +group-READ only), so a folder a customer made in FileBrowser could not be written by the content apps +in group 1000. The gtstef/filebrowser image is a single Go binary (`entrypoint ./filebrowser`) and does +NOT honor a `UMASK` env (verified live: `-e UMASK=002` leaves PID1 at 0022), so `RenderFileBrowserCompose` +(`internal/infra/infra.go`) now wraps the entrypoint: +`["sh","-c","umask 002; exec /home/filebrowser/filebrowser"]`. Customer-created folders now come out +**2775** (group-writable) so all group-1000 apps can use them. Test asserts the rendered compose carries +the wrapper. (Pre-existing pre-fix folders stay 2755 — recreated on the demo; no data.) + ### v0.66.1 — fix USERDATA_PATH on first deploy (2026-06-14) The initial deploy path (`DeployStack` → `composeExecWithEnv`) builds its compose env from the deploy diff --git a/controller/internal/infra/infra.go b/controller/internal/infra/infra.go index a4f15e9..ad762eb 100644 --- a/controller/internal/infra/infra.go +++ b/controller/internal/infra/infra.go @@ -129,6 +129,11 @@ services: image: %s container_name: filebrowser restart: unless-stopped + # umask 002 so folders the customer creates here come out group-writable (2775 with the parent's + # setgid), letting the content apps (group 1000) write into them. The gtstef/filebrowser image is a + # single Go binary (entrypoint ./filebrowser) and does NOT honor a UMASK env (verified: -e UMASK=002 + # leaves PID1 at 0022), so we wrap the entrypoint to set the process umask before exec. + entrypoint: ["sh", "-c", "umask 002; exec /home/filebrowser/filebrowser"] environment: - TZ=Europe/Budapest - FILEBROWSER_CONFIG=/home/filebrowser/config.yaml diff --git a/controller/internal/infra/infra_test.go b/controller/internal/infra/infra_test.go index d19d62f..a3c91f6 100644 --- a/controller/internal/infra/infra_test.go +++ b/controller/internal/infra/infra_test.go @@ -223,4 +223,10 @@ func TestFileBrowserRender(t *testing.T) { if !strings.Contains(withMounts, "/mnt/hdd_1:/srv/hdd_1") { t.Errorf("storage mount not wired into filebrowser compose: %q", withMounts) } + + // v0.66.2: the entrypoint wrapper sets umask 002 so customer-created folders are group-writable + // (2775). The image doesn't honor a UMASK env, so this MUST be the entrypoint mechanism. + if !strings.Contains(compose, `entrypoint: ["sh", "-c", "umask 002; exec /home/filebrowser/filebrowser"]`) { + t.Errorf("filebrowser compose missing the umask-002 entrypoint wrapper: %q", compose) + } }