Feature 17: Shopping List and Supply Archive (#140)
CI / ci (pull_request) Successful in 5m23s
CI / ci (push) Successful in 5m45s

Co-authored-by: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com>
This commit was merged in pull request #140.
This commit is contained in:
2026-10-08 15:16:51 -04:00
committed by approver_agent
parent 7003ff92ec
commit cb451baed4
67 changed files with 9252 additions and 1666 deletions
+18 -23
View File
@@ -1,20 +1,15 @@
# MealQuest production environment. Copy to deploy/.env (never committed)
# and replace the placeholders. The service fails fast: a missing or invalid
# required variable stops it at boot with the variable named.
# MealQuest production environment: the template for deploy/.env (never
# committed). The service fails fast: a missing or invalid required variable
# stops it at boot with the variable named. Creating deploy/.env: CTXD
# project mealquest, RUNBOOKS.MD "Stack and first deploy" > "3. Environment
# file".
#
# Secrets are never set here. They live in deploy/secrets/ (never committed),
# one value per file, owned by the container user and readable only by it:
#
# mkdir -p deploy/secrets && chmod 700 deploy/secrets
# head -c 32 /dev/urandom | base64 > deploy/secrets/secret_key
# printf '%s\n' '<Authentik client secret>' > deploy/secrets/oidc_client_secret
# printf '%s\n' '<Google OAuth client secret>' > deploy/secrets/google_client_secret
# sudo chown 10001:10001 deploy/secrets/* && sudo chmod 600 deploy/secrets/*
#
# SearXNG's secret key is the exception: compose reads it itself, so it
# stays owned by you (mode 0600). Create it after the chown above:
#
# (umask 077; printf 'SEARXNG_SECRET=%s\n' "$(openssl rand -hex 32)" > deploy/secrets/searxng.env)
# one value per file, owned by the container user 10001:10001 with mode
# 0600: secret_key, oidc_client_secret and google_client_secret. SearXNG's
# searxng.env is the exception: compose reads it itself, so it is owned by
# the host account that runs compose, mode 0600. Creating them: CTXD project
# mealquest, RUNBOOKS.MD "Stack and first deploy" > "4. Secrets".
#
# deploy/compose.yaml mounts them at /run/secrets/<name> and points the
# *_FILE variables at them.
@@ -42,8 +37,7 @@ MEALQUEST_TRUSTED_PROXY=10.60.1.33
# IANA zone the household settings are created with on first boot. Required
# until those settings exist; ignored afterwards (change the zone in
# household settings instead). Confirm the household's zone before the first
# deploy.
# household settings instead).
MEALQUEST_DEFAULT_TZ=America/New_York
# --- Authentik OIDC ----------------------------------------------------------
@@ -57,10 +51,10 @@ MEALQUEST_OIDC_ALLOWED_GROUPS=mealquest-admin
# --- Google Calendar (Push to Calendar) ------------------------------------
# Client ID of the Google OAuth web client (deploy/RUNBOOK.md "Google
# Calendar OAuth client"). Required: the service will not start without it
# and the client secret file. Its authorized redirect URI is
# <MEALQUEST_PUBLIC_URL origin>/api/v1/integrations/google/callback.
# Client ID of the Google OAuth web client (CTXD project mealquest,
# RUNBOOKS.MD "Google Calendar OAuth client"). Required: the service will
# not start without it and the client secret file. Its authorized redirect
# URI is <MEALQUEST_PUBLIC_URL origin>/api/v1/integrations/google/callback.
MEALQUEST_GOOGLE_CLIENT_ID=<client id>.apps.googleusercontent.com
# Optional session lifetimes. A session ends after IDLE unused and always MAX
@@ -82,13 +76,14 @@ MEALQUEST_SESSION_MAX=4320h
# The SearXNG recipe-search sidecar on the compose network. The Settings
# screen pre-fills it as the SearXNG URL until one is saved; the saved
# provider and base URL come from PATCH /api/v1/settings/recipe-search.
# See deploy/RUNBOOK.md "Recipe search (SearXNG)".
# See CTXD project mealquest, RUNBOOKS.MD "Recipe search (SearXNG)".
# --- Planned; not read by the service yet -------------------------------------
#
# Added to deploy/compose.yaml and this file by the features that use them.
#
# Web Push (Feature 19). Generate the key pair with cmd/vapidgen.
# Web Push (Feature 19). Key pair: CTXD project mealquest, RUNBOOKS.MD
# "VAPID keys (Web Push)".
# MEALQUEST_VAPID_PUBLIC_KEY=<base64url VAPID public key>
# MEALQUEST_VAPID_PRIVATE_KEY_FILE=/run/secrets/vapid_private_key
# MEALQUEST_VAPID_SUBJECT=mailto:<owner address>
-1417
View File
File diff suppressed because it is too large Load Diff
+4 -5
View File
@@ -1,8 +1,7 @@
# Development override: publishes SearXNG on the dev machine's loopback so
# it can be queried directly, e.g.
#
# docker compose -f deploy/compose.yaml -f deploy/compose.dev.yaml up -d searxng
# curl 'http://127.0.0.1:8888/search?q=chicken+tikka+masala+recipe&format=json'
# Development override layered on deploy/compose.yaml: publishes SearXNG
# on the dev machine's loopback (127.0.0.1:8888) so it can be queried
# directly. Using it: CTXD project mealquest, RUNBOOKS.MD "Local
# development".
#
# Loopback only, never a LAN address. Never used in production: the
# systemd unit starts deploy/compose.yaml alone.
+10 -12
View File
@@ -1,18 +1,16 @@
# Production stack for MealQuest on 10.60.1.14 (D-018). Build on the host,
# then start through systemd:
#
# docker compose -f deploy/compose.yaml build
# sudo systemctl restart mealquest
# Production stack for MealQuest on 10.60.1.14 (D-018). Building, deploying
# and operating it: CTXD project mealquest, RUNBOOKS.MD "Stack unit" and
# "Routine deploy and rollback".
#
# The services use restart: "no" on purpose: Docker must not start them
# before the DOCKER-USER firewall is applied. deploy/systemd/mealquest.service
# owns start and stop and requires mealquest-firewall.service first.
#
# Configuration comes from deploy/.env (copy deploy/.env.example) and secrets
# from deploy/secrets/; neither is committed. Compose bind-mounts file secrets
# with their host owner and mode, so each file in deploy/secrets/ must be
# owned by the container user 10001:10001 with mode 0600 (except
# searxng.env, read by compose itself; see the searxng service).
# Configuration comes from deploy/.env (template: deploy/.env.example) and
# secrets from deploy/secrets/; neither is committed. Compose bind-mounts
# file secrets with their host owner and mode, so each file in
# deploy/secrets/ must be owned by the container user 10001:10001 with mode
# 0600 (except searxng.env, read by compose itself; see the searxng service).
name: mealquest
services:
@@ -65,8 +63,8 @@ services:
# the app's own user (owner of the volume) with a read-only root
# filesystem, no privilege escalation and no Linux capabilities.
#
# Restore: follow "Restore the database" in deploy/RUNBOOK.md (stop the
# stack, move the database with its -wal and -shm aside, restore, check).
# Restoring the database: CTXD project mealquest, RUNBOOKS.MD "Restore
# the database".
litestream:
image: litestream/litestream:0.5.17
user: "10001:10001"
+3 -2
View File
@@ -5,8 +5,9 @@
# are one-way: a failure here fails this unit visibly and never fails
# docker.service.
#
# Start MealQuest only after this unit has succeeded:
# systemctl start mealquest-firewall && docker compose up -d
# mealquest.service requires this unit and starts the stack only after it
# has succeeded. Installing and operating both: CTXD project mealquest,
# RUNBOOKS.MD "Host firewall" and "Stack unit".
[Unit]
Description=Restrict MealQuest port 8090 to Traefik (DOCKER-USER)
After=docker.service
@@ -1,8 +1,7 @@
# Runs the nightly MealQuest media backup (/usr/local/sbin/mealquest-media-backup).
# Triggered by mealquest-media-backup.timer; run by hand with
# systemctl start mealquest-media-backup
# and read the result with
# journalctl -u mealquest-media-backup
# Triggered by mealquest-media-backup.timer; output goes to the journal.
# Installing it and running it by hand: CTXD project mealquest,
# RUNBOOKS.MD "Media — nightly rsync".
#
# The script runs as the app's user (10001, host user "mealquest") with no
# capabilities. systemd, as root, only bind-mounts the data volume's root
+3 -2
View File
@@ -15,8 +15,9 @@
# swapping the path afterwards cannot redirect it. Symlinks inside the
# directory are copied as links (-a), never followed.
#
# The media directory is created at deploy time (deploy/RUNBOOK.md). If it
# is missing the job fails; it is never treated as "nothing to back up".
# The media directory is created at deploy time (CTXD project mealquest,
# RUNBOOKS.MD "Media — nightly rsync"). If it is missing the job fails; it
# is never treated as "nothing to back up".
#
# rsync mirrors into .../mealquest-backups/media/ only: the target ends in
# a slash, so --delete removes files from that directory and nothing