How would I run multiple services on multiple IP addresses on a single Fly VM?

Hi! This is my first foray into the forums so sorry if I goof a little.

I’d like to run multiple SSH services on a single Fly app. SSH doesn’t have a facility for any kind of virtual hosting (i.e. there’s no Host header that will let the SSH server know which service the client is trying to contact), so what I want to do is just buy a dedicated IP for each SSH server, assign them all to a single Fly app, and have the servers listen on, say, 1.1.1.1:22, 2.2.2.2:22, etc.

Where I think I’ll run into trouble is that there’s no way to bind to IP addresses in fly.toml. I can’t say “this SSH server listens on this IP, and this other SSH server listens on this other IP”. I can only specify ports. That makes me think there isn’t a way to do this, and I need to use separate Fly apps. I can work with that, but I’m just confirming here. Thanks in advance!

Hi @camgunz,

You’re right that what you intend might be infeasible to achieve mainly because the machine does not have the IP addresses assigned; they are assigned to your app, but since the machine itself does not have them (i.e. they don’t appear in ip addr) you will not be able to bind the sshd process to each address.

However I think you could do what you intend (I haven’t tested it! this is theoretical) using ports instead of ip addresses. And then try starting your SSH processes in a wrapper script - this is a common trick to run multiple server processes in a single machine.

So your Dockerfile could start the wrapper script :slight_smile:

CMD ["/bin/wrapper.sh"]

and the wrapper script can be, using the port-only syntax to ListenAddress

/usr/sbin/sshd -o ListenAddress=:2022
/usr/sbin/sshd -o ListenAddress=:2023
# and so on ...
#finally, ensure there's a continuously running process to keep the machine up
/usr/sbin/sleep infinity

then in fly.toml you map the raw TCP ports to the same external one:

[[services]]
  protocol = "tcp"
  internal_port = 2022

  [[services.ports]]
    port = 2022

[[services]]
  protocol = "tcp"
  internal_port = 2023

  [[services.ports]]
    port = 2023

finally one connects from the outside like so:

ssh your-app.fly.dev -p 2022

It’s not exactly what you had in mind with the IP addresses, but this might work well for you. If not, the “separate fly apps” approach you mentioned would certainly work as well.

  • Daniel

Oh, hey Daniel! Thanks for writing all that up :slight_smile:

Huh! OK I see what you’re doing here. I think I’m too persnickety about users having to specify a port though, unfortunately for me and my budget. I’ll pursue the separate Fly apps thing–feels easier to scale, etc. anyway.