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.
Advertisement
Answer
It is pretty seamless.
Requirements:
The sshtunnel
package https://github.com/pahaz/sshtunnel
- In the django
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()
- Then add the DB info block in the
settings.py
. Here I am adding a default local DB and the remote DB that we connect to using the ssh tunnel
DATABASES = { '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