SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-13

Как установить Mealie на VPS через Docker Compose

Разверните собственный менеджер рецептов Mealie на сервере с помощью Docker Compose. В статье описана настройка контейнера, конфигурация Nginx, TLS сертификатов и бэкапов.

Что делает self-hosted менеджер рецептов

Self-hosted менеджер рецептов хранит ваши рецепты в базе данных на сервере, который принадлежит вам, и Mealie — это решение, которое выбирает большинство домашних пользователей. Вы вставляете адрес страницы с рецептом, а Mealie извлекает из него ингредиенты, шаги приготовления, выход готового продукта и время готовки, отбрасывая лишние истории и рекламу. В вашу коллекцию попадает только суть — еда.

Остальной функционал приложения невелик. Есть еженедельный план питания, куда можно перетаскивать рецепты, и список покупок, который формируется на основе этого плана. Каждый, кто готовит, получает собственный логин. Всё это работает в одном контейнере и простаивает между запросами, поэтому даже скромный VPS справится с нагрузкой без проблем.

В этом руководстве используется Docker Compose. Если термины services: и volumes: вам незнакомы, сначала прочитайте как устроены файлы Docker Compose, так как всё нижеописанное представляет собой один compose-файл и четыре команды.

Install Mealie with Docker Compose

Mealie publishes its images to the GitHub container registry. As of July 2026 the current stable tag is v3.22.0. Pin a version rather than using latest: with latest, a docker compose pull on an unrelated day can move you across a database migration you were not ready for.

sudo mkdir -p /srv/mealie
cd /srv/mealie
sudo nano docker-compose.yml
services:
  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:

Two lines deserve a look before you start it.

The port is written as 127.0.0.1:9925:9000 and not as 9925:9000. The container listens on 9000 inside, and the host maps 9925 to it. Binding that map to the loopback address means nginx can reach Mealie and the internet cannot. Docker writes its own rules into the packet filter, so a plain 9925:9000 is reachable from outside even when your firewall says the port is closed. That surprise is worth understanding once: see why published Docker ports ignore ufw.

BASE_URL must be the exact public address you will use, with the scheme and no trailing slash. Mealie builds password reset links and invitation links from it. Set it to http://localhost:9925 and the invitation you send your partner will contain a link that only works on the server itself.

Start it and watch the first boot.

sudo docker compose up -d
sudo docker compose logs -f mealie

The first start creates the SQLite database and runs the migrations, which takes a few seconds. When the log settles and stops printing migration lines, check the app locally.

curl -I http://127.0.0.1:9925

A 200 OK means the app is up. Connection refused means the container is not running: run sudo docker compose ps and read the exit code. A container that stopped with code 137 was killed for exceeding the 1000M memory limit, which happens on the smallest plans.

Первый вход в систему и отключение открытой регистрации

Учетная запись по умолчанию — changeme@example.com с паролем MyPassword. Войдите в систему под этими данными и немедленно измените их, так как эта пара указана в документации и поэтому присутствует во всех сканерах.

Значение ALLOW_SIGNUP: "false" в файле compose выбрано намеренно. Если регистрация открыта, любой, кто найдет адрес, сможет создать учетную запись в вашей базе рецептов. Если она закрыта, вы добавляете пользователей через панель администратора, которая генерирует ссылку-приглашение для отправки пользователю. Эта ссылка формируется на основе BASE_URL, поэтому данное значение имеет важное значение. Если вы запускаете несколько приложений на одном сервере и хотите использовать один пароль для всех, Mealie может передать аутентификацию внешнему провайдеру, например собственному экземпляру Authentik.

Mealie объединяет пользователей в домохозяйство. Все участники одного домохозяйства совместно используют коллекцию рецептов, план питания и список покупок, что удобно для семьи. Раздельные домохозяйства на одном сервере имеют отдельные коллекции, что подходит для совместной аренды жилья, когда вкусы участников не совпадают.

Импортер — основная причина использования

Откройте коллекцию рецептов, выберите создание рецепта по URL и вставьте ссылку. Mealie загружает страницу и ищет структурированные данные рецепта — машиночитаемый блок, который большинство кулинарных сайтов встраивают для поисковых систем. Если этот блок присутствует, импорт выполняется корректно и мгновенно.

Вы также можете импортировать данные из изображения или вставленного текста, что удобно для фотографий страниц из кулинарных книг. Эти методы работают медленнее и требуют последующей проверки, так как рукописные дроби легко распознать неверно.

