Как установить MongoDB на Ubuntu: пользователи, безопасный доступ и резервное копирование

Валерий Волков

Время прочтения 41 минута

Если нужен только рабочий маршрут без подробных объяснений, ниже — короткая последовательность настройки MongoDB на Ubuntu: от установки и пользователей до безопасного доступа и проверки backup/restore.

  1. Установите MongoDB Community Edition из официального repository и убедитесь, что сервис mongod запущен.
  2. Пока MongoDB принимает подключения только через 127.0.0.1, создайте административного пользователя. После этого включите обязательную авторизацию в /etc/mongod.conf:
    security:
  authorization: enabled

и перезапустите MongoDB.

  1. Создайте отдельного пользователя приложения с минимально необходимыми правами, например readWrite только для app_db.

Подключение будет выглядеть примерно так:

    mongodb://app_user:password@127.0.0.1:27017/app_db?authSource=app_db
  1. Если приложение находится на другом сервере, разрешите MongoDB слушать нужный интерфейс через bindIp и откройте 27017/tcp в firewall только для доверенного IP. Не публикуйте MongoDB в интернет без сетевых ограничений.
  2. Создайте тестовые данные и убедитесь, что app_user может читать и изменять свою database, но не получает административных прав.
  3. Сделайте резервную копию:
    mongodump --db app_db --out /var/backups/mongodb

Затем удалите тестовую database и восстановите ее:

    mongorestore --db app_db /var/backups/mongodb/app_db
  1. После восстановления снова подключитесь к MongoDB и проверьте, что collections и documents вернулись.

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

Что разберем в статье

В этой статье настроим MongoDB на Ubuntu с нуля и сразу доведем установку до состояния, пригодного для небольшого рабочего проекта. Создадим административного пользователя и отдельную учетную запись приложения, включим обязательную авторизацию, ограничим сетевой доступ и отдельно разберем типичные ошибки подключения.

После этого проверим резервное копирование не только созданием файла. Добавим реальные документы, сделаем backup через mongodump, удалим тестовую database, восстановим ее через mongorestore и убедимся, что данные действительно вернулись.

Прежде чем переходить к архитектуре сервера, коротко напомним основные термины.

MongoDB — это документоориентированная база данных. Вместо привычных таблиц и строк данные здесь хранятся в виде документов, которые объединяются в коллекции. Несколько коллекций, относящихся к одному приложению или сервису, находятся внутри database.

Сам сервер MongoDB работает как процесс mongod. Именно он принимает подключения клиентов, выполняет запросы, управляет данными на диске и применяет настройки безопасности.

Как будет устроен MongoDB-сервер

Как обычно, прежде чем устанавливать пакеты и редактировать mongod.conf, разберемся, какую схему мы в итоге хотим получить.

У нас будет один Ubuntu VPS с MongoDB Community Edition. На нем работает серверный процесс mongod, а приложение подключается к своей database под отдельным пользователем с ограниченными правами.

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

Таким образом, сразу разделяем две роли:

  • admin управляет MongoDB;
  • app_user работает только с данными приложения.

На первом этапе MongoDB будет доступна только локально через 127.0.0.1. Это позволит спокойно создать пользователей и включить authorization до того, как база станет доступна с других серверов.

А уже после проверки локальной схемы отдельно настроим удаленное подключение — но только если оно действительно понадобится.

Что установим и проверим

Основной серверный процесс MongoDB называется: mongod.

Он отвечает за хранение данных, обработку запросов, пользователей и сетевые подключения.

Для работы с MongoDB из терминала понадобится MongoDB Shell: mongosh

Через него мы будем:

  • Создавать пользователей;
  • Переключаться между databases;
  • Добавлять documents;
  • Проверять права;
  • Удалять тестовую database;
  • Проверять результат восстановления.

Для backup и restore понадобятся отдельные утилиты:

    mongodump
mongorestore

В итоге проверим полный рабочий цикл:

С общей схемой разобрались. Теперь посмотрим, как к MongoDB будет обращаться само приложение.

Как приложение будет подключаться к MongoDB

Приложения обычно подключаются к MongoDB через connection URI.

Для нашей локальной схемы он будет выглядеть примерно так:

    mongodb://app_user:password@127.0.0.1:27017/app_db?authSource=app_db

Здесь указаны:

  • app_user — пользователь приложения;
  • password — его пароль;
  • 127.0.0.1 — адрес MongoDB;
  • 27017 — стандартный порт;
  • app_db — рабочая database;
  • authSource=app_db — database, в которой MongoDB должна искать пользователя.

Последний параметр важен. Пользователь MongoDB создается внутри определенной authentication database, и при неправильном authSource можно получить ошибку авторизации даже с правильным логином и паролем.

Поэтому для приложения создадим отдельного пользователя с понятной областью прав:

Он сможет читать и изменять данные приложения, но не получит административный доступ ко всему серверу.

Прежде чем создавать такую учетную запись, нужно безопасно подготовить саму MongoDB.

Почему сначала настраиваем локальный доступ

Сразу после установки нет смысла открывать MongoDB внешней сети.

Пока мы еще не создали admin и не включили обязательную авторизацию, безопаснее оставить mongod доступным только через: 127.0.0.1

Тогда к базе можно подключиться только с самого VPS.

Последовательность получится простой:

  1. Устанавливаем MongoDB;
  2. Проверяем сервис;
  3. Создаем admin;
  4. Включаем authorization;
  5. Создаем app_user;
  6. Проверяем его права;
  7. Только после этого решаем, нужен ли внешний доступ.

Если приложение работает на том же VPS, MongoDB вообще можно оставить на localhost.

Если приложение находится на другом сервере, позже разрешим подключение только с его доверенного IP и отдельно ограничим доступ firewall.

Так мы не создаем сначала потенциально открытую базу, а расширяем доступ только после того, как пользователи и авторизация уже настроены.

Что подготовить перед установкой

Перед началом понадобится совсем небольшой набор исходных данных:

Компонент Назначение Что подготовить 
Ubuntu VPS Сервер MongoDB SSH-доступ, CPU, RAM и SSD 
MongoDB Community Edition Хранение данных Поддерживаемая версия Ubuntu 
mongosh Администрирование Локальный доступ к серверу 
MongoDB Database Tools Backup и restore mongodump и mongorestore 
Admin user Управление MongoDB Отдельный надежный пароль 
app_user Доступ приложения Пароль и права только на app_db 
app_db Рабочая database Используем и для тестовых данных 
Backup storage Хранение копий Локальный каталог и желательно внешнее хранилище 
Trusted IP Удаленный доступ Нужен только при подключении с другого сервера 

Теперь логика дальнейшей настройки уже определена: сначала устанавливаем MongoDB и защищаем локальный доступ, затем разделяем административного и прикладного пользователей, а уже после этого переходим к сети и резервному копированию.

Выбираем версию MongoDB и конфигурацию VPS

С общей схемой мы уже разобрались: MongoDB будет работать на одном Ubuntu VPS, приложение подключится под отдельным пользователем, а административные права останутся только у admin. Теперь нужно выбрать конкретную версию MongoDB и понять, сколько ресурсов достаточно для небольшого рабочего сервера.

Здесь важен баланс. Для тестов MongoDB можно запустить и на очень скромном VPS, но для постоянной работы лучше сразу оставить запас по памяти и диску. У базы данных эти два ресурса заметно влияют на отзывчивость, особенно когда появляются indexes, регулярная запись и backup.

В этом руководстве используем MongoDB 8.0 Community Edition на Ubuntu 24.04 LTS.

Какие ресурсы нужны небольшой MongoDB

MongoDB не требует огромного сервера для небольшого проекта.

Если речь идет о тестовом стенде, небольшом внутреннем сервисе или приложении с умеренным числом запросов, вполне можно начинать с нескольких vCPU и нескольких гигабайт RAM.

Практический ориентир для небольшой standalone MongoDB:

  • 2 vCPU
  • 4 ГБ RAM
  • 40–60 ГБ SSD

Этого достаточно, чтобы:

  • Запустить сам mongod;
  • Хранить небольшую рабочую database;
  • Создавать indexes;
  • Выполнять mongodump;
  • Восстанавливать данные через mongorestore;
  • Оставить системе запас под filesystem cache.

Сервер на 1 vCPU и 2 ГБ RAM тоже может работать, особенно для лабораторных задач, но запас там уже небольшой. Как только растут данные, indexes или нагрузка, память заканчивается гораздо быстрее.

Поэтому для статьи не будем брать совсем минимальную конфигурацию. Нам важнее получить предсказуемое окружение, на котором можно спокойно пройти весь цикл от установки до restore.

Почему для MongoDB важны RAM и диск

MongoDB активно использует память для cache.

Storage engine WiredTiger держит часть часто используемых данных в собственном cache, а сама Linux дополнительно использует свободную RAM для filesystem cache. В результате часто читаемые данные не приходится каждый раз забирать с диска.

Поэтому для базы важен не только показатель used, но и то, сколько памяти остается доступной системе.

Если RAM становится мало и сервер начинает постоянно обращаться к swap, задержки растут. Swap лучше воспринимать как аварийный запас, а не как обычное продолжение оперативной памяти.

С диском ситуация похожая.

MongoDB постоянно работает с:

  • Data files;
  • Indexes;
  • Journal;
  • Временными файлами;
  • Logs.

Если диск медленный, это напрямую отражается на записи и чтении данных.

Поэтому для рабочего сервера лучше использовать SSD. Особенно это заметно, когда database уже не помещается целиком в память и MongoDB чаще обращается к storage.

Кроме скорости важен и запас места. Сегодня база может занимать несколько гигабайт, а позже к ней добавятся indexes, backup и временные данные.

Поэтому диск тоже не стоит выбирать впритык.

Какую конфигурацию используем в статье

Для нашего стенда возьмем:

  • Ubuntu 24.04 LTS;
  • MongoDB 8.0 Community Edition;
  • 2 vCPU;
  • 4 ГБ RAM;
  • 60 ГБ SSD;
  • Один standalone-процесс mongod;
  • Стандартный storage engine WiredTiger.

Этого достаточно для небольшой database.

Мы сможем:

  • Создать пользователей;
  • Добавить данные;
  • Проверить indexes и доступ;
  • Сделать backup;
  • Удалить тестовую database;
  • Восстановить ее;
  • Оставить на сервере нормальный запас ресурсов.

Если потом MongoDB начнет обслуживать более крупный проект, увеличивать ресурсы нужно уже по фактической нагрузке: смотреть RAM, disk I/O, размер working set и частоту запросов, а как альтернативу - MongoDB поддерживает горизонтальное масштабирование (разные инстансы на разных VPS).

Для ориентира сравним три сценария:

Ресурс Минимальный тестовый стенд Небольшой рабочий сервер Конфигурация статьи 
CPU 1 vCPU 2+ vCPU 2 vCPU 
RAM 2 ГБ 4+ ГБ 4 ГБ 
Диск 20–30 ГБ 40–60+ ГБ SSD 60 ГБ SSD 
Swap Небольшой резерв Только как страховка Проверим отдельно 
Назначение Lab / тесты Небольшое приложение Учебный рабочий стенд 

