In Chapter 2, we covered the basics of starting MongoDB. This chapter will go into more detail about which options are important for setting up MongoDB in production, including:
Commonly used options
Starting up and shutting down MongoDB
Security-related options
Logging considerations
The MongoDB server is started with the mongod
executable. mongod
has many configurable startup options; to
view all of them, run mongod --help
from the command line. A couple of the options are widely used and
important to be aware of:
--dbpath
Specify an alternate directory to use as the data directory;
the default is /data/db/ (or,
on Windows, datadb on the
MongoDB binary’s volume). Each mongod
process on a machine needs its own
data directory, so if you are running three instances of mongod
on one machine, you’ll need three
separate data directories. When mongod
starts up, it creates a mongod.lock file in its data directory,
which prevents any other mongod
process from using that directory. If you attempt to start another
MongoDB server using the same data directory, it will give an
error:
exception in initAndListen: DBPathInUse: Unable to lock the lock file: data/db/mongod.lock (Resource temporarily unavailable). Another mongod instance is already running on the data/db directory, terminating
--port
Specify the port number for the server to listen on. By
default, mongod
uses port 27017,
which is unlikely to be used by another process (besides other
mongod
processes). If you would
like to run more than one mongod
process on a single machine, you’ll need to specify different ports
for each one. If you try to start mongod
on a port that is already being
used, it will give an error:
Failed
to
set
up
listener
:
SocketException
:
Address
already
in
use
.
--fork
On Unix-based systems, fork the server process, running MongoDB as a daemon.
If you are starting up mongod for the first time (with an empty
data directory), it can take the filesystem a few minutes to
allocate database files. The parent process will not return from
forking until the preallocation is done and
mongod is ready to start accepting connections.
Thus, fork may appear to hang.
You can tail the log to see what it is doing. You must use
--logpath
if you specify
--fork
.
--logpath
Send all output to the specified file rather than
outputting on the command line. This will create the file if it does
not exist, assuming you have write permissions to the directory. It
will also overwrite the log file if it already exists, erasing any
older log entries. If you’d like to keep old logs around, use the
--logappend
option in addition to
--logpath
(highly recommended).
--directoryperdb
Put each database in its own directory. This allows you to mount different databases on different disks, if necessary or desired. Common uses for this are putting a local database on its own disk (replication) or moving a database to a different disk if the original one fills up. You could also put databases that handle more load on faster disks and databases with a lower load on slower disks. This basically gives you more flexibility to move things around later.
--config
Use a configuration file for additional options not specified on the command line. This is typically used to make sure options are the same between restarts. See “File-Based Configuration” for details.
For example, to start the server as a daemon listening on port 5586 and sending all output to mongodb.log, we could run this:
$ ./mongod --dbpath data/db --port 5586 --fork --logpath mongodb.log --logappend 2019-09-06T22:52:25.376-0500 I CONTROL [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none' about to fork child process, waiting until server is ready for connections. forked process: 27610 child process started successfully, parent exiting
When you first install and start MongoDB, it is a good idea to look at the log. This might be an easy thing to miss, especially if MongoDB is being started from an init script, but the log often contains important warnings that prevent later errors from occurring. If you don’t see any warnings in the MongoDB log on startup, then you are all set. (Startup warnings will also appear on shell startup.)
If there are any warnings in the startup banner, take note of them. MongoDB will warn you about a variety of issues: that you’re running on a 32-bit machine (which MongoDB is not designed for), that you have NUMA enabled (which can slow your application to a crawl), or that your system does not allow enough open file descriptors (MongoDB uses a lot of file descriptors).
The log preamble won’t change when you restart the database, so feel free to run MongoDB from an init script and ignore the logs, once you know what they say. However, it’s a good idea to check again each time you do an install, upgrade, or recover from a crash, just to make sure MongoDB and your system are on the same page.
When you start the database, MongoDB will write a document to the local.startup_log collection that describes the version of MongoDB, underlying system, and flags used. We can look at this document using the mongo shell:
>
use
local
switched
to
db
local
>
db
.
startup_log
.
find
().
sort
({
startTime
:
-
1
}).
limit
(
1
).
pretty
()
{
"_id"
:
"server1-1544192927184"
,
"hostname"
:
"server1.example.net"
,
"startTime"
:
ISODate
(
"2019-09-06T22:50:47Z"
),
"startTimeLocal"
:
"Fri Sep 6 22:57:47.184"
,
"cmdLine"
:
{
"net"
:
{
"port"
:
5586
},
"processManagement"
:
{
"fork"
:
true
},
"storage"
:
{
"dbPath"
:
"data/db"
},
"systemLog"
:
{
"destination"
:
"file"
,
"logAppend"
:
true
,
"path"
:
"mongodb.log"
}
},
"pid"
:
NumberLong
(
27278
),
"buildinfo"
:
{
"version"
:
"4.2.0"
,
"gitVersion"
:
"a4b751dcf51dd249c5865812b390cfd1c0129c30"
,
"modules"
:
[
"enterprise"
],
"allocator"
:
"system"
,
"javascriptEngine"
:
"mozjs"
,
"sysInfo"
:
"deprecated"
,
"versionArray"
:
[
4
,
2
,
0
,
0
],
"openssl"
:
{
"running"
:
"Apple Secure Transport"
},
"buildEnvironment"
:
{
"distmod"
:
""
,
"distarch"
:
"x86_64"
,
"cc"
:
"gcc: Apple LLVM version 8.1.0 (clang-802.0.42)"
,
"ccflags"
:
"-mmacosx-version-min=10.10 -fno-omit
-frame-pointer -fno-strict-aliasing
-ggdb -pthread -Wall
-Wsign-compare -Wno-unknown-pragmas
-Winvalid-pch -Werror -O2 -Wno-unused
-local-typedefs -Wno-unused-function
-Wno-unused-private-field
-Wno-deprecated-declarations
-Wno-tautological-constant-out-of
-range-compare
-Wno-unused-const-variable -Wno
-missing-braces -Wno-inconsistent
-missing-override
-Wno-potentially-evaluated-expression
-Wno-exceptions -fstack-protector
-strong -fno-builtin-memcmp"
,
"cxx"
:
"g++: Apple LLVM version 8.1.0 (clang-802.0.42)"
,
"cxxflags"
:
"-Woverloaded-virtual -Werror=unused-result
-Wpessimizing-move -Wredundant-move
-Wno-undefined-var-template -stdlib=libc++
-std=c++14"
,
"linkflags"
:
"-mmacosx-version-min=10.10 -Wl,
-bind_at_load -Wl,-fatal_warnings
-fstack-protector-strong
-stdlib=libc++"
,
"target_arch"
:
"x86_64"
,
"target_os"
:
"macOS"
},
"bits"
:
64
,
"debug"
:
false
,
"maxBsonObjectSize"
:
16777216
,
"storageEngines"
:
[
"biggie"
,
"devnull"
,
"ephemeralForTest"
,
"inMemory"
,
"queryable_wt"
,
"wiredTiger"
]
}
}
This collection can be useful for tracking upgrades and changes in behavior.
MongoDB supports reading configuration information from a file.
This can be useful if you have a large set of options you want to use or
are automating the task of starting
up MongoDB. To tell the server to get options from a
configuration file, use the -f
or
--config
flags. For example, run mongod --config ~/.mongodb.conf
to use
~/.mongodb.conf as a configuration
file.
The options supported in a configuration file are the same as those accepted at the command line. However, the format is different. As of MongoDB 2.6, MongoDB configuration files use the YAML format. Here’s an example configuration file:
systemLog: destination: file path: "mongod.log" logAppend: true storage: dbPath: data/db processManagement: fork: true net: port: 5586 ...
This configuration file specifies the same options we used earlier when starting with regular command-line arguments. Note that these same options are reflected in the startup_log collection document we looked at in the previous section. The only real difference is that the options are specified using JSON rather than YAML.
In MongoDB 4.2, expansion directives were added to allow the
loading of specific configuration file options or loading of the entire
configuration file. The advantage of expansion directives is that
confidential information, such as passwords and security certificates,
does not have to be stored in the config file directly. The --configExpand
command-line option enables this feature and must include the expansion
directives you wish to enable. __rest
and __exec
are the current
implementation of the expansion directives in MongoDB. The __rest
expansion directive loads specific
configuration file values or loads the entire configuration file from a
REST endpoint. The __exec
expansion
directive loads specific configuration file values or loads the entire
configuration file from a shell or terminal command.
Being able to safely stop a running MongoDB server is at least as important as being able to start one. There are a couple of different options for doing this effectively.
The cleanest way to shut down a running server is to use
the shutdown
command,
{"shutdown" : 1}
. This is an admin command and must be run on the
admin database. The shell features a helper function
to make this easier:
>
use
admin
switched
to
db
admin
>
db
.
shutdownServer
()
server
should
be
down
...
When run on a primary, the shutdown
command steps down the primary and
waits for a secondary to catch up before shutting down the server. This
minimizes the chance of rollback, but the shutdown isn’t guaranteed to
succeed. If there is no secondary available that can catch up within a few
seconds, the shutdown
command will fail
and the (former) primary will not shut down:
>
db
.
shutdownServer
()
{
"closest"
:
NumberLong
(
1349465327
),
"difference"
:
NumberLong
(
20
),
"errmsg"
:
"no secondaries within 10 seconds of my optime"
,
"ok"
:
0
}
You can force the shutdown
command to shut down a primary by using the force
option:
db
.
adminCommand
({
"shutdown"
:
1
,
"force"
:
true
})
This is equivalent to sending a SIGINT or SIGTERM signal (all three of these options
result in a clean shutdown, but there may be unreplicated data). If the
server is running as the foreground process in a terminal, a SIGINT can be
sent by pressing Ctrl-C. Otherwise, a command like kill
can be used to send the signal. If
mongod had 10014 as its PID, the command would be kill -2
10014
(SIGINT) or kill 10014
(SIGTERM).
When mongod receives a SIGINT or SIGTERM, it will do a clean shutdown. This means it will wait for any running operations or file preallocations to finish (this could take a moment), close all open connections, flush all data to disk, and halt.
Do not set up publicly addressable MongoDB servers. You should restrict access as tightly as possible between the outside world and MongoDB. The best way to do this is to set up firewalls and only allow MongoDB to be reachable on internal network addresses. Chapter 24 covers what connections it’s necessary to allow between MongoDB servers and clients.
Beyond firewalls, there are a few options you can add to your config file to make it more secure:
--bind_ip
Specify the interfaces that you want MongoDB to listen on. Generally you want this to be an internal IP: something application servers and other members of your cluster can access but that is inaccessible to the outside world. localhost is fine for mongos processes if you’re running the application server on the same machine. For config servers and shards, they’ll need to be addressable from other machines, so stick with non-localhost addresses.
Starting in MongoDB 3.6, mongod and mongos processes bind to localhost by default. When bound only to
localhost, mongod and mongos will only accept connections from
clients running on the same machine. This helps limit the exposure
of unsecured MongoDB instances. To bind to other addresses, use the
net.bindIp
configuration file setting or the
--bind_ip
command-line option to specify a list of
hostnames or IP addresses.
--nounixsocket
Disable listening on the UNIX domain socket. If you’re not planning to connect via filesystem socket, you might as well disallow it. You would only connect via filesystem socket on a machine that is also running an application server: you must be local to use a filesystem socket.
--noscripting
Disable server-side JavaScript execution. Some security issues that have been reported with MongoDB have been JavaScript-related, so it’s generally safer to disallow it, if your application allows.
Several shell helpers assume that JavaScript is available on
the server, notably sh.status()
. You will see errors if you
attempt to run any of these helpers with JavaScript
disabled.
Data encryption is available in MongoDB Enterprise. These options are not supported in the Community version of MongoDB.
The data encryption process includes the following steps:
Generate a master key.
Generate keys for each database.
Encrypt data with the database keys.
Encrypt the database keys with the master key.
When using data encryption, all data files are encrypted in the filesystem. Data is only unencrypted in memory and during transmission. To encrypt all of MongoDB’s network traffic, you can use TLS/SSL. The data encryption options that MongoDB Enterprise users can add to their config files are:
--enableEncryption
Enables encryption in the WiredTiger storage engine. With
this option, data stored in memory and on disk will be
encrypted. This is sometimes referred to as “encryption at
rest.” You must set this to true
in order to pass in encryption
keys and to configure encryption. This option is false
by default.
--encryptionCipherMode
Set the cipher mode for encryption at rest in WiredTiger. There are two modes available: AES256-CBC and AES256-GCM. AES256-CBC is an acronym for 256-bit Advanced Encryption Standard in Cipher Block Chaining Mode. AES256-GCM uses Galois/Counter Mode. Both are standard encryption ciphers. As of MongoDB 4.0, MongoDB Enterprise on Windows no longer supports AES256-GCM.
--encryptionKeyFile
Specify the path to the local keyfile if you are managing keys using a process other than the Key Management Interoperability Protocol (KMIP).
MongoDB Enterprise also supports key management using KMIP. A discussion of KMIP is beyond the scope of this book. Please see the MongoDB documentation for details on using KMIP with MongoDB.
As we saw in Chapter 18, MongoDB
supports transport encryption using TLS/SSL. This feature is available in all editions of MongoDB. By
default, connections to MongoDB transfer data unencrypted. However,
TLS/SSL ensures transport encryption. MongoDB uses native TSL/SSL
libraries available on your operating system. Use the option --tlsMode
and related options to
configure TLS/SSL. Refer to Chapter 18 for more
detail, and consult your driver’s documentation on how to create TLS/SSL
connections using your language.
By default, mongod sends
its logs to stdout. Most init scripts use the --logpath
option to send logs to a
file. If you have multiple MongoDB instances on a single machine
(say, a mongod and a mongos), make sure that their logs are stored
in separate files. Be sure that you know where the logs are and have read
access to the files.
MongoDB spits out a lot of log messages, but please do not run with
the --quiet
option (which suppresses some of them).
Leaving the log level at the default is usually perfect: there is enough
information for basic debugging (why is this slow, why isn’t this starting
up, etc.), but the logs do not take up too much space.
If you are debugging a specific issue with your application,
there are a couple of options for getting more information from the logs.
You can change the log level by running the setParameter
command, or
by setting the log level at startup time by passing it as a string using
the --setParameter
option.
>
db
.
adminCommand
({
"setParameter"
:
1
,
"logLevel"
:
3
})
You can also change the log level for a particular component. This is helpful if you are debugging a specific aspect of your application and require more information, but only from that component. In this example, we set the default log verbosity to 1 and the query component verbosity to 2:
>
db
.
adminCommand
({
"setParameter"
:
1
,
logComponentVerbosity
:
{
verbosity
:
1
,
query
:
{
verbosity
:
2
}}})
Remember to turn the log level back down to 0 when you’re done
debugging, or your logs may be needlessly noisy. You can turn the level
all the way up to 5, at which point mongod
will print out almost every action it
takes, including the contents of every request handled. This can cause a
lot of I/O as mongod writes
everything to the log file, which can slow down a busy system. Turning on
profiling is a better option if you need to see every operation as it’s
happening.
By default, MongoDB logs information about queries that take longer
than 100 ms to run. If 100 ms is too short or too long for your
application, you can change the threshold with setProfilingLevel
:
>
// Only log queries that take longer than 500 ms
>
db
.
setProfilingLevel
(
1
,
500
)
{
"was"
:
0
,
"slowms"
:
100
,
"ok"
:
1
}
>
db
.
setProfilingLevel
(
0
)
{
"was"
:
1
,
"slowms"
:
500
,
"ok"
:
1
}
The second line will turn off profiling, but the value in
milliseconds given in the first line will continue to be used as a
threshold for the log (across all databases). You can also set this
parameter by restarting MongoDB with the --slowms
option.
Finally, set up a cron job that rotates your log every day or week. If
MongoDB was started with --logpath
, sending the process a
SIGUSR1 signal will make it rotate the log. There is also a logRotate
command that does the same thing:
>
db
.
adminCommand
({
"logRotate"
:
1
})
You cannot rotate logs if MongoDB was not
started with --logpath
.
3.17.174.156