Массовый импорт запускается с того же экрана: вставьте список адресов (по одному на строку), и Mealie обработает их в фоновом режиме. Коллекция из 200 закладок переносится за один сеанс.

Планы питания и список покупок

Планировщик питания представляет собой календарь. Перетащите рецепт на нужный день, чтобы запланировать его. Список покупок автоматически собирает ингредиенты из запланированных рецептов в единый перечень и объединяет дубликаты: если в двух рецептах требуется лук, в списке появится одна строка вместо двух.

Список — это интерактивная страница, доступная на вашем телефоне прямо в магазине. Поскольку данные хранятся на вашем собственном сервере, все члены семьи видят один и тот же список в режиме реального времени. Если один человек отметит молоко как купленное, оно мгновенно исчезнет с экрана другого пользователя.

Размещение nginx и TLS перед приложением

Mealie работает по обычному HTTP и не имеет встроенных средств для обработки сертификатов. Выполните TLS termination (завершение TLS) на стороне nginx перед приложением. Сначала направьте DNS A-запись на ваш сервер, так как процесс получения сертификата требует подтверждения доменного имени.

sudo apt update && sudo apt install -y nginx
sudo nano /etc/nginx/sites-available/mealie
server {
    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 nginx

nginx -t с выводом syntax is ok и test is successful является обязательной проверкой. Выполняйте перезагрузку только после успешного прохождения теста, так как перезагрузка с некорректной конфигурацией сохранит работу старой версии и скроет ошибку до следующего перезапуска.

Параметр client_max_body_size 64M необходим, так как значение по умолчанию в nginx составляет 1 MB. Загрузка фотографии рецепта или восстановление резервной копии через браузер передает данные большего размера, и без этой строки вы получите ошибку 413 Request Entity Too Large от nginx, а не от Mealie, поэтому в логах приложения не будет никаких записей.

Затем выпустите сертификат. Этот этап и настройка таймера его обновления описаны в выпуске сертификата Let's Encrypt для nginx с помощью certbot.

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d recipes.example.com

Certbot перепишет блок server для прослушивания порта 443 и добавит редирект с порта 80. Откройте сайт по адресу https:// и убедитесь, что браузер принимает сертификат. Если Mealie загружается, но внутренние ссылки перенаправляют вас на http://, значит, переменная BASE_URL всё ещё содержит http и требует исправления, после чего необходимо выполнить sudo docker compose up -d для пересоздания контейнера с новым значением.

Размещение Mealie по подпути, например example.com/recipes, не будет работать, так как фронтенд не поддерживает работу из подпути. Используйте поддомен.

Резервное копирование и процесс восстановления

Все данные Mealie хранятся в /app/data/ внутри контейнера, что соответствует тому, как смонтирован том mealie-data. Скопируйте этот том, и вы получите полную копию рецептов, изображений и базы данных.

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 mealie

Имя тома содержит префикс с названием проекта, а название проекта совпадает с именем каталога, в котором находится файл compose. В /srv/mealie том называется mealie_mealie-data, поэтому первая команда — docker volume ls: используйте имя, которое выведет система, а не то, что указано в этом руководстве. Остановка контейнера перед копированием обязательна, так как SQLite часто находится в процессе записи, и «живая» копия может оказаться нечитаемой при восстановлении.

В панели администратора Mealie также есть собственная страница резервного копирования. Она создает переносимый архив, содержащий базу данных в формате JSON и ваши изображения. Используйте этот метод для миграции между серверами, так как он корректно работает при смене версий, в отличие от простого копирования файлов. Восстановление из такого архива является деструктивной операцией: текущая база данных удаляется перед загрузкой архива, и это действие нельзя отменить. После завершения процесса вы будете автоматически выведены из системы.

Любая копия не является резервной, пока она хранится на том же сервере. Регулярно отправляйте архивы на внешнее хранилище, для чего предназначено шифрованное резервное копирование на удаленный сервер с помощью restic.

Обновление Mealie

cd /srv/mealie
sudo nano docker-compose.yml
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f mealie

Увеличьте номер закрепленной версии в файле, затем выполните pull и пересоздайте контейнер. Миграции базы данных запускаются при первом старте нового образа. Перед обновлением мажорной версии создайте резервную копию тома, так как в случае сбоя миграции база данных может стать несовместимой с предыдущей версией образа. Ознакомьтесь с примечаниями к выпуску (release notes) для всех версий, разделяющих вашу текущую и целевую сборки.

Когда импорт завершается с ошибкой

Некоторые сайты не публикуют структурированные данные рецептов, поэтому Mealie импортирует только заголовок с пустым списком ингредиентов. Эту проблему нельзя решить настройками. В таких случаях вносите текст рецепта вручную.

Другие сбои вызваны защитой от ботов на стороне сайта, которая вместо рецепта возвращает страницу с проверкой (challenge). Mealie имитирует работу браузера и меняет User-Agent для обхода таких ограничений. Если сайт всё равно блокирует запросы, используйте прокси с более высокой репутацией IP-адреса или запустите экземпляр FlareSolverr, который проходит проверку в полноценном браузере. Оба метода являются опциональными и настраиваются через переменные окружения контейнера.

Если импорт не удаётся из-за того, что ваш сервер вообще не может связаться с сайтом, причина в другом. Проверьте доступность ресурса с сервера с помощью curl -I https://the-site.example/recipe и изучите строку состояния, прежде чем винить скрипт импорта.

Место в инфраструктуре

Mealie — отличное первое приложение для домашнего использования, так как домочадцы будут пользоваться им без лишних напоминаний. По сложности обслуживания оно сопоставимо с собственной фотобиблиотекой на базе Immich, хотя требует значительно меньше ресурсов. Это приложение входит в более широкий список сервисов, которые стоит развернуть самостоятельно в этом году. Один небольшой сервер способен обслуживать оба решения. Immich — не единственный кандидат на эту роль, и если вы еще не определились, различия в требованиях к оперативной памяти и командах резервного копирования PhotoPrism и Immich достаточно существенны, чтобы ознакомиться с ними до того, как вы выделите под них оставшееся место на диске.

FAQ

Почему импорт рецепта по URL завершается ошибкой?

Существует две основные причины. Либо на странице отсутствуют структурированные данные рецепта, поэтому парсер ничего не находит и вы получаете заголовок без списка ингредиентов, либо система защиты от ботов перед сайтом возвращает страницу с проверкой вместо самого рецепта. Во втором случае для Mealie можно настроить прокси с более высокой репутацией IP-адреса или использовать собственный экземпляр FlareSolverr, который проходит проверку в полноценном браузере. Прежде чем вносить изменения, убедитесь, что ваш сервер вообще может получить доступ к странице с помощью curl -I.

Нужен ли мне PostgreSQL или достаточно SQLite?

Для домашнего использования достаточно SQLite, он установлен по умолчанию. Переходите на PostgreSQL, если каталог с данными находится на сетевом хранилище (NAS), так как работа SQLite через сетевую файловую систему приводит к ошибкам блокировки базы данных и может повредить файл. При восстановлении из резервной копии в PostgreSQL пользователю базы данных требуются права суперпользователя, так как процесс восстановления удаляет все данные перед загрузкой архива.

Могу ли я запустить Mealie без доменного имени?

Да, в своей локальной сети. Установите BASE_URL в значение адреса, который вы будете вводить в браузере, например http://192.168.1.20:9925, и пропустите настройку nginx. Ссылки для приглашений и сброса пароля формируются на основе BASE_URL, поэтому неверное значение сделает ссылки нерабочими для других пользователей. Не открывайте доступ к сервису из Интернета по обычному HTTP, так как в этом случае данные для входа передаются в открытом виде.

Как предоставить членам семьи собственные учетные записи?

Оставьте ALLOW_SIGNUP установленным в "false" и добавляйте пользователей через панель администратора — это создаст ссылку-приглашение, которую вы сможете им отправить. Объедините всех, кто пользуется одной кухней, в одно домохозяйство (household), чтобы они могли совместно использовать рецепты, план питания и список покупок. Разные домохозяйства на одном сервере сохраняют свои коллекции отдельно.

Что произойдет с моими рецептами, если я перестану использовать Mealie?

Они останутся у вас. Функция резервного копирования администратора сохраняет данные в формате JSON, также Mealie позволяет экспортировать рецепты в виде обычных файлов markdown. Они останутся читаемыми в любом текстовом редакторе без какого-либо дополнительного ПО. Сделайте один экспорт заранее и убедитесь, что можете открыть полученные файлы.