Skip to content

Flotillafile

melonfleet edited this page Oct 12, 2026 · 5 revisions

Flotillafile

A Flotillafile describes machines and containers in one file. Think Vagrantfile rather than Docker Compose.

It is version 1 of Flotilla's configuration format. Version 2 is the .flotilla file, which also carries groups, networks, volumes, clusters, hosts and more, and is what Flotilla writes when you export; see Sharing and export. A Flotillafile still reads, through the same door.

What the app actually does with one, today

File ▸ Import Configuration… (also in Go To, ⌘K) opens a Flotillafile as readily as a .flotilla file: the panel accepts both, and the parser tells them apart by version. Then:

  • It parses and validates the whole file before showing anything.
  • It shows a review screen listing every machine and container the file declares. Nothing is pulled, created or started until you press Import.
  • Anything whose name is already taken here is yours to decide, item by item: Skip it, Rename what the file brings, or, where it can, Replace what is here. Replace is destructive, and the final confirmation names everything it will delete.
  • Images the file names are pulled if this Mac does not have them. Machines are created, and containers are created stopped, so nothing runs until you start it.

The import runs as one job with a line per step. If a step fails, it says which, and what had already been built.

The machine form's import is withheld

Earlier builds had Import Flotillafile… in the machine create form, which loaded only the first machine and left containers behind. That button is withheld from this release: the format was not settled enough to put in front of testers, and a half-ready import is worse than none. The parser and its tests are untouched, so restoring it is a UI change and nothing more. Use Import Configuration… instead, which reads every machine and every container.

It does not run anything by being opened

Opening the file creates nothing. Every creation goes through the same allowlist as if you had typed it — at Import time, after the review, not when the file is read.

There is no flotilla up. A file someone sent you cannot cause anything to happen by being opened. The parser also resolves no paths, reads no other files, and follows no includes or URLs: the file you point at is the entire input.

The file panel does not insist on a particular extension beyond .flotilla or .json, because the parser takes JSON from anywhere and an extension it cannot rely on is not a check. The version inside the file is what counts.

One difference from version 2 worth knowing

A .flotilla file may mount named volumes only: a host folder in someone else's file is never mounted, and the parser refuses it. A Flotillafile is read by version 1's rules, which allow a host path such as /srv/shared:/host:rw, and an import on This Mac runs with your own permissions. So read a Flotillafile's volumes before you import one you did not write.

Apple's container has no such format

This is entirely Flotilla's own. There is no compose, manifest or declarative format anywhere in container — verified against the captured --help corpus for every subcommand, not assumed.

Format

JSON. version is required; everything else is optional. {"version": 1} is valid and does nothing.

{
  "version": 1,
  "machines": [
    { "name": "builder", "image": "alpine:3.22", "cpus": 4, "memory": "8G", "homeMount": "ro" }
  ],
  "containers": [
    {
      "name": "web",
      "image": "docker.io/library/nginx:latest",
      "ports": ["8080:80", "127.0.0.1:9000:9000/tcp"],
      "env": ["KEY=VALUE", "DEBUG=1"],
      "volumes": ["shared-data:/data:ro", "/srv/shared:/host:rw"],
      "cpus": 2,
      "memory": "512M"
    }
  ]
}

A version number Flotilla does not know — 3, say — is refused with the versions it supports, rather than read as if it were one of them.

Machines

Field Required Notes
name yes validated as an identifier
image yes use alpine; see Machines for why the others do not boot
cpus no omit to let the CLI apply its own default
memory no e.g. 8G, 512M
homeMount no ro, rw or none — three states, not a boolean, because the CLI has three

Containers

Field Required Notes
name, image yes
ports no 8080:80, or 127.0.0.1:9000:9000/tcp to bind one interface
env no KEY=VALUE
volumes no named volume or host path
cpus, memory no

Note the format is narrower than the Run form, which also offers a Command, a Network and Detach (run in background). None has a Flotillafile field, so an imported container runs its image's own entrypoint on the default network. Version 2 carries a command and a network.

Validation refuses rather than ignores

An unknown key is an error. Surplus fields are not skipped, because a typo in a key you meant to set is exactly the case where silently ignoring it produces the wrong machine and no warning.

Values are checked against the same vocabulary the allowlist uses for the CLI — the same identifier rule, the same port-mapping shape, the same mount spelling — so there is no second definition of what a valid port looks like to drift out of step.

Limits, applied before most of the file is read

Limit Default
File size 1 MiB
Machines 64
Containers 64
Ports per container 16
Environment variables per container 24
Volumes per container 16

Exceeding one gives a clear error naming the limit — "machines has more entries than the 64-entry limit" — not a truncated import that half-worked.

What it does not cover

No health checks, no restart policies, no dependency ordering, no build steps, no groups and no secrets. It describes machines and containers, and that is all. For containers that run together, with passwords kept in the Keychain rather than the file, use a group and export it as a .flotilla file; see Groups and suggestions.

Clone this wiki locally