Attempting to run MongoDB through Nginx via the conventional means fails. For starters, it is because the Nginx server blocks within the /etc/nginx/sites-available/*
directory symlinked to the /etc/nginx/sites-enabled
folder all fall under the http { ... }
Nginx block. To use MongoDB behind Nginx successfully, it should happen via the stream { ... }
block.
Using the http { .. }
fails for obvious reasons. MongoDB communication with the server ain’t an ‘HTTP’ communication. HTTP is a protocol, and the server doesn’t understand such a protocol.
Thus, when a request is processed through the http { ... }
which is rigged to receive HTTP requests, Nginx transforms the requests somehow that before it reaches MongoDB, it ain’t in a form MongoDB understands.
However, with the stream { ... }
, the module block proxies exactly what it receives without any form of manipulation directly to the upstream server, which in this case is MongoDB.
MongoDB therefore understands what it hears, and responds accordingly!
Take a look at the configuration file below. The contents in this file can reside in a file somewhere, perhaps, /etc/nginx/streams/available/mongo
:
stream { server { listen 27020; proxy_connect_timeout 5s; proxy_timeout 20s; proxy_pass stream_mongo_backend; } upstream stream_mongo_backend { server 127.0.0.1:27017; } }
We’re using the Nginx stream { ... }
module.
The setup is pretty straightforward. With the above, you open up an extra port of 27020
; which if you have Uncomplicated FireWall (ufw) enabled, you should allow incoming connection from there:
sudo ufw allow 27020/tcp
Now, notice the values of proxy_timeout
specifically. The above is set to 20s which mean
Set the
timeout
between two successive read or write operations on client or proxied server connections [to 20s]. If no data is transmitted within this time, the connection is closed.
Setting this value too low might mean your terminal connection via mongo
and or via your web application might have to reconnect to communicate with mongodb anytime a new command is issued.
Test with whatever value works well for you use case.
The upstream obviously points to our already existing and running MongoD instance hooked to port 27017.
Why through Nginx?
Not everyone might need to go through this hurdle just to run their MongoDB. Use cases vary. For some, the need to ensure a centralize SSL certification is essentials.
For instance, by passing through MongoDB via Nginx, one can not bother about enabling SSL at the MongoDB level, however do so via Nginx level, which can be easier to configure.
Using Nginx in front of MongoDB, I have no idea what the benchmarks are for huge traffic. However, I doubt because Nginx sits in front, even up to 2% of delay time will be incurred on large scale deployments.
Nginx is used for proxying a lot, especially in WordPress and or Django instances, where requests are passed on to either PHP-FPM or gUnicorn for processing respectively.
I’ll love to be enlightened on the downsides of having Nginx sit in front of MongoDB.
Nginx also comes with rate-limiting abilities, fail2ban integrations, and many other little features that can help rig the receiving end of the spectrum in a way only the sweet traffic gets to MongoDB, and that’s it.
I plan to use the above process in an upcoming project to learn more about how it works and how reliable it can be.
Do you have any experience with the above approach? Lemme know in the comments what you think of it, and if it works.