Skip to content

Commit fc2098b

Browse files
nciminoclaude
andcommitted
fix(anythingllm): caddy /var/log perms + ANYTHINGLLM_IMAGE bootstrap prompt
Post-deploy follow-ups from the INT-S004 rebuild: 1) Hardened non-root caddy:2 crash-looped with "permission denied" writing /var/log/caddy/<site>.log — nothing created that host bind-mount dir writable. ansible/deploy.yml now ensures /var/log/caddy (0777) before `docker compose up` (template + s004.ccc.bot + ai.weown.agency). 2) ANYTHINGLLM_IMAGE is now a required Infisical secret (compose reads it fail-loud). bootstrap-s004-infisical.sh prompts for it (plain read — not a secret, but carries the private registry namespace, so it stays in Infisical not the repo), and the s004.ccc.bot README documents it. Render parity (template==site deploy.yml), bash -n, YAML all verified. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0a03e8c commit fc2098b

6 files changed

Lines changed: 48 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Changes in this section will be promoted to a dated release entry on merge to `m
6060

6161
### Fixed
6262

63+
- **Post-deploy follow-ups: caddy log-dir perms + `ANYTHINGLLM_IMAGE` bootstrap (2026-06-02)** — (1) the hardened (non-root) `caddy:2` crash-looped with `permission denied` writing `/var/log/caddy/<site>.log` because nothing created that host bind-mount dir writable; `ansible/deploy.yml` now ensures `/var/log/caddy` (mode 0777) before `docker compose up` (template + `s004.ccc.bot` + `ai.weown.agency`). (2) `scripts/bootstrap-s004-infisical.sh` now prompts for the now-required `ANYTHINGLLM_IMAGE`, and the `s004.ccc.bot` README documents it, so a rebuild repopulates the image ref in Infisical.
6364
- **AnythingLLM published no host port → deploy health probe + runbook tunnel could never connect (2026-06-02)** — the `anythingllm` service had no `ports:` (caddy proxies it over the internal Docker network), yet `ansible/deploy.yml`'s health task polls `http://127.0.0.1:3001/api/ping` on the *host* and the runbook's Phase-4 validation uses `ssh -L 3001:127.0.0.1:3001` — both assume 3001 is published on the droplet loopback. The container was healthy the whole time (`docker inspect` health=healthy, internal ping `{"online":true}`); the probe was checking an unpublished port and failed with `Connection refused`. Added `ports: ["127.0.0.1:3001:3001"]` (loopback-only — not internet-exposed; caddy still serves the public via the internal network) to the template + `s004.ccc.bot` + `ai.weown.agency`.
6465
- **AnythingLLM image pin `1.7.2` was invalid + hardcoded a private registry path (2026-06-02)** — the compose pinned `reg.mini.dev/anythingllm:1.7.2`, but that tag was never in the Minimus registry (the source box actually ran `:latest`, and Minimus rotates tags + had moved the image to a private namespaced path), so the deploy 404'd on image pull. The image ref is now injected from Infisical (`ANYTHINGLLM_IMAGE`, e.g. `reg.mini.dev/<ns>/anythingllm:v1.12.1`): compose reads `${ANYTHINGLLM_IMAGE:?…}` (fail-loud) and `docker compose up` pulls it under `infisical run`, so the private namespace never enters this public repo and each site pins its own version. The deploy's image-pull task now pulls only the static `caddy` ref. Applied to the template + `s004.ccc.bot` + `ai.weown.agency`; render parity + compose interpolation verified.
6566
- **Infisical machine-identity auth hung on headless boxes — `infisical run` fell back to an interactive login prompt (2026-06-02)**`ansible/deploy.yml`, `scripts/backup.sh`, and `scripts/restore.sh` ran `infisical login --method=universal-auth …` followed by a bare `infisical run …`, but a universal-auth (machine identity) login does **not** leave a session that `infisical run` reuses. `run` therefore saw no auth and dropped to the interactive `Select hosting option / Email / Password` prompt, which hangs forever on a no-TTY ansible/cron run (`Login via browser failed. inappropriate ioctl for device`). Fixed by capturing the token — `export INFISICAL_TOKEN="$(infisical login … --plain --silent)"` — which `infisical run` reads directly (the documented headless/CI pattern). Applied to the template + `s004.ccc.bot` + `ai.weown.agency`; render parity and `bash -n` verified.

anythingllm-docker/sites/ai.weown.agency/ansible/deploy.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,18 @@
154154
delay: 5
155155
until: image_pull is succeeded
156156

