Skip to content

GettingStarted

Jeff Lindsay edited this page Oct 4, 2016 · 23 revisions

What is Cmd.io and what is it for?

Cmd.io is a service that remotely runs commands and scripts. The primary interface to Cmd.io is SSH, meaning you can use Cmd.io commands from any host with zero configuration. A couple of use cases for Cmd.io include:

  • CLI utilities as a service. Example, bring jq wherever you go, without installing it.
  • Avoid installing big CLI programs. Example, latex is huge and difficult to build but used infrequently.
  • Scripts you can use from anywhere. Trigger and orchestrate other systems using any language.
  • Share and control access to automation. Build tools for your team or Rickroll your friends.

Cmd.io commands can run any x86 64-bit program in an Linux Docker container. However, it's designed for commands and scripts as opposed to long-running daemons. In fact, commands can only run for a limited time before they timeout. So Cmd.io is also not suitable for replacing your shell. However, kudos for such a clever idea.

Commands are unable to listen on routable ports, which is not common with most commands anyway. In the rare cases you need to, such as debugging with netcat, consider using a tool like ngrok.

Another important constraint of commands is that other than configured environment variables they are stateless. If the command makes a file, it will not be there the next time you run it. Utilities that expect files on the filesystem will need to be wrapped so they can receive the file(s) via STDIN. There are examples of this later.

First time access

Cmd.io uses your GitHub user for authentication. It also relies on the public keys stored with your GitHub account. If you haven't uploaded a public key to GitHub, you can easily add one in Settings under SSH and GPG keys.

Now you can connect to Cmd.io over SSH:

$ ssh progrium@cmd.io
Usage:
  ssh <user>@cmd.io [command]

Available Commands:
  :add             Install a command
  :ls              List installed commands
  :rm              Uninstall a command

Use "[command] --help" for help about a meta command.

If you're logged into a user on your local machine with the same username as your GitHub username, SSH will use it by default. If not, you can still skip specifying a username with some configuration added to your ~/.ssh/config file:

Host cmd.io
    User progrium

Installing a command

When you start, the only commands available will be the root meta commands. Meta commands are prefixed with : and can either be root commands or meta commands on the commands you install. We'll talk about the former first. Root commands deal with managing your Cmd.io commands. For example, we can install a command with :add. We can see how with --help:

$ ssh cmd.io :add --help
Install a command

Usage:
  ssh <user>@cmd.io :add <name> <source>

Although this help could be more helpful, it does at least tell us the arguments to :add. The first, name, is a name you choose for the command. The second, source, is where to get the command. Right now, the only supported sources are public Docker registries like Docker Hub. Let's use this mysterious Docker image, progrium/welcome:

$ ssh cmd.io :add demo progrium/welcome
Command installed
$ ssh cmd.io
Usage:
  ssh <user>@cmd.io [command]

Available Commands:
  :add             Install a command
  :ls              List installed commands
  :rm              Uninstall a command
  demo

Use "[command] --help" for help about a meta command.

Although it lacks a description, the command demo is now available. Run it:

$ ssh cmd.io demo

Hello! This is a cmd.io command. All it does is display this message.
However, cmd.io commands can do lots more. They can pretty much do
anything you can do in a Docker container, except for long-running
processes like daemons.

You can install cmd.io commands from a number of sources, including
anything off Docker Hub. Once you have a command installed, you can
configure it and share access to it. Anybody that has access to your
command can run it from anywhere they have an SSH client.

Ignoring the fact this message is lying to you (Docker Hub is currently the only source for commands), you've run your first Cmd.io command!

The container images you install don't need to be specific to Cmd.io. Pretty much any CLI tool in a container can be installed. Here's a netcat container we can use to show that cmd.io port 22 is open:

$ ssh cmd.io :add nc gophernet/netcat
Command installed
$ ssh cmd.io nc -z -v cmd.io 22
cmd.io (159.203.159.60:22) open

Making commands

You'll probably be using your own commands more than off-the-shelf commands. Right now, since Docker Hub is the only source for commands, making and publishing commands is as easy any Docker container. Once you've gone through this once, you'll be surprised at how quick the workflow is for making and updating Cmd.io commands. It's literally build, push, use.

Up to this point, we haven't needed to use or install Docker. For the time being, you'll need Docker to make Cmd.io commands. We highly recommend Docker for Mac if you're running macOS.

You'll also need a Docker Hub account and be sure to login with Docker (docker login).

Commands based on existing utilities

The recommended way to build commands from existing open source utilities is to install them via a package manager. Since Cmd.io may enforce a size limit on images, and also to keep your experience snappy, we highly encourage you to use Alpine Linux for all command containers.

Alpine combines the small size of Busybox (~5MB) with a large package index optimized for small disk footprints. You can search for packages based on name or based on contents. If you can't find a package for a utility, you can try using ubuntu-debootstrap, which is a minimal Ubuntu image with apt-get. However it starts at ~90MB and easily bloats from there.

Here is jq for Alpine v3.4, so we can make a container for it with a simple Dockerfile that uses the apk package tool:

FROM alpine:3.4
RUN apk add --update jq
ENTRYPOINT ["/usr/bin/jq"]

The directives used in this example are nearly all that make sense to use for Cmd.io commands, but here is the full Dockerfile reference.

Now we can build this with Docker, assuming we're in the directory with the Dockerfile. Immediately after building, we can push to Docker Hub. Replace progrium with your Docker ID.

$ docker build -t progrium/jq .
...
$ docker push progrium/jq
...

At this point you can now install this command on Cmd.io like before. If you push new versions of the image, Cmd.io will pull it with the next run.

Clone this wiki locally