Creating a machine with SSH

I need to be able to connect to my VMs with ssh from code (not the CLI)

I followed the instructions here Run an SSH server · Fly Docs
And created a custom docker image to have SSH server running.

This is how my Dockerfile looks:

ROM ubuntu:latest

RUN apt-get update \
 && apt-get install -y openssh-server \
 && cp /etc/ssh/sshd_config /etc/ssh/sshd_config-original \
 && sed -i 's/^#\s*Port.*/Port 2222/' /etc/ssh/sshd_config \
 && sed -i 's/^#\s*PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config \
 && mkdir -p /root/.ssh \
 && chmod 700 /root/.ssh \
 && mkdir /var/run/sshd \
 && chmod 755 /var/run/sshd \
 && rm -rf /var/lib/apt/lists /var/cache/apt/archives

RUN mkdir -p /root/.ssh && \
    echo "<my ssh public key>" > /root/.ssh/authorized_keys && \
    chmod 700 /root/.ssh && \
    chmod 600 /root/.ssh/authorized_keys && \
    chown -R root:root /root/.ssh

EXPOSE 2222

CMD ["/usr/sbin/sshd", "-D"]

When I run this image locally I can connect to it with ssh.

When I deploy this with the API, without any “init” section, so that the docker “CMD” will work.
I do have this to map the port:

"services": [
                {
                    "protocol": "tcp",
                    "internal_port": 2222,
                    "ports": [
                        {"port": 22}
                    ]
                }
            ]

I’m trying to connect with ssh root@vast-vm-app.fly.dev -p 22
I get Connection closed by 66.241.125.127 port 22

What am I missing?

Hm… It looks like this might be a shared IPv4 address, actually. What does fly ips list show?

1 Like
VERSION IP              TYPE                            REGION  CREATED AT 
v4      37.16.29.25     public (dedicated, $2/mo)       global  47s ago 

Changed to a dedicated IP and it works. Thanks!!!

Do you know the answer to this followup question.
If I need to have multiple VMs and be able to ssh into each one individually (a specific one each time). Can I do that with one app, or do I need a different one (and an IP) for each?

1 Like

I think that can be done with multiple ports, i.e., by giving each Machine a distinct internal_port+port pair† in its services block.

Thus, the second VM would get:

"services": [
                {
                    "protocol": "tcp",
                    "internal_port": 2223,
                    "ports": [
                        {"port": 8023}
                    ]
                }
            ]

Another classic approach is to have a single intermediary Machine that everyone on the outside SSHes into first, and then they SSH again to the specific <machine-id>.vm.<appname>.internal address once they have a shell inside.

(I’ve used both in the past, at different organizations…)


A third thing that should work is to use kernel-mode WireGuard to connect into the whole .internal network. This doesn’t require the flyctl CLI on the clients, but it may give them more access to other stuff than you intended…


†Edit: It would probably be prudent to make the internal_ports on their own be unique, actually. I.e., have only one of them be 2222.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.