I'm using org-babel to do litterate programming and I find it very convenient. I am able to execute shell commands on remote hosts, and local database commands with the postgres client. To open a file as postgres user, it would look for example like

C-x C-f /sshx:user@remotehost|sudo:postgres@remotehost:/tmp/testfile

To do so on Emacs 24.5.1, I needed to add:

(require 'tramp)
(add-to-list 'tramp-default-proxies-alist
             '(nil "\\`postgres\\'" "/ssh:%h:"))
(add-to-list 'tramp-default-proxies-alist
             '((regexp-quote (system-name)) nil nil))

So far, I have failed to understand how one could execute a postgresql (or mysql if you so choose) command on a remote server. The database server is not accessible directly over the network, I have to ssh into the remote host, su as the postgres user and then I'm able to execute commands through the psql client.

How could one use such a command:

#+BEGIN_SRC sql :engine postgresql :ExtraParametersIfNeeded
SELECT * from pg_database

On a remote host? I know the :dir switch, but have so far only been able to use it for shell scripts.

Many thanks!

  • 1
    You could do some SSH tunnelling... You would do something akin to "ssh yourbox -L7590:" replacing the "7590" with whatever port your database is on. Then, in your Org babel block, you can use the ":cmdline" header argument to set a command line argument to set the database port. The whole thing might look something like this at the top of your Org file: "#+PROPERTY: header-args:sql :engine mysql :dbhost :dbuser someone :dbpassword somepassword :database database :cmdline -P7590 ". After C-c C-c-ing that, you can use any SQL block in your buffer like that.
    – Archenoth
    Jul 27, 2015 at 17:53
  • Hi, I thought about it and I could not find any other way myself too. If you make it an answer, I'll gladly accept it. Jul 29, 2015 at 7:22
  • Well... I posted that as a comment because, while it solves your problem, it doesn't really answer your question. Nothing has changed on the Emacs end; you would just be creating an SSH tunnel manually so that the database can be accessed directly as opposed to making Emacs control the entire process through a header argument or some arbitrary configuration--so, I don't think I'll make an answer of that. Maybe someone else knows of a way to tell Org-babel to create this tunnel without any manual fudging.
    – Archenoth
    Jul 29, 2015 at 16:16

2 Answers 2


I'm not sure if it is working now because of updates in Emacs and tramp, but as there is no accepted solution and no exact snippet of code for those who are looking for answer, I'm providing one which is working in Emacs 25 and recent org-mode and tramp.

As you already proposed in your question, :dir is the solution, just take your src section and add same string as you used for opening files to the :dir arugment. There is no need to do SSH tunnel as this is something tramp can do out of the box.

#+BEGIN_SRC sql :engine postgresql :dir /sshx:user@remotehost|sudo:postgres@remotehost:
SELECT * FROM pg_database

Working just find and returns:

| datname             | datdba | encoding | datcollate  | datctype    | datistemplate | datallowconn | datconnlimit | datlastsysoid | datfrozenxid | datminmxid | dattablespace | datacl                              |
| postgres            |     10 |        6 | C.UTF-8     | C.UTF-8     | f             | t            |           -1 |         12408 |          545 |          1 |          1663 |                                     |
| template0           |     10 |        6 | C.UTF-8     | C.UTF-8     | t             | f            |           -1 |         12408 |          545 |          1 |          1663 | {=c/postgres,postgres=CTc/postgres} |
  • 1
    Confirming that this also works for emacs 26(.1), org 9.1.9, tramp Dec 23, 2019 at 3:31

I'm not an org user, so I can answer only from the Tramp point of view. The Tramp settings you have shown above are not needed (add-to-list forms), since you are using ad-hoc multi-hops in your file name. So I assume a simple :dir "/sshx:user@remotehost|sudo:postgres@remotehost:/path/to/dir" should do the job.

  • Thanks for you comment. In order to execute shell scripts (using the :dir command) I had to use the lines mentionned above, as I was getting a message in the style of "sudo is only allowed on local host". Jul 27, 2015 at 13:07
  • You're right, there is a subtle error in Tramp. I could reproduce the problem with the following code snippet: #+BEGIN_SRC sh :dir /ssh:remotehost|sudo:postgres@remotehost:/tmp whoami #+END_SRC As workaround, you could do something like this (untested): #+BEGIN_SRC emacs-lisp (progn (require 'tramp) (add-to-list 'tramp-default-proxies-alist '(nil "\`root\\'" "/ssh:%h:"))) #+END_SRC #+BEGIN_SRC sh :dir /sudo:remotehost:/tmp whoami #+END_SRC Jul 27, 2015 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.