Why Self-Hosting Your Meal Planner Makes Sense
Meal planning apps have a habit of disappearing. Services shut down, pricing models shift, and your carefully curated recipe library gets locked behind a paywall or deleted outright. Mealie solves this problem by giving you a self-hosted recipe manager and meal planner that runs entirely on your own hardware – no subscriptions, no data harvesting, and no risk of the service going dark.
Mealie is a modern web application built with a FastAPI backend and a Vue.js frontend. It supports recipe importing from URLs, full meal planning calendars, shopping list generation, multi-user households, and a clean API that integrates with home automation tools like Home Assistant. Everything stores in a local database you control, and the entire stack ships as a Docker container that takes roughly ten minutes to get running.
This guide walks through a full Mealie deployment using Docker Compose, including persistent storage, environment configuration, and basic reverse proxy setup for remote access.

Prerequisites and System Requirements
Mealie runs on any machine capable of running Docker – a Raspberry Pi 4, an old mini PC, a VPS, or a home server all work fine. You need at least 1GB of RAM, though 2GB is more comfortable during recipe scraping. Docker and Docker Compose must already be installed on the host. If you are managing multiple containers and want a visual interface for monitoring your stack, setting up Portainer alongside Mealie is worth considering.
Mealie supports two database backends: SQLite for simple single-user or small household setups, and PostgreSQL for anything more demanding. SQLite requires zero additional configuration and is perfectly stable for most home use cases. PostgreSQL becomes worth the extra setup if you plan to run multiple concurrent users, take frequent automated backups, or eventually migrate data to a more powerful server. This guide covers both paths.
You will also need a domain or local hostname if you want to access Mealie outside your home network. A reverse proxy like Caddy or Nginx Proxy Manager handles SSL termination and clean URLs. That part of the setup is covered at the end of this guide. For now, local network access on a raw port is enough to get the instance running and tested.
Deploying Mealie with Docker Compose
Create a working directory for the project – something like /opt/mealie on Linux. Inside that directory, create a file named docker-compose.yml. The minimal SQLite configuration looks like this:
version: "3.7"
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:latest
container_name: mealie
restart: unless-stopped
ports:
- "9000:9000"
volumes:
- mealie-data:/app/data
environment:
- ALLOW_SIGNUP=false
- MAX_WORKERS=1
- WEB_CONCURRENCY=1
- BASE_URL=http://your-server-ip:9000
- DEFAULT_EMAIL=admin@example.com
- DEFAULT_PASSWORD=changethispassword
volumes:
mealie-data:
Set ALLOW_SIGNUP=false immediately. With it enabled, anyone who reaches your Mealie instance can register an account. The BASE_URL variable should match whatever address you will use to access the service – either your local IP and port or a domain name if you set up a reverse proxy later. The DEFAULT_EMAIL and DEFAULT_PASSWORD values create the initial admin account on first launch. Change the password to something strong and update it again inside the Mealie interface after your first login.
Run docker compose up -d from the project directory. Docker pulls the Mealie image, creates the named volume for persistent storage, and starts the container in the background. Give it thirty to sixty seconds on first launch while it initializes the database. Navigate to http://your-server-ip:9000 in a browser and the Mealie login screen should appear. Log in with the admin credentials you set in the compose file.

Switching to PostgreSQL for Production Use
If you want PostgreSQL instead of SQLite, expand the compose file to include a second service. Add the following under services and update the Mealie environment block accordingly:
postgres:
image: postgres:15
container_name: mealie-db
restart: unless-stopped
environment:
- POSTGRES_USER=mealie
- POSTGRES_PASSWORD=securepassword
- POSTGRES_DB=mealie
volumes:
- mealie-pgdata:/var/lib/postgresql/data
volumes:
mealie-data:
mealie-pgdata:
In the Mealie service environment block, replace the SQLite default by adding these variables: DB_ENGINE=postgres, POSTGRES_USER=mealie, POSTGRES_PASSWORD=securepassword, POSTGRES_SERVER=postgres, POSTGRES_PORT=5432, and POSTGRES_DB=mealie. The POSTGRES_SERVER value matches the service name in the compose file, which Docker’s internal networking resolves automatically.
Bring the stack down with docker compose down if it is already running, then restart it with docker compose up -d. Mealie detects the PostgreSQL connection on startup and runs its migrations against the new database. If the container logs show connection errors on first boot, wait a few seconds and check again – PostgreSQL sometimes takes a moment longer to become ready than Mealie expects on initial startup.
Configuring a Reverse Proxy and Remote Access
Accessing Mealie over a raw IP and port is fine on a local network, but reaching it from outside your home requires proper domain routing and HTTPS. Caddy is the most straightforward option here. A minimal Caddyfile entry for Mealie looks like this:
mealie.yourdomain.com {
reverse_proxy localhost:9000
}
Caddy automatically provisions a Let’s Encrypt certificate for the domain, handles HTTPS redirection, and proxies requests to Mealie’s container port. Point your domain’s DNS A record to your server’s public IP, open ports 80 and 443 on your firewall and router, and Caddy handles the rest. Update the BASE_URL environment variable in your compose file to use the new HTTPS domain, then run docker compose up -d to apply the change. Mealie uses BASE_URL for things like generating share links and API callbacks, so keeping it accurate matters.
Once the domain resolves correctly and HTTPS is working, the Mealie interface is accessible from any device on any network. The mobile experience is solid – Mealie ships with a progressive web app manifest, so adding it to your phone’s home screen gives you something close to a native app feel. Recipe imports work from the mobile browser too, which makes saving recipes directly from cooking sites while grocery shopping practical rather than awkward.
Mealie’s built-in backup tool lives under Admin – Maintenance and exports everything – recipes, meal plans, users, and settings – as a single zip file. Schedule this manually or automate it with a cron job that hits the API endpoint. The API is fully documented at /docs on your Mealie instance, and it covers nearly every action the UI exposes, which means you can wire recipe imports, shopping list updates, or meal plan generation into any automation workflow you already have running.

The part most people discover last: Mealie can scrape recipes from a wide range of cooking websites automatically, but structured data quality varies by site. When a site’s markup is inconsistent or paywalled, Mealie’s parser falls back to a best-guess extraction that may grab the wrong ingredients or miss steps entirely. Manual correction is fast, but it means the “import and done” promise has real exceptions – and knowing that before you migrate a hundred bookmarked recipes saves a frustrating afternoon.





