diff --git a/.daemonless/config.yaml b/.daemonless/config.yaml index 43b6aeb..5789121 100644 --- a/.daemonless/config.yaml +++ b/.daemonless/config.yaml @@ -11,5 +11,6 @@ cit: port: 8080 # Served with no auth middleware, so it answers before any user is created. health: /health + ready: "Running at" # Frontend (npm ci + vite) plus a full Go build from source. timeout: 180 diff --git a/Containerfile b/Containerfile index 8363fac..923765e 100644 --- a/Containerfile +++ b/Containerfile @@ -52,19 +52,21 @@ RUN if [ -z "${APP_VERSION}" ]; then \ rm /tmp/src.tar.gz # --- Frontend --- -# MUST run before `go build`: the backend go:embed's backend/http/embed/*. -# Use `npm run build` (NOT `build:docker`) — build:docker emits only -# backend/http/dist, which is the on-disk path, leaving embed/ empty. +# MUST run before `go build`: the backend go:embed's frontend assets. +# In v1.5.x, assets embed into backend/http/embed/*. +# In v2.0.x, assets embed into backend/internal/web/embed/* (e.g. public/index.html). +# Use `npm run build` (NOT `build:docker`) — build:docker emits only the +# on-disk dist path, leaving embed/ empty. # `npm ci` against the committed lockfile, not upstream's `npm i`, which can # silently update it. WORKDIR /src/frontend RUN npm ci --no-audit --no-fund -RUN mkdir -p /src/backend/http/embed && npm run build +RUN mkdir -p /src/backend/http/embed /src/backend/internal/web/embed && npm run build # Drift guard: if upstream renames the embed target, `go build` would still # succeed against a stale or empty embed dir and ship a blank UI. -RUN test -n "$(find /src/backend/http/embed -type f -name '*.html' -print -quit)" || \ - { echo "EMBED DRIFT: no HTML in backend/http/embed after 'npm run build'"; exit 1; } +RUN test -n "$(find /src/backend -type f -name '*.html' -path '*/embed/*' -print -quit)" || \ + { echo "EMBED DRIFT: no HTML in backend embed directory after 'npm run build'"; exit 1; } # --- Backend --- # CGO_ENABLED=0 is deliberate and load-bearing: @@ -76,7 +78,11 @@ RUN test -n "$(find /src/backend/http/embed -type f -name '*.html' -print -quit) # Result: a static binary, no C toolchain, no runtime shared-library deps. WORKDIR /src/backend ENV CGO_ENABLED=0 -RUN VERSION_PKG="github.com/gtsteffaniak/filebrowser/backend/common/version" && \ +RUN if [ -d /src/backend/internal/version ]; then \ + VERSION_PKG="github.com/gtsteffaniak/filebrowser/backend/internal/version"; \ + else \ + VERSION_PKG="github.com/gtsteffaniak/filebrowser/backend/common/version"; \ + fi && \ APP_VERSION=$(cat /tmp/app_version) && \ go build -trimpath \ -ldflags "-w -s -X '${VERSION_PKG}.Version=${APP_VERSION}'" \ @@ -142,11 +148,12 @@ RUN mkdir -m 0755 -p /app /config /srv && \ COPY --chmod=0755 --chown=bsd:bsd --from=builder /filebrowser-quantum /app/filebrowser-quantum COPY --chmod=0644 --chown=bsd:bsd --from=builder /tmp/version /app/version -# NOTE: deliberately no /app/http/dist on disk. -# backend/cmd/root.go does os.Stat("http/dist") *relative to the process CWD* and -# prefers on-disk assets over the embedded FS when that path exists. Shipping the -# dist tree would make the UI depend on whatever directory s6 happens to exec -# from. The embedded FS has no such dependency, so the binary stands alone. +# NOTE: deliberately no dist directory on disk. +# backend/cmd/root.go checks relative to the process CWD (http/dist in v1.5, +# internal/web/dist in v2.0) and prefers on-disk assets over the embedded FS +# when that path exists. Shipping the dist tree would make the UI depend on +# whatever directory s6 happens to exec from. The embedded FS has no such +# dependency, so the binary stands alone. COPY root/ / diff --git a/Containerfile.j2 b/Containerfile.j2 index a18ecab..4e7f247 100644 --- a/Containerfile.j2 +++ b/Containerfile.j2 @@ -46,19 +46,21 @@ RUN if [ -z "${APP_VERSION}" ]; then \ rm /tmp/src.tar.gz # --- Frontend --- -# MUST run before `go build`: the backend go:embed's backend/http/embed/*. -# Use `npm run build` (NOT `build:docker`) — build:docker emits only -# backend/http/dist, which is the on-disk path, leaving embed/ empty. +# MUST run before `go build`: the backend go:embed's frontend assets. +# In v1.5.x, assets embed into backend/http/embed/*. +# In v2.0.x, assets embed into backend/internal/web/embed/* (e.g. public/index.html). +# Use `npm run build` (NOT `build:docker`) — build:docker emits only the +# on-disk dist path, leaving embed/ empty. # `npm ci` against the committed lockfile, not upstream's `npm i`, which can # silently update it. WORKDIR /src/frontend RUN npm ci --no-audit --no-fund -RUN mkdir -p /src/backend/http/embed && npm run build +RUN mkdir -p /src/backend/http/embed /src/backend/internal/web/embed && npm run build # Drift guard: if upstream renames the embed target, `go build` would still # succeed against a stale or empty embed dir and ship a blank UI. -RUN test -n "$(find /src/backend/http/embed -type f -name '*.html' -print -quit)" || \ - { echo "EMBED DRIFT: no HTML in backend/http/embed after 'npm run build'"; exit 1; } +RUN test -n "$(find /src/backend -type f -name '*.html' -path '*/embed/*' -print -quit)" || \ + { echo "EMBED DRIFT: no HTML in backend embed directory after 'npm run build'"; exit 1; } # --- Backend --- # CGO_ENABLED=0 is deliberate and load-bearing: @@ -70,7 +72,11 @@ RUN test -n "$(find /src/backend/http/embed -type f -name '*.html' -print -quit) # Result: a static binary, no C toolchain, no runtime shared-library deps. WORKDIR /src/backend ENV CGO_ENABLED=0 -RUN VERSION_PKG="github.com/gtsteffaniak/filebrowser/backend/common/version" && \ +RUN if [ -d /src/backend/internal/version ]; then \ + VERSION_PKG="github.com/gtsteffaniak/filebrowser/backend/internal/version"; \ + else \ + VERSION_PKG="github.com/gtsteffaniak/filebrowser/backend/common/version"; \ + fi && \ APP_VERSION=$(cat /tmp/app_version) && \ go build -trimpath \ -ldflags "-w -s -X '${VERSION_PKG}.Version=${APP_VERSION}'" \ @@ -147,11 +153,12 @@ RUN mkdir -m 0755 -p /app /config /srv && \ COPY --chmod=0755 --chown=bsd:bsd --from=builder /filebrowser-quantum /app/filebrowser-quantum COPY --chmod=0644 --chown=bsd:bsd --from=builder /tmp/version /app/version -# NOTE: deliberately no /app/http/dist on disk. -# backend/cmd/root.go does os.Stat("http/dist") *relative to the process CWD* and -# prefers on-disk assets over the embedded FS when that path exists. Shipping the -# dist tree would make the UI depend on whatever directory s6 happens to exec -# from. The embedded FS has no such dependency, so the binary stands alone. +# NOTE: deliberately no dist directory on disk. +# backend/cmd/root.go checks relative to the process CWD (http/dist in v1.5, +# internal/web/dist in v2.0) and prefers on-disk assets over the embedded FS +# when that path exists. Shipping the dist tree would make the UI depend on +# whatever directory s6 happens to exec from. The embedded FS has no such +# dependency, so the binary stands alone. COPY root/ / diff --git a/compose.yaml b/compose.yaml index d4f8d1e..64d8bd0 100644 --- a/compose.yaml +++ b/compose.yaml @@ -40,7 +40,7 @@ services: - TZ=UTC volumes: - - /path/to/containers/filebrowser-quantum:/config + - /containers/filebrowser-quantum:/config - /path/to/your/files:/srv ports: diff --git a/root/etc/services.d/filebrowser-quantum/run b/root/etc/services.d/filebrowser-quantum/run index 72c32a9..bc24384 100755 --- a/root/etc/services.d/filebrowser-quantum/run +++ b/root/etc/services.d/filebrowser-quantum/run @@ -11,9 +11,10 @@ if [ ! -f "$CONFIG_FILE" ]; then # 8080, not upstream's default of 80: this container runs the app as the # unprivileged `bsd` user, and binding <1024 fails with # "listen tcp 0.0.0.0:80: bind: permission denied". -server: +http: port: 8080 baseURL: "/" +server: cacheDir: "/config/cache" sources: - path: "/srv" @@ -32,17 +33,16 @@ EOF fi export FILEBROWSER_CONFIG="$CONFIG_FILE" -export FILEBROWSER_DATABASE="${FILEBROWSER_DATABASE:-/config/database.db}" +export FILEBROWSER_DATABASE_PATH="${FILEBROWSER_DATABASE_PATH:-/config/filebrowser.sqlite}" -# The config file's parent dir holds the BoltDB, so it must be writable by bsd. +# The config file's parent dir holds the database, so it must be writable by bsd. chown -R bsd:bsd /config 2>/dev/null || true exec 2>&1 # `cd /app` is load-bearing, not tidiness: backend/cmd/root.go does -# os.Stat("http/dist") relative to the process CWD and serves from disk if it -# finds one. /app deliberately has no http/dist, so the embedded assets win and -# the UI cannot depend on where s6 happened to exec from. +# os.Stat("internal/web/dist") relative to the process CWD and serves from disk +# if it finds one. /app deliberately has no dist tree, so the embedded assets win. s6-ready-when fetch -qo /dev/null "${HEALTHCHECK_URL:-http://localhost:8080/health}" -exec s6-setuidgid bsd cd /app /app/filebrowser-quantum +cd /app && exec s6-setuidgid bsd /app/filebrowser-quantum