
Overview
A number of tools allow you to interact with your server over SSH. These tools are useful for tasks such as copying files (rsync, scp, sshfs), editing (emacs, vim, vscode), and deployment (ansible, github actions, and kamal). One way to use these tools is to set up a wireguard VPN and issue a new SSH credential. This may be impractical for some use cases (example: github actions). As an alternative, you can configure and deploy an SSH server on your machine(s). This guide will walk you through the process. Before proceeding, a caution: unless you are certain that all of the clients will access this service through IPv6, you will need a dedicated IPv4 address.Install and configure opensshd
Most Docker images are ultimately based on Debian, so the following will work. Adjust as necessary for other operating systems (example: Alpine).- This runs
sshdinternally on port 2222. This is because by defaultsshdlistens on all network interfaces, but fly.io machines already are listening on port 22 on the private network (ipv6) interface, so sshd will either complain or fail to start. Additionally,fly deploywill attempt to verify that your application is listening on the interfaces your application exports, and will incorrectly treat fly’s listening on port 22 as evidence that your application is up and running. - Password Authentication is disabled. This avoids unnecessary prompts. We will be using SSH keys instead.
- The above assumes
rootuser. If your application is running under a different user, replace/rootwith the home directory of that user (example:/home/rails).
Map internal port 2222 to external port 22
Add the following tofly.toml:
internal_portneeds to match the port you selected in the previous step.portcan be any available port.22is the default port for SSH, and the one that most applications expect to be used.- Like with your web server port, your server can be configured to spin down when idle and restart when accessed.
Feel free to adjust
auto_stop_machinesandauto_start_machinesif your needs differ.
Start the openssh server
There are a number of ways to run multiple processes. The most straightforward way to start sshd before your application. Locate theENTRYPOINT in your Dockerfile. If you don’t have
one, create a script in your application directory, name that script as the ENTYRPOINT, and make it
executable.
An example of such a script:
USER, you can work around this
by installing and configuring sudo and then removing sudo access before running your main process.
For example, if your userid is rails, you would add the following to your Dockerfile:
sshd as root, then remove sudo access from your unprivileged userid.
Upload your SSH key
First, locate your SSH key. You can create a new key usingssh-keygen,
Or you can use an existing one: look inside the .ssh folder in your home directory for a file with a name like id_rsa.pub.
Once located, there are multiple ways to proceed. Following you will find two ways. Depending on the framework your
application uses, you may have other ways to store credentials or environment variables. As this step only deals with
public keys, one need not take extraordinary measures to prevent leakage.
Alternative 1: Set and use a secret
Alternative 2: Copy from a volume
If you have a volume and if you can arrange to upload the file there, you can directly copy it as a part of your entrypoint script.[RECOMMENDED] Make SSH host keys stable
The first time you SSH into a server you will be presented with a fingerprint for the server you are accessing. If you accept that fingerprint, it will be added to yourknown_hosts file in your .ssh directory. This key
is generated when you install openssh-server.
The issue arises when you redeploy your application. If something changes (or your docker cache expires),
the installation of openssh-server may be rerun, and new keys will be generated. To avoid these keys from
being used, you can capture and restore the keys.
The following assumes that you have a volume mounted at /volume, and an entrypoint
script.
- These keys are expected to be private, so if you go with an alternate route, make sure that these values are not committed to a public repository unencrypted.
- If you are running with
sudo, you need to addsudobefore themkdir, thelsand both of thecpstatements. - If you have multiple machines, you may want all of them to share the same keys.
[OPTIONAL] Configure client user and aliases
Your full dnsname may be a mouthful, the user the application runs under may be different than the one you use on your laptop. the port you expose may be non-standard, or you may have multiple machines and a desire to be able to SSH into a specific one. If any of these apply to you, you can create or update a file namedconfig in your .ssh directory.
Following is an example that illustrates addressing a number of the above cases:
Host entries:
Related reading
flyctlSSH commands Official reference for how to usefly ssh/fly ssh sftpto access running machines.- Multiple processes inside a Fly.io app Explains how to run multiple process groups in a single machine/container. Relevant when you’re adding
sshdalongside your main app.