Пример настройки MongoDB с закрытым доступом через сеть Интернет. В данной статье приведен пример разворачивания трех Replica Set и активацией OpLog на одном сервере. OpLog необходим "реактивным" приложениям, которые следят (слушают) за изменениями в MongoDB, например для приложений на основе Meteor (для отключения long-polling'а).
Не смотря на то что пример ниже ориентирован на работу в рамках одного сервера, в целях стабильности рекомендуем развернуть каждого члена Replica Set на отдельном сервере. Для этого необходимо изменить адреса членов Replica Set, передаваемые в метод rs.initiate({/*...*/})
.
В конфигурации членов Replica Set в качестве движка БД используется wiredTiger, о преимуществах данного движка Вы можете прочитать в release notes.
Определения:
- Пользователь
admin
— Пользователь с полными правами доступа (root
) ко всем функциям и командам MongoDB; appUser
— Пользователь с ограниченными правами на чтение и запись (readWrite
) только для БД приложения;appDB
— БД используемая для приложения;- Пользователь
oplogger
— Пользователь с правами на чтение (read
) БДlocal
, база в которой хранится OpLog; - Роль
oplogger
— Роль с правами на чтение (read
) БДlocal
; <password>
— Данный плейсхолдер необходимо заменить на пароль. Всегда указывается в двойных кавычках.
Примеры приведены для MongoDB >= 3.1, и Debian >= 7
- Выполните шаги указанные в инструкции по установке. В процессе установки автоматически будет создан системный пользователь
mongodb
, состоящий в группеmongodb
- Создайте и укажите права для директорий файлов БД:
$ mkdir -p /data/mongos/one /data/mongos/two /data/mongos/three $ chmod 755 /data $ chown -R mongodb:mongodb /data/mongos
- Создайте и укажите права для директорий журнала MongoDB (логов):
$ mkdir -p /var/log/mongodb/one /var/log/mongodb/two /var/log/mongodb/three $ chown -R mongodb:mongodb /var/log/mongodb
- Удалите сервис
mongod
:
$ rm /etc/init.d/mongod
- Создайте конфигурационный файл MongoDB для первого члена Replica Set (
nano /etc/mongod-one.conf
):
storage: dbPath: /data/mongos/one journal: enabled: true engine: wiredTiger systemLog: verbosity: 0 traceAllExceptions: false destination: file logAppend: true path: /var/log/mongodb/one/mongod.log net: port: 27017 bindIp: 0.0.0.0 operationProfiling: slowOpThresholdMs: 2100 mode: off replication: replSetName: rs0
- Создайте конфигурационный файл MongoDB для второго члена Replica Set (
nano /etc/mongod-two.conf
):
storage: dbPath: /data/mongos/two journal: enabled: true engine: wiredTiger systemLog: verbosity: 0 traceAllExceptions: false destination: file logAppend: true path: /var/log/mongodb/two/mongod.log net: port: 27018 bindIp: 0.0.0.0 operationProfiling: slowOpThresholdMs: 2100 mode: off replication: replSetName: rs0
- Создайте конфигурационный файл MongoDB для третьего члена Replica Set (
nano /etc/mongod-three.conf
):
storage: dbPath: /data/mongos/three journal: enabled: true engine: wiredTiger systemLog: verbosity: 0 traceAllExceptions: false destination: file logAppend: true path: /var/log/mongodb/three/mongod.log net: port: 27019 bindIp: 0.0.0.0 operationProfiling: slowOpThresholdMs: 2100 mode: off replication: replSetName: rs0
- Создайте и укажите права для файла с общим ключом аутентификации, данный ключ будут использовать члены Replica Set для коммуникации друг с другом:
$ openssl rand -base64 741 > /data/mongos/key $ chown mongodb:mongodb /data/mongos/key $ chmod 400 /data/mongos/key
- Создайте Cron-файл для запуска MongoDB от имени пользователя
mongodb
(crontab -u mongodb -e
):
@reboot /usr/bin/mongod --config /etc/mongod-one.conf --fork @reboot /usr/bin/mongod --config /etc/mongod-two.conf --fork @reboot /usr/bin/mongod --config /etc/mongod-three.conf --fork
- Перезагрузите машину (сервер)
- Укажите конфигурацию для Replica Set, и инициируйте RS:
// Mongo Shell: $ mongo var conf = { "_id" : "rs0", "members" : [ { "_id" : 0, "host" : "127.0.0.1:27017" }, { "_id" : 1, "host" : "127.0.0.1:27018" }, { "_id" : 2, "host" : "127.0.0.1:27019" } ] } rs.initiate(conf)
- Создайте пользователя
admin
, сroot
правами (убедитесь что Вы вводите команды на PRIMARY члене Replica Set):
// Mongo Shell: $ mongo --port 27017 use admin db.createUser({user:"admin", pwd:<password>, roles:[{role:"root", db:"admin"}]})
- Обновите Cron-файл для запуска MongoDB с
--auth
флагом (crontab -u mongodb -e
) это закроет MongoDB от неавторизованного доступа (прочтите статью по безопасности MongoDB для обеспечения надежной защиты):
@reboot /usr/bin/mongod --config /etc/mongod-one.conf --auth --fork @reboot /usr/bin/mongod --config /etc/mongod-two.conf --auth --fork @reboot /usr/bin/mongod --config /etc/mongod-three.conf --auth --fork
- Укажите путь к общему ключу аутентификации для каждого члена Replica Set:
# nano /etc/mongod-one.conf # nano /etc/mongod-two.conf # nano /etc/mongod-three.conf security: keyFile: /data/mongos/key
- Перезагрузите машину (сервер)
- Создайте пользователя с правами на чтение и запись
readWrite
для БД приложения (используйте данного пользователя для доступа к MongoDB, в коде Вашего приложения):
// Mongo Shell: $ mongo -u "admin" -p <password> --authenticationDatabase "admin" use admin db.createUser({user:"appUser", pwd:<password>, roles:[{role:"readWrite", db:"appDB"}]})
- Создайте роль
oplogger
:
// Mongo Shell: $ mongo -u "admin" -p <password> --authenticationDatabase "admin" use admin db.runCommand({createRole:"oplogger", privileges:[{resource: {db:"local", collection:"system.replset"}, actions: ["find"]}], roles:[{role:"read", db:"local"}]})
- Создайте пользователя
oplogger
, и присвойте ему рольoplogger
:
// Mongo Shell: $ mongo -u "admin" -p <password> --authenticationDatabase "admin" use admin // Для MongoDB 2.4 db.createUser({user:"oplogger", pwd:<password>, roles:[], otherDBRoles:{local:["read"]}}) // Для MongoDB >= 2.6 db.createUser({user:"oplogger", pwd:<password>, roles:[{role: "read", db: "local"}]}) db.runCommand({grantRolesToUser:"oplogger", roles:["oplogger"]})
- Убедитесь что все пользователи корректно созданы:
// Mongo Shell: $ mongo -u "admin" -p <password> --authenticationDatabase "admin" use admin show users
С этого момента MongoDB доступна по публичному IP-адресу сервера (машины), так же как и на loopback и localhost.
Строки подключения:
- Для приложения:
mongodb://appUser:<password>@<PUBLIC_IP>:27017,<PUBLIC_IP>:27018,<PUBLIC_IP>:27019/appDB?authSource=admin&replicaSet=rs0
- Для OpLog:
mongodb://oplogger:<password>@<PUBLIC_IP>:27017,<PUBLIC_IP>:27018,<PUBLIC_IP>:27019/local?authSource=admin&replicaSet=rs0
Update:
Начиная с mongodb@2.2.0 (драйвер), необходимо использовать одинаковый IP-адрес / доменное имя как в строке подключения, так и в конфигурации Replica Set, см.: баг #NODE-746.
Данные нововведения в драйвере влекут ошибки: no valid replicaset members found
и no primary found in replicaset
.
Для удовлетворения новых требований — присвойте доменное имя хосту (серверу) где находится MongoDB, суб-домен так же подойдет. Представим что мы выбрали домен mongo.example.com
.
На сервере MongoDB выполните:
// Mongo Shell:
$ mongo
var rsconf = rs.conf();
rsconf.members[0].host = 'mongo.example.com:27017';
rsconf.members[1].host = 'mongo.example.com:27018';
rsconf.members[2].host = 'mongo.example.com:27019';
rs.reconfig(rsconf);
Обновите строки подключения к базе:
- Для приложения:
mongodb://appUser:<password>@mongo.example.com:27017,mongo.example.com:27018,mongo.example.com:27019/appDB?authSource=admin&replicaSet=rs0
- Для OpLog:
mongodb://oplogger:<password>@mongo.example.com:27017,mongo.example.com:27018,mongo.example.com:27019/local?authSource=admin&replicaSet=rs0