GNU ELPA - ssh-deploy


Deployment via TRAMP, global or per directory.
ssh-deploy-2.0.tar, 2018-Oct-21, 150kB
Christian Johansson <>
Home page
Browse ELPA's repository
CGit or Gitweb

To install this package, run in Emacs:

M-x package-install RET ssh-deploy RET

Full description

ssh-deploy enables automatic deploys on explicit-save actions, manual uploads, renaming,
deleting, downloads, file and directory differences, launching remote terminals (eshell, shell),
detection of remote changes, remote directory browsing, remote SQL database sessions and
running custom deployment scripts via TRAMP.

For asynchronous operations it uses package '`make-thread' or if not available '`async.el'.

By setting the variables (globally, per directory or per file):
ssh-deploy-root-local,ssh-deploy-root-remote, ssh-deploy-on-explicit-save
you can setup a directory for TRAMP deployment.

For asynchronous transfers you need to setup ~/.netrc, ~/.authinfo or ~/.authinfo.gpg or key-based authorization or equivalent for automatic authentication.

Example contents of ~/.netrc, ~/.authinfo or ~/.authinfo.gpg for password-based interaction-free authentication:
machine login myuser port ftp password mypassword
machine login myuser2 port ssh password mypassword2
machine login myuser3 port sftp password mypassword3

Set permissions to this file to 600 with your user as the owner.