Осталось проверить, что реальный VPS соответствует выбранным параметрам.

Команды проверки сервера

Сначала посмотрим версию Ubuntu:

    lsb_release -a

Если lsb_release отсутствует, можно использовать:

    cat /etc/os-release

В нашем случае должна быть установлена Ubuntu 24.04 LTS.

Количество доступных CPU:

    nproc

Более подробные характеристики:

    lscpu

Теперь проверим память:

    free -h

Нас интересуют общий объем RAM и значение available.

Отдельно посмотрим swap:

    swapon --show

Если команда ничего не выводит, активный swap отсутствует.

Теперь диски:

    lsblk

И свободное место:

    df -h

Позже MongoDB будет хранить данные в:

    /var/lib/mongodb

Поэтому особенно важно проверить раздел, на котором находится этот каталог.

Основные команды можно оставить в коротком справочнике:

Что проверяем Зачем Команда 
Ubuntu Проверить версию системы lsb_release -a 
CPU Убедиться, что процессоров достаточно nproc 
RAM Проверить общий и доступный объем памяти free -h 
Swap Посмотреть резерв виртуальной памяти swapon --show 
Диски Увидеть устройства и разделы lsblk 
Свободное место Проверить запас под данные и backup df -h 

Устанавливаем MongoDB на Ubuntu

С версией и ресурсами определились. Теперь можно переходить к самой установке MongoDB на Ubuntu.

На этом этапе задача простая: подключить официальный repository, установить нужные пакеты, запустить mongod и убедиться, что MongoDB Shell подключается к локальному серверу. Авторизацию пока не включаем — сначала нужно получить рабочую базовую установку.

Почему лучше использовать официальный repository MongoDB

В Ubuntu MongoDB можно встретить в системных пакетах, но для актуальной Community Edition лучше использовать официальный repository MongoDB.

Это дает несколько преимуществ:

  • Устанавливается нужная версия MongoDB;
  • Пакеты обновляются из того же источника;
  • Структура установки соответствует стандартной документации MongoDB;
  • Вместе с сервером можно установить mongosh и Database Tools;
  • Проще контролировать обновления между версиями.

Для статьи используем MongoDB 8.0, поэтому repository сразу подключим для этой ветки.

После этого MongoDB будет устанавливаться обычным apt, как и остальные пакеты Ubuntu.

Какие пакеты входят в MongoDB

Основной метапакет называется:

    mongodb-org

Он устанавливает набор компонентов, необходимых для обычного standalone-сервера.

Ключевые из них:

  • mongodb-org-server — серверный процесс mongod;
  • mongodb-mongosh — MongoDB Shell;
  • mongodb-org-tools — набор дополнительных утилит;
  • MongoDB Database Tools — в том числе mongodump и mongorestore.

Самая важная часть — mongod.

Именно он принимает подключения, работает с databases и collections, сохраняет документы и управляет storage engine.

mongosh нужен уже администратору и разработчику: через него можно выполнять запросы и управлять MongoDB.

А mongodump и mongorestore понадобятся позже, когда будем проходить полный цикл резервного копирования.

Как работает сервис mongod

После установки MongoDB сервер запускается как systemd service:

    mongod.service

Посмотреть его состояние можно так:

    sudo systemctl status mongod

Для короткой проверки:

    sudo systemctl is-active mongod

Если сервис работает, получим:

    active

Чтобы MongoDB автоматически запускалась после reboot:

    sudo systemctl enable mongod

Управление стандартное:

    sudo systemctl start mongod
sudo systemctl stop mongod
sudo systemctl restart mongod

Если MongoDB не запускается, первое место для проверки — systemd logs:

    sudo journalctl -u mongod -n 100 --no-pager

Позже, когда начнем менять mongod.conf, эта команда особенно пригодится: ошибка YAML или неправильный параметр может помешать сервису стартовать.

Где находятся конфигурация, данные и логи

После стандартной установки основные файлы лежат в предсказуемых местах.

Конфигурация:

    /etc/mongod.conf

Именно здесь позже будем включать authorization и менять сетевые параметры вроде bindIp.

Данные MongoDB по умолчанию находятся в:

    /var/lib/mongodb

Этот каталог содержит файлы WiredTiger и другие данные базы.

Логи:

    /var/log/mongodb/mongod.log

Получается простая тройка:

    /etc/mongod.conf
/var/lib/mongodb
/var/log/mongodb/mongod.log

Первый путь отвечает за настройки, второй — за данные, третий — за диагностику.

Именно поэтому при проблемах стоит сразу понимать, где искать причину: конфигурация — в mongod.conf, запуск сервиса — в systemctl и journal, ошибки MongoDB — в mongod.log.

Теперь можно перейти к установке.

Практика: устанавливаем и запускаем MongoDB

Сначала обновим индекс пакетов:

    sudo apt update

Установим утилиты, которые понадобятся для добавления repository:

    sudo apt install -y curl gnupg

Добавим GPG key MongoDB:

    curl -fsSL https://pgp.mongodb.com/server-8.0.asc | \
  sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \
  --dearmor

Теперь добавим repository для Ubuntu 24.04:

    echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | \
  sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list

Обновим индекс пакетов:

    sudo apt update

Установим MongoDB:

    sudo apt install -y mongodb-org

Проверим установленную версию сервера:

    mongod --version

Версию shell:

    mongosh --version

И наличие Database Tools:

    mongodump --version
mongorestore --version

Теперь запустим MongoDB:

    sudo systemctl start mongod

Добавим автозапуск:

    sudo systemctl enable mongod

Проверим состояние:

    sudo systemctl status mongod

Для краткой проверки:

    sudo systemctl is-active mongod

Теперь попробуем подключиться:

    mongosh

Если все работает, откроется MongoDB Shell.

Выполним простую проверку:

    db.runCommand({ ping: 1 })

Успешный ответ будет содержать:

    ok: 1

Это подтверждает, что mongod работает и принимает локальное соединение.

Выйти из shell можно командой:

    exit

Основные команды установки и проверки можно оставить в небольшой таблице:

Задача Команда 
Установить MongoDB sudo apt install -y mongodb-org 
Запустить сервис sudo systemctl start mongod 
Включить автозапуск sudo systemctl enable mongod 
Проверить состояние sudo systemctl status mongod 
Подключиться через shell mongosh 
Проверить сервер db.runCommand({ ping: 1 }) 
Посмотреть log sudo tail -n 100 /var/log/mongodb/mongod.log 

На этом базовая установка готова: mongod запущен, shell подключается, а основные пути и команды уже понятны.

Следующий шаг — настроить authentication. Сначала разберемся, как в MongoDB устроены пользователи, authentication database и roles, а затем создадим первого административного пользователя.

Разбираемся с аутентификацией MongoDB

Почему MongoDB нельзя оставлять без authentication

Пока authentication не включена, сам факт сетевой доступности MongoDB уже становится риском.

Если mongod слушает только:

    127.0.0.1

угроза меньше, потому что подключиться можно только с самого сервера.

Но если затем изменить bindIp и открыть MongoDB в сеть, не настроив пользователей, любой клиент, который доберется до порта 27017, потенциально сможет работать с данными без нормальной проверки личности.

Поэтому мы и строим настройку в таком порядке:

  1. Сначала локальная MongoDB;
  2. Затем административный пользователь;
  3. После этого обязательная authentication;
  4. Потом пользователь приложения;
  5. И только затем — удаленный доступ, если он вообще нужен.

Так безопаснее и понятнее: сначала создаем механизм доступа, потом расширяем сеть.

Что такое user и authentication database

В MongoDB пользователь создается не просто «на сервере вообще», а внутри определенной database.

Например:

    use app_db

а затем:

    db.createUser({
    user: "app_user",
    pwd: "StrongPassword",
    roles: [
      { role: "readWrite", db: "app_db" }
    ]
})

В таком случае authentication database для app_user — это:

    app_db

Именно там MongoDB хранит учетную запись пользователя и проверяет credentials.

Поэтому connection string должен учитывать не только рабочую database, но и authSource.

Например:

    mongodb://app_user:password@127.0.0.1:27017/app_db?authSource=app_db

Здесь обе database совпадают:

  • Приложение работает с app_db;
  • Пользователь тоже создан в app_db.

Но это не обязательное правило.

Например, административный пользователь часто создается в:

    admin

Тогда подключение может выглядеть так:

    mongodb://admin_user:password@127.0.0.1:27017/?authSource=admin

Если authSource указан неправильно, MongoDB будет искать пользователя не там, где он создан, и аутентификация завершится ошибкой.

Позже специально воспроизведем такую ситуацию при разборе Authentication failed.

Чем административный пользователь отличается от пользователя приложения

Административный пользователь нужен для управления самим сервером.

Он может:

  • Создавать других пользователей;
  • Назначать roles;
  • Просматривать databases;
  • Выполнять административные операции;
  • Управлять доступом.

Приложению большая часть этих возможностей вообще не нужна.

Обычному веб-приложению обычно достаточно работать только со своей database:

    app_db

и выполнять там операции чтения и записи.

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

Условно:

Поэтому разделение пользователей — не формальность.

Для приложения создаем отдельную учетную запись с минимально необходимыми permissions, а admin используем только для администрирования MongoDB.

Чтобы эти права задавать осмысленно, нужно понять, как работают roles.

Как работают roles

Role определяет, какие действия разрешены пользователю.

Одна из самых распространенных ролей приложения:

    readWrite

Она позволяет читать и изменять данные в указанной database.

Например:

    roles: [
  { role: "readWrite", db: "app_db" }
]

Такой пользователь сможет:

  • Выполнять find;
  • Добавлять documents;
  • Изменять их;
  • Удалять данные;
  • Создавать нужные collections и indexes в пределах своих полномочий.

Но это не делает его администратором всего MongoDB-сервера.

Есть и более ограниченная роль: read

Она подходит для сервисов, которым нужно только читать данные.

Административные роли уже дают значительно более широкие возможности. Например, для административной учетной записи можно использовать root, если действительно нужен полный контроль над сервером.

То есть логика простая: role должна соответствовать реальной задаче пользователя.

Не стоит выдавать root, если приложению достаточно readWrite для одной database.

Какую схему пользователей используем в статье

Чтобы дальше не путаться в пользователях и правах, сразу зафиксируем две учетные записи.

Первая:

    mongo_admin

Создадим ее в database:

    admin

и используем для административных операций.

Вторая:

    app_user

Создадим в:

    app_db

и дадим только:

    readWrite

на эту database.

Получается такая схема:

Пользователь Authentication DB Role Назначение 
mongo_admin admin root Управление MongoDB и пользователями 
app_user app_db readWrite для app_db Работа приложения со своими данными 

Такое разделение пригодится практически сразу.

Создаем административного пользователя

Теперь, когда понятны роли и authentication database, можно создать первого пользователя MongoDB — административного.

Этот шаг лучше сделать до включения обязательной authorization. Пока mongod доступен только локально и не принимает внешние подключения, можно спокойно создать admin, проверить его credentials и только после этого закрыть анонимный доступ.

