Jump to content

Services/Mealie

From Stronghold Wiki
Revision as of 18:16, 5 July 2026 by Wikibot (talk | contribs) (Genericize example password placeholder)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

As of: 2026-07-05 — migrated from `services/MEALIE.md`

Mealie — Recipe Manager

Complete setup & operations guide for Mealie (recipe management app) with Authentik OAuth integration.


Overview

Mealie is a self-hosted recipe management app. We run it on Stronghold with:

  • Authentik OAuth2 for user authentication
  • Group-based access control (admin vs user roles)
  • HTTPS via Cloudflare (cook.wilsoz.com)
  • Persistent data storage in Docker volume

Current Users: marcus (admin via Authentik) Access: https://cook.wilsoz.com


Service Information

Property Value
URL https://cook.wilsoz.com
Container name mealie
Compose file /library/mealie-app/docker-compose.yml
Data volume mealie-app_mealie-data:/app/data
Internal port 9000
Host port 9925
Network mealie-app_mealie (MTU 1280)
Image ghcr.io/mealie-recipes/mealie:latest

Initial Setup from Scratch

1. Create Directory & Files

<syntaxhighlight lang="bash"> mkdir -p /library/mealie-app cd /library/mealie-app </syntaxhighlight>

2. Create docker-compose.yml

<syntaxhighlight lang="yaml"> version: "3.8" services:

 mealie:
   image: ghcr.io/mealie-recipes/mealie:latest
   container_name: mealie
   restart: unless-stopped
   env_file:
     - .env
   volumes:
     - mealie-data:/app/data
   ports:
     - "9925:9000"
   networks:
     - mealie

volumes:

 mealie-data:

networks:

 mealie:
   driver: bridge
   driver_opts:
     com.docker.network.driver.mtu: 1280

</syntaxhighlight>

3. Create .env File

<syntaxhighlight lang="bash">

  1. App Configuration

PUID=1000 PGID=1000 TZ=America/Chicago BASE_URL=https://cook.wilsoz.com ALLOW_SIGNUP=false

  1. OIDC Authentication (Authentik)

OIDC_AUTH_ENABLED=true OIDC_PROVIDER_NAME=Authentik OIDC_CONFIGURATION_URL=https://key.wilsoz.com/application/o/mealie/.well-known/openid-configuration OIDC_CLIENT_ID=3fUfT5FALoAqvWHzqiD0eLNYKd3fsyYjdUkEUVy5 OIDC_CLIENT_SECRET=D5IbtoxMgx6Kkmry296bXUz6G3NcvzT70wIBrr7RFu8 OIDC_SIGNUP_ENABLED=true OIDC_AUTO_REDIRECT=false OIDC_USER_GROUP=family-and-friends OIDC_ADMIN_GROUP=authentik Admins OIDC_GROUPS_CLAIM=groups OIDC_USER_CLAIM=email OIDC_NAME_CLAIM=name </syntaxhighlight>

4. Set Up Authentik OAuth Provider

Create OAuth2 Provider in Authentik

  1. Go to https://key.wilsoz.com/if/admin/
  2. Applications → Providers → Create OAuth2/OpenID Provider
  3. Fill in:

Name:** mealie-oauth Authorization flow:** (default-authentication-flow) Client type:** Confidential Redirect URIs:** (one per line)

    ```
    https://cook.wilsoz.com/login
    https://cook.wilsoz.com/login?direct=1
    ```
  1. Save — note the Client ID and Client Secret

Configure Provider: Signing Key

⚠️ CRITICAL: Assign the signing key or JWKS endpoint will return {} and OAuth will fail.

<syntaxhighlight lang="bash"> docker exec authentik-app_server_1 ak shell -c " from authentik.providers.oauth2.models import OAuth2Provider from authentik.crypto.models import CertificateKeyPair

p = OAuth2Provider.objects.get(name='mealie-oauth') jwt_key = CertificateKeyPair.objects.get(name='authentik Internal JWT Certificate') p.signing_key = jwt_key p.save() print('Assigned JWT Certificate signing key') " </syntaxhighlight>

