Deploy Mealie recipe manager (#299)
## 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:
parent
b54d87e071
commit
11330ebea0
22 changed files with 489 additions and 3 deletions
17
argocd/apps/mealie.yaml
Normal file
17
argocd/apps/mealie.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: mealie
|
||||
namespace: argocd
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git
|
||||
targetRevision: main
|
||||
path: argocd/manifests/mealie
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: mealie
|
||||
syncPolicy:
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
|
|
@ -345,3 +345,47 @@ data:
|
|||
provider: !KeyOf jellyfin-provider
|
||||
meta_launch_url: https://jellyfin.ops.eblu.me
|
||||
policy_engine_mode: all
|
||||
|
||||
mealie.yaml: |
|
||||
version: 1
|
||||
metadata:
|
||||
name: BlumeOps Mealie SSO
|
||||
labels:
|
||||
blueprints.goauthentik.io/description: "Mealie OIDC provider and application"
|
||||
entries:
|
||||
# OAuth2 provider for Mealie (confidential — Mealie requires client_secret)
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: mealie-provider
|
||||
identifiers:
|
||||
name: Mealie
|
||||
attrs:
|
||||
name: Mealie
|
||||
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
|
||||
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
||||
client_type: confidential
|
||||
client_id: mealie
|
||||
client_secret: !Env AUTHENTIK_MEALIE_CLIENT_SECRET
|
||||
redirect_uris:
|
||||
- matching_mode: strict
|
||||
url: https://meals.ops.eblu.me/login
|
||||
- matching_mode: strict
|
||||
url: https://meals.tail8d86e.ts.net/login
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
||||
property_mappings:
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
|
||||
sub_mode: hashed_user_id
|
||||
include_claims_in_id_token: true
|
||||
|
||||
# Mealie application — all authenticated users allowed (admin mapped via OIDC_ADMIN_GROUP)
|
||||
- model: authentik_core.application
|
||||
id: mealie-app
|
||||
identifiers:
|
||||
slug: mealie
|
||||
attrs:
|
||||
name: Mealie
|
||||
slug: mealie
|
||||
provider: !KeyOf mealie-provider
|
||||
meta_launch_url: https://meals.ops.eblu.me
|
||||
policy_engine_mode: all
|
||||
|
|
|
|||
|
|
@ -78,6 +78,11 @@ spec:
|
|||
secretKeyRef:
|
||||
name: authentik-config
|
||||
key: argocd-client-secret
|
||||
- name: AUTHENTIK_MEALIE_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: authentik-config
|
||||
key: mealie-client-secret
|
||||
volumeMounts:
|
||||
- name: blueprints
|
||||
mountPath: /blueprints/custom
|
||||
|
|
|
|||
|
|
@ -57,3 +57,7 @@ spec:
|
|||
remoteRef:
|
||||
key: "Authentik (blumeops)"
|
||||
property: argocd-client-secret
|
||||
- secretKey: mealie-client-secret
|
||||
remoteRef:
|
||||
key: "Authentik (blumeops)"
|
||||
property: mealie-client-secret
|
||||
|
|
|
|||
79
argocd/manifests/mealie/deployment.yaml
Normal file
79
argocd/manifests/mealie/deployment.yaml
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mealie
|
||||
namespace: mealie
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mealie
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mealie
|
||||
spec:
|
||||
containers:
|
||||
- name: mealie
|
||||
image: registry.ops.eblu.me/blumeops/mealie:kustomized
|
||||
ports:
|
||||
- containerPort: 9000
|
||||
env:
|
||||
- name: BASE_URL
|
||||
value: "https://meals.ops.eblu.me"
|
||||
- name: ALLOW_SIGNUP
|
||||
value: "false"
|
||||
- name: TZ
|
||||
value: "America/Los_Angeles"
|
||||
- name: MAX_WORKERS
|
||||
value: "1"
|
||||
- name: WEB_CONCURRENCY
|
||||
value: "1"
|
||||
# OIDC — Authentik (public client, PKCE)
|
||||
- name: OIDC_AUTH_ENABLED
|
||||
value: "true"
|
||||
- name: OIDC_CONFIGURATION_URL
|
||||
value: "https://authentik.ops.eblu.me/application/o/mealie/.well-known/openid-configuration"
|
||||
- name: OIDC_CLIENT_ID
|
||||
value: "mealie"
|
||||
- name: OIDC_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mealie-oidc
|
||||
key: client-secret
|
||||
- name: OIDC_AUTO_REDIRECT
|
||||
value: "false"
|
||||
- name: OIDC_PROVIDER_NAME
|
||||
value: "Authentik"
|
||||
- name: OIDC_ADMIN_GROUP
|
||||
value: "admins"
|
||||
- name: OIDC_SIGNUP_ENABLED
|
||||
value: "true"
|
||||
- name: OIDC_USER_CLAIM
|
||||
value: "email"
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /app/data
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "1000Mi"
|
||||
cpu: "500m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/app/about
|
||||
port: 9000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/app/about
|
||||
port: 9000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: mealie-data
|
||||
19
argocd/manifests/mealie/external-secret.yaml
Normal file
19
argocd/manifests/mealie/external-secret.yaml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: mealie-oidc
|
||||
namespace: mealie
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: onepassword-blumeops
|
||||
target:
|
||||
name: mealie-oidc
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey: client-secret
|
||||
remoteRef:
|
||||
key: "Authentik (blumeops)"
|
||||
property: mealie-client-secret
|
||||
25
argocd/manifests/mealie/ingress-tailscale.yaml
Normal file
25
argocd/manifests/mealie/ingress-tailscale.yaml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mealie-tailscale
|
||||
namespace: mealie
|
||||
annotations:
|
||||
tailscale.com/proxy-class: "default"
|
||||
tailscale.com/proxy-group: "ingress"
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/name: "Mealie"
|
||||
gethomepage.dev/group: "Home"
|
||||
gethomepage.dev/icon: "mealie.png"
|
||||
gethomepage.dev/description: "Recipe manager"
|
||||
gethomepage.dev/href: "https://meals.ops.eblu.me"
|
||||
gethomepage.dev/pod-selector: "app=mealie"
|
||||
spec:
|
||||
ingressClassName: tailscale
|
||||
defaultBackend:
|
||||
service:
|
||||
name: mealie
|
||||
port:
|
||||
number: 9000
|
||||
tls:
|
||||
- hosts:
|
||||
- meals
|
||||
15
argocd/manifests/mealie/kustomization.yaml
Normal file
15
argocd/manifests/mealie/kustomization.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: mealie
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- pvc.yaml
|
||||
- ingress-tailscale.yaml
|
||||
- external-secret.yaml
|
||||
|
||||
images:
|
||||
- name: registry.ops.eblu.me/blumeops/mealie
|
||||
newTag: v3.12.0-5c5fd18
|
||||
13
argocd/manifests/mealie/pvc.yaml
Normal file
13
argocd/manifests/mealie/pvc.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: mealie-data
|
||||
namespace: mealie
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: standard
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
13
argocd/manifests/mealie/service.yaml
Normal file
13
argocd/manifests/mealie/service.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mealie
|
||||
namespace: mealie
|
||||
spec:
|
||||
selector:
|
||||
app: mealie
|
||||
ports:
|
||||
- name: http
|
||||
port: 9000
|
||||
targetPort: 9000
|
||||
protocol: TCP
|
||||
Loading…
Add table
Add a link
Reference in a new issue