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:
- http://tmate.io/ for the public SSH proxy
- https://tmate-bootstrap.cfapps.io/ to host the bootstrap app that connects outwards to tmate.io from the application container
Both are shown in the top diagram.
The source code for both are open source:
- tmate.io server – https://github.com/nviennot/tmate-slave/
- tmate-bootstrap – https://github.com/cloudfoundry-community/tmate-bootstrap
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 missinglibevent
dependency) - a CLI called
tmate-bootstrap
that unpackstmate
&libevent
and launches atmate
/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.
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 [email protected]
command from the log output. Finally, it runs the ssh [email protected]
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.
If you have any questions about how cf-ssh
works, or how to actually use it, please let me know in the comments!