Why JWT Certificate?

  • Uses HS256 algorithm (Mealie's OIDC library supports it)
  • Self-signed Certificate uses RS256 (rejected by Mealie)

Configure Provider: Property Mappings

Add OAuth scope property mappings:

<syntaxhighlight lang="bash"> docker exec authentik-app_server_1 ak shell -c " from authentik.providers.oauth2.models import OAuth2Provider from authentik.core.models import PropertyMapping

p = OAuth2Provider.objects.get(name='mealie-oauth') email_pm = PropertyMapping.objects.get(name='authentik default OAuth Mapping: OpenID \\'email\\) profile_pm = PropertyMapping.objects.get(name='authentik default OAuth Mapping: OpenID \\'profile\\) openid_pm = PropertyMapping.objects.get(name='authentik default OAuth Mapping: OpenID \\'openid\\)

p.property_mappings.add(email_pm, profile_pm, openid_pm) p.include_claims_in_id_token = True p.save() print('Added property mappings and enabled claims in ID token') " </syntaxhighlight>

Create Application in Authentik

  1. Go to Applications → Applications → Create
  2. Fill in:

Name:** Mealie Slug:** mealie Provider:** mealie-oauth (select from dropdown) Authorization flow:** default-authorization-flow

  1. Save

5. Start Mealie

<syntaxhighlight lang="bash"> cd /library/mealie-app docker compose up -d </syntaxhighlight>

Wait ~10 seconds for startup, then check:

<syntaxhighlight lang="bash"> docker logs mealie --tail=20

  1. Should show: "Application startup complete"
  2. And: "Enabled: True" under the OIDC section

</syntaxhighlight>

6. Configure VPS Nginx Proxy

On VPS, add server block to nginx config (or update if exists):

<syntaxhighlight lang="nginx"> server {

   listen 443 ssl http2;
   server_name cook.wilsoz.com;
   ssl_certificate /etc/letsencrypt/live/cook.wilsoz.com/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/cook.wilsoz.com/privkey.pem;
   location / {
       proxy_pass http://100.64.207.155:9925;
       proxy_set_header Host $host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "upgrade";
   }

} </syntaxhighlight>

Then:

<syntaxhighlight lang="bash"> sudo systemctl reload nginx </syntaxhighlight>

7. Create First Admin User (In-App)

  1. Navigate to https://cook.wilsoz.com
  2. You'll see the login page with "Authentik" button
  3. If Mealie is brand new with no users, it may show an initial setup screen
  4. Use Authentik to log in with an account in the authentik Admins group
    • This account gets Mealie admin role automatically

Operations

Start/Stop/Restart

<syntaxhighlight lang="bash"> cd /library/mealie-app

  1. Start

docker compose up -d

  1. Stop

docker compose down

  1. Restart

docker compose restart mealie

  1. Full restart (clears cached config)

docker compose down && sleep 2 && docker compose up -d </syntaxhighlight>

View Logs

<syntaxhighlight lang="bash">

  1. Live logs

docker logs -f mealie

  1. Last 50 lines

docker logs mealie --tail=50

  1. Filter for errors

docker logs mealie 2>&1 | grep -i "error\|exception"

  1. Filter for OIDC

docker logs mealie 2>&1 | grep -i "oidc" </syntaxhighlight>

Reset Admin Password (Database)

If you lose the admin password:

<syntaxhighlight lang="bash"> docker exec mealie python3 -c " import sqlite3 import bcrypt

db = sqlite3.connect('/app/data/mealie.db') cursor = db.cursor()

  1. Set new password for marcus

new_password = '<choose-a-new-password-here>' salt = bcrypt.gensalt(rounds=10) hashed = bcrypt.hashpw(new_password.encode('utf-8'), salt).decode('utf-8')

cursor.execute('UPDATE users SET password = ? WHERE username = ?', (hashed, 'marcus')) db.commit() print(f'Password reset to: {new_password}') db.close() " </syntaxhighlight>

Then log in and change it in Mealie settings.

Manage Users & Groups

Via Authentik:

  • Users must be added to Authentik first
  • Create/manage groups: Directory → Groups
  • Add users to groups for role assignment

Via Mealie:

  • Settings → Users — shows Mealie users (created on first OAuth login)
  • User roles are determined by Authentik group membership:

authentik Admins** → Mealie admin family-and-friends** → Mealie user


Configuration Reference

Environment Variables (.env)

Variable Purpose Example
BASE_URL External URL for Mealie https://cook.wilsoz.com
ALLOW_SIGNUP Allow registration without OIDC false
OIDC_AUTH_ENABLED Enable OAuth login true
OIDC_CLIENT_ID Authentik provider client ID (from Authentik)
OIDC_CLIENT_SECRET Authentik provider secret (from Authentik)
OIDC_CONFIGURATION_URL OIDC discovery endpoint https://key.wilsoz.com/application/o/mealie/.well-known/openid-configuration
OIDC_USER_GROUP Authentik group for regular users family-and-friends
OIDC_ADMIN_GROUP Authentik group for admins authentik Admins
OIDC_GROUPS_CLAIM OIDC claim name for groups groups
OIDC_SIGNUP_ENABLED Auto-create users on first OIDC login true
OIDC_AUTO_REDIRECT Skip login page, go straight to Authentik false
TZ Timezone America/Chicago
PUID / PGID Linux user/group for file permissions 1000

Data & Backups

Data Location

<syntaxhighlight lang="text"> /library/mealie-app/mealie-data:/app/data

Contents: - mealie.db (SQLite database — all recipes, users, settings) - recipes/ (recipe files) - users/ (user data) - backups/ (exported recipe backups) - templates/ (custom templates) - groups/ (group/household data) </syntaxhighlight>

Backup Procedure

<syntaxhighlight lang="bash">

  1. Backup the entire data volume

docker run --rm \

 -v mealie-app_mealie-data:/data \
 -v /home/mnw/backups:/backup \
 ubuntu tar czf /backup/mealie-$(date +%Y%m%d).tar.gz /data
  1. List backups

ls -lh /home/mnw/backups/mealie-*.tar.gz </syntaxhighlight>

Restore from Backup

<syntaxhighlight lang="bash">

  1. Stop Mealie

cd /library/mealie-app && docker compose down

  1. Restore data

docker run --rm \

 -v mealie-app_mealie-data:/data \
 -v /home/mnw/backups:/backup \
 ubuntu bash -c "rm -rf /data/* && tar xzf /backup/mealie-20260513.tar.gz -C /data"
  1. Restart

docker compose up -d </syntaxhighlight>


Troubleshooting

Login Issues

"Something went wrong" on OAuth callback

Symptoms:

  • Authentik login succeeds, but Mealie shows error when redirected back

Common causes & fixes:

Error Cause Fix
KeyError: 'keys' JWKS endpoint returns {} Assign signing key to OAuth provider (see Setup step 4)
UnsupportedAlgorithmError: RS256 not allowed Wrong signing key algorithm Use "authentik Internal JWT Certificate" (HS256), not "Self-signed Certificate" (RS256)
invalid_client: Client authentication failed Client secret mismatch Verify OIDC_CLIENT_SECRET in .env matches Authentik provider
HTTP 500 at /api/auth/oauth/callback Mealie can't reach Authentik's token endpoint Check network connectivity, SSL certificates, DNS

Debug steps:

<syntaxhighlight lang="bash">

  1. Check OIDC config is loaded

docker logs mealie | grep -i "oidc\|enabled"

  1. Test discovery endpoint

docker exec mealie curl -s "https://key.wilsoz.com/application/o/mealie/.well-known/openid-configuration" -k | jq .

  1. Check JWKS endpoint has keys

docker exec mealie curl -s "https://key.wilsoz.com/application/o/mealie/jwks/" -k | jq '.keys | length'

  1. View OAuth errors

docker logs mealie --tail=100 | grep -i "oauth\|error\|exception" | tail -20 </syntaxhighlight>

"OIDC not appearing on login page"

  • Verify OIDC_AUTH_ENABLED=true in .env
  • Restart container: docker compose down && docker compose up -d
  • Check logs for startup errors

"Redirect URI mismatch" error

User not getting admin role

  • Confirm user is in authentik Admins group (Directory → Groups)
  • Log out and log back in (roles are assigned at login time)
  • Check Mealie Settings → Users to see assigned role

Performance

Slow startup

Mealie can take 30-60 seconds on first start or after upgrade. Check:

<syntaxhighlight lang="bash"> docker logs mealie | tail -20

  1. Look for "Application startup complete"

</syntaxhighlight>

High memory usage

Default image is fine for small recipe collections. For very large:

  • Monitor: docker stats mealie
  • Limit: Add mem_limit: 2g to compose file if needed

Network Issues

Can't access https://cook.wilsoz.com

  1. Check VPS nginx config (see Setup step 6)
  2. Verify SSL cert is valid: curl -I https://cook.wilsoz.com
  3. Check Mealie is running: docker ps | grep mealie
  4. Check port: netstat -tlnp | grep 9925

Mealie can't reach Authentik (key.wilsoz.com)

From Mealie container:

<syntaxhighlight lang="bash"> docker exec mealie curl -v https://key.wilsoz.com/api/v3/ -k

  1. Should return 401 (not accessible, but shouldn't timeout)

docker exec mealie ping -c 1 key.wilsoz.com

  1. Should succeed

</syntaxhighlight>


Security Notes

  • OIDC_CLIENT_SECRET: Store securely in .env, never commit to git
  • Database: /app/data/mealie.db contains all user data — protect with filesystem permissions
  • Backups: Backup volume includes full database — encrypt backups if stored externally
  • User signup: ALLOW_SIGNUP=false means only Authentik users can access (good)
  • Groups: Ensure only trusted users are in authentik Admins group

Links & References


Related Services

  • Authentik (auth): /library/authentik-app/ — OAuth provider
  • Nginx (proxy): VPS /etc/nginx/sites-available/ — external access
  • Backups: /home/mnw/backups/ — data snapshots