From 515c92c40382b1958fcb880113eab6f8c7c540bb Mon Sep 17 00:00:00 2001 From: Nathan Schneider Date: Fri, 23 Oct 2026 10:57:25 -0600 Subject: [PATCH] log-guard: root supervisord program keeps dated log files cloudron-owned A host-side daily job creates the next day's dated log files as root:root at 00:00 UTC; LibreChat (cloudron user) then EACCES-crashes on its first log write of the day (2026-10-22 and 2026-10-23 incidents). The guard pre-creates today's and tomorrow's files as cloudron and repairs strays every minute. Defense-in-depth until the host rotation config is fixed. --- Dockerfile | 8 ++++++ __pycache__/patch_index.cpython-313.pyc | Bin 0 -> 3671 bytes assets/log-guard.sh | 33 ++++++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 __pycache__/patch_index.cpython-313.pyc create mode 100755 assets/log-guard.sh diff --git a/Dockerfile b/Dockerfile index a1c6418..825fec0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,3 +65,11 @@ RUN python3 /app/code/patch_index.py && \ # light + dark pair so browser/PWA chrome matches the phone theme natively. RUN sed -i 's|"theme_color": *"#009688"|"theme_color":"#eaf3ea"|; s|"background_color": *"#000000"|"background_color":"#eaf3ea"|' /app/code/librechat/client/dist/manifest.webmanifest && \ sed -i 's||\n |' /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. +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\n' > /etc/supervisor/conf.d/logguard.conf diff --git a/__pycache__/patch_index.cpython-313.pyc b/__pycache__/patch_index.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dfc3dd300a732ca694c47ffe058c278db2a76ee9 GIT binary patch literal 3671 zcmbVP&2!tv6<-h_36dr$QBowkj=iSU$h1Y$`ttZgRK{^^$93&Af*l{ssRja<6eJQr z7N97h&J2BOk{+U@%~Xf}0ZwKz&C$JinwiE&a_Ej}^pZ(WzDc7VI_;%z!4J`LoYcV# zh_~!}0Xm_mPIn$=8H|w46?-8^~$tU?|Jgo)wN@CV~jzdTuK?UzQf{nGw1(2))R^)r_`2-K^L%ErLvr&Mh~I+Tq`hqJM1LBa>nvOov3gK;Ds z=|q;|(otzt`guxl`LA{PV?V$@*40mR^^b%8i4^a88SiqFJ=|26n{IK_KFIH+n_sIY zKUC-F{PFLtX1_EcO`h>|d}EY-1@fEPv!32v7d%H$*5^ku>?Y9mgErTZ5-yK2{9%;m z{vVyhO!-S_(<|CCQ7o+JN!`GURMv8;R=_8)j15AQi)FQ#!zG!n5QCVfJ7`at&~kmFQpXIw8gG4)1iVGuGylhtw6bonYd}K7YXD{tTkMLS3_Dc{QsrXORG@b<6XR@?5h^Q|x=NB2HCG^3hQfBT zi3xq}da^J71fy}hs*;MKQ!ANQt&F0>&avO=sZmMR)I2e}Zzq-Ra8ebr*r6dEs+*=x z)q<*J;$@R06-siDA0z?wv8P_%<($J+?CBqC=?;QkG-dY5@LZ!h0(%Wkpet~K<`N{n zz}V%BU~-L=7Gby*SP?Xm!{@I+**opd_OwCORoNmKrXh5%Mk?|m?CcV3xFT#+9j1br zazZfX+-`vZjy*tZC~cShjnGjtP0U}E0}x^+d+6hDd*p6fRM z`f3KYDG!(u9AzI}Ci8=xh&%iiT6@}9cRUNLGzyYyOoe@*R8ccFv@x`y{ORcCP%V16 zCLZ1aHnNA?TTF${Nlu)ZT!TAhXa&dLUf2P(Bo|1U@pxHVPY7;c$LltnBUtMOar{P^ z8oEjBk+!>%Y_70^B$?lqznO{2HMkwIBeRdTm0?nWrlpsaC09Q=ar)#M+-)4KMS^$Z zQkD%JWY9aY@-oa|KtDCPHr2xJb;;)xCQhwQoN}FdUDEL~JM$^~PJ^=gSot)|KG^A_ zv+W~Kb(_~($1v0E$=$)(k@p;ldk#Z(ZjxML*zqqc%38(#r~Qe0iOgWXs`U064zZiR*YPRJDlX zz1DKMY(l4b7u<(X)WNf-l!w-{C=Ij9v955uIXDYV#|u5IS)U^cAMJ=nm_(d~4lcvs zr_-=x&1K$#@@(-O$88HDC+x%!x9?m3R8`m#cy8oLD7qnRR_dX#$D#3hXuJ_hRo~nS zB5~hu@7%pp8%)(s-fZ~a1#KS^hBtE!KHdyPKc4+?wkgJ%;#*BIu;Ul@`COyD3TK<5 z+M^IbLTq!e!N1xJpL!h5)Wey-C=W)zN&GeO^@+yZ^+x#Z>ZP{x&0uYG`m5FYXy*QV zjnH}U9&1Bt3TK+awH+@ndH|Hz<=z58o4XxEoVR-8gQ?BoIy&+gjn&cEJ>d~bf_mWf zs&~tCkQ@1jF!F66^6`O>4t(Hjr%erS9*4c(s;O>*DermR1*amvy?)cjm#B+O5U9sO;(tKRi(v z-`%_33i}6qfUt7+>UJOU20j?t;5Q3(;kC!YcwHF3ck|D;zqoxr_TYRydFhdG`H2vy z1&=)v65Bq+`D(tie@Ey3y#-w&Mt2YgEfE~tc;|P?nlQ||X5_zH@IUDLMgK9`!24+E a(lq+|=mqhz5B+UAdYR|H@kK8W@&5zHOY<@S literal 0 HcmV?d00001 diff --git a/assets/log-guard.sh b/assets/log-guard.sh new file mode 100755 index 0000000..eb55f90 --- /dev/null +++ b/assets/log-guard.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Log ownership guard for /app/data/logs. +# +# A host-side daily job creates the next day's dated log files +# (error-.log, meiliSync-.log, ...) as root:root at 00:00 UTC. +# LibreChat runs as the `cloudron` user and crashes (EACCES on uncaught +# error) the first time it tries to append to a root-owned log. This guard +# runs as root (via supervisord) and, every minute: +# 1. pre-creates TODAY's and TOMORROW's dated files owned by cloudron +# (an existing correctly-owned file defeats the ownership flip — +# open(O_TRUNC) preserves the inode's owner), +# 2. chowns any root-owned strays back to cloudron. +# +# This is a defense-in-depth stopgap; the host-side rotation config should +# still be fixed to create files as cloudron (see co-op/support thread and +# the overlay README). +set -u +LOGDIR="/app/data/logs" +mkdir -p "$LOGDIR" + +while true; do + for offset in 0 1; do + d=$(date -u -d "+${offset} day" +%F 2>/dev/null) + [ -z "$d" ] && continue + for prefix in error meiliSync; do + f="$LOGDIR/${prefix}-${d}.log" + [ -e "$f" ] || : > "$f" + done + done + # Repair any root-owned strays (covers unknown file prefixes too). + find "$LOGDIR" ! -user cloudron -exec chown cloudron:cloudron {} \; 2>/dev/null + sleep 60 +done