Почему первого пользователя создают до включения authorization

После включения:

    security:
  authorization: enabled

MongoDB начинает требовать учетную запись для операций, которые раньше выполнялись без аутентификации.

Поэтому сначала логично создать пользователя, под которым мы сможем продолжить администрирование.

В нашем случае это:

    mongo_admin

Он будет создан в authentication database:

    admin

После этого можно включить authorization и уже входить в MongoDB с логином и паролем.

Так последовательность остается предсказуемой:

  1. Локально подключаемся без credentials;
  2. Создаем mongo_admin;
  3. Проверяем, что пользователь существует;
  4. Включаем authorization;
  5. Подключаемся уже под admin.

Если перепутать порядок и закрыть доступ раньше времени, настройка становится заметно неудобнее.

Какие права нужны администратору

Для статьи административному пользователю нужен полный контроль над MongoDB-сервером.

Поэтому назначим роль:

    root

Она даст mongo_admin права на управление databases, пользователями и другими административными операциями.

Для production можно строить более детальную модель доступа и разделять обязанности между несколькими учетными записями. Но для одного небольшого standalone-сервера отдельный admin с root — понятная и практичная схема.

Главное — не использовать эту учетную запись внутри самого приложения.

Приложение позже получит собственного пользователя:

    app_user

с readWrite только для app_db.

Теперь создадим admin на практике.

Практика: создаем admin и проверяем вход

Подключаемся локально:

    mongosh

Переходим в database admin:

    use admin

Создаем пользователя:

    db.createUser({
    user: "mongo_admin",
    pwd: passwordPrompt(),
    roles: [
      { role: "root", db: "admin" }
    ]
})

passwordPrompt() удобнее, чем записывать пароль прямо в команду: значение не остается в явном виде в примере и не попадает в shell history как часть команды.

MongoDB запросит пароль интерактивно.

После успешного создания можно проверить пользователя:

    db.getUser("mongo_admin")

В выводе должны быть видны имя пользователя и назначенная роль root.

Теперь выйдем из shell:

    exit

На этом этапе authorization еще не включена, поэтому сам факт существования пользователя пока не заставляет MongoDB требовать login при каждом подключении.

Но credentials уже можно проверить явно.

Подключимся так:

    mongosh --username mongo_admin --authenticationDatabase admin --password

После ввода пароля откроется MongoDB Shell.

Внутри можно проверить текущего пользователя и выполнить административную команду:

    use admin
db.runCommand({ connectionStatus: 1 })

В ответе должна присутствовать информация об аутентифицированном пользователе mongo_admin.

Можно также выполнить:

    show dbs

Если команда работает, административные права применились корректно.

Теперь у нас есть рабочая административная учетная запись, и можно переходить к следующему важному шагу — включать обязательную authorization.

После этого обычный mongosh без credentials уже не должен давать полноценный доступ к данным и административным операциям.

Включаем обязательную авторизацию

Что меняется после authorization: enabled

Ключевой параметр выглядит так:

    security:
  authorization: enabled

После его включения MongoDB начинает применять role-based access control.

То есть одного подключения к серверу уже недостаточно. Клиенту нужно аутентифицироваться под конкретным пользователем, а затем MongoDB проверит, разрешена ли ему нужная операция.

Например, административный пользователь сможет:

  • Создавать пользователей;
  • Просматривать databases;
  • Менять роли;
  • Выполнять административные команды.

А будущий app_user сможет работать только с app_db в рамках роли readWrite.

Именно с этого момента разделение пользователей, которое мы настроили раньше, начинает реально работать.

Где настраивается security в mongod.conf

Основной конфигурационный файл MongoDB находится здесь:

    /etc/mongod.conf

Откроем его:

    sudo nano /etc/mongod.conf

Нас интересует секция security.

Если ее еще нет, добавим:

    security:
  authorization: enabled

Важно сохранить правильные отступы. mongod.conf использует YAML, поэтому ошибка в структуре может привести к тому, что mongod вообще не запустится после перезагрузки.

Заодно можно убедиться, что сетевые настройки пока остаются локальными:

    net:
  port: 27017
  bindIp: 127.0.0.1

На этом этапе это именно то, что нам нужно: authorization уже включается, но MongoDB все еще не доступна извне.

Следующий вопрос — что увидит пользователь, если попробует подключиться без credentials.

Что произойдет с подключением без credentials

После включения authorization команда:

    mongosh

по-прежнему может установить соединение с локальным mongod.

Но это не означает, что клиент получил полноценный доступ к данным.

Например, shell может открыться, но защищенные операции начнут возвращать ошибки авторизации.

Если попытаться посмотреть список databases:

    show dbs

MongoDB должна отказать в выполнении команды, потому что клиент не аутентифицирован.

То же самое произойдет при попытке выполнять операции, для которых требуются права.

То есть важно различать два понятия:

  • Подключение к серверу;
  • Авторизованный доступ к данным.

Сетевое соединение может установиться, но MongoDB не даст выполнять защищенные действия без пользователя.

Для нормальной работы после этого нужно подключаться, например, так:

    mongosh --username mongo_admin --authenticationDatabase admin --password

Теперь включим authorization и проверим это поведение на практике.

Практика: включаем authorization и перезапускаем MongoDB

Открываем конфигурацию:

    sudo nano /etc/mongod.conf

Добавляем:

    security:
  authorization: enabled

Вместе с текущей сетевой настройкой соответствующая часть файла может выглядеть так:

Сохраняем файл.

Теперь перезапускаем MongoDB:

    sudo systemctl restart mongod

Сразу проверим состояние сервиса:

    sudo systemctl status mongod

Если видим:

    active (running)

конфигурация принята.

Если сервис не запустился, первым делом смотрим:

    sudo journalctl -u mongod -n 100 --no-pager

и:

    sudo tail -n 100 /var/log/mongodb/mongod.log

Теперь проверим подключение без credentials:

    mongosh

Внутри попробуем:

    show dbs

MongoDB должна сообщить, что операция требует authentication.

Выйдем:

    exit

Теперь подключимся правильно:

    mongosh --username mongo_admin --authenticationDatabase admin --password

После ввода пароля проверим:

    show dbs

и:

    db.runCommand({ connectionStatus: 1 })

Теперь команды должны выполняться с правами mongo_admin.

Коротко результат можно свести так:

Изменение Что происходит Как проверить 
authorization: enabled MongoDB начинает проверять пользователей и роли Перезапустить mongod 
Подключение без credentials Соединение возможно, но защищенные операции блокируются mongosh → show dbs 
Подключение под admin Доступ определяется ролью пользователя mongosh --username mongo_admin --authenticationDatabase admin --password 
Ошибка в mongod.conf mongod может не запуститься systemctl status и journalctl 

Теперь анонимный доступ к MongoDB закрыт, а административные операции выполняются только после аутентификации.

Создаем отдельного пользователя приложения

Обязательная авторизация уже включена, а mongo_admin может управлять сервером. Теперь нужно отделить административный доступ от обычной работы приложения.

Это важный момент: приложение не должно подключаться к MongoDB под root-пользователем просто потому, что «так проще». Для него создадим отдельную учетную запись с правами только на рабочую database.

Почему приложение не должно работать от admin

Административный пользователь имеет слишком широкие права для обычного приложения.

Если приложение подключается как mongo_admin, оно потенциально может:

  • Работать с чужими databases;
  • Создавать и удалять пользователей;
  • Менять роли;
  • Выполнять административные команды;
  • Затронуть весь MongoDB-сервер при ошибке в коде.

Для приложения это лишнее.

Ему обычно нужно гораздо меньше:

  • Читать свои данные;
  • Добавлять документы;
  • Изменять их;
  • Удалять их;
  • Создавать необходимые indexes.

Поэтому правильнее создать отдельного пользователя:

    app_user

и ограничить его только:

    app_db

Если потом приложение будет скомпрометировано, зона поражения хотя бы останется в пределах этой database, а не всего сервера.

Как ограничить пользователя одной database

Пользователь MongoDB создается внутри конкретной authentication database и получает роли с указанием database, к которой они относятся.

Для нашего приложения перейдем в:

    use app_db

и создадим пользователя именно там.

Тогда его authentication database тоже будет:

    app_db

Это удобно и для connection string:

    mongodb://app_user:password@127.0.0.1:27017/app_db?authSource=app_db

При таком подходе учетная запись и рабочая database логически находятся в одном месте.

Права задаются через roles.

Например:

    roles: [
  { role: "readWrite", db: "app_db" }
]

Так пользователь получает доступ к чтению и записи только в app_db.

Он не становится администратором и не получает права на другие databases автоматически.

Какие роли нужны для чтения и записи

Для обычного приложения чаще всего подходит роль:

    readWrite

Она позволяет работать с данными в конкретной database.

Пользователь с readWrite может:

  • Читать documents;
  • Вставлять новые;
  • Изменять существующие;
  • Удалять documents;
  • Создавать collections;
  • Работать с indexes в рамках своих полномочий.

Если сервису нужно только читать данные, можно использовать более ограниченную роль:

    read

Например, для отдельного reporting-сервиса это может быть достаточно.

Но нашему тестовому приложению понадобится полный обычный CRUD, поэтому используем:

    readWrite

для app_db.

Теперь создадим пользователя и сразу проверим несколько сценариев: успешную запись, чтение, отсутствие административных прав и ошибку при неправильном пароле.

Практика: создаем app_user и проверяем права

Сначала подключимся под административным пользователем:

    mongosh --username mongo_admin --authenticationDatabase admin --password

Переходим в рабочую database:

    use app_db

Создаем пользователя:

    db.createUser({
    user: "app_user",
    pwd: passwordPrompt(),
    roles: [
      { role: "readWrite", db: "app_db" }
    ]
})

После успешного создания проверим учетную запись:

    db.getUser("app_user")

В выводе должна быть видна роль:

    readWrite

для:

    app_db

Теперь выходим:

    exit

И подключаемся уже как приложение:

    mongosh \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  app_db

После ввода правильного пароля shell должен открыться.

Теперь проверим запись.

Создадим collection и добавим документ:

    db.users.insertOne({
    name: "Alice",
    email: "alice@example.com",
    active: true
})

При успешной записи MongoDB вернет результат с acknowledged: true и insertedId.

Теперь проверим чтение:

    db.users.find()

В выводе должен появиться добавленный документ.

Следом проверим изменение:

    db.users.updateOne(
  { name: "Alice" },
  { $set: { active: false } }
)

И снова посмотрим данные:

    db.users.find({ name: "Alice" })

Теперь active должен быть false.

Можно проверить и удаление:

    db.users.deleteOne({ name: "Alice" })

То есть пользователь действительно умеет работать с данными своей database.

Теперь проверим обратную сторону — отсутствие административных прав.

Например, попробуем перейти в admin и запросить список пользователей:

    use admin
db.getUsers()

app_user не должен получить административный доступ к управлению пользователями.

