Oh we yearn for simple SSH sessions into old fashioned servers in this new world of short-lived containers and PaaS. I wrote cf-ssh (learn more) to make it dead simple; but cf-ssh builds upon the work & services other others.

Currently cf-ssh requires that your Cloud Foundry has outbound Internet access. If you're interested in the goal of how to make cf-ssh work on your private Cloud Foundry (which doesn't have any Internet access) you might like to first know how it all works.

TL;DR

At its core, cf-ssh deploys a new Cloud Foundry application, containing the same bits as your target application, with the same bound services, same environment variables, and same buildpack.

The new application's container does not start your web application as per normal. Instead, it starts an outbound reverse SSH tunnel to a public proxy (sponsored by http://tmate.io/).

The local cf-ssh client then launches an interactive ssh connect to the public proxy, which tunnels through to the application container.

cf-ssh calls out to ssh locally. tmate locally runs a tmux session which is accessible via a reverse proxy from the tmate.io proxy in the middle.

New application?

Currently, Cloud Foundry's terminology for "runnable software" is an "application". One application is scalable to hundreds of concurrent containers; but each container will run the same process.

If you want a different process to run - such as an outbound SSH connection to an SSH proxy - then you must create a different "application".

The cf-ssh command deploys a new Cloud Foundry application. The name of the temporary application is the same as your target application with -ssh suffixed. If your app name is spring-music then the application created will be called spring-music-ssh.

What about my private Cloud Foundry?

In the current implementation there are two public Internet services being used:

Both are shown in the top diagram.

The source code for both are open source:

To enable cf-ssh on a private Cloud Foundry we need to migrate both these two web services into your private infrastructure.

tmate-bootstrap

tmate-bootstrap is conceptually simple - it bootstraps the tmate process within your Cloud Foundry application. The tmate process makes an outbound connection to sf.tmate.io and runs a tmux session. Now it waits for the first inbound ssh session to connect to it.

The problem that tmate-bootstrap solves is that the tmate CLI does not exist within your application droplet. It's job is to download tmate and launch it.

And install libevent since its missing from Cloud Foundry's Ubuntu Lucid container root filesystem.

tmate-bootstrap comes in several parts:

  • the tmate CLI (and the missing libevent dependency)
  • a CLI called tmate-bootstrap that unpacks tmate & libevent and launches a tmate/tmux session
  • a simple web application that hosts the tmate-bootstrap CLI [source], etc for download
  • the web application also hosts the bootstrap script [source]

Today I patched the web application to allow it to be hosted on your own Cloud Foundry. See the README for instructions.

tmate-bootstrap was originally written by Dan Higham. I discovered it when he wasn't looking and today he explained to me how it all worked so I could explain it above. cf-ssh wouldn't exist without Dan's idea of bringing https://tmate.io to Cloud Foundry.

tmate

The backend magic of cf-ssh is the hosted https://tmate.io service. The core service allows you to initiate a pseudo-tmux session on any Internet connected computer, and be given a shareable SSH URI.

tmate-demo

The user-facing job of cf-ssh is to launch an application container that runs tmate-bootstrap which launches tmate; and then cf-ssh scrapes the ssh USERNAME@cf.tmate.io command from the log output. Finally, it runs the ssh USERNAME@cf.tmate.io command locally to kick off the SSH connection.

I tried once to convert the tmate server code, https://github.com/nviennot/tmate-slave, into a BOSH release. I got bogged down in porting the build-tooling for tmate-slave to BOSH and abandoned the effort at the time.

I think the path forward will be to Dockerize tmate-slave and then ship it as a Docker-based BOSH release. This way I can avoid BOSH-ifying tmate-slave, which didn't seem that interested in being ported to a BOSH release. Docker really shines at packaging anything.

The "Host your own tmate server" section on http://tmate.io/ also documents the requirements for clients to connect to a non-standard tmate.io proxy.

Almost there...

So we almost have all the pieces for supporting cf-ssh on your private Cloud Foundry installation. BOSHifying tmate-slave and configuring SSH to talk to the non-standard tmate-slave is the last step.

And then?

Once the Cloud Foundry CLI supports plugins, then cf-ssh will be ported into the plugin system. Hopefully it will be then very easy to install, and appear nicely in the help output of cf.

Also, it'd be great to see cf-ssh and its proxy backend as an installable tile on Pivotal Network. Then it would be super easy for PivotalCF operators to install and offer to their users.

piv-net

If you have any questions about how cf-ssh works, or how to actually use it, please let me know in the comments!