# Inference Co-op LibreChat — brand overlay on the official Cloudron package
#
# Build:  cloudron builder build --repository registry.inference.coop/co-op/librechat-custom --tag <yyyymmdd>-<gitsha>
# Deploy: cloudron update --app <app-id> --image registry.inference.coop/co-op/librechat-custom:<tag>
#         (run from THIS directory — the CLI reads CloudronManifest.json here)
#
# Rules that keep this image safe:
#   1. The base tag is PINNED to the exact appstore image the app runs
#      (manifest.dockerImage). Never a floating tag: a rebuild must never
#      silently pull a newer LibreChat than the one we validated.
#   2. CloudronManifest.json keeps the OFFICIAL appstore addons block
#      (postgresql, mongodb, oidc, sendmail, localstorage) — never remove or
#      hand-edit those, or the app crash-loops (mkdir: Read-only file system).
#      The ONLY field we change is `dockerImage`, repointed to the overlay tag
#      built from this repo on every deploy (the base FROM stays the appstore
#      image we validated). A stale dockerImage pin silently redeploys an old
#      build — that is what broke the sandbox on 2026-10-18/19.
#   3. This image changes ONLY static brand assets plus operational scripts that
#      must not depend on the persistent volume (currently sync-keys.js, run by
#      the manifest's scheduler task). All other behavior lives on the
#      persistent volume (/app/data/librechat.yaml, /app/data/env,
#      /app/data/mcp/) and survives image updates unchanged.
FROM cloudron/ai.librechat.cloudronapp:202610230221180000

# Login-page + header logo (the client bundle references assets/logo.svg)
COPY assets/logo.svg /app/code/librechat/client/dist/assets/logo.svg
# favicon.ico (multi-size, generated from the 192 icon) — some Android
# shortcut/icon-resolution flows request it explicitly.
COPY assets/favicon.ico /app/code/librechat/client/dist/assets/favicon.ico
# Root-level favicon.ico — browsers/launchers request /favicon.ico by default
COPY assets/favicon.ico /app/code/librechat/client/dist/favicon.ico
# Browser favicons + PWA icons (referenced by dist/index.html + manifest.webmanifest)
COPY assets/favicon-32x32.png /app/code/librechat/client/dist/assets/favicon-32x32.png
COPY assets/favicon-16x16.png /app/code/librechat/client/dist/assets/favicon-16x16.png
COPY assets/apple-touch-icon-180x180.png /app/code/librechat/client/dist/assets/apple-touch-icon-180x180.png
COPY assets/icon-192x192.png /app/code/librechat/client/dist/assets/icon-192x192.png
COPY assets/maskable-icon.png /app/code/librechat/client/dist/assets/maskable-icon.png
# Figtree font (design kit, SIL OFL) — self-hosted, matches homepage/dashboard
COPY assets/fonts/ /app/code/librechat/client/dist/assets/fonts/

# Custom stylesheet and optional helper JS
COPY assets/custom.css /app/code/librechat/client/dist/assets/custom.css
# rebuild trigger
COPY assets/custom2.js /app/code/librechat/client/dist/assets/custom2.js

# Per-member key seed (manifest scheduler task `librechat_key_sync`). Shipping it
# in the image rather than on the volume means it cannot vanish with a volume
# restore and cannot drift from this repo; the script prints its own md5 prefix
# on every run so the running revision is auditable.
COPY sync-keys.js /app/code/sync-keys.js

# Co-op UI strings: rename the "MCP Servers" button to "Tools" and replace
# the LibreChat footer tagline with the co-op footer. Non-fatal at build.
COPY patch_ui_strings.py /app/code/patch_ui_strings.py
RUN python3 /app/code/patch_ui_strings.py

# Inject branding into built HTML (dist) before image is packaged.
# patch_index.py: title, custom.css/custom2.js links, and a per-build
# x-coop-build meta (unique every build → service worker precache revision
# changes → stale clients self-heal on deploy). Non-fatal at build.
# rebuild marker 20261019-$(date +%s)
COPY patch_index.py /app/code/patch_index.py
RUN python3 /app/code/patch_index.py && \
    sed -i 's|assets/logo.svg|assets/logo.svg?v=3|g' /app/code/librechat/client/dist/assets/index.*.js && \
    rm -f /app/code/librechat/client/dist/assets/index.*.js.gz /app/code/librechat/client/dist/assets/index.*.js.br && \
    echo "// coop-build-$(date +%s)" >> /app/code/librechat/client/dist/sw.js

# PWA chrome colors: LibreChat ships a teal theme_color (#009688) in the web
# manifest (the bright green bar Firefox PWAs draw across the top) and black
# background_color. Point both at the light page color — CREAM #faf8f5, the
# dashboard's page background (the manifest can only hold one value; custom2.js
# re-syncs the meta tags to the app's actual theme at runtime). The index.html
# meta gets a light + dark pair so browser/PWA chrome matches the phone theme
# natively. KEEP THESE THREE IN SYNC: this sed, custom.css's html:not(.dark)
# background, and custom2.js COOP_BG.light — the green wash #eaf3ea used to sit
# in all three and made the installed app read as green.
RUN sed -i 's|"theme_color": *"#009688"|"theme_color":"#faf8f5"|; s|"background_color": *"#000000"|"background_color":"#faf8f5"|' /app/code/librechat/client/dist/manifest.webmanifest && \
    sed -i 's|<meta name="theme-color" content="#171717" />|<meta name="theme-color" media="(prefers-color-scheme: light)" content="#faf8f5" />\n    <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#22271f" />|' /app/code/librechat/client/dist/index.html

# Log ownership guard: a host-side daily job creates the next day's dated log
# files in /app/data/logs as root:root at 00:00 UTC; LibreChat (cloudron user)
# then crashes with EACCES on its first log write of the day. This supervisor
# program runs as root and keeps the dated files cloudron-owned (see
# assets/log-guard.sh). Remove once the host logrotate config is fixed.
# NOTE: stdout/stderr MUST be explicit paths — supervisord's auto-named child
# logs go to a directory that does not exist in this image and crash it.
COPY assets/log-guard.sh /app/code/log-guard.sh
RUN printf '[program:logguard]\ncommand=/bin/bash /app/code/log-guard.sh\nuser=root\nautorestart=true\nstartsecs=0\npriority=1\nredirect_stderr=true\nstdout_logfile=/app/data/logs/logguard.log\nstdout_logfile_maxbytes=10MB\nstdout_logfile_backups=2\n' > /etc/supervisor/conf.d/logguard.conf
