Instalar Mealie en una VPS con Docker Compose
Instala Mealie en tu VPS con Docker Compose y fija la versión estable de julio de 2026. Importa recetas desde enlaces, crea planes, listas y copias de seguridad.
Qué hace un gestor de recetas autoalojado
Un gestor de recetas autoalojado guarda tus recetas en una base de datos de un servidor que administras, y Mealie es la opción que elige la mayoría de los hogares. Pegas la dirección de una página de recetas y Mealie extrae los ingredientes, los pasos, las cantidades y el tiempo de cocción, y descarta el texto narrativo y la publicidad. En tu colección sólo queda la receta.
El resto de la aplicación es pequeño. Incluye un plan semanal de comidas al que arrastras recetas y una lista de la compra que se genera a partir de ese plan. Cada persona que cocina tiene su propio inicio de sesión. Todo se ejecuta en un contenedor y permanece inactivo entre peticiones, por lo que una VPS modesta puede alojarlo sin problemas.
Esta guía usa Docker Compose. Si los términos services: y volumes: son nuevos para ti, lee primero cómo se estructuran los archivos de Docker Compose, porque todo lo que sigue consiste en un archivo compose y cuatro comandos.
Instalar Mealie con Docker Compose
Mealie publica sus imágenes en el registro de contenedores de GitHub. En julio de 2026, la etiqueta estable actual es v3.22.0. Fije una versión en lugar de usar latest: con latest, un docker compose pull en un día cualquiera puede hacerle pasar a una migración de base de datos para la que no estaba preparado.
sudo mkdir -p /srv/mealie
cd /srv/mealie
sudo nano docker-compose.ymlservices:
mealie:
image: ghcr.io/mealie-recipes/mealie:v3.22.0
container_name: mealie
restart: always
ports:
- "127.0.0.1:9925:9000"
deploy:
resources:
limits:
memory: 1000M
volumes:
- mealie-data:/app/data/
environment:
ALLOW_SIGNUP: "false"
PUID: 1000
PGID: 1000
TZ: Europe/Amsterdam
BASE_URL: https://recipes.example.com
volumes:
mealie-data:Conviene revisar dos líneas antes de iniciarlo.
El puerto aparece como 127.0.0.1:9925:9000 y no como 9925:9000. El contenedor escucha en 9000 internamente y el host asigna 9925 a ese puerto. Vincular esa asignación a la dirección de loopback permite que nginx llegue a Mealie, pero impide el acceso desde Internet. Docker escribe sus propias reglas en el filtro de paquetes, por lo que un 9925:9000 simple es accesible desde fuera aunque el firewall indique que el puerto está cerrado. Conviene entender una vez este comportamiento: consulte por qué los puertos publicados por Docker ignoran ufw.
BASE_URL debe ser la dirección pública exacta que usará, con el esquema y sin una barra final. Mealie genera a partir de ella los enlaces para restablecer contraseñas y los enlaces de invitación. Si la establece como http://localhost:9925, la invitación que envíe a su pareja contendrá un enlace que sólo funcionará en el propio servidor.
Inícielo y supervise el primer arranque.
sudo docker compose up -d
sudo docker compose logs -f mealieEl primer arranque crea la base de datos SQLite y ejecuta las migraciones, lo que tarda unos segundos. Cuando el registro se estabilice y deje de mostrar líneas de migración, compruebe la aplicación localmente.
curl -I http://127.0.0.1:9925Un 200 OK indica que la aplicación está activa. Connection refused indica que el contenedor no está en ejecución: ejecute sudo docker compose ps y lea el código de salida. Un contenedor que se detuvo con el código 137 terminó debido a que superó el límite de memoria de 1000M, algo que ocurre en los planes más pequeños.
Primer inicio de sesión y desactivación del registro abierto
La cuenta predeterminada es changeme@example.com y la contraseña es MyPassword. Inicie sesión con ellas y cambie ambas de inmediato, porque esa combinación aparece en la documentación y, por tanto, está incluida en todos los escáneres.
ALLOW_SIGNUP: "false" en el archivo compose es intencionado. Con el registro abierto, cualquiera que encuentre la dirección puede crear una cuenta en su recetario. Con el registro cerrado, añade usuarios desde el área de administración, que genera un enlace de invitación para enviarlo personalmente. Ese enlace se construye a partir de BASE_URL, por lo que el valor es importante. Si termina ejecutando varias aplicaciones en el mismo servidor y quiere usar una sola contraseña para todas, Mealie puede delegar el inicio de sesión en un proveedor de identidad externo, como una instancia de Authentik autohospedada.
Mealie agrupa a los usuarios en un hogar. Todos los miembros de un hogar comparten la colección de recetas, el plan de comidas y la lista de compras. Esto es lo habitual en una familia. Los hogares independientes del mismo servidor mantienen colecciones separadas. Esto resulta útil en un piso compartido cuando nadie se pone de acuerdo sobre las anchoas.
El importador, que es el motivo para ejecutar esto
Abra la colección de recetas, elija crear una receta a partir de una URL y pegue un enlace. Mealie carga la página y busca datos estructurados de recetas, el bloque legible por máquinas que la mayoría de los sitios de recetas incorporan para los motores de búsqueda. Cuando ese bloque está presente, la importación es limpia e inmediata.
También puede importar desde una imagen o desde texto sin formato que pegue directamente. Esto permite importar una fotografía de una página de un libro de cocina. Estos métodos siguen una ruta más lenta y requieren una comprobación posterior, porque es fácil interpretar mal una fracción escrita a mano.
Las importaciones masivas se ejecutan desde la misma pantalla: pegue una lista de direcciones, una por línea, y Mealie las procesa en segundo plano. Una colección de doscientas marcadores pasa de un sistema a otro en una sola sesión.
Planes de comidas y lista de la compra
El planificador de comidas es un calendario. Arrastre una receta a un día para planificarla. La lista de la compra recopila los ingredientes de las recetas planificadas en una sola lista y combina los duplicados. Si dos recetas necesitan cebollas, aparece una sola línea en lugar de dos.
La lista es una página dinámica que puede consultar desde el teléfono mientras hace la compra. Como el servidor propio la almacena, todos los miembros del hogar ven la misma lista al mismo tiempo. Cuando una persona marca la leche como comprada, desaparece de la pantalla de la otra.
Configurar nginx y TLS delante de Mealie
Mealie utiliza HTTP sin cifrar y no gestiona certificados por sí mismo. Termine TLS en nginx, situado delante de Mealie. Primero, apunte un registro DNS A a su servidor, porque el paso de emisión del certificado verifica ese nombre.
sudo apt update && sudo apt install -y nginx
sudo nano /etc/nginx/sites-available/mealieserver {
listen 80;
server_name recipes.example.com;
client_max_body_size 64M;
location / {
proxy_pass http://127.0.0.1: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;
}
}sudo ln -s /etc/nginx/sites-available/mealie /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxnginx -t muestra syntax is ok y test is successful es la comprobación decisiva. Recargue nginx sólo después de que pase, porque recargar una configuración defectuosa mantiene activa la configuración anterior y oculta el error hasta el siguiente reinicio.
client_max_body_size 64M es necesario porque el valor predeterminado de nginx es 1 MB. Al subir una foto de una receta o restaurar una copia de seguridad desde el navegador, el cuerpo de la petición supera ese tamaño. Sin esa línea, nginx devuelve 413 Request Entity Too Large, no Mealie, por lo que el registro de la aplicación no muestra nada.
A continuación, emita el certificado. Ese paso y su temporizador de renovación se describen en emitir un certificado de Let's Encrypt para nginx con certbot.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d recipes.example.comCertbot modifica el bloque de servidor para escuchar en 443 y añade una redirección desde el puerto 80. Cargue el sitio mediante https:// y confirme que el navegador acepta el certificado. Si Mealie carga, pero sus propios enlaces le redirigen a http://, entonces BASE_URL todavía indica http. Corríjalo y ejecute sudo docker compose up -d para recrear el contenedor con el nuevo valor.
Mealie no funciona cuando se sirve bajo una subruta como example.com/recipes, porque el frontend no puede servirse desde una subruta. Use un subdominio.
Copias de seguridad y lo que hace realmente una restauración
Todo lo que administra Mealie se encuentra en /app/data/ dentro del contenedor. Ese es el volumen mealie-data. Si copia ese volumen, copia conjuntamente las recetas, las imágenes y la base de datos.
sudo docker volume ls
sudo docker compose stop mealie
sudo docker run --rm -v mealie_mealie-data:/data -v "$PWD":/backup \
alpine tar czf /backup/mealie-data.tgz -C /data .
sudo docker compose start mealieEl nombre del volumen lleva el nombre del proyecto como prefijo. El nombre del proyecto es el directorio que contiene el archivo compose. Desde /srv/mealie, el volumen es mealie_mealie-data. Por eso el primer comando es docker volume ls: use el nombre que muestra, no el nombre de esta guía. Es importante detener primero el contenedor. SQLite puede estar escribiendo en ese momento, y una copia en ejecución puede restaurarse como un archivo ilegible.
Mealie también tiene su propia página de copias de seguridad en el área de administración. Esta página escribe un archivo portable que contiene la base de datos en formato JSON junto con las imágenes. Úselo para migrar entre servidores, porque resiste un cambio de versión que una copia directa de archivos podría no soportar. La restauración es destructiva por diseño: elimina la base de datos actual antes de cargar el archivo y no se puede deshacer. La sesión se cierra cuando termina.
Ninguna de las dos copias es una copia de seguridad mientras permanezca en el mismo servidor. Envíe el archivo a otra ubicación según una programación. Para eso sirven las copias de seguridad cifradas fuera del servidor con restic.
Actualizar Mealie
cd /srv/mealie
sudo nano docker-compose.yml
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f mealieAumente la versión fijada en el archivo y, después, descargue la imagen y vuelva a crear el contenedor. Las migraciones se ejecutan durante el primer arranque de la nueva imagen. Haga una copia del volumen antes de cambiar de versión principal, porque una migración que falla a mitad del proceso puede dejar una base de datos que la imagen anterior ya no podrá abrir. Lea las notas de la versión correspondientes a todos los cambios entre su versión actual y la nueva.
Cuando falla el importador
Algunos sitios no publican ningún dato estructurado de recetas y Mealie importa entonces el título con la lista de ingredientes vacía. No es algo que pueda corregirse mediante configuración. Pegue el texto de la receta manualmente.
Otros fallos se deben a la protección contra bots del sitio de recetas, que responde a Mealie con una página de verificación en lugar de la receta. Mealie ya simula el comportamiento de un navegador y rota su user agent para reducir este problema. Si el sitio sigue rechazando la solicitud, las opciones documentadas son enviar el scraper mediante un proxy con mejor reputación de dirección IP o ejecutar una instancia de FlareSolverr que resuelva la verificación en un navegador real. Ambas opciones son voluntarias y se configuran mediante variables de entorno en el contenedor.
Un import que falla porque el servidor no puede acceder al sitio es un problema distinto. Pruébelo desde el servidor con curl -I https://the-site.example/recipe y lea la línea de estado antes de atribuir el fallo al scraper.
Dónde encaja
Mealie es una buena primera aplicación autohospedada para un hogar, porque las personas con las que vive la usarán sin que tenga que pedírselo. Cumple una función parecida a su propia biblioteca de fotos con Immich, aunque es mucho más ligera, y forma parte de la lista más amplia de servicios que merece la pena autohospedar este año. Un solo servidor puede alojar ambas aplicaciones. Immich no es la única opción para esa segunda función y, si todavía está decidiendo, los requisitos mínimos de memoria y los comandos de copia de seguridad de PhotoPrism e Immich son suficientemente distintos como para que convenga leerlos antes de destinar el resto del disco. Si el hogar también guarda sus planes y notas, además de sus cenas, un espacio de trabajo AFFiNE autohospedado vuelve a ser el mismo ejercicio con un archivo compose, pero necesita cuatro contenedores y bastante más memoria que Mealie, así que compruebe primero cuánta memoria queda disponible en el equipo. Y si el hogar quiere registrar también sus entrenamientos, además de sus cenas, openGym conserva los entrenamientos y requiere la misma etiqueta fijada, el mismo archivo compose y el mismo certificado que acaba de configurar. La velada posterior a la cena tiene su propia variante, porque Halcyon reconstruye una biblioteca Jellyfin existente como un videoclub de los años 90 por el que puede desplazarse, lo que añade otro contenedor pequeño delante de algo que ya ejecuta, en lugar de otra base de datos que haya que respaldar. No todo lo de esta familia es una aplicación doméstica y, si alguna vez el mismo enfoque tiene que cubrir una necesidad de trabajo, un servicio de asistencia Chatwoot autohospedado vuelve a requerir la misma etiqueta fijada y el mismo certificado, con Postgres, Redis y el correo saliente operativo detrás. Es un servicio mucho más pesado que un gestor de recetas y merece su propio servidor.
FAQ
¿Por qué falla la importación de una URL de receta?
Hay dos causas habituales. La página no publica datos estructurados de recetas, por lo que el scraper no encuentra nada y sólo obtiene el título, sin ingredientes. O una capa de protección contra bots situada delante del sitio devuelve una página de desafío en lugar de la receta. En el segundo caso, Mealie puede usar un proxy con mejor reputación de dirección, o una instancia de FlareSolverr autohospedada que resuelva el desafío en un navegador real. Antes de cambiar nada, confirme que el servidor puede acceder a la página con curl -I.
¿Necesito PostgreSQL o basta con SQLite?
SQLite basta para un hogar y es la opción predeterminada. Cambie a PostgreSQL cuando el directorio de datos esté en almacenamiento conectado a la red, porque SQLite sobre un sistema de archivos de red produce errores de base de datos bloqueada y puede dañar el archivo. Las restauraciones con PostgreSQL requieren que el usuario de la base de datos sea superuser, porque la restauración elimina todo antes de cargar el archivo.
¿Puedo ejecutar Mealie sin un nombre de dominio?
Sí, en su propia red. Establezca BASE_URL con la dirección que realmente escribirá, como http://192.168.1.20:9925, y omita nginx. Los enlaces de invitación y de restablecimiento de contraseña se generan a partir de BASE_URL, por lo que un valor incorrecto produce enlaces que nadie más puede abrir. No lo exponga a Internet mediante HTTP sin cifrar, porque las credenciales de inicio de sesión se transmitirían sin cifrar.
¿Cómo doy a mi familia sus propias cuentas?
Deje ALLOW_SIGNUP establecido en "false" y añada a las personas desde el área de administración. Se generará un enlace de invitación que podrá enviarles. Incluya en el mismo household a todas las personas que compartan una cocina para que compartan las recetas, el plan de comidas y la lista de compras. Los household separados en un mismo servidor mantienen colecciones independientes.
¿Qué ocurre con mis recetas si dejo de ejecutar Mealie?
Se conservan. La copia de seguridad del área de administración guarda sus datos como JSON. Mealie también puede exportar las recetas como archivos markdown sin formato, que siguen siendo legibles en cualquier editor de texto sin necesidad de software adicional. Haga una exportación antes de necesitarla y compruebe que puede abrirla.