I am developing a GUI using Flask. I am running Ubuntu 20.04. The data that I need is from MongoDB, which is running on a Docker container on a server. My Mongo URI is "mongodb://<USERNAME>:<PASSWORD>@localhost:9999/<DB>?authSource=<AUTHDB>"
.
First I tunnel the SSH connection to the server:
ssh -L 9999:localhost:27017 -N <USER>@<HOST>
When I connect to a Mongo shell after tunneling the connection, it works as expected. The issue is when I try to run the Flask app. PyMongo cannot seem to connect to the database (connection refused).
pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:9999: [Errno 111] Connection refused, Timeout: 30s, Topology Description: <TopologyDescription id: 62fa50c9015294b6e1df5811, topology_type: Unknown, servers: [<ServerDescription ('127.0.0.1', 9999) server_type: Unknown, rtt: None, error=AutoReconnect('127.0.0.1:9999: [Errno 111] Connection refused')>]>
Another error I’ve been seeing is PyMongo authentication failed. This only happens if I have a Docker container with Mongo running on my local machine. (The previous error only happens when the local container is not running).
pymongo.errors.OperationFailure: Authentication failed., full error: {'ok': 0.0, 'errmsg': 'Authentication failed.', 'code': 18, 'codeName': 'AuthenticationFailed', '$clusterTime': {'clusterTime': Timestamp(1660576452, 1), 'signature': {'hash': b'x16x8cx11xb2Ufxe3x80x85xb0 >xcbxbexa5Sx8fxec(g', 'keyId': 7128054189753630722}}, 'operationTime': Timestamp(1660576452, 1)}
One last thing: I have not experienced any errors when trying to connect to the local MongoDB running in a local Docker container. This leads me to believe that I am missing a step when connecting to the remote MongoDB. And it’s not a problem with the URI since I can log into a Mongo shell with it when the SSH connection is up.
Here is some code from my Flask app:
init.py
from flask import Flask
from flask_bootstrap import Bootstrap
from .frontend import frontend
from .database import mongo
def create_app(configfile=None):
app = Flask(__name__)
app.config["MONGO_URI"] = "mongodb://<USERNAME>:<PASSWORD>@localhost:9999/<DB>?authSource=<AUTHDB>"
Bootstrap(app)
mongo.init_app(app)
app.register_blueprint(frontend)
app.secret_key = os.environ['SECRET_KEY']
app.config['BOOTSTRAP_SERVER_LOCAL'] = True
return app
database.py
from flask_pymongo import PyMongo
mongo = PyMongo()
frontend.py
from flask import Blueprint
from .database import mongo
frontend = Blueprint('frontend', __name__)
# Rest of file contains routes with calls to database
Does anyone know why I am getting these errors? Thanks.
2
Answers
I discovered that pymongo isn't setting the port correctly, possibly due to a bug in the package. Even though I specify the port as 9999, it thinks it should connect to 27017.
If I set the URI to
"mongodb://<USERNAME>:<PASSWORD>@garbage:9999/<DB>?authSource=<AUTHDB>"
, then it will actually try to connect to port 9999.I ended up changing my ssh tunnel to port 27017, and everything worked.
ssh -L 27017:localhost:27017 -N <USER>@<HOST>
SSH tunneling is not supported in pymongo unless you use directConnection=True
https://pymongo.readthedocs.io/en/stable/common-issues.html?highlight=tunnel#timeout-when-accessing-mongodb-from-pymongo-with-tunneling