Можно также попробовать создать пользователя:

    db.createUser({
    user: "should_not_work",
    pwd: passwordPrompt(),
    roles: []
})

Операция должна завершиться ошибкой авторизации.

Теперь проверим неправильный пароль.

Выйдем из shell:

    exit

И попробуем подключиться так:

    mongosh \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  app_db

На запрос пароля намеренно вводим неверное значение.

В ответ должны получить ошибку вида:

    Authentication failed

Это важная проверка: MongoDB не просто знает пользователя, а действительно проверяет credentials.

После этого снова подключаемся с правильным паролем и убеждаемся, что доступ восстановлен.

Для итоговой проверки можно оставить четыре сценария:

Проверка Ожидаемый результат 
Запись в app_db Успешно 
Чтение из app_db Успешно 
Административная команда Access denied / Unauthorized 
Неправильный пароль Authentication failed 

Теперь модель доступа работает так, как и планировалось: mongo_admin управляет сервером, а app_user работает только со своей database.

Следующий шаг — сетевой уровень. Разберемся с bindIp, портом 27017 и тем, как открыть удаленный доступ только доверенному адресу, не выставляя MongoDB наружу без ограничений.

Настраиваем безопасный сетевой доступ

Почему MongoDB по умолчанию не стоит открывать всему интернету

MongoDB — это сервер базы данных, а не публичный веб-сервис.

Если открыть порт 27017 для всех адресов, любой клиент из интернета сможет хотя бы попытаться установить соединение с mongod.

Даже при включенной authorization это создает лишнюю поверхность атаки:

  • Постоянные попытки подбора credentials;
  • Сканирование порта;
  • Лишняя нагрузка;
  • Риск ошибки в настройках пользователей;
  • Риск случайно отключить authentication в будущем и оставить базу открытой.

Поэтому лучше строить доступ по принципу: MongoDB слушает только там, где действительно нужно, а firewall пропускает только доверенные источники.

В идеале оба ограничения работают одновременно.

Первое задается через bindIp.

Второе — через firewall.

Как работает bindIp

Параметр bindIp определяет, на каких сетевых интерфейсах mongod принимает подключения.

Он находится в секции net файла:

    /etc/mongod.conf

Например:

    net:
  port: 27017
  bindIp: 127.0.0.1

В такой конфигурации MongoDB слушает только localhost.

То есть подключиться можно с самого VPS:

    mongosh

но другой сервер в сети уже не сможет достучаться до 27017.

Если нужно разрешить соединения еще и через private IP сервера, можно указать оба адреса:

    net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.10

Теперь mongod слушает:

  • localhost;
  • private interface 10.0.0.10.

Важно понимать: bindIp отвечает именно за то, где MongoDB слушает соединения.

Он не заменяет firewall.

Даже если mongod слушает private или public interface, сетевой доступ все равно лучше отдельно ограничить правилами firewall.

Когда достаточно 127.0.0.1

Если приложение работает на том же VPS, ничего открывать наружу вообще не нужно.

Схема тогда простая:

Connection string:

    mongodb://app_user:password@127.0.0.1:27017/app_db?authSource=app_db

Это один из самых безопасных и простых вариантов.

Порт 27017 не доступен снаружи, а приложение общается с базой через loopback interface.

Такую схему стоит оставлять, если нет конкретной причины для удаленного подключения.

Чем меньше сетевых интерфейсов слушает MongoDB, тем меньше настроек нужно защищать и диагностировать.

Когда нужен удаленный доступ

Удаленный доступ нужен, если приложение и MongoDB находятся на разных серверах.

Например: Application VPS → MongoDB VPS

В таком случае база должна принимать соединения по адресу, доступному приложению.

Лучше использовать private network, если облачный провайдер ее предоставляет.

Например:

Тогда в mongod.conf можно оставить:

    net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.10

А приложение будет подключаться к:

    mongodb://app_user:password@10.0.0.10:27017/app_db?authSource=app_db

Так database traffic вообще не нужно выводить в публичный интернет.

Если private network нет и приходится использовать public IP, особенно важно ограничить firewall только конкретным доверенным адресом приложения.

То есть нежелательный вариант: 0.0.0.0:27017 → доступно всем

Нормальный вариант: MongoDB public IP:27017 → доступ только с IP приложения

Теперь настроим этот второй уровень защиты.

Как ограничить порт 27017 через firewall

Предположим, доверенный IP приложения:

    203.0.113.20

Если используется UFW, можно разрешить подключение только с этого адреса:

    sudo ufw allow from 203.0.113.20 to any port 27017 proto tcp

Проверим правила:

    sudo ufw status numbered

Не нужно добавлять:

    sudo ufw allow 27017/tcp

если MongoDB не должна быть доступна всем.

Такое правило откроет порт для любого источника, что нам как раз не нужно.

Если VPS находится у облачного провайдера с отдельным network firewall или security group, ограничение стоит повторить и там.

Тогда получается два слоя: Cloud firewall → UFW → mongod bindIp

Чтобы соединение прошло, все три уровня должны разрешить нужный маршрут.

Практика: открываем доступ только доверенному адресу

Предположим, MongoDB VPS имеет private IP:

    10.0.0.10

а приложение:

    10.0.0.20

Откроем конфигурацию:

    sudo nano /etc/mongod.conf

Настроим секцию net:

    net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.10

Сохраняем файл и перезапускаем MongoDB:

    sudo systemctl restart mongod

Проверяем:

    sudo systemctl is-active mongod

Теперь посмотрим, где реально слушает порт:

    sudo ss -lntp | grep 27017

В выводе должны присутствовать только нужные адреса.

Если используется UFW, разрешаем доступ с сервера приложения:

    sudo ufw allow from 10.0.0.20 to any port 27017 proto tcp

Проверяем:

    sudo ufw status

Теперь с Application VPS можно проверить сам TCP-порт:

    nc -vz 10.0.0.10 27017

Если nc отсутствует:

    sudo apt install -y netcat-openbsd

После этого уже проверим полноценное подключение:

    mongosh \
  "mongodb://app_user@10.0.0.10:27017/app_db?authSource=app_db" \
  --password

При правильном пароле пользователь должен войти и получить доступ к app_db.

С другого, недоверенного адреса порт при этом должен оставаться недоступным.

Для удобства сравним основные варианты:

Схема bindIp Firewall Когда использовать 
Localhost 127.0.0.1 27017 наружу закрыт Приложение и MongoDB на одном VPS 
Private network 127.0.0.1,10.0.0.10 Разрешен только private IP приложения Лучший вариант для двух VPS в одной private network 
Public network Localhost + нужный public interface 27017 разрешен только доверенному public IP Если private network недоступна 

Идём дальше.

Проверяем подключение к MongoDB

Сетевой доступ уже настроен: локальный клиент может обращаться к MongoDB через 127.0.0.1, а при необходимости удаленный сервер получает доступ только через доверенный адрес. Теперь осталось проверить, что connection string составлен правильно и MongoDB действительно различает успешное подключение, неверный authSource и неправильный пароль.

Здесь полезно пройти сразу несколько сценариев. Тогда позже при ошибке будет проще понять, проблема в credentials, authentication database или самой сети.

Как выглядит connection string

Для подключения к MongoDB обычно используют URI вида:

    mongodb://username:password@host:27017/database?authSource=authentication_database

В нашем случае локальная строка выглядит так:

    mongodb://app_user:password@127.0.0.1:27017/app_db?authSource=app_db

Здесь:

  • app_user — пользователь приложения;
  • password — его пароль;
  • 127.0.0.1 — адрес MongoDB;
  • 27017 — стандартный порт;
  • app_db — рабочая database;
  • authSource=app_db — database, где создан пользователь.

Для удаленного подключения меняется в первую очередь host:

    mongodb://app_user:password@10.0.0.10:27017/app_db?authSource=app_db

или доверенный public IP, если private network недоступна.

В production лучше не передавать пароль прямо в командной строке, потому что он может попасть в shell history или список процессов. Для ручной проверки удобнее использовать --password и вводить значение интерактивно.

Зачем нужен authSource

MongoDB должна знать, в какой database искать учетную запись пользователя.

Мы создавали:

    app_user

в:

    app_db

Поэтому правильный authSource:

    authSource=app_db

Если вместо этого указать:

    authSource=admin

MongoDB будет искать app_user в другой authentication database.

В результате пароль может быть совершенно правильным, но аутентификация все равно завершится ошибкой.

Это одна из причин, почему Authentication failed не всегда означает «неправильный пароль».

Сначала стоит проверить сразу три вещи:

  • username;
  • password;
  • authSource.

Теперь проверим правильный локальный сценарий.

Как проверить локальное подключение

На MongoDB VPS подключимся так:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

После запроса вводим пароль app_user.

Если все настроено правильно, откроется MongoDB Shell.

Проверим текущую database:

    db

Ожидаем:

    app_db

Теперь выполним простой запрос:

    db.runCommand({ ping: 1 })

И проверим доступ к данным:

    db.users.find()

Если collection еще пустая или отсутствует, это не проблема. Главное, что команда выполняется без Unauthorized.

Так мы подтверждаем сразу три вещи:

  • MongoDB доступна локально;
  • credentials работают;
  • пользователь имеет права на app_db.

После этого можно проверить ту же схему с другого сервера.

Как проверить удаленное подключение

На Application VPS сначала убедимся, что порт доступен:

    nc -vz 10.0.0.10 27017

Если соединение проходит, переходим к MongoDB authentication:

    mongosh \
  "mongodb://app_user@10.0.0.10:27017/app_db?authSource=app_db" \
  --password

После правильного пароля shell должен открыться так же, как при локальном подключении.

Внутри можно выполнить:

    db.runCommand({ ping: 1 })

и:

    db.users.find()

Если TCP-порт недоступен вообще, до authentication дело еще не дошло.

Тогда нужно возвращаться к предыдущему уровню и проверять:

  • bindIp;
  • UFW;
  • cloud firewall;
  • IP MongoDB VPS;
  • маршрут между серверами.

То есть ошибка подключения и ошибка авторизации — это два разных этапа.

Что должно происходить при неправильном пароле

Теперь намеренно проверим негативный сценарий.

Выполним ту же команду:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

Но введем неправильный пароль.

MongoDB должна отказать в аутентификации и вернуть ошибку вида:

    Authentication failed

Это ожидаемое поведение.

Можно отдельно проверить неправильный authSource:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=admin" \
  --password

Даже с правильным паролем подключение под app_user должно завершиться ошибкой, потому что пользователь создан в app_db, а не в admin.

Таким образом, у нас уже есть несколько контрольных сценариев:

Сценарий Строка подключения / проверка Ожидаемый результат 
Локально, правильные credentials mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db Успешный вход 
Удаленно с доверенного сервера mongodb://app_user@10.0.0.10:27017/app_db?authSource=app_db Успешный вход 
Неправильный пароль Та же URI, неверный password Authentication failed 
Неправильный authSource authSource=admin для app_user Authentication failed 
Недоверенный IP Проверка 27017 с другого адреса Соединение блокируется firewall 

