chore(searxng): adopt the concurrent v4 work, with its dead mechanism marked

Picks up uncommitted searxng changes left by another session and makes them
truthful rather than committing them as written. The stack itself verifies
clean: canonical and live are byte-identical for both compose.yaml and
searxng-settings.yml, the container is running with zero restarts, and live
queries return 51-54 results from 5-6 engines with braveapi contributing 20
each time.

compose.yaml gains SEARXNG_BRAVE_API_KEY, which NOTHING READS. It was added on
the belief that settings.yml could pull it via `!ENV SEARXNG_BRAVE_API_KEY`;
this build has no !ENV YAML constructor, so that attempt made the file
unparseable and crash-looped the container ten times with fleet search down.
The comment claiming the variable is "consumed by settings.yml" is replaced
with what is actually true. The variable is kept, unused, in case upstream ever
gains env interpolation — a comment that lies is worse than a variable that
does nothing.

The Tier A playbook is marked superseded FOR THE SETTINGS FILE ONLY, and
scoped deliberately: its v4 design uploads a settings file carrying the !ENV
tag, which would re-break the container, so settings deployment goes through
scripts/deploy-stack.sh like every other stack. Its .env merge and
up-d-not-restart steps remain useful, as do its two warnings recording real
bugs it hit — a wholesale .env overwrite that clobbered SEARXNG_SECRET, and a
sed that inserted literal backslash-n into compose.yaml. An unscoped
"superseded" banner would have buried those; that failure mode cost an outage
earlier today.

Also folds in the regenerated graphify report.
This commit is contained in:
vh
2026-09-18 14:11:58 -07:00
parent d812bfe96d
commit 5b20b02fb9
3 changed files with 142 additions and 111 deletions
+56 -10
View File
@@ -1,32 +1,78 @@
# SearXNG Tier A captcha fix (2026-09-18): remove scraped engine families that
# CAPTCHA this egress (brave/duckduckgo/startpage), enable mojeek.
# File: /opt/docker/conf/searxng/searxng-settings.yml (bind-mounted ro into the
# container) -> restart required to take effect. Rerunnable.
# CAPTCHA this egress (brave/duckduckgo/startpage), wikidata 403'd too.
#
# ⚠ SUPERSEDED FOR THE SETTINGS FILE — read the scope of this note.
# The v4 design here assumed settings.yml could pull the Brave key via
# `!ENV SEARXNG_BRAVE_API_KEY`. This build has NO !ENV YAML constructor: that
# attempt made the file unparseable and crash-looped the container ten times
# with fleet search down. The key is now INLINE in the canonical settings file
# (operator decision, the key is low-value free-tier), and settings deployment
# goes through `scripts/deploy-stack.sh nh3-docker searxng --conf` like every
# other stack. Do NOT upload a settings file from here expecting !ENV to work.
#
# What is still worth keeping below: the `.env` merge step and the
# `up -d`-not-`restart` step, plus the two ⚠ notes recording real bugs this
# playbook hit (a wholesale .env overwrite that clobbered SEARXNG_SECRET, and a
# sed that inserted literal backslash-n into compose.yaml).
#
# Rerunnable. Pass the key at the CLI: --var brave_key=... (never store it here).
vars:
conf: /opt/docker/conf/searxng/searxng-settings.yml
compose_dir: /opt/docker/compose/searxng
brave_key: ""
searxng_secret: "" # from vault nh3-docker/searxng-secret, passed via --var
steps:
- name: Timestamped backup of current settings
shell: cp {{ conf }} {{ conf }}.bak-$(date +%Y%m%d-%H%M%S)
# Only back up while this version of the change has not been applied yet.
when: "! grep -q 'Tier A (v3' {{ conf }}"
when: "! grep -q 'Tier A (v4' {{ conf }}"
- name: Install new settings
upload:
src: /tmp/searxng-tierA/searxng-settings.yml
dest: "{{ conf }}"
mode: "0644"
when: "! grep -q 'Tier A (v3' {{ conf }}"
when: "! grep -q 'Tier A (v4' {{ conf }}"
- name: Restart searxng to pick up settings
shell: docker restart searxng
- name: Write .env with BOTH keys (a previous run clobbered SEARXNG_SECRET)
# ⚠ This dir already had a .env holding SEARXNG_SECRET; an earlier version
# of this step overwrote the file wholesale. Merge, never truncate.
sudo: true
shell: |
test -n '{{ brave_key }}' && test -n '{{ searxng_secret }}' && \
printf 'SEARXNG_SECRET=%s\nSEARXNG_BRAVE_API_KEY=%s\n' '{{ searxng_secret }}' '{{ brave_key }}' | tee {{ compose_dir }}/.env >/dev/null && \
chown infra-ops:docker {{ compose_dir }}/.env && chmod 600 {{ compose_dir }}/.env
# Skip only when .env already holds both keys (values are stable; to force
# a rewrite, delete the file).
when: "grep -q SEARXNG_SECRET {{ compose_dir }}/.env 2>/dev/null && grep -q SEARXNG_BRAVE_API_KEY {{ compose_dir }}/.env && exit 1 || exit 0"
- name: Ensure compose references the key (undo bad sed, then append cleanly)
# ⚠ `sed 's/$/\\n.../'` inserted LITERAL backslash-n text, not a newline —
# compose then parsed one env entry. awk-append instead.
sudo: true
shell: |
sed -i 's|\\n - SEARXNG_BRAVE_API_KEY=${SEARXNG_BRAVE_API_KEY}||' {{ compose_dir }}/compose.yaml
grep -q SEARXNG_BRAVE_API_KEY {{ compose_dir }}/compose.yaml || \
awk '{print} /SEARXNG_SECRET/ {print " - SEARXNG_BRAVE_API_KEY=${SEARXNG_BRAVE_API_KEY}"}' {{ compose_dir }}/compose.yaml > {{ compose_dir }}/.c.new && mv {{ compose_dir }}/.c.new {{ compose_dir }}/compose.yaml
when: "! grep -q 'SEARXNG_SECRET=${SEARXNG_SECRET}$' {{ compose_dir }}/compose.yaml || ! grep -q SEARXNG_BRAVE_API_KEY {{ compose_dir }}/compose.yaml"
- name: Recreate container (env changes need up -d, not restart)
shell: cd {{ compose_dir }} && docker compose up -d
verify:
- name: New config in place
shell: grep -q 'Tier A (v3' {{ conf }}
shell: grep -q 'Tier A (v4' {{ conf }}
changed_when: "false"
- name: Container serving /healthz after restart
- name: Compose references the key
shell: grep -q SEARXNG_BRAVE_API_KEY {{ compose_dir }}/compose.yaml
changed_when: "false"
- name: Key is in the container env
shell: docker exec searxng printenv SEARXNG_BRAVE_API_KEY >/dev/null
changed_when: "false"
- name: Container serving /healthz after recreate
shell: sleep 8; curl -sf http://127.0.0.1:9996/healthz
changed_when: "false"