- To setup an upload hook on save do this:
    (add-hook 'after-save-hook
              (lambda () (if (bound-and-true-p ssh-deploy-on-explicit-save)

- To setup automatic storing of base revisions and detection of remote changes do this:
    (add-hook 'find-file-hook
              (lambda ()
                (if (bound-and-true-p ssh-deploy-automatically-detect-remote-changes)
                    (ssh-deploy-remote-changes-handler)) ))

- To set key-bindings do something like this:

    (global-set-key (kbd "C-c C-z f") 'ssh-deploy-upload-handler-forced)
    (global-set-key (kbd "C-c C-z u") 'ssh-deploy-upload-handler)
    (global-set-key (kbd "C-c C-z D") 'ssh-deploy-delete-handler)
    (global-set-key (kbd "C-c C-z d") 'ssh-deploy-download-handler)
    (global-set-key (kbd "C-c C-z x") 'ssh-deploy-diff-handler)
    (global-set-key (kbd "C-c C-z t") 'ssh-deploy-remote-terminal-eshell-base-handler)
    (global-set-key (kbd "C-c C-z T") 'ssh-deploy-remote-terminal-eshell-handler)
    (global-set-key (kbd "C-c C-z h") 'ssh-deploy-remote-terminal-shell-base-handler)
    (global-set-key (kbd "C-c C-z H") 'ssh-deploy-remote-terminal-shell-handler)
    (global-set-key (kbd "C-c C-z R") 'ssh-deploy-rename-handler)
    (global-set-key (kbd "C-c C-z e") 'ssh-deploy-remote-changes-handler)
    (global-set-key (kbd "C-c C-z b") 'ssh-deploy-browse-remote-base-handler)
    (global-set-key (kbd "C-c C-z B") 'ssh-deploy-browse-remote-handler)
    (global-set-key (kbd "C-c C-z o") 'ssh-deploy-open-remote-file-handler)
    (global-set-key (kbd "C-c C-z m") 'ssh-deploy-remote-sql-mysql-handler)
    (global-set-key (kbd "C-c C-z s") 'ssh-deploy-run-deploy-script-handler)

- To install and set-up using use-package and hydra do this:
  (use-package ssh-deploy
    :ensure t
    :bind (("C-c C-z" . hydra-ssh-deploy/body))
    :hook ((after-save . (lambda () (if (bound-and-true-p ssh-deploy-on-explicit-save) (ssh-deploy-upload-handler)) ))
           (find-file . (lambda () (if (bound-and-true-p ssh-deploy-automatically-detect-remote-changes) (ssh-deploy-remote-changes-handler)) )))
    (defhydra hydra-ssh-deploy (:color red :hint nil)
_u_: Upload                              _f_: Force Upload
_d_: Download
_D_: Delete
_x_: Difference
_t_: Eshell Base Terminal                _T_: Eshell Relative Terminal
_h_: Shell Base Terminal                 _H_: Shell Relative Terminal
_e_: Detect Remote Changes
_R_: Rename
_b_: Browse Base                         _B_: Browse Relative
_o_: Open current file on remote         _m_: Open sql-mysql on remote
_s_: Run deploy script
      ("f" ssh-deploy-upload-handler-forced)
      ("u" ssh-deploy-upload-handler)
      ("d" ssh-deploy-download-handler)
      ("D" ssh-deploy-delete-handler)
      ("x" ssh-deploy-diff-handler)
      ("t" ssh-deploy-remote-terminal-eshell-base-handler)
      ("T" ssh-deploy-remote-terminal-eshell-handler)
      ("h" ssh-deploy-remote-terminal-shell-base-handler)
      ("H" ssh-deploy-remote-terminal-shell-handler)
      ("e" ssh-deploy-remote-changes-handler)
      ("R" ssh-deploy-rename-handler)
      ("b" ssh-deploy-browse-remote-base-handler)
      ("B" ssh-deploy-browse-remote-handler)
      ("o" ssh-deploy-open-remote-file-handler)
      ("m" ssh-deploy-remote-sql-mysql-handler)
      ("s" ssh-deploy-run-deploy-script-handler)))

Here is an example for SSH deployment, /Users/Chris/Web/Site1/.dir-locals.el:
((nil . (
  (ssh-deploy-root-local . "/Users/Chris/Web/Site1/")
  (ssh-deploy-root-remote . "/")
  (ssh-deploy-on-explicit-save . t)
  (ssh-deploy-async . t)

Here is an example for SFTP deployment, /Users/Chris/Web/Site2/.dir-locals.el:
((nil . (
  (ssh-deploy-root-local . "/Users/Chris/Web/Site2/")
  (ssh-deploy-root-remote . "/")
  (ssh-deploy-on-explicit-save . nil)
  (ssh-deploy-async . nil)
  (ssh-deploy-script . (lambda() (let ((default-directory ssh-deploy-root-remote))(shell-command "bash"))))

Here is an example for FTP deployment, /Users/Chris/Web/Site3/.dir-locals.el:
((nil . (
  (ssh-deploy-root-local . "/Users/Chris/Web/Site3/")
  (ssh-deploy-root-remote . "/")

Now when you are in a directory which is configured for deployment.

Here is a list of other variables you can set globally or per directory:

* `ssh-deploy-root-local' - The local root that should be under deployment *(string)*
* `ssh-deploy-root-remote' - The remote TRAMP root that is used for deployment *(string)*
* `ssh-deploy-debug' - Enables debugging messages *(boolean)*
* `ssh-deploy-revision-folder' - The folder used for storing local revisions *(string)*
* `ssh-deploy-automatically-detect-remote-changes' - Enables automatic detection of remote changes *(boolean)*
* `ssh-deploy-on-explicit-save' - Enabled automatic uploads on save *(boolean)*
* `ssh-deploy-exclude-list' - A list defining what paths to exclude from deployment *(list)*
* `ssh-deploy-async' - Enables asynchronous transfers (you need to have `(make-thread)` or `async.el` available as well) *(boolean)*
* `ssh-deploy-remote-sql-database' - Default database when connecting to remote SQL database *(string)*
* `ssh-deploy-remote-sql-password' - Default password when connecting to remote SQL database *(string)*
* `ssh-deploy-remote-sql-port' - Default port when connecting to remote SQL database *(integer)*
* `ssh-deploy-remote-sql-server' - Default server when connecting to remote SQL database *(string)*
* `ssh-deploy-remote-sql-user' - Default user when connecting to remote SQL database *(string)*
* `ssh-deploy-remote-shell-executable' - Default shell executable when launching shell on remote host
* `ssh-deploy-verbose' - Show messages in message buffer when starting and ending actions, default t *(boolean)*
* `ssh-deploy-script' - Our custom lambda function that will be called using (funcall) when running deploy script

Please see from the same repository for extended documentation.