Is there a python native way to connect django to a database through an ssh tunnel? I have seen people using ssh port forwarding in the host machine but I would prefer a solution that can be easily containerized.
It is pretty seamless.
Requirements:
The sshtunnel
package https://github.com/pahaz/sshtunnel
settings.py
create an ssh tunnel before the django DB settings block:from sshtunnel import SSHTunnelForwarder
# Connect to a server using the ssh keys. See the sshtunnel documentation for using password authentication
ssh_tunnel = SSHTunnelForwarder(
SERVER_IP,
ssh_private_key=PATH_TO_SSH_PRIVATE_KEY,
ssh_private_key_password=SSH_PRIVATE_KEY_PASSWORD,
ssh_username=SSH_USERNAME,
remote_bind_address=('localhost', LOCAL_DB_PORT_ON_THE_SERVER),
)
ssh_tunnel.start()
settings.py
. Here I am adding a default local DB and the remote DB that we connect to using the ssh tunnelDATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'HOST': NORMAL_DB_HOST,
'PORT': NORMAL_DB_PORT,
'NAME': NORMAL_DB_NAME,
'USER': NORMAL_DB_USER,
'PASSWORD': NORMAL_DB_PASSWORD,
},
'shhtunnel_db': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'HOST': 'localhost',
'PORT': ssh_tunnel.local_bind_port,
'NAME': REMOTE_DB_DB_NAME,
'USER': REMOTE_DB_USERNAME,
'PASSWORD': REMOTE_DB_PASSWORD,
},
}
That is it. Now one can make migratations to the remote db using commands like $ python manage.py migrate --database=shhtunnel_db
or make calls to the db from within the python code using lines like Models.objects.all().using('shhtunnel_db')
Extra: In my case the remote db was created by someone else and I only wanted to read it. In order to avoid writing the models and deactivating the model manager I used the following django command to get the models from the database [src]:
python manage.py inspectdb