Managing multiple apps from one repo/codebase

I have a few HTTPS REST and Websocket services I want to deploy on fly. I’m having trouble figuring out what the best way to use process groups, the fly.toml, and Dockerfiles is to create separate apps I can launch and deploy from one monolithic codebase. For context, it’s a big TypeScript repo with a few Express and Websocket Servers (though I’m planning on migrating to bun.js) defined at the top level of the src/ directory.

If I try to use process groups, I can get both processes running but only one of the internal ports can be exposed as a service in the fly.toml config.

As far as I know, there’s no good way to keep two apps in the same fly.toml or multiple fly.toml files in the same repo or root directory.

I could use a process manager and expose an HTTP service to route between my other services internally, but that seems like over-engineering.

Another option is to factor out common code into a library I install into separate repos or subdirectories that contain their own fly.toml files defining separate apps. This seems workable but I don’t like being forced to maintain separate repos for every microservice.

Any recommendations, or something I’m missing?

Thanks

This shouldn’t be true. I have an app that has to expose multiple internal ports.
ex

[[services]]
  internal_port = 4318
  protocol = "tcp"
  auto_start_machines = false
  auto_stop_machines = false
  min_machines_running = 1

  [[services.ports]]
    handlers = ["http"]
    port = 4318
    force_https = false

[[services]]
  internal_port = 13133
  protocol = "tcp"
  auto_start_machines = false
  auto_stop_machines = false
  min_machines_running = 1

  [[services.ports]]
    port = 13133

  [[services.http_checks]]
    path = "/health"
    method = "GET"
    interval = "10s"
    timeout = "2s"

Unless I misunderstand or you have other reasons to try and keep the services in a single Fly app, I’ve found it’s much less complex to manage multiple apps especially if they still need to communicate with each other regardless of how they’re deployed.

The Fly CLI allows you to specify the toml file to use so that shouldn’t be the limiting factor either. You can also specify which Dockerfile to use in the toml config if you end up sharing the same directory.


Here’s my setup if it helps give you any ideas:

I use an Nx monorepo to manage all my apps so each app gets it’s own sub-directory, then there’s shared libraries that multiple apps can use.

  • in each app directory, I have multiple configs, ex: fly.prod.toml and fly.staging.toml
  • Nx has “executors” and I created a custom executor to easily deploy apps using Fly’s API and CLI
"deploy": {
   "dependsOn": ["build"],
   "executor": "@streamersonglist/fly:deploy",
   "options": {
     "appName": "ssl-staging-identity-api",
     "tomlFile": "fly.staging.toml",
     "dockerfile": "Dockerfile",
     "organization": "ssl-staging",
     "regions": ["sea"]
   },
   "configurations": {
     "production": {
       "appName": "ssl-prod-identity-api",
       "tomlFile": "fly.prod.toml",
       "organization": "ssl-prod",
       "regions": ["sea"]
     }
   }
 }

The advantage of the executor is that I have additional functionality that sets up the IP addresses for private networking so I don’t have to run multiple Fly CLI commands for each app.

Then from the root directory of the repo I can run commands like:

# automatically builds and deploys all apps based on what files have changed
nx affected --target=deploy

# run a single app build & deploy to staging
nx run app1:deploy:staging

# run multiple
nx run-many -t deploy -c staging -p app1 app2 app3 app4

I may be completely misunderstanding the requirements…

If you really want multiple apps (each with separate ip addresses and dns names, etc) that are deployed separately, then have two fly.toml files in separate directories (i.e., at the root of each separate application).

If you want a single fly.toml in the root directory, then use something like concurrently in the start script in the package.json in that directory to start the two applications and expose whatever ports you want to in the fly.toml.

My recommendation would be to start with the latter and see if there are specific problems. An example of something to look for: if you need these applications to scale differently – say, one app should have more apps or more regions.