Files
shelfmark/Dockerfile
T
dependabot[bot]andCaliBrain efb1f66bc3 build(deps): bump astral-sh/uv from 0.12.16 to 0.12.19 in the docker-base-image-digests group across 1 directory (#1392)
> [!WARNING]
> Cooldown could not be applied because no publication date was
available from the registry.
>

Bumps the docker-base-image-digests group with 1 update in the /
directory: [astral-sh/uv](https://github.com/astral-sh/uv).

Updates `astral-sh/uv` from 0.12.16 to 0.12.19
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/uv/releases">astral-sh/uv's
releases</a>.</em></p>
<blockquote>
<h2>0.12.19</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Python</h3>
<ul>
<li>Add PyPy 3.11.16 and 3.12.14 (<a
href="https://redirect.github.com/astral-sh/uv/pull/21847">#21847</a>)</li>
<li>Update GraalPy 3.13.0 to build 25.4.4 (<a
href="https://redirect.github.com/astral-sh/uv/pull/21847">#21847</a>)</li>
</ul>
<h3>Enhancements</h3>
<ul>
<li>Format upload URLs with backticks in <code>uv publish</code> errors
(<a
href="https://redirect.github.com/astral-sh/uv/pull/21934">#21934</a>)</li>
</ul>
<h3>Preview features</h3>
<ul>
<li>Run build-backend hooks with lazy imports on CPython 3.15 and later
using the <code>build-lazy-imports</code> preview feature (<a
href="https://redirect.github.com/astral-sh/uv/pull/21967">#21967</a>)</li>
<li>Omit unused resolution settings from <code>uv.lock</code> and ignore
changes to them when checking lockfile freshness with the
<code>resolution-inputs</code> preview feature (<a
href="https://redirect.github.com/astral-sh/uv/pull/21913">#21913</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Preserve signed and encoded query parameters in direct-URL metadata
to avoid reinstalling unchanged packages (<a
href="https://redirect.github.com/astral-sh/uv/pull/21971">#21971</a>)</li>
<li>Recognize <code>1.0.0</code> as satisfying <code>===1</code> during
installed-package checks, matching resolution (<a
href="https://redirect.github.com/astral-sh/uv/pull/21931">#21931</a>)</li>
<li>Avoid collisions between Git checkout readiness markers and
<code>.ok</code> files in dependencies (<a
href="https://redirect.github.com/astral-sh/uv/pull/21891">#21891</a>)</li>
<li>Preserve always-false <code>python_version</code> markers when
parsing their serialized form (<a
href="https://redirect.github.com/astral-sh/uv/pull/21939">#21939</a>)</li>
</ul>
<h3>Rust API</h3>
<ul>
<li>Restore the public <code>FlatDistributions</code> export and its
<code>BTreeMap</code> conversion for downstream resolvers (<a
href="https://redirect.github.com/astral-sh/uv/pull/21965">#21965</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Make individual preview-feature reference entries linkable by name
(<a
href="https://redirect.github.com/astral-sh/uv/pull/21950">#21950</a>)</li>
</ul>
<h2>Install uv 0.12.19</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/uv/releases/download/0.12.19/uv-installer.sh
| sh
</code></pre>
<h3>Install prebuilt binaries via powershell script</h3>
<pre lang="sh"><code>powershell -ExecutionPolicy Bypass -c &quot;irm
https://releases.astral.sh/github/uv/releases/download/0.12.19/uv-installer.ps1
| iex&quot;
</code></pre>
<h2>Download uv 0.12.19</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/uv/blob/main/CHANGELOG.md">astral-sh/uv's
changelog</a>.</em></p>
<blockquote>
<h2>0.12.19</h2>
<p>Released on 2026-09-24.</p>
<h3>Python</h3>
<ul>
<li>Add PyPy 3.11.16 and 3.12.14 (<a
href="https://redirect.github.com/astral-sh/uv/pull/21847">#21847</a>)</li>
<li>Update GraalPy 3.13.0 to build 25.4.4 (<a
href="https://redirect.github.com/astral-sh/uv/pull/21847">#21847</a>)</li>
</ul>
<h3>Enhancements</h3>
<ul>
<li>Format upload URLs with backticks in <code>uv publish</code> errors
(<a
href="https://redirect.github.com/astral-sh/uv/pull/21934">#21934</a>)</li>
</ul>
<h3>Preview features</h3>
<ul>
<li>Run build-backend hooks with lazy imports on CPython 3.15 and later
using the <code>build-lazy-imports</code> preview feature (<a
href="https://redirect.github.com/astral-sh/uv/pull/21967">#21967</a>)</li>
<li>Omit unused resolution settings from <code>uv.lock</code> and ignore
changes to them when checking lockfile freshness with the
<code>resolution-inputs</code> preview feature (<a
href="https://redirect.github.com/astral-sh/uv/pull/21913">#21913</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Preserve signed and encoded query parameters in direct-URL metadata
to avoid reinstalling unchanged packages (<a
href="https://redirect.github.com/astral-sh/uv/pull/21971">#21971</a>)</li>
<li>Recognize <code>1.0.0</code> as satisfying <code>===1</code> during
installed-package checks, matching resolution (<a
href="https://redirect.github.com/astral-sh/uv/pull/21931">#21931</a>)</li>
<li>Avoid collisions between Git checkout readiness markers and
<code>.ok</code> files in dependencies (<a
href="https://redirect.github.com/astral-sh/uv/pull/21891">#21891</a>)</li>
<li>Preserve always-false <code>python_version</code> markers when
parsing their serialized form (<a
href="https://redirect.github.com/astral-sh/uv/pull/21939">#21939</a>)</li>
</ul>
<h3>Rust API</h3>
<ul>
<li>Restore the public <code>FlatDistributions</code> export and its
<code>BTreeMap</code> conversion for downstream resolvers (<a
href="https://redirect.github.com/astral-sh/uv/pull/21965">#21965</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Make individual preview-feature reference entries linkable by name
(<a
href="https://redirect.github.com/astral-sh/uv/pull/21950">#21950</a>)</li>
</ul>
<h2>0.12.18</h2>
<p>Released on 2026-09-22.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/uv/security/advisories/GHSA-2cv4-cqwr-gwf7">GHSA-2cv4-cqwr-gwf7</a>,
which is a path traversal weakness during wheel installation on Windows.
No other platforms are affected by this advisory.</p>
<h3>Enhancements</h3>
<ul>
<li>Add <code>--output-format json</code> to <code>uv pip install</code>
and <code>uv pip sync</code>, including for <code>--dry-run</code> and
<code>--check</code> (<a
href="https://redirect.github.com/astral-sh/uv/pull/21893">#21893</a>)</li>
<li>Add <code>--check</code> to <code>uv pip install</code> and <code>uv
pip sync</code> to report planned changes without modifying the
environment (<a
href="https://redirect.github.com/astral-sh/uv/pull/21844">#21844</a>)</li>
<li>Identify failures from <code>get_requires_for_build_*</code> hooks
correctly in build errors (<a
href="https://redirect.github.com/astral-sh/uv/pull/21881">#21881</a>)</li>
</ul>
<h3>Preview features</h3>
<ul>
<li>Validate build requirements for <code>uv build
--no-build-isolation</code> with <code>--preview-features
build-dependency-check</code>; use <code>--skip-dependency-check</code>
to opt out (<a
href="https://redirect.github.com/astral-sh/uv/pull/21880">#21880</a>)</li>
</ul>
<h3>Performance</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/uv/commit/bea138450f0e620a4ce5765b0e38cff7b9f0799f"><code>bea1384</code></a>
Bump version to 0.12.19 (<a
href="https://redirect.github.com/astral-sh/uv/issues/21975">#21975</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/299a93de4b94e754f260c673d2de456afbdd4fb7"><code>299a93d</code></a>
Sync latest Python releases (<a
href="https://redirect.github.com/astral-sh/uv/issues/21970">#21970</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/30de9e2cc92018c7c16a1ab66bb9b8341fbf0eff"><code>30de9e2</code></a>
Preserve query parameters in direct URL metadata (<a
href="https://redirect.github.com/astral-sh/uv/issues/21971">#21971</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/0e7433eee906fe81709c95c5bde556263367f21f"><code>0e7433e</code></a>
Filter distribution hashes in tests (<a
href="https://redirect.github.com/astral-sh/uv/issues/21941">#21941</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/c73db78f0b00580b3c67279b59b85153a9d0264d"><code>c73db78</code></a>
Omit unused runtime settings from lockfiles (<a
href="https://redirect.github.com/astral-sh/uv/issues/21913">#21913</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/ad123420aaa75b3bdbccf81496aaece8b9045b30"><code>ad12342</code></a>
Add a preview feature for lazy build backend imports (<a
href="https://redirect.github.com/astral-sh/uv/issues/21967">#21967</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/dd965a276182e2d46d80439feecd03216cc6643a"><code>dd965a2</code></a>
Restore <code>FlatDistributions</code> for downstream resolvers (<a
href="https://redirect.github.com/astral-sh/uv/issues/21965">#21965</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/214d7f677585fbb0bb46fadef890335e388641c0"><code>214d7f6</code></a>
Use Astra for PR security reviews (<a
href="https://redirect.github.com/astral-sh/uv/issues/21959">#21959</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/3db665232544183edcb80dd7077b8051b365e236"><code>3db6652</code></a>
Disable incremental compilation when publishing docs (<a
href="https://redirect.github.com/astral-sh/uv/issues/21955">#21955</a>)</li>
<li><a
href="https://github.com/astral-sh/uv/commit/e18f413b23bfe5f33bcc1a3a3de330e4716aedcf"><code>e18f413</code></a>
Reproduce editable project relocation failure (<a
href="https://redirect.github.com/astral-sh/uv/issues/21948">#21948</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/uv/compare/0.12.16...0.12.19">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: CaliBrain <calibrain@l4n.xyz>
2026-09-25 19:18:30 -04:00

290 lines
12 KiB
Docker

ARG TARGETPLATFORM
ARG TARGETARCH
ARG BUILDPLATFORM
ARG BUILDARCH
# Frontend build stage.
FROM --platform=$BUILDPLATFORM node:24-alpine@sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1 AS frontend-builder
# Helpful debug output to see what platforms BuildKit thinks it's using
RUN echo "BUILDPLATFORM=$BUILDPLATFORM BUILDARCH=$BUILDARCH TARGETPLATFORM=$TARGETPLATFORM TARGETARCH=$TARGETARCH"
WORKDIR /frontend
# Copy frontend package files
COPY src/frontend/package*.json ./
# Install dependencies (cache mount for faster rebuilds)
RUN --mount=type=cache,target=/root/.npm \
npm ci
# Copy frontend source
COPY src/frontend/ ./
# Build the frontend
RUN npm run build
# uv is a build-time tool only, so it is mounted into the RUNs that need it rather
# than copied into the image. A COPY here would land ~24 MB in a `base` layer that
# every published image inherits, and a later `rm` cannot take it back out again --
# a RUN adds a layer, it does not rewrite the one underneath.
FROM ghcr.io/astral-sh/uv:0.12.19@sha256:04d046b13e60d6bcec73cbc5e1cad25d680dea90c8573340950a0ac2d1aef424 AS uv
# Use python-slim as the base image
FROM python:3.14.7-slim@sha256:cad9a2c871761c413caa6fdd6441c783451e740a48aaeba60ae62a8b53525ef6 AS base
# Set shell to bash with pipefail option
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Consistent environment variables grouped together
ENV DEBIAN_FRONTEND=noninteractive \
DOCKERMODE=true \
UV_LINK_MODE=copy \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONIOENCODING=UTF-8 \
NAME=Shelfmark \
PATH=/app/.venv/bin:$PATH \
PYTHONPATH=/app \
# PUID/PGID will be handled by entrypoint script, but TZ/Locale are still needed
LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8
# Set ARG for build-time expansion (FLASK_PORT), ENV for runtime access
ENV FLASK_PORT=8084
# Configure locale, timezone, and perform initial cleanup in a single layer
RUN apt-get update && \
apt-get install -y --no-install-recommends \
# For building C-extensions (cffi, gevent, etc.)
gcc \
g++ \
libffi-dev \
python3-dev \
# For locale
locales tzdata \
# For healthcheck
curl \
# For entrypoint
dumb-init \
# For debug
zip iputils-ping \
# For user switching
gosu \
# --- Tor support (activated via USING_TOR=true) ---
tor \
supervisor \
iptables \
# --- WireGuard support (activated via USING_WIREGUARD=true) ---
wireguard-tools \
iproute2 \
procps \
ca-certificates && \
# Configure iptables alternatives for tor.sh compatibility
update-alternatives --set iptables /usr/sbin/iptables-legacy && \
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy && \
# Cleanup APT cache *after* all installs in this layer
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
# Default to UTC timezone but will be overridden by the entrypoint script
ln -snf /usr/share/zoneinfo/UTC /etc/localtime && echo UTC > /etc/timezone && \
# Configure locale
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen en_US.UTF-8 && \
echo "LC_ALL=en_US.UTF-8" >> /etc/environment && \
echo "LANG=en_US.UTF-8" > /etc/locale.conf
# Create a fixed runtime user/group so hardened Docker/Kubernetes deployments
# can start the container directly as a non-root user with a passwd entry.
RUN groupadd -g 1000 shelfmark && \
useradd -u 1000 -g shelfmark -d /home/shelfmark -s /usr/sbin/nologin shelfmark && \
mkdir -p /home/shelfmark && \
chown 1000:1000 /home/shelfmark
# Set working directory
WORKDIR /app
# Install core Python dependencies first for better layer caching
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=from=uv,source=/uv,target=/usr/local/bin/uv \
uv sync --locked --no-default-groups
# Runtime dependencies are installed into /app/.venv during the build. Remove the
# base image's system pip so stale installer CVEs do not ship in the final image.
RUN rm -rf \
/usr/local/bin/pip \
/usr/local/bin/pip3 \
/usr/local/bin/pip3.* \
/usr/local/lib/python*/site-packages/pip \
/usr/local/lib/python*/site-packages/pip-*.dist-info
# The application code is deliberately NOT copied here. `base` is shared by the
# final stages, so a COPY of the source at this point invalidates every layer
# built on top of it -- the Chromium install, the browser dependency sync and
# the SeleniumBase driver download -- on any source change. Each stage copies
# the source as its last step instead, so a code-only rebuild rewrites one small
# layer and every expensive layer is reused. `[tool.uv] package = false` is what
# makes this safe: no `uv sync` needs the project source.
# Expose the application port
EXPOSE ${FLASK_PORT}
# Add healthcheck for container status
# Uses /api/health which doesn't require authentication.
# curl needs -f so an HTTP error status fails the probe instead of passing it:
# plain `curl -s` exits 0 on a 500, which reported a broken app as healthy.
# timeout stays well under interval so a hung probe cannot occupy a whole cycle.
# --start-interval matches the daemon default (5s), made explicit so startup
# probing does not depend on that default staying put.
HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --start-interval=5s --retries=3 \
CMD curl -fsS http://localhost:${FLASK_PORT}/api/health > /dev/null || exit 1
# Use dumb-init as the entrypoint to handle signals properly
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
FROM base AS shelfmark
# --- Chromium (PINNED to 149.0.7827.196) ---
# Debian's chromium 150.0.7871.46-1~deb13u1 security update (trixie-security,
# 2026-07-05) no longer opens the DevTools remote-debugging TCP port at all
# (no listener, no DevToolsActivePort file, even with a custom --user-data-dir;
# the RemoteDebuggingAllowed policy does not restore it). The SeleniumBase
# Pure-CDP driver connects through that port (/json/version), so with 150 every
# internal bypass dies with "Pure CDP browser startup failed" and all
# CF-gated downloads fail. Install the last working version from
# snapshot.debian.org until the bypasser can talk to Chromium >= 150 (e.g.
# pipe-based DevTools / UC mode) or seleniumbase ships a fix.
# Chrome 144+ requires --enable-unsafe-swiftshader for WebGL in Docker.
# This flag is set in internal_bypasser.py _get_browser_args()
ARG CHROMIUM_VERSION=149.0.7827.196-1~deb13u1
ARG CHROMIUM_SNAPSHOT=20260704T000000Z
RUN echo "deb [check-valid-until=no] https://snapshot.debian.org/archive/debian-security/${CHROMIUM_SNAPSHOT}/ trixie-security main" \
> /etc/apt/sources.list.d/chromium-pin-snapshot.list && \
apt-get update -o Acquire::Retries=5 && \
apt-get install -y --no-install-recommends -o Acquire::Retries=5 \
# For dumb display
xvfb \
# For screen recording
ffmpeg \
chromium=${CHROMIUM_VERSION} \
chromium-common=${CHROMIUM_VERSION} \
# For tkinter (pyautogui)
python3-tk \
# For RAR extraction
unrar-free && \
# Keep apt from "upgrading" chromium past the pin inside derived images
printf 'Package: chromium chromium-common\nPin: version %s\nPin-Priority: 1001\n' "${CHROMIUM_VERSION}" \
> /etc/apt/preferences.d/chromium-pin && \
rm /etc/apt/sources.list.d/chromium-pin-snapshot.list && \
# Create symlink so rarfile library can find unrar
ln -sf /usr/bin/unrar-free /usr/bin/unrar && \
# Cleanup APT cache
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Install the browser automation stack used by the full image
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=from=uv,source=/uv,target=/usr/local/bin/uv \
uv sync --locked --no-default-groups --extra browser
# Deterministically resolve the Xlib namespace collision.
# pyautogui/mouseinfo pull the stale `python3-xlib` (0.15, 2014), while the
# `--extra browser` set pulls `python-xlib` (0.33). Both packages install into
# the same top-level `Xlib/` namespace, so whichever lands last wins. When the
# 2014 build wins, `Xlib.X` is missing `FamilyServerInterpreted`, which the
# SeleniumBase Pure-CDP driver requires at browser startup -> every bypass fails
# with "module 'Xlib.X' has no attribute 'FamilyServerInterpreted'" and no
# Cloudflare/DDoS-Guard protected download can complete. Drop the stale package
# and force python-xlib 0.33 to own the namespace. pyautogui runs fine against
# 0.33 (superset API).
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=from=uv,source=/uv,target=/usr/local/bin/uv \
uv pip uninstall --python /app/.venv/bin/python python3-xlib && \
uv pip install --python /app/.venv/bin/python --reinstall python-xlib==0.33 && \
/app/.venv/bin/python -c "import Xlib.X; assert hasattr(Xlib.X, 'FamilyServerInterpreted'), 'Xlib.X.FamilyServerInterpreted missing after fix'; print('Xlib namespace OK:', Xlib.__version__)"
# Keep SeleniumBase's bundled driver cache writable for the fixed non-root user.
RUN SELENIUMBASE_DRIVERS_DIR=$(/app/.venv/bin/python -c "import pathlib, seleniumbase; print(pathlib.Path(seleniumbase.__file__).resolve().parent / 'drivers')") && \
chown -R 1000:1000 "${SELENIUMBASE_DRIVERS_DIR}" && \
chmod -R u+rwX,go+rX "${SELENIUMBASE_DRIVERS_DIR}" && \
if [ -f "${SELENIUMBASE_DRIVERS_DIR}/uc_driver" ]; then chmod +x "${SELENIUMBASE_DRIVERS_DIR}/uc_driver"; fi
# Grant read/execute permissions to others
RUN chmod -R o+rx /usr/bin/chromium
# --- Application code: last, so every expensive layer above stays cached ---
COPY . .
COPY --from=frontend-builder /frontend/dist /app/frontend-dist
# Image-owned runtime paths for the fixed non-root user. Root/PUID mode still
# re-homes ownership at startup when needed.
RUN mkdir -p \
/config \
/books \
/var/log/shelfmark \
/tmp/shelfmark/seleniumbase/downloaded_files \
/tmp/shelfmark/seleniumbase/archived_files && \
rm -rf /app/downloaded_files /app/archived_files && \
ln -s /tmp/shelfmark/seleniumbase/downloaded_files /app/downloaded_files && \
ln -s /tmp/shelfmark/seleniumbase/archived_files /app/archived_files && \
chown -R 1000:1000 /config /books /home/shelfmark /tmp/shelfmark /var/log/shelfmark && \
chmod -R a+rX /app && \
chmod +x /app/entrypoint.sh /app/tor.sh /app/wireguard.sh /app/genDebug.sh
# Default command to run the application entrypoint script
# Version stamp last. These carry the commit sha, so they change on every
# build and everything below them rebuilds. Kept here, the dependency and
# browser layers above stay valid and a pull only fetches what changed.
ARG BUILD_VERSION
ENV BUILD_VERSION=${BUILD_VERSION}
ARG RELEASE_VERSION
ENV RELEASE_VERSION=${RELEASE_VERSION}
CMD ["/app/entrypoint.sh"]
FROM base AS shelfmark-lite
ENV USING_EXTERNAL_BYPASSER=true
# --- Application code: last, so every expensive layer above stays cached ---
COPY . .
COPY --from=frontend-builder /frontend/dist /app/frontend-dist
# Image-owned runtime paths for the fixed non-root user. Root/PUID mode still
# re-homes ownership at startup when needed.
RUN mkdir -p \
/config \
/books \
/var/log/shelfmark \
/tmp/shelfmark/seleniumbase/downloaded_files \
/tmp/shelfmark/seleniumbase/archived_files && \
rm -rf /app/downloaded_files /app/archived_files && \
ln -s /tmp/shelfmark/seleniumbase/downloaded_files /app/downloaded_files && \
ln -s /tmp/shelfmark/seleniumbase/archived_files /app/archived_files && \
chown -R 1000:1000 /config /books /home/shelfmark /tmp/shelfmark /var/log/shelfmark && \
chmod -R a+rX /app && \
chmod +x /app/entrypoint.sh /app/tor.sh /app/wireguard.sh /app/genDebug.sh
# Version stamp last. These carry the commit sha, so they change on every
# build and everything below them rebuilds. Kept here, the dependency and
# browser layers above stay valid and a pull only fetches what changed.
ARG BUILD_VERSION
ENV BUILD_VERSION=${BUILD_VERSION}
ARG RELEASE_VERSION
ENV RELEASE_VERSION=${RELEASE_VERSION}
CMD ["/app/entrypoint.sh"]