157+
- name: Ensure caddy log dir is writable (hardened caddy runs non-root)
158+
# caddy:2 (Minimus-hardened) runs as a non-root user and writes access
159+
# logs to the /var/log/caddy host bind mount. Without a writable dir it
160+
# crash-loops with "permission denied". 0777 is acceptable for a
161+
# single-tenant log dir; otel-agent also reads these files.
162+
ansible.builtin.file:
163+
path: /var/log/caddy
164+
state: directory
165+
owner: root
166+
group: root
167+
mode: "0777"
168+
157169
- name: Ensure compose stack is running (idempotent — `up -d` is a no-op if nothing changed)
158170
ansible.builtin.shell: |
159171
set -euo pipefail

anythingllm-docker/sites/s004.ccc.bot/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,10 @@ bash scripts/bootstrap-s004-infisical.sh
6262
```
6363

6464
It sets `JWT_SECRET` (generated, never rotate), `OPENROUTER_API_KEY` (a **fresh**
65-
key — the old one expired 2026-06-01), `ADMIN_EMAIL`, `SPACES_ACCESS_KEY`,
66-
`SPACES_SECRET_KEY`.
65+
key — the old one expired 2026-06-01), `ADMIN_EMAIL`, `ANYTHINGLLM_IMAGE` (the
66+
container image ref, e.g. `reg.mini.dev/<ns>/anythingllm:v1.12.1` — kept in
67+
Infisical so the private registry namespace stays out of this public repo),
68+
`SPACES_ACCESS_KEY`, `SPACES_SECRET_KEY`.
6769

6870
### 2. Provision (terraform — first-boot bootstrap)
6971

anythingllm-docker/sites/s004.ccc.bot/ansible/deploy.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,18 @@
220220
delay: 5
221221
until: image_pull is succeeded
222222

223+
- name: Ensure caddy log dir is writable (hardened caddy runs non-root)
224+
# caddy:2 (Minimus-hardened) runs as a non-root user and writes access
225+
# logs to the /var/log/caddy host bind mount. Without a writable dir it
226+
# crash-loops with "permission denied". 0777 is acceptable for a
227+
# single-tenant log dir; otel-agent also reads these files.
228+
ansible.builtin.file:
229+
path: /var/log/caddy
230+
state: directory
231+
owner: root
232+
group: root
233+
mode: "0777"
234+
223235
- name: Ensure compose stack is running (idempotent — `up -d` is a no-op if nothing changed)
224236
ansible.builtin.shell: |
225237
set -euo pipefail

anythingllm-docker/sites/s004.ccc.bot/scripts/bootstrap-s004-infisical.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ _maybe_push_secret OPENROUTER_API_KEY "Paste the OpenRouter key value (blank to
117117
read -rp " ADMIN_EMAIL (blank to skip): " ADMIN_EMAIL
118118
if [ -n "${ADMIN_EMAIL:-}" ]; then _push ADMIN_EMAIL "$ADMIN_EMAIL"; else echo " • skipped ADMIN_EMAIL (left blank)"; fi
119119

120+
# ANYTHINGLLM_IMAGE - the container image ref. NOT a secret, but it carries the
121+
# private registry namespace, so it lives in Infisical (not this public repo).
122+
# Required: compose reads ${ANYTHINGLLM_IMAGE} fail-loud and the deploy pulls it
123+
# under `infisical run`. plain read (not a secret); blank = skip.
124+
read -rp " ANYTHINGLLM_IMAGE (e.g. reg.mini.dev/<ns>/anythingllm:v1.12.1; blank to skip): " ANYTHINGLLM_IMAGE
125+
if [ -n "${ANYTHINGLLM_IMAGE:-}" ]; then _push ANYTHINGLLM_IMAGE "$ANYTHINGLLM_IMAGE"; else echo " • skipped ANYTHINGLLM_IMAGE (left blank)"; fi
126+
120127
# SPACES_* — required for offsite backups; blank = skip.
121128
_maybe_push_secret SPACES_ACCESS_KEY "SPACES_ACCESS_KEY (DO Spaces, for backups; blank to skip): "
122129
_maybe_push_secret SPACES_SECRET_KEY "SPACES_SECRET_KEY (blank to skip): "

anythingllm-docker/template/ansible/deploy.yml.jinja

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,18 @@
220220
delay: 5
221221
until: image_pull is succeeded
222222

223+
- name: Ensure caddy log dir is writable (hardened caddy runs non-root)
224+
# caddy:2 (Minimus-hardened) runs as a non-root user and writes access
225+
# logs to the /var/log/caddy host bind mount. Without a writable dir it
226+
# crash-loops with "permission denied". 0777 is acceptable for a
227+
# single-tenant log dir; otel-agent also reads these files.
228+
ansible.builtin.file:
229+
path: /var/log/caddy
230+
state: directory
231+
owner: root
232+
group: root
233+
mode: "0777"
234+
223235
- name: Ensure compose stack is running (idempotent — `up -d` is a no-op if nothing changed)
224236
ansible.builtin.shell: |
225237
set -euo pipefail

0 commit comments

Comments
 (0)