Deploying a website with lftp

There still are web hosting providers offering only ftp access to your website files. No fun if you’re used to version control systems and shell access.

I had to deal with that situation, and used Linux’s strength: combining several small tools.

I have a laptop running Ubuntu, a website in WordPress, git for version control, and use Eclipse as my development environment. I first looked at Aptana and other options for Eclipse, but I wanted a more light-weight solution that I could also use outside Eclipse.


Ubuntu comes with lftp, an ftp client that can be scripted and has a “mirror” command to basically get a target location synchronised to a source.

(It actually can do a lot more, and work over http or bittorrent too, but that’s outside the scope of this post.)


Not all files need to be uploaded. Typically, the .gitignore file already has a list of files and directories that are not under version control and wouldn’t go live when using git to update a server.

The lftp mirror command lets you exclude files and directories too, but curiously has no option to read a list of exclusions from a file. Martin Boze wrote how he fixed that, by using sed and tr.


I didn’t want to write a series of lftp commands, but instead would prefer to connect once, then run a series of transfers, inside a single script.

Specifically for WordPress, I also like to have a local mirror of images and documents uploaded on the live site.

It is possible use lftp as the shell to run a script, but unfortunately, it’s not possible to use environment variables or Martin’s “sed” trick in such scripts.

But it’s not to hard to do using the Heredoc syntax.

git branches

I use branches in git to separate my development version from a preview and a live version. By adapting the upload script in each branch, I can simply call “deploy” to upload the files to the right place.

lftp <<EOF
user ftp-username ftp-password

# "mirror" from local copy to server, use .gitignore to excude files (sed, tr), delete remote files if needed
mirror -R -e -v -x \.git.+ -x scripts `sed 's/^/-X /' .gitignore | tr '\n' ' '` /var/www/dev_sites/ /www

# wordpress-specific
# "mirror" uploaded images on live back to local, don't delete local files if not on remote
mirror -v /www/wp-content/uploads/ /var/www/dev_sites/

The only thing left to desire is a way to speed up ftp deployment…


Join the conversation

comment 1 comment
  • Rolf says:

    It’s not a perfect solution yet, file patterns in .gitignore are interpreted differently in git and lftp.

    For instance: git lets you specify a path relative to the git base directory, so you can specify e.g. /*.sql to ignore only .sql files in the base directory.

    In lftp, the glob pattern /*.sql would select .sql files in your file system root. In effect: the .sql files in your project will still be uploaded to the remote host.

    There are more differences like that. For individual file and directory names, it works, but YMMV.

Leave a comment

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.