podlet turns a podman run command into a systemd-managed Quadlet unit
Generate Podman Quadlet files from a Podman command, compose file, or existing object
At a glance
- What is it?
- Podlet is a Rust CLI in the containers organisation that converts Podman commands, compose files and existing objects into Quadlet units, with a systemd services conflict check and a Podman version compatibility flag. It prints to stdout by default and only writes files when you ask.
- Who is it for?
- Adopt podlet when you have working podman invocations and want them to become systemd-managed Quadlet units without rewriting them by hand, and keep --podman-version aligned with the Podman on each host. Do not use it as a compose runtime, since it only generates files.
- Can I use it commercially?
- Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three inputs, one output: units that systemd can manage
Podlet takes a Podman command, a compose file, or an object that already exists in a Podman store, and writes the equivalent Quadlet unit. Quadlet is the mechanism where a .container, .pod, .network, .volume, .build, .image or .kube file in a unit directory becomes a systemd service.
The `podman` subcommand maps one command to one file type: run produces a .container file, pod create a .pod, kube play a .kube, network create a .network, volume create a .volume, build a .build, image pull an .image and artifact pull an .artifact. That mapping is why the subcommand list in the help output mirrors the Podman verbs exactly: the tool is a translator with a fixed vocabulary rather than a configuration language.
The `generate` subcommand is the one for objects that already exist, covering containers, pods, networks, volumes and images. It is the path for capturing what you have running today rather than what you intended to run.
The `compose` subcommand has three output shapes and the choice matters. It can emit multiple .container files, or a .pod file plus its .container files, or a .kube file plus Kubernetes Pod YAML. A fourth option, --quadlets-file, writes a single .quadlets file for `podman quadlet install`.
The crate is at version 0.3.2 with the Rust 2024 edition and a rust-version floor of 1.85. It depends on clap for the argument parsing and compose_spec for compose files, and it builds with clippy pedantic plus a long list of restriction lints, which is unusual care for a utility of this size.
Default output is stdout, and files are opt-in
The design decision worth noticing first is that nothing touches your filesystem unless you ask. The help output states that -f, --file generates files instead of printing to stdout, and -u, --unit-directory writes into the Podman unit directory instead, with --unit-dir as an alias.
That default is not a style preference. The services check that runs by default looks for an existing systemd service of the same name, and --skip-services-check turns it off. A generator whose output goes straight into /etc/systemd/system with a conflict check as the only guard would be a bad neighbour; a generator that prints is trivially reviewable.
Other naming and placement flags: -n, --name overrides the generated filename without its extension, --overwrite permits replacing an existing file, and --service-name changes the systemd service name Quadlet generates, which is how you avoid a collision with an unrelated unit of the same name.
For the systemd dependency options, the set is complete enough to be worth reading rather than guessing. --wants and --requires are the weak and strong requirement dependencies, --binds-to stops this unit when the dependency stops, --part-of only stops it when the dependency is explicitly stopped, and --upholds keeps restarting dependencies that go inactive or fail. On the parent side, -i, --install adds an [Install] section and then --wanted-by, --required-by and --upheld-by set the parent relationship. --before and --after configure ordering.
Two flags shape the unit's relationship to Podman itself: --disable-default-quadlet-dependencies removes the default network dependencies, and --no-start-with-pod stops a container unit from starting with its pod.
Podman version compatibility is an explicit, enumerated choice
Quadlet keys changed between Podman releases, and a unit written for a newer Podman than the one on a host fails in ways that are hard to read. Podlet makes that a first-class flag: -p, --podman-version takes 4.4, 4.5, 4.6, 4.7, 4.8, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7 or 5.8, and the default is 5.8. The aliases --compatibility and --compat exist for muscle memory.
The fact that the flag enumerates versions rather than taking a free-form string is the interesting part: the accepted values are the versions the generator knows how to emit for. If your fleet runs 5.4, pass 5.4 rather than relying on the default, because the default is the newest dialect the tool supports, not the newest your hosts understand.
The other environment-sensitive flag is -a, --absolute-host-paths, which takes an optional resolve directory and converts relative host paths to absolute ones. This matters in systemd, where the working directory is not your shell's working directory; a relative bind mount path that works when you type the command can resolve somewhere else entirely once Quadlet runs it as a service.
There is also -s, --split-options, which controls whether repeated Quadlet options such as Environment, Label, Volume or Mount are split into separate lines instead of joined, with a fixed list of accepted option names.
Installing it: five routes, and one of them is a container
The distribution options are unusually broad for a small utility. A prebuilt binary can be downloaded from the releases page. A container image is published at ghcr.io/containers/podlet, so the tool can run itself as a container. cargo-binstall fetches a prebuilt binary with `cargo binstall podlet`, and cargo install builds from source. Homebrew has a formula, `brew install podlet`.
cargo binstall podletThe container route is worth a second look if your build machine is a locked-down CI runner. A code generator that converts a podman command into a unit file needs no host Podman at all, so running it as an image sidesteps that dependency entirely.
The recent tags tell you how much churn to expect: v0.3.2 on 2026-05-18, v0.3.1 on 2026-02-02 and v0.3.0 on 2024-05-21. That is a low version number on a mature-looking tool, and the two releases in 2026 came after a two-year gap. The last push to the repository was on 2026-10-08, so work is landing after the 0.3.2 tag.
Because the project lives in the containers organisation, its communication channels are the shared ones, with dedicated #podlet and #podlet-dev channels on the Podman Discord and issues, discussions and pull requests on GitHub. That matters for a tool whose output format is tied to another project's releases.
What it does not do, and what to reach for instead
Podlet generates files. It does not run containers, install units, or reload systemd. After you write a.container file into the unit directory you still need `podman quadlet install` or the systemd daemon reload yourself. The tool covers the translation and nothing past it, which is a fair boundary for a converter and a source of confusion if you expected an installer.
The alternative approaches differ in what they preserve. Writing the.container unit by hand gives full control and no dependency, at the cost of transcribing a command you already know works.
The case where podlet is the wrong tool is a compose project you intend to keep running from compose. The compose subcommand emits units and does not act as a runtime for later compose changes. It suits the moment of migration from imperative commands to declarative units, and then the unit is the artefact you maintain.
One caution on the version flag: because the default is 5.8, generating units for an older fleet without passing -p means the output is not validated against what those hosts parse.
Editorial conclusion
Adopt podlet when you have working podman invocations and want them to become systemd-managed Quadlet units without rewriting them by hand, and keep --podman-version aligned with the Podman on each host. Do not use it as a compose runtime, since it only generates files. Before writing units, run without -f and read the output, and keep the services check enabled so a name collision does not overwrite an existing service.
Frequently asked questions
How do I install podlet?
Download a prebuilt binary from the GitHub releases, use cargo binstall podlet, build with cargo install podlet, install the homebrew formula with brew install podlet, or run the container image ghcr.io/containers/podlet. Building from source needs Rust 1.85 or newer.
How do I write the generated Quadlet files to disk?
Pass -f or --file to generate files instead of printing to stdout, or -u, --unit-directory (alias --unit-dir) to generate them in the Podman unit directory. Add --overwrite to replace existing files and -n to override the generated name.
What does --podman-version do?
It sets which Podman release the generated Quadlet files should conform to. Accepted values run from 4.4 to 5.8 and the default is 5.8, with --compatibility and --compat as aliases.
Can podlet convert a docker compose file?
Yes. The compose subcommand can produce multiple .container files, a .pod file with .container files, or a .kube file with Kubernetes Pod YAML. The --quadlets-file option writes a single .quadlets file for podman quadlet install.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/containers-podlet)Was this useful?