Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Psycopg2 access PostgreSQL database on remote host without manually opening ssh tunnel

My standard procedure for accessing a PostgreSQL database on a remote server is to first create an ssh tunnel as:

ssh [email protected] -L 5432:localhost:5432 -p 222

and then run my query in python from another shell as:

conn = psycopg2.connect("host=localhost" + " dbname=" +
                         conf.dbname + " user=" + conf.user + 
                         " password=" + conf.password)

cur = conn.cursor()

cur.execute(query)

This piece of python code works nicely once the tunnel is created. However, I would like psycopg2 to already open the SSH tunnel or reach "somehow" the remote database without need to redirect it on my localhost.

Is it possible to do this with psycopg2?

Is otherwise possible open the ssh tunnel in my python code?

if I use:

os.system("ssh [email protected] -L 5432:localhost:5432 -p 222")

The shell will be redirected to the remote host blocking the execution of main thread.

like image 856
Luca Fiaschi Avatar asked Feb 26 '14 16:02

Luca Fiaschi


People also ask

How do I connect to PostgreSQL database using SSH?

Type "localhost" in the "Host name/address". Enter your PostgreSQL username and password provided by Hanlon Lab and save your password if you would like. Switch on the "Use SSH tunneling" tab. Enter the hostname provided by the lab in "Tunnel host." Enter your Linux username provided by Hanlon Lab.

How do I connect to PostgreSQL database with Python using SSH Tunnelling?

Start PuTTY and enter ssh.pythonanywhere.com into the "Host name" field. In the "Category" tree on the left, open Connection -> SSH -> Tunnels. If you don't have a Postgres database running on your local machine, enter "Source port" 5432. If you do have one running, use some other port, for example 3333.

Does psycopg2 need PostgreSQL?

Prerequisites. The current psycopg2 implementation supports: Python versions from 3.6 to 3.11. PostgreSQL server versions from 7.4 to 15.


2 Answers

You could also use sshtunnel, short and sweet:

from sshtunnel import SSHTunnelForwarder

PORT=5432
with SSHTunnelForwarder((REMOTE_HOST, REMOTE_SSH_PORT),
         ssh_username=REMOTE_USERNAME,
         ssh_password=REMOTE_PASSWORD,
         remote_bind_address=('localhost', PORT),
         local_bind_address=('localhost', PORT)):
    conn = psycopg2.connect(...)
like image 192
mrts Avatar answered Sep 18 '22 08:09

mrts


With sshtunnel package

I was not familiar with SSH tunnels, so I had some difficulties to use mrts's answer. Maybe thoses precisions could help someone.

In psycopg2.connect(), host and port are the one you just created by connecting remote host by ssh tunnel.

Here is my code :

from sshtunnel import SSHTunnelForwarder

server = SSHTunnelForwarder((REMOTE_HOST, REMOTE_SSH_PORT),
         ssh_username=REMOTE_USERNAME,
         ssh_password=REMOTE_PASSWORD,
         remote_bind_address=('localhost', PORT),
         local_bind_address=('localhost', PORT))
server.start()

import psycopg2
conn = psycopg2.connect(
    database=DATABASE,
    user=USER,
    host=server.local_bind_host,
    port=server.local_bind_port,
    password=PWD)
cur = conn.cursor()
cur.execute("select * from yourtable limit 1;")
data = cur.fetchall()
print(data)

I hope this example make it clearer.

like image 45
J.Delannoy Avatar answered Sep 18 '22 08:09

J.Delannoy