This is about how to SSH into your Fly.io Machines, specifically using the fly ssh and fly console commands.

First, the surprising bit: fly ssh doesn’t actually give you a traditional SSH daemon running on your machine. Instead, it’s a client that connects to a proxy on Fly.io’s infrastructure, which then forwards your connection to your Machine’s agent. This means you don’t need to manage SSH keys on your machines in the same way you would with a bare metal server.

Let’s see it in action. Imagine you have a simple Fly app deployed.

# First, ensure you have the flyctl CLI installed and logged in.
# Then, deploy your app (or have one already running).
fly deploy

# Once deployed, you can SSH into a specific Machine.
# Replace 'your-app-name' with your actual app name.
# Replace '1' with the Machine ID if you have multiple.
fly ssh console --app your-app-name --machine 1

You’ll be dropped into a shell on your Machine. You can run commands like ls, ps, or even apt update if your Machine’s OS allows it.

# Example session
root@fly-machine-1:/app# ls -l
total 8
-rw-r--r-- 1 root root 1234 Jan 1 10:00 app.py
drwxr-xr-x 1 root root 4096 Jan 1 10:00 config
root@fly-machine-1:/app# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  12345  6789 ?        Ss   Jan01   0:00 /usr/bin/python3 /app/app.py
root        42  0.0  0.0   5678  2345 pts/0    Ss+  10:05   0:00 bash
root        67  0.0  0.0   5000  1234 pts/0    R+   10:06   0:00 ps aux
root@fly-machine-1:/app# exit

The fly ssh command is essentially a wrapper. When you run fly ssh console --app your-app-name --machine 1, flyctl does a few things:

  1. It checks if your app has SSH enabled (which is the default for Machines).
  2. It finds the IP address of the target Machine.
  3. It initiates a connection to a Fly.io-managed SSH proxy.
  4. This proxy then establishes a secure tunnel to the SSH daemon running on your specific Machine.
  5. Your local terminal is connected to this tunnel, giving you the interactive shell.

The fly console command is a shortcut that implies you want an interactive shell, often used in conjunction with fly ssh. So, fly ssh console is the most common way to get a shell.

You can also use fly ssh to execute a single command non-interactively:

fly ssh --app your-app-name --machine 1 "ls -l /app"

This will connect, run ls -l /app, print the output to your terminal, and disconnect.

The mental model to hold onto is that your Machine has a small, secure agent listening for commands from Fly’s control plane. flyctl talks to the control plane, which then orchestrates the connection to your Machine’s agent. You don’t need to open inbound ports on your Machine for SSH, nor do you need to manage public/private keys directly on the Machine itself for this to work. Fly handles the authentication and secure tunneling.

One thing many people miss is how Fly manages the SSH identity. When you flyctl auth signup or flyctl auth login, flyctl generates an SSH key pair locally (~/.fly/fly-ssh.key and ~/.fly/fly-ssh.key.pub). It uploads your public key to Fly’s control plane. When you initiate an SSH connection, flyctl uses your local private key to authenticate with the Fly proxy, and the proxy uses the public key associated with your account to authenticate with your Machine’s agent. This means the keys are managed by flyctl and Fly’s infrastructure, not directly by your deployed application’s environment.

This SSH access is crucial for debugging and understanding what’s happening inside your deployed Machines, especially when dealing with application errors or performance issues.

The next step after getting comfortable with SSH access is often understanding how to manage secrets and environment variables securely for your applications.

Want structured learning?

Take the full Fly-io course →