Теперь подключение проверено и с сетевой, и с authentication стороны. Следующий шаг — перейти от самой инфраструктуры к данным: создадим тестовую collection, добавим несколько documents и подготовим их для полного цикла backup → удаление → restore.

Записываем тестовые данные

Создаем тестовую database и collection

В MongoDB не требуется заранее создавать database отдельной командой.

Database и collection фактически появляются после первой записи данных. Поэтому достаточно подключиться к app_db:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

После ввода пароля убедимся, что выбрана нужная database:

    db

Ожидаемый результат:

    app_db

Collection можно создать явно:

    db.createCollection("products")

При успешном выполнении получим результат с:

    ok: 1

Проверим список collections:

    show collections

Теперь среди них должна присутствовать:

    products

Явное создание collection здесь не обязательно — MongoDB могла бы создать ее автоматически при первой вставке. Но для пошаговой проверки удобнее сначала создать структуру, а затем отдельно добавить документы.

Добавляем несколько documents

Добавим сразу несколько записей через insertMany():

    db.products.insertMany([
    {
      sku: "TEST-001",
      name: "Mechanical Keyboard",
      price: 89.90,
      stock: 12,
      active: true
    },
    {
      sku: "TEST-002",
      name: "Wireless Mouse",
      price: 39.50,
      stock: 27,
      active: true
    },
    {
      sku: "TEST-003",
      name: "USB-C Dock",
      price: 119.00,
      stock: 5,
      active: false
    }
])

Если запись прошла успешно, MongoDB вернет:

    acknowledged: true

а также _id созданных документов.

Получается небольшой, но удобный набор данных. Записи легко отличить друг от друга по sku, названию, цене и остатку.

Теперь специально не будем их изменять до backup. Именно это состояние базы понадобится сравнить с результатом после восстановления.

Проверяем записанные данные

Посмотрим все документы:

    db.products.find()

Для более компактного результата можно вывести только нужные поля:

    db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    price: 1,
    stock: 1,
    active: 1
  }
)

Должны увидеть три записи:

  • TEST-001
  • TEST-002
  • TEST-003

Посчитаем документы:

    db.products.countDocuments()

Ожидаемый результат: 3

Можно дополнительно проверить конкретную запись:

    db.products.findOne({ sku: "TEST-003" })

MongoDB должна вернуть документ с USB-C Dock.

Теперь у нас есть несколько удобных контрольных признаков:

  • database — app_db;
  • collection — products;
  • количество документов — 3;
  • уникальные sku — TEST-001, TEST-002, TEST-003.

После восстановления проверим те же значения. Если collection снова содержит все три документа с исходными полями, restore действительно вернул данные.

Практика: готовим данные для backup

Перед созданием резервной копии проведем финальную проверку.

Сначала убедимся, что работаем в нужной database:

    db

Результат:

    app_db

Проверяем collection:

    show collections

В списке должна быть:

    products

Проверяем количество записей:

    db.products.countDocuments()

Получаем:

    3

Теперь выведем контрольный набор:

    db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    stock: 1
  }
).sort({ sku: 1 })

Перед backup результат должен соответствовать примерно такой структуре:

    {
  sku: 'TEST-001',
  name: 'Mechanical Keyboard',
  stock: 12
}
{
  sku: 'TEST-002',
  name: 'Wireless Mouse',
  stock: 27
}
{
  sku: 'TEST-003',
  name: 'USB-C Dock',
  stock: 5
}

На этом тестовый набор готов.

Дальше начнется основной цикл проверки резервного копирования:

Следующий шаг — создать резервную копию через mongodump и убедиться, что backup действительно содержит нашу app_db, прежде чем что-либо удалять.

Создаем резервную копию через mongodump

Что сохраняет mongodump

mongodump подключается к работающей MongoDB и выгружает содержимое databases в BSON.

При обычном backup одной database структура будет примерно такой:

Файл products.bson содержит сами documents.

А products.metadata.json хранит метаданные collection, например информацию об indexes и дополнительных параметрах.

Если в database несколько collections, для каждой появятся соответствующие BSON- и metadata-файлы.

То есть mongodump сохраняет не текстовый экспорт вроде CSV, а структуру, предназначенную именно для последующего восстановления MongoDB.

Чем logical backup отличается от копирования файлов MongoDB

Можно было бы предположить, что достаточно скопировать:

    /var/lib/mongodb

но это совсем другой подход.

В этом каталоге находятся внутренние файлы WiredTiger, journal и служебные данные работающего storage engine. Простое копирование файлов во время работы mongod не равно корректному logical backup и может дать несогласованное состояние.

mongodump работает на более высоком уровне:

Он подключается к серверу как обычный клиент и выгружает доступные ему данные.

Это удобно для:

  • Резервного копирования отдельных databases;
  • Переноса данных между MongoDB-серверами;
  • Восстановления отдельных collections;
  • Небольших и средних объемов данных;
  • Тестирования процедуры restore.

Но logical backup тоже не заменяет полноценную стратегию резервирования для любой нагрузки. Чем больше database и интенсивнее запись, тем важнее заранее продумать консистентность, окно backup и способ хранения копий.

Как передать credentials безопаснее

Самый очевидный вариант выглядел бы так:

    mongodump \
  --username app_user \
  --password MySecretPassword \
  --authenticationDatabase app_db \
  --db app_db

Но пароль в командной строке — плохая идея.

Он может остаться в shell history, попасть в скрипт или быть случайно сохранен вместе с другими командами.

Поэтому лучше передать только имя пользователя и попросить утилиту запросить пароль интерактивно:

    mongodump \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  --db app_db

После запуска появится запрос пароля.

Другой вариант — использовать URI без пароля:

    mongodump \
  --uri="mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

В обоих случаях секрет не записывается прямо в команду.

Если backup автоматизируется через cron или systemd timer, credentials уже нужно хранить отдельно с ограниченными правами, а не вставлять пароль непосредственно в shell-команду.

Куда сохранять backup

По умолчанию mongodump создает каталог dump в текущей директории.

Для разового теста этого достаточно, но на сервере удобнее заранее выделить понятный путь:

    /var/backups/mongodb

Создадим его:

    sudo install -d \
  -m 700 \
  -o "$(id -un)" \
  -g "$(id -gn)" \
  /var/backups/mongodb

Права 700 означают, что читать и изменять содержимое может только владелец каталога.

Это особенно полезно, потому что backup содержит реальные данные приложения.

При этом хранить единственную резервную копию на том же VPS недостаточно. Если сервер потеряет диск, backup исчезнет вместе с MongoDB.

Поэтому для production логика должна быть такой:

Например, второе хранилище, Object Storage или отдельный backup-сервер.

Сначала создадим локальную копию и проверим полный цикл восстановления 

Практика: создаем backup app_db

Перед началом еще раз проверим, что исходные данные существуют.

Подключаемся:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

Считаем документы:

    db.products.countDocuments()

Ожидаем: 3

Можно еще раз вывести контрольные записи:

    db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    stock: 1
  }
).sort({ sku: 1 })

После проверки выходим:

    exit

Теперь создаем отдельный каталог для этой копии:

    mkdir -p /var/backups/mongodb/app-db-backup

Запускаем mongodump:

    mongodump \
  --host 127.0.0.1 \
  --port 27017 \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  --db app_db \
  --out /var/backups/mongodb/app-db-backup

Вводим пароль app_user.

При успешной работе в выводе будут сообщения о выгрузке collection products.

Теперь посмотрим структуру:

    find /var/backups/mongodb/app-db-backup -maxdepth 2 -type f

Должны увидеть примерно:

    /var/backups/mongodb/app-db-backup/app_db/products.bson
/var/backups/mongodb/app-db-backup/app_db/products.metadata.json

Проверим размер:

    du -sh /var/backups/mongodb/app-db-backup

И отдельно содержимое database:

    ls -lh /var/backups/mongodb/app-db-backup/app_db

Перед удалением исходной database важно убедиться хотя бы в трех вещах:

  • Mongodump завершился без ошибки;
  • Каталог app_db действительно появился;
  • Внутри есть products.bson.

Для разных сценариев команды выглядят так:

Сценарий Пример 
Dump доступных databases сервера mongodump --username mongo_admin --authenticationDatabase admin --password --out /var/backups/mongodb/full 
Dump одной database mongodump --username app_user --authenticationDatabase app_db --password --db app_db --out /var/backups/mongodb/app-db-backup 
Один archive-файл mongodump --username app_user --authenticationDatabase app_db --password --db app_db --archive=/var/backups/mongodb/app_db.archive.gz --gzip 

Archive-режим удобен, если вместо каталога с несколькими BSON-файлами хочется получить один сжатый файл:

    app_db.archive.gz

Для нашего наглядного теста оставим обычный directory dump — так проще увидеть, что backup действительно содержит products.

Теперь резервная копия существует отдельно от исходной database.

Удаляем тестовую database

Backup уже создан и сохранен отдельно от рабочей MongoDB. Теперь нужно проверить его по-настоящему: удалить исходную database и убедиться, что данных больше нет.

Именно этот шаг отличает реальную проверку восстановления от ситуации, когда mongorestore запускается поверх уже существующих collections и нельзя однозначно понять, что именно вернулось из backup.

Почему перед удалением еще раз проверяем backup

Перед dropDatabase() стоит сделать последнюю контрольную проверку.

После удаления исходной database единственным источником данных останется созданный dump. Если backup оказался пустым, записан не в тот каталог или завершился с ошибкой, восстанавливать будет уже нечего.

Поэтому еще раз проверим файлы:

    find /var/backups/mongodb/app-db-backup -maxdepth 2 -type f

Ожидаем увидеть:

    /var/backups/mongodb/app-db-backup/app_db/products.bson
/var/backups/mongodb/app-db-backup/app_db/products.metadata.json

Проверим размер:

    du -sh /var/backups/mongodb/app-db-backup

И отдельно содержимое каталога:

    ls -lh /var/backups/mongodb/app-db-backup/app_db

Если products.bson существует и mongodump ранее завершился без ошибок, можно переходить к удалению.

Для дополнительной проверки можно еще раз посмотреть исходные данные:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

Внутри shell:

    db.products.countDocuments()

Ожидаемый результат: 3

И:

    db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1
  }
).sort({ sku: 1 })

После этого можно удалять database.

Практика: выполняем dropDatabase() и убеждаемся, что данных больше нет

Мы уже подключены к:

    app_db

Проверим это:

    db

Ожидаем:

    app_db

Теперь выполняем:

    db.dropDatabase()

При успешном удалении MongoDB вернет результат примерно такого вида:

    { ok: 1, dropped: 'app_db' }

На этом database удалена вместе с ее collections и documents.

Проверим список databases:

    show dbs

app_db больше не должна появляться в списке.

Теперь попробуем посмотреть collection:

    show collections

И выполнить запрос:

    db.products.find()

Так как исходная database уже удалена, прежних документов там больше нет.

Можно также проверить количество:

    db.products.countDocuments()

Для отсутствующей или заново не созданной collection результат будет: 0

Важно понимать один нюанс: команда:

    use app_db

сама по себе не восстанавливает database.

Она лишь переключает текущий контекст shell. Database появится снова только после записи данных или восстановления через mongorestore.

Поэтому после dropDatabase() мы специально ничего не вставляем вручную.

Контрольное состояние теперь такое:

Теперь исходные данные действительно удалены, а единственная копия тестового набора находится в backup.

Следующий шаг — восстановить app_db через mongorestore и проверить, что collection products снова содержит все три исходных документа.

Восстанавливаем MongoDB через mongorestore

Как mongorestore читает данные mongodump

mongorestore работает в паре с mongodump.

Ранее mongodump создал структуру:

Теперь mongorestore читает эти файлы и создает соответствующие databases и collections обратно в MongoDB.

Упрощенно процесс выглядит так:

При этом восстанавливаются сами documents и связанная с collection metadata.

Так как app_db сейчас удалена полностью, ситуация максимально чистая: восстановление должно фактически создать ее заново из dump.

Что происходит с существующими collections

Если database или collection уже существуют, mongorestore не всегда ведет себя так, как ожидает пользователь.

Без дополнительных параметров restore пытается добавить данные из backup в существующие collections.

Это может привести к нескольким сценариям:

  • Документы добавятся к существующим;
  • Возникнут конфликты по _id;
  • Часть записей уже будет присутствовать;
  • Результат перестанет быть точной копией состояния backup.

Именно поэтому перед restore нужно понимать, куда именно загружаются данные.

В нашей текущей проверке проблема отсутствует: app_db удалена, поэтому products будет создана заново.

Но если restore выполняется поверх существующей database, часто удобнее заранее очистить нужные collections.

Для этого и используется --drop.

Когда использовать --drop

Параметр:

    --drop

говорит mongorestore удалить соответствующую collection перед восстановлением ее из backup.

Например:

    mongorestore \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  --drop \
  /var/backups/mongodb/app-db-backup/app_db

Логика становится такой:

Это удобно, когда нужно именно заменить текущее состояние данными из dump.

Но --drop стоит использовать осознанно. Если в существующей collection есть новые данные, которых нет в backup, они будут удалены.

В нашем сценарии app_db уже отсутствует, поэтому технически --drop не обязателен. Но сам параметр полезно знать, потому что при повторных restore он часто становится важен.

Теперь восстановим удаленную database.

Практика: восстанавливаем удаленную app_db

Сначала убедимся, что backup на месте:

    find /var/backups/mongodb/app-db-backup -maxdepth 2 -type f

Ожидаем:

    /var/backups/mongodb/app-db-backup/app_db/products.bson
/var/backups/mongodb/app-db-backup/app_db/products.metadata.json

Теперь запускаем restore. Здесь есть важный нюанс: хотя мы полностью удалили app_db через db.dropDatabase(), созданный в ней пользователь app_user не удаляется вместе с данными. MongoDB хранит сведения о пользователях отдельно от пользовательских коллекций, поэтому dropDatabase() удаляет данные базы, но не связанную с ней учетную запись.

Поэтому для восстановления мы по-прежнему можем аутентифицироваться как app_user, указав app_db в качестве authentication database:

    mongorestore \
  --host 127.0.0.1 \
  --port 27017 \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  /var/backups/mongodb/app-db-backup/app_db

После запуска вводим пароль app_user.

При успешном восстановлении в выводе должны появиться сообщения о восстановлении app_db.products и количестве успешно импортированных документов.

Так как пользовательские данные app_db были удалены полностью, mongorestore заново создаст необходимые коллекции базы, включая products.

Если нужно восстановить те же данные поверх уже существующей collection, команда выглядела бы так:

    mongorestore \
  --host 127.0.0.1 \
  --port 27017 \
  --username app_user \
  --authenticationDatabase app_db \
  --password \
  --drop \
  /var/backups/mongodb/app-db-backup/app_db

После завершения restore можно сразу переходить к проверке результата.

Проверяем documents после restore

Подключаемся снова:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

Проверяем текущую database:

    db

Ожидаем:

    app_db

Теперь смотрим collections:

    show collections

В списке снова должна появиться:

    products

Проверим количество документов:

    db.products.countDocuments()

Ожидаемый результат:

    3

Теперь выведем контрольные записи:

    db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    price: 1,
    stock: 1,
    active: 1
  }
).sort({ sku: 1 })

Должны вернуться те же три документа:

    {
  sku: 'TEST-001',
  name: 'Mechanical Keyboard',
  price: 89.9,
  stock: 12,
  active: true
}
{
  sku: 'TEST-002',
  name: 'Wireless Mouse',
  price: 39.5,
  stock: 27,
  active: true
}
{
  sku: 'TEST-003',
  name: 'USB-C Dock',
  price: 119,
  stock: 5,
  active: false
}

Для дополнительной проверки можно запросить конкретную запись:

    db.products.findOne({ sku: "TEST-003" })

Если вернулся USB-C Dock с исходными полями, backup восстановился корректно.

Получается полный цикл:

Или чуть подробнее:

Теперь backup проверен полностью: данные были записаны, выгружены, исходная database удалена, затем восстановлена из dump и снова проверена через запросы.

Исправляем ошибки авторизации

К этому моменту у нас уже есть два пользователя с разными задачами: mongo_admin управляет сервером, а app_user работает только с app_db. Поэтому большинство проблем со входом теперь можно разбирать довольно системно.

Обычно ошибка авторизации возникает из-за одного из четырех факторов:

  • Неправильный username;
  • Неправильный password;
  • Неверный authSource;
  • Недостаточные roles.

Важно сначала понять, к какому типу относится ошибка, и только потом менять конфигурацию.

Что означает Authentication failed

Сообщение: Authentication failed, означает, что MongoDB не смогла успешно аутентифицировать пользователя.

Чаще всего причины простые:

  • Введен неверный пароль;
  • Указано неправильное имя пользователя;
  • Выбран неверный authSource;
  • Пользователь создан не в той authentication database, которую использует клиент.

Например, наш app_user создан в:

    app_db

Поэтому такая команда корректна:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

А здесь уже есть проблема:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=admin" \
  --password

MongoDB будет искать app_user в admin, а там такой учетной записи нет.

Результат — Authentication failed, даже если пароль введен правильно.

Почему важен правильный authSource

authSource указывает database, где хранится учетная запись пользователя.

Это не обязательно та же database, с которой пользователь работает.

Например, административный пользователь:

    mongo_admin

создан в:

    admin

Поэтому для него используется:

    authSource=admin

А пользователь приложения:

    app_user

создан в:

    app_db

Значит, для него:

    authSource=app_db

Полезно мысленно разделять два параметра: рабочая database ≠ authentication database

Иногда они совпадают, как у app_user.

Иногда нет.

Например, пользователь может быть создан в admin, но иметь права на другую database. Тогда connection string будет содержать рабочую database в пути, а authSource=admin.

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

Что происходит при подключении пользователя не к той database

Здесь важно различать две ситуации.

Первая — неправильная authentication database.

Например: app_user

создан в app_db, а клиент использует:

    authSource=admin

В этом случае пользователь вообще не пройдет аутентификацию.

Вторая ситуация — пользователь успешно аутентифицирован, но переключается на database, где у него нет нужной роли.

Например, app_user подключился правильно:

    authSource=app_db

а затем выполнил:

    use admin

Сам переход контекста еще не означает, что пользователь получил права на admin.

Если после этого выполнить административную команду:

    db.getUsers()

MongoDB должна вернуть ошибку авторизации.

То есть: успешный login ≠ права на любую database.

Права определяются назначенными roles.

Как проверить roles пользователя

Проверять пользователя удобнее под mongo_admin.

Подключаемся:

    mongosh \
  --username mongo_admin \
  --authenticationDatabase admin \
  --password

Если нужно посмотреть app_user, переходим в его authentication database:

    use app_db

Теперь:

    db.getUser("app_user")

В выводе должна быть роль:

    readWrite

для:

    app_db

Для более полного списка пользователей можно использовать:

    db.getUsers()

Если нужно проверить административного пользователя:

    use admin
db.getUser("mongo_admin")

Так можно быстро ответить на два вопроса:

  • Где пользователь создан;
  • Какие roles ему назначены.

Если пользователь успешно входит, но конкретная операция завершается Unauthorized, проблема чаще всего уже не в пароле, а именно в правах.

Практика: диагностируем ошибку входа

Разберем типичный сценарий.

Пользователь пытается подключиться:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=admin" \
  --password

Пароль вводится правильный, но получаем:

    Authentication failed

Сначала проверяем, существует ли пользователь.

Под mongo_admin:

    use app_db
db.getUser("app_user")

Если пользователь найден, смотрим, в какой database мы его проверяем.

У нас это:

    app_db

Значит, authentication database должна быть такой же.

Исправляем connection string:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

Теперь вводим тот же пароль.

Подключение должно пройти успешно.

Если нет, проверяем username:

    app_user

и повторно вводим пароль вручную.

Следующий сценарий — login проходит, но операция запрещена.

Например:

    use admin
db.getUsers()

и получаем ошибку Unauthorized.

В этом случае аутентификация работает нормально. Просто app_user не имеет административных roles.

Проверяем его права:

    use app_db
db.getUser("app_user")

Если видим:

    readWrite

для app_db, поведение правильное.

Основные ошибки можно свести в одну таблицу:

Ошибка Возможная причина Что проверить Решение 
Authentication failed Неверный password Ввести пароль повторно Использовать правильные credentials 
Authentication failed Неверный username Имя пользователя Исправить username 
Authentication failed Неправильный authSource Где создан пользователь Указать правильную authentication database 
Unauthorized Недостаточно прав db.getUser() и roles Назначить нужную role или использовать другого пользователя 
Login работает, но admin-команда запрещена Пользователь не admin Roles пользователя Использовать mongo_admin 
Пользователь не найден Проверяется не та database Выполнить use <auth_db> Перейти в правильную authentication database 

Главное различие здесь простое:

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

Исправляем ошибки подключения

С ошибками авторизации мы уже разобрались. Теперь перейдем к другому классу проблем — когда клиент вообще не может установить соединение с mongod.

Здесь важно разделять уровни диагностики. Если MongoDB отвечает и возвращает Authentication failed, сеть уже работает. А вот Connection refused, timeout или полное отсутствие ответа обычно указывают на сервис, bindIp, порт или firewall.

Что означает Connection refused

Ошибка вида:

    Connection refused

обычно означает, что клиент смог обратиться к нужному адресу, но на указанном порту никто не принял соединение.

Чаще всего причины такие:

  • mongod не запущен;
  • MongoDB слушает другой interface;
  • указан неправильный IP;
  • указан неправильный port;
  • сервис завершился после ошибки конфигурации.

Сначала проверяем сам mongod:

    sudo systemctl status mongod

Для короткой проверки:

    sudo systemctl is-active mongod

Ожидаем:

    active

Если сервис остановлен, пробуем запустить:

    sudo systemctl start mongod

Если запуск завершается ошибкой:

    sudo journalctl -u mongod -n 100 --no-pager

После изменения mongod.conf это особенно важно: неправильный YAML, неверный IP в bindIp или другая ошибка конфигурации могут не дать серверу запуститься вообще.

Почему MongoDB может слушать только localhost

Даже если mongod работает, удаленное подключение может не проходить из-за:

    net:
  port: 27017
  bindIp: 127.0.0.1

В такой конфигурации MongoDB принимает соединения только через loopback interface.

Локально все будет работать:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

Но попытка обратиться к public или private IP сервера извне не пройдет.

Проверить текущую конфигурацию можно так:

    grep -A 4 "^net:" /etc/mongod.conf

Или посмотреть, какие адреса реально слушает процесс:

    sudo ss -lntp | grep 27017

Если видим только:

    127.0.0.1:27017

MongoDB доступна исключительно локально.

Если удаленный доступ действительно нужен, добавляем локальный адрес нужного interface:

    net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.10

После изменения:

    sudo systemctl restart mongod

И снова проверяем:

    sudo ss -lntp | grep 27017

Как проверить порт 27017

Диагностику удобнее проводить с двух сторон.

Сначала на самом MongoDB VPS:

    sudo ss -lntp | grep 27017

Эта команда показывает, слушает ли какой-либо процесс TCP-порт 27017 и на каком адресе.

Например:

    127.0.0.1:27017

означает только localhost.

А:

    10.0.0.10:27017

означает, что MongoDB принимает соединения на private interface.

Теперь проверяем порт с Application VPS:

    nc -vz 10.0.0.10 27017

При успешном соединении получим сообщение о том, что TCP connection установлено.

Если nc отсутствует:

    sudo apt install -y netcat-openbsd

Только после успешного TCP-теста имеет смысл проверять mongosh.

Например:

    mongosh \
  "mongodb://app_user@10.0.0.10:27017/app_db?authSource=app_db" \
  --password

Так намного проще локализовать проблему.

Если nc не соединяется, дело еще не в MongoDB credentials.

Как отличить проблему firewall от MongoDB

Предположим, удаленное подключение не работает.

Сначала проверяем MongoDB локально:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

Если локальное подключение работает, значит:

  • mongod запущен;
  • authentication работает;
  • пользователь существует.

Следом смотрим:

    sudo ss -lntp | grep 27017

Если нужный private или public IP присутствует, MongoDB действительно слушает внешний interface.

Теперь проверяем firewall:

    sudo ufw status numbered

Для нашей private-схемы должно быть разрешение примерно такого вида:

10.0.0.20 → 27017/tcp

Если правила нет:

    sudo ufw allow from 10.0.0.20 to any port 27017 proto tcp

Если UFW настроен правильно, но соединения все равно нет, нужно проверить внешний firewall облачного провайдера.

То есть диагностика идет последовательно:

Если на локальном сервере ss показывает нужный address, а удаленный nc не проходит, подозрение уже смещается в сторону firewall или маршрутизации.

Что делать при timeout

Timeout отличается от Connection refused.

При Connection refused ответ обычно приходит быстро: удаленная сторона сообщает, что соединение принять некому.

При timeout клиент отправляет запрос, но не получает нормального ответа в отведенное время.

Типичные причины:

  • firewall silently drops packets;
  • cloud firewall блокирует трафик;
  • указан неправильный IP;
  • нет маршрута между private networks;
  • приложение обращается к private IP из сети, которая его не видит;
  • проблема в network ACL или routing.

Начнем с IP:

    ip addr

На MongoDB VPS проверяем, действительно ли указанный в bindIp адрес существует.

Например, если в конфигурации:

    bindIp: 127.0.0.1,10.0.0.10

у сервера действительно должен быть адрес:

    10.0.0.10

Далее с Application VPS:

    nc -vz 10.0.0.10 27017

Если private network используется впервые, полезно проверить маршрут:

    ip route

Можно посмотреть и сам путь до узла:

    tracepath 10.0.0.10

Но отсутствие ответа на ICMP само по себе еще не доказывает, что MongoDB недоступна: некоторые сети фильтруют диагностический трафик отдельно.

Поэтому ключевой тест остается TCP-подключение именно к 27017.

Команды диагностики подключения

При проблеме с MongoDB удобнее не менять все настройки подряд, а пройти короткую последовательность.

На MongoDB VPS:

    sudo systemctl is-active mongod

Затем:

    sudo ss -lntp | grep 27017

Проверяем конфигурацию:

    grep -A 4 "^net:" /etc/mongod.conf

Проверяем UFW:

    sudo ufw status numbered

Смотрим последние сообщения сервиса:

    sudo journalctl -u mongod -n 100 --no-pager

И MongoDB log:

    sudo tail -n 100 /var/log/mongodb/mongod.log

Теперь на Application VPS:

    nc -vz 10.0.0.10 27017

Если TCP работает, проверяем уже MongoDB:

    mongosh \
  "mongodb://app_user@10.0.0.10:27017/app_db?authSource=app_db" \
  --password

Так можно быстро определить, на каком именно уровне ломается соединение.

Симптом Возможная причина Команда Что делать 
Connection refused mongod остановлен systemctl status mongod Запустить сервис и проверить logs 
Connection refused при удаленном доступе MongoDB слушает только localhost ss -lntp | grep 27017 Добавить нужный server IP в bindIp 
Timeout Firewall блокирует трафик ufw status numbered Разрешить 27017 только доверенному IP 
Timeout при private IP Нет маршрута между серверами ip route Проверить private network и routing 
Локально работает, удаленно нет bindIp или firewall ss, ufw, nc Проверять сеть по уровням 
TCP работает, но mongosh не входит Authentication problem mongosh ... --password Проверить username, password и authSource 
mongod не запускается после правок Ошибка в mongod.conf journalctl -u mongod Исправить конфигурацию и перезапустить сервис 

Главное правило диагностики здесь простое: сначала проверяем сервис и TCP-доступность, а уже потом credentials.

Если 27017 недоступен на сетевом уровне, изменение пароля или authSource ничего не исправит. И наоборот, если TCP-соединение проходит, но MongoDB возвращает Authentication failed, искать проблему в firewall уже не нужно.

Проверяем MongoDB после перезагрузки

Основные настройки уже готовы: MongoDB запускается как systemd service, authorization включена, пользователи созданы, сетевой доступ ограничен, а данные успешно прошли полный цикл backup и restore.

Осталось проверить еще один важный сценарий — что произойдет после обычной перезагрузки VPS. Сервер должен вернуться в рабочее состояние без ручного запуска mongod и без потери настроек.

Что должно запуститься автоматически

Ранее мы включили автозапуск:

    sudo systemctl enable mongod

Поэтому после reboot systemd должен автоматически запустить:

    mongod.service

При этом должны сохраниться все настройки из:

    /etc/mongod.conf

В том числе:

    security:
  authorization: enabled

и текущая секция net.

То есть после перезагрузки мы ожидаем сразу несколько вещей:

  • Mongod запущен;
  • MongoDB слушает нужный interface;
  • Authorization остается включенной;
  • Пользователи сохраняются;
  • app_db и collection products остаются на месте;
  • Приложение может подключиться тем же connection string.

Теперь проверим это на практике.

Как проверить service

Перезагружаем VPS:

    sudo reboot

После повторного подключения по SSH сначала проверяем состояние MongoDB:

    sudo systemctl status mongod

Ожидаем:

    active (running)

Короткий вариант:

    sudo systemctl is-active mongod

Результат:

    active

Отдельно можно убедиться, что автозапуск действительно включен:

    sudo systemctl is-enabled mongod

Ожидаем:

    enabled

Если mongod после reboot не запустился, смотрим:

    sudo journalctl -u mongod -b --no-pager

Параметр:

    -b

показывает сообщения текущей загрузки системы, поэтому здесь удобно искать именно ошибки, возникшие после reboot.

Проверяем авторизацию

Теперь проверим, что MongoDB не вернулась к анонимному доступу.

Подключаемся без credentials:

    mongosh

Внутри пробуем:

    show dbs

Защищенная команда не должна выполняться без аутентификации.

Теперь выходим:

    exit

И подключаемся как app_user:

    mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

При правильном пароле вход должен пройти успешно.

Это подтверждает сразу две вещи:

  • authorization: enabled сохранилась после reboot;
  • Учетная запись app_user осталась доступна.

При необходимости можно проверить и admin:

    mongosh \
  --username mongo_admin \
  --authenticationDatabase admin \
  --password

Проверяем данные после reboot

Теперь убедимся, что сохраненные данные никуда не исчезли.

Под app_user:

    db

Ожидаем:

    app_db

Проверяем collection:

    show collections

В списке должна быть:

    products

Теперь считаем документы:

    db.products.countDocuments()

Ожидаемый результат:

    3

И выводим контрольные записи:

    db.products.find(
  {},
  {
    _id: 0,
    sku: 1,
    name: 1,
    stock: 1
  }
).sort({ sku: 1 })

Снова должны увидеть:

  • TEST-001
  • TEST-002
  • TEST-003

Так мы подтверждаем, что данные пережили не только restore, но и обычный restart всего VPS.

Заодно можно еще раз проверить сетевую часть:

    sudo ss -lntp | grep 27017

MongoDB должна слушать те же адреса, которые указаны в mongod.conf.

Если используется удаленный Application VPS, оттуда повторяем:

    nc -vz 10.0.0.10 27017

и затем:

    mongosh \
  "mongodb://app_user@10.0.0.10:27017/app_db?authSource=app_db" \
  --password

Итоговую проверку удобно свести в четыре уровня:

Проверка Команда Ожидаемый результат 
Service systemctl is-active mongod active 
Auth mongosh ... --password Пользователь успешно входит 
Data db.products.countDocuments() 3
Network ss -lntp | grep 27017 MongoDB слушает нужные адреса 

Если все четыре проверки проходят после reboot, MongoDB возвращается в рабочее состояние автоматически: сервис запускается, authorization продолжает действовать, данные сохраняются, а сетевой доступ остается таким же, как до перезагрузки.

Теперь можно перейти к финальной части и собрать основные рекомендации для production: как хранить credentials, ограничивать сетевой доступ, работать с backup и следить за состоянием сервера.

Как безопасно использовать MongoDB в production

Не использовать административного пользователя для приложения

mongo_admin нужен для управления MongoDB, а не для повседневной работы приложения.

Приложение должно подключаться под отдельной учетной записью:

    app_user

с правами только на свою database:

    app_db

Причина простая: если приложение работает под admin, любая ошибка или компрометация приложения получает слишком широкий доступ.

Гораздо безопаснее схема:

Пароли этих учетных записей тоже должны храниться раздельно. Admin credentials не должны попадать в .env приложения, deployment scripts или CI/CD variables, которые используются самим приложением.

Не открывать 27017 всему интернету

MongoDB не должна становиться публичным сервисом только потому, что приложению нужен удаленный доступ.

Если приложение и MongoDB находятся на одном VPS, лучше оставить:

    net:
  bindIp: 127.0.0.1

Если серверы разнесены, предпочтительнее использовать private network.

Например: Application VPS → 10.0.0.10:27017 → MongoDB VPS

И только если private network недоступна, можно использовать public interface, но firewall при этом должен пропускать соединения только с конкретного доверенного IP.

То есть нежелательный вариант: 27017/tcp → доступен всем

а нормальный: 27017/tcp → доступен только Application VPS

Authorization остается обязательной в любом случае. Firewall не заменяет пользователей и roles, а дополняет их.

Ограничивать roles

Каждому пользователю нужно выдавать только те права, которые реально нужны для его задачи.

Для обычного приложения мы использовали:

    readWrite

на:

    app_db

Если отдельному сервису нужна только аналитика или чтение, вместо readWrite лучше дать:

    read

Не стоит выдавать root, если пользователь должен работать только с одной database.

Чем уже права, тем меньше последствий у ошибки приложения, утечки credentials или неправильно написанного запроса.

Для быстрой проверки пользователей можно периодически смотреть:

    db.getUser("app_user")

и убеждаться, что список roles не разросся со временем без необходимости.

Хранить backup вне MongoDB VPS

Локальный backup удобен:

    /var/backups/mongodb

но он не должен быть единственной копией.

Если VPS потеряет диск, будет удален или станет недоступен из-за аварии, локальная backup исчезнет вместе с исходными данными.

Поэтому production-схема должна выглядеть примерно так:

В качестве внешнего места подойдет:

  • Object Storage;
  • отдельный backup VPS;
  • другое хранилище в отдельной fault domain;
  • защищенное корпоративное backup storage.

Главное — не хранить единственную копию рядом с оригиналом.

Регулярно проверять restore

Создание backup само по себе еще не гарантирует, что данные реально можно восстановить.

Мы уже проверяли это вручную:

В production такую проверку тоже стоит выполнять регулярно, только уже на отдельном тестовом окружении.

Нужно убедиться, что:

  • backup читается;
  • mongorestore завершается без ошибок;
  • collections появляются;
  • документы восстанавливаются;
  • indexes возвращаются;
  • приложение после restore видит нужные данные.

Хорошая backup-стратегия — это не «файл создается каждую ночь», а «мы знаем, что этот файл можно восстановить».

Контролировать диск и логи

MongoDB постоянно растет вместе с данными, indexes и журналами.

Поэтому свободное место нужно контролировать заранее, а не после того, как файловая система заполнится.

Для быстрой проверки:

    df -h

Размер данных:

    sudo du -sh /var/lib/mongodb

Размер logs:

    sudo du -sh /var/log/mongodb

Сами последние сообщения:

    sudo tail -n 100 /var/log/mongodb/mongod.log

И состояние сервиса:

    sudo systemctl status mongod

Особенно важно следить за диском перед крупными backup, restore и обновлениями.

Если свободного места почти нет, даже обычная служебная операция может закончиться неприятно.

Обновлять MongoDB по поддерживаемому upgrade path

MongoDB не стоит обновлять скачком через несколько major versions без проверки совместимости.

Перед upgrade нужно заранее посмотреть:

  • Текущую версию;
  • Целевую версию;
  • Поддерживается ли прямой переход;
  • Есть ли breaking changes;
  • Требуется ли промежуточный upgrade;
  • Совместимы ли drivers приложения.

Текущую версию сервера можно посмотреть так:

    mongod --version

Перед обновлением полезно обязательно иметь свежий backup и проверенный restore.

Для production лучше придерживаться последовательного upgrade path:

а не пытаться сразу перепрыгнуть через несколько поколений MongoDB.

После обновления стоит повторить знакомые проверки:

    sudo systemctl status mongod
mongosh \
  "mongodb://app_user@127.0.0.1:27017/app_db?authSource=app_db" \
  --password

и убедиться, что приложение по-прежнему видит свои данные.

Что проверить перед production

Перед тем как приложение начнет постоянно работать с MongoDB, достаточно пройти несколько коротких проверок.

Доступ и права

  • authorization включена;
  • приложение использует отдельного app_user;
  • app_user не имеет административных roles;
  • mongo_admin не используется приложением;
  • credentials не записаны прямо в команды или код.

Сеть и данные

  • 27017 не открыт всему интернету;
  • bindIp содержит только нужные server interfaces;
  • firewall пропускает только доверенные источники;
  • MongoDB запускается после reboot;
  • данные сохраняются и читаются после перезагрузки.

Backup и эксплуатация

  • mongodump запускается регулярно;
  • копии уходят на внешнее хранилище;
  • restore был реально проверен;
  • свободное место контролируется;
  • logs просматриваются при ошибках;
  • major upgrades выполняются последовательно и с backup перед обновлением.

Если эти пункты выполняются, базовая MongoDB-конфигурация уже выглядит достаточно здорово для небольшого production-проекта: приложение работает с минимальными правами, сеть ограничена, а данные резервируются.

Заключение

Standalone MongoDB на одном VPS хорошо подходит для разработки, тестовых окружений, небольших внутренних сервисов и проектов, где допустима ручная работа при отказе сервера. Такая схема проста в обслуживании: один mongod, понятная конфигурация, отдельные пользователи, контролируемый сетевой доступ и обычный backup через mongodump.

Но у standalone-сервера есть принципиальное ограничение — это единственная точка отказа. Если VPS или сам mongod недоступен, приложение теряет доступ к базе до восстановления сервиса. Поэтому для полноценной production-системы, где важны высокая доступность и автоматическое переключение при отказе узла, уже стоит переходить на replica set. В self-managed варианте это обычно несколько MongoDB-узлов, а если не хочется самостоятельно заниматься отказоустойчивостью, обновлениями, мониторингом и резервным копированием, можно рассмотреть managed MongoDB. Replica set обеспечивает избыточность и автоматический failover, тогда как standalone этого не дает. 

Независимо от архитектуры базовые принципы остаются теми же: не использовать административного пользователя внутри приложения, не открывать 27017 без необходимости, ограничивать roles, хранить backup отдельно от основного сервера и периодически проверять restore. Тогда даже небольшая MongoDB остается предсказуемой в эксплуатации и значительно проще диагностируется при сбоях.

FAQ

Обязательно ли включать authentication, если MongoDB доступна только с localhost?

Для локального тестового окружения риск действительно ниже, потому что mongod, привязанный к 127.0.0.1, не принимает удаленные подключения.

Но для рабочего сервера authentication все равно лучше включать. Локальный процесс, скомпрометированное приложение или другой пользователь системы иначе сможет обращаться к MongoDB без отдельной проверки credentials.

Кроме того, если позже понадобится удаленный доступ, база уже будет защищена и не придется менять модель безопасности на работающем сервере.

Можно ли использовать одного пользователя для нескольких приложений?

Технически можно, если приложения работают с одной database и им нужны одинаковые права.

Но отдельные учетные записи обычно удобнее.

Например:

    backend_user
analytics_user
worker_user

Так проще:

  • выдавать разные roles;
  • менять password одного приложения;
  • отключать отдельный сервис;
  • понимать, какие credentials где используются и кто что изменил\удалил.

Если один общий пароль утечет, придется менять его сразу во всех приложениях.

Зачем нужен authSource?

authSource указывает database, в которой MongoDB должна искать учетную запись пользователя.

Например, если:

    app_user

создан в:

    app_db

то используется:

    authSource=app_db

А если mongo_admin создан в admin:

    authSource=admin

Рабочая database и authentication database при этом не обязаны совпадать.

Поэтому неправильный authSource способен вызвать Authentication failed, даже если username и password правильные.

Можно ли делать mongodump без остановки MongoDB?

Да. mongodump подключается к работающему mongod, поэтому останавливать сервер для обычного dump не требуется.

Но есть нюанс: если во время backup продолжаются записи, dump отдельной database или collection не обязательно будет представлять единую точку времени. Для нагруженных систем и строгих требований к консистентности нужно учитывать характер записи и использовать подходящую backup-стратегию. Для replica set доступны дополнительные механизмы с oplog.

Что будет, если выполнить mongorestore поверх существующей database?

Без --drop утилита пытается восстановить данные в уже существующие collections.

Из-за этого могут возникнуть:

  • конфликты по _id;
  • сочетание старых и восстановленных данных;
  • результат, отличающийся от состояния backup.

Если нужно заменить соответствующие collections содержимым dump, можно использовать:

    mongorestore --drop ...

Перед восстановлением --drop удаляет именно те collections, которые затем будут восстановлены из backup. Collections, отсутствующие в dump, этот параметр сам по себе не удаляет. 

Сохраняет ли mongodump пользователей?

Зависит от способа создания dump.

При backup конкретной database через --db определения пользователей и roles можно включить параметром:

    --dumpDbUsersAndRoles

При dump всего экземпляра определения пользователей и roles включаются автоматически.

Поэтому не стоит считать, что любой dump одной database по умолчанию обязательно содержит ее пользователей.

Можно ли сделать backup только одной collection?

Да.

Например:

    mongodump \
  --db app_db \
  --collection products \
  --out /var/backups/mongodb/products-backup

Так в dump попадет только products, а не вся app_db. MongoDB

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

Почему mongosh подключается локально, а с другого сервера — нет?

Если локальное подключение работает, а удаленное нет, в первую очередь стоит проверить:

    sudo ss -lntp | grep 27017

Если MongoDB слушает только:

    127.0.0.1:27017

удаленный сервер подключиться не сможет.

Дальше проверяются:

  • bindIp;
  • UFW;
  • cloud firewall;
  • private network;
  • маршрут между VPS.

То есть работающий локальный mongosh еще не означает, что mongod принимает подключения на внешнем interface.

Что делать, если после включения authorization потерян admin password?

Сначала стоит исключить банальные причины:

  • неправильный username;
  • неправильный authSource;
  • другой сохраненный admin user;
  • ошибка при вводе пароля.

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

Для production лучше не импровизировать на работающем сервере: перед такими действиями стоит сохранить backup, ограничить сетевой доступ и использовать процедуру восстановления, соответствующую установленной версии MongoDB.

Достаточно ли mongodump для production?

Для небольших баз и ряда backup-сценариев mongodump вполне полезен, но универсальным ответом для любой production-системы он не является.

При большом объеме данных dump может создавать заметную нагрузку, а при активной записи нужно отдельно учитывать консистентность backup. Replica set также дает дополнительные возможности для получения согласованной копии с использованием oplog. 

Поэтому production backup нужно выбирать исходя из:

  • размера базы;
  • частоты записи;
  • допустимой потери данных;
  • требуемого времени восстановления;
  • архитектуры standalone / replica set;
  • доступного внешнего хранилища.

И главное — любой выбранный способ должен регулярно проходить реальную проверку restore.

Список источников

  1. MongoDB Docs — Install MongoDB Community Edition on Ubuntu
  2. MongoDB Docs — Enable Access Control on Self-Managed Deployments
  3. MongoDB Docs — Configure MongoDB with the Self-Managed Configuration File
  4. MongoDB Database Tools — mongodump
  5. MongoDB Database Tools — mongorestore

Подпишитесь на нашу рассылку и получайте статьи и новости

    Ознакомьтесь с другими нашими материалами