Deploy Mealie recipe manager (#299)
All checks were successful
Build Container (Nix) / detect (push) Successful in 2s
Build Container / detect (push) Successful in 2s
Build Container (Nix) / build (mealie) (push) Successful in 2s
Build Container / build (mealie) (push) Successful in 8s

## Summary

- Deploy Mealie (self-hosted recipe manager) on minikube-indri via ArgoCD
- Build container from source via forge mirror (`mirrors/mealie`) — multi-stage Dockerfile with Node.js frontend + Python/uv backend
- Add Caddy proxy entry for `meals.ops.eblu.me`
- Part of a larger meal planning pipeline: Mealie stores categorized recipes, a planner script selects balanced meals, and Ollama generates unified cooking timelines

## Status

- [x] Mirror mealie repo on forge
- [x] Dockerfile (from-source build)
- [x] ArgoCD app + k8s manifests
- [x] Caddy proxy entry
- [x] Service docs, routing table, app registry
- [ ] Local Dagger build test
- [ ] Container build + push to registry
- [ ] Update kustomization.yaml with real image tag
- [ ] Deploy and verify
- [ ] Provision Caddy

## Test plan

- Build container locally via `dagger call build --src=. --container-name=mealie`
- Trigger CI build via `mise run container-build-and-release mealie`
- Deploy from branch: `argocd app set mealie --revision deploy-mealie && argocd app sync mealie`
- Verify Mealie UI at `https://meals.ops.eblu.me`
- Verify API docs at `https://meals.ops.eblu.me/docs`

Reviewed-on: #299
This commit is contained in:
Erich Blume 2026-03-16 21:59:10 -07:00
commit 11330ebea0
22 changed files with 489 additions and 3 deletions

View file

@ -40,6 +40,7 @@ DNS points to [[indri]]'s Tailscale IP. TLS via Let's Encrypt (ACME DNS-01 with
| [[navidrome]] | https://dj.ops.eblu.me | Music streaming |
| [[jellyfin]] | https://jellyfin.ops.eblu.me | Media server |
| [[postgresql]] | pg.ops.eblu.me:5432 | Database |
| [[mealie]] | https://meals.ops.eblu.me | Recipe manager |
| [[sifaka|Sifaka]] | https://nas.ops.eblu.me | NAS dashboard |
## Public Services (`*.eblu.me`)

View file

@ -39,6 +39,7 @@ Registry of all applications deployed via [[argocd]].
| `cv` | cv | `argocd/manifests/cv/` | [[cv]] |
| `forgejo-runner` | forgejo-runner | `argocd/manifests/forgejo-runner/` | [[forgejo]] CI |
| `ollama` | ollama | `argocd/manifests/ollama/` | [[ollama]] |
| `mealie` | mealie | `argocd/manifests/mealie/` | [[mealie]] |
## Sync Policies

View file

@ -1,6 +1,6 @@
---
title: Borgmatic
modified: 2026-02-10
modified: 2026-03-16
tags:
- service
- backup
@ -26,11 +26,15 @@ Daily backup system using Borg backup, running on indri.
- `/opt/homebrew/var/forgejo` - Git forge data
- `~/.config/borgmatic` - Borgmatic config
- `~/Documents` - Personal documents
- `~/.local/share/borgmatic/k8s-dumps/` - SQLite dumps from k8s pods
**Databases:**
**PostgreSQL databases:**
- `miniflux` on [[postgresql]]
- `teslamate` on [[postgresql]]
**K8s SQLite databases (pre-backup dump via kubectl exec):**
- [[mealie]] - Recipe manager (`/app/data/mealie.db`)
**Not backed up (by design):**
- ZIM archives (re-downloadable)
- Prometheus metrics (ephemeral)

View file

@ -0,0 +1,61 @@
---
title: Mealie
modified: 2026-03-16
tags:
- service
- recipes
---
# Mealie
Self-hosted recipe manager with a REST API. Part of the meal planning pipeline: Mealie stores categorized recipes, a planner script selects balanced meals, and [[ollama]] generates a unified cooking timeline.
## Quick Reference
| Property | Value |
|----------|-------|
| **URL** | https://meals.ops.eblu.me |
| **Tailscale URL** | https://meals.tail8d86e.ts.net |
| **Namespace** | `mealie` |
| **Image** | `registry.ops.eblu.me/blumeops/mealie` (built from source) |
| **Database** | SQLite (local, at `/app/data/`) |
| **API Docs** | https://meals.ops.eblu.me/docs |
| **Upstream** | https://github.com/mealie-recipes/mealie |
| **Manifests** | `argocd/manifests/mealie/` |
## Features
- Full REST API (FastAPI) for recipe CRUD, filtering by tag/category
- Structured recipe data: ingredients (quantity/unit/food), step-by-step instructions
- Built-in meal planning and shopping lists
- Recipe import from URLs
- API token auth for automation
- OIDC login via [[authentik]] (confidential client)
## Authentication
OIDC via [[authentik]] using a confidential client. Client secret stored in 1Password (`Authentik (blumeops)` / `mealie-client-secret`) and delivered via ExternalSecret. All Authentik users can log in; members of the `admins` group get Mealie admin privileges via `OIDC_ADMIN_GROUP`.
## Storage
- 2Gi PVC at `/app/data/` via `standard` storageClassName (minikube-hostpath)
- SQLite database (sufficient for single-user)
- Recipe images and assets stored alongside the database
## Backup
SQLite database backed up via [[borgmatic]]'s `before_backup` hook. Borgmatic runs `kubectl exec` to create a safe `.backup` copy (via Python's `sqlite3` module), then `kubectl cp` to the host. The dump lands in `~/.local/share/borgmatic/k8s-dumps/mealie.db` and is included in both local (sifaka) and offsite (BorgBase) backups.
## Networking
| Endpoint | Reachable from |
|----------|----------------|
| `https://meals.ops.eblu.me` | Tailnet clients (via Caddy) |
| `https://meals.tail8d86e.ts.net` | Tailnet clients |
| `http://mealie.mealie.svc.cluster.local:9000` | In-cluster |
## Related
- [[authentik]] — OIDC identity provider
- [[ollama]] — LLM backend for meal timeline generation
- [[borgmatic